Problem bei Programmierung zyklischer Listen



  • Hallo,

    ich habe ein Problem bei der Programmierung einer zyklischen Liste. Und zwar sollen Elemente in eine Liste eingetragen werden können und auch wieder gelöscht werden können. Dabei möchte ich, dass nur ein Anker verwendet wird. Dieser Anker soll eine Referenz sein, die auf das jüngste Element der Liste zeigt. Und dieses jüngste Element soll auf das älteste Element zeigen, so dass im Prinzip ein verketteter Ring entsteht. Achso die Liste bzw. der Ring ist ein vorwärtsverketteter Ring. Nun klappt das mit dem Eintragen ganz gut, hab ich auch schon in einem seperaten Testtreiber getestet. Aber die Sache mit dem Entfernen bekomme ich einfach nicht hin. Es soll immer das älteste Element dabei gelöscht werden und nicht das jüngste. Im folgenden mal ein Ausschnitt aus dem Programm. Vielleicht könnt ihr mir ja helfen. Wär euch echt sehr dankbar.

    public class WarteschlangeListe<Element> implements Warteschlange<Element>{
    
    	private class Knoten<Element>{
    
                Element wert;
    	      Knoten<Element> verbindung;
    
    		Knoten(final Element wert, final Knoten<Element> verbindung){
    			this.wert = wert;
    			this.verbindung = verbindung;
    		}
    
    		Knoten(final Element wert){
    			this(wert, null);
    		}
    	}
    
    private Knoten<Element> anker = null; //Anker
    public int anzahl;
    
    public WarteschlangeListe(){
    		anker = null;
    	}
    
          //Liste entleeren
    	public void entleeren(){
    		anker = null;
    	}
    
          //Element in die Liste eintragen und am Ende einfügen
    	public void eintragen(final Element element) throws VollAusnahme{
    		try{
    			if (istLeer()){
    				anker = new Knoten<Element>(element, null);
    				anker.verbindung = anker;
    			}
    			else
    			{
    				anker = new Knoten<Element>(element, anker.verbindung);
    			}
    			anzahl++;
    		}
    		catch(OutOfMemoryError ausnahme){
    			throw new VollAusnahme();
    		}
    	}
    
          //ältestes Element entfernen
    	public void entfernen() throws LeerAusnahme{//fertig
    		try{
    			//HIER BRAUCHE ICH DIE HILFE VON EUCH!!!!!
    			anzahl--;
    		}
    		catch(NullPointerException ausnahme){
    			throw new LeerAusnahme();
    		}
    	}
    
          //ältestes Element lesen
    	public Element lesen() throws LeerAusnahme{
    		try{
    			return (Element)anker.verbindung.wert;
    		}
    		catch(NullPointerException ausnahme){
    			throw new LeerAusnahme();
    		}
    	}
    
          //Anfrage ob Liste leer ist
    	public boolean istLeer(){
    		return anker == null;
    	}
    
          //Anfrage ob Liste voll ist
    	public boolean istVoll(){
    		try{
    			Knoten<Element> knoten = new Knoten<Element>(null, null);
    			return false;
    		}
    		catch(OutOfMemoryError ausnahme){
    			return true;
    		}
    	}
    
    	public int anzahlElemente(){
    		return anzahl;
    	}
    
          //jüngstes Element lesen
    	public Element lesen_juengstes() throws LeerAusnahme{//Zusatzmethode
    		if (istLeer()){
    			throw new LeerAusnahme();
    		}
    		else return (Element)anker.wert;
    	}
    }
    

    Achso mir ist da noch was eingefallen. Und zwar hab ich noch nie ein Objektdiagramm gezeichnet und weiß auch leider nicht so recht wie es funktioniert. Es soll aber einige Dinge besser verständlich machen. Könnt ihr mir vielleicht auch Tipps geben, wie an solch eine Sache rangehe oder habt ihr vielleicht ein Beispiel parat? Danke euch echt.



  • Hoffentlich hab' ich das jetzt richtig überschaut. Könnte man nicht deiner Klasse "Knoten<Element>" eine Eigenschaft "Knoten<Element> vorgänger" verpassen, in welcher dann jeweils der Vorgängerknoten abgelegt wird?

    Dein Konstruktor würde dann wie folgt aussehen:

    Knoten(final String wert, final Knoten<Element> verbindung, Knoten<Element> vorgänger)
         {
          this.wert = wert;
          this.verbindung = verbindung;
          this.vorgänger = vorgänger;
         }
    

    Danach folgt bei deiner Methode "eintragen":

    try{
                if (istLeer()){
                    anker = new Knoten<Element>(element, null, null);
                    anker.verbindung = anker;
                }
                else
                {
                    anker = new Knoten<Element>(element, anker.verbindung, anker);
    
                }
                anzahl++;
    

    Das Entfernen könnte vielleicht so ablaufen:

    Knoten<Element> temp = anker;
                Knoten<Element> nachfolger = null;
    
                for (int k = anzahl; k > 0; k--)
                {
                 if (temp.vorgänger == null)
                 {
                  nachfolger.vorgänger = null;
                  anker.verbindung = nachfolger;
                  break;
                 }
                 nachfolger = temp;
                 temp = temp.vorgänger;
                }
    
                anzahl--;
    

    Man überprüft also immer den jeweiligen Vorgänger (aktueller Knoten wird gespeichert). Ist dieser null, so wurde der Anfang erreicht. Als neuen "ältesten" Knoten setzt man dann den temporär gespeicherten "Nachfolger". Ist vielleicht nicht die eleganteste Lösung, aber sie könnte klappen.

    ----

    Objektdiagramme gemäß UML ähneln dem Klassendiagramm (einfach mal suchen; du wirst genügend Abbildungen finden). Der Objektname wird jedoch unterstrichen und die Eigenschaften erhalten kokrete Werte. Auf die Darstellung der Methoden kann man im Objektdiagramm verzichten.



  • TFH-Berlin, 2 Sem. medieninformatik bei Solymosi?
    Haben wir gerade als Übung gehabt:

    package liste;
    
    class Knoten<Element> {
        public Element wert = null;
    	public Knoten<Element> verbindung = null;
    	public Knoten (final Element wert, final Knoten<Element> verbindung){
    		this.wert = wert;
    		this.verbindung = verbindung;
    	}
    }
    
    package liste;
    
    import lehrbuch.*;
    
    class ListRing<Element> implements WarteschlangeImpl<Element>{
    
    	private Knoten<Element> anker = null;
       private final NoMoreMemoryException outOfMemory = new NoMoreMemoryException("OutOfMemoryError");
    	private class NoMoreMemoryException extends VollAusnahme{
          private String info;
          public NoMoreMemoryException(String info){
             super();
             this.info = info;
          }
          public String toString(){
             return info;
          }
       }
       public void entleeren(){
    		anker = null;
    	}
    
    	public void eintragen(final Element element) throws VollAusnahme{
    		try{
    			Knoten<Element> last = anker;
    			//wenn anker ==null: Exception
    			anker = new Knoten<Element>(element, last.verbindung); 
    			last.verbindung = anker;
    
    		}catch(OutOfMemoryError ausnahme){
    			//throw new VollAusnahme();  //Neues Objekt ohne Memory ?! Na dann viel Glück ...
             throw outOfMemory;
    		}
    		//Alternativ hätte man mit if(!istLeer)/else arbeiten können 
    		catch(NullPointerException e){
    			anker = new Knoten<Element>(element,anker); 
    			anker.verbindung = anker;
    		}
    	}
    
    	public Element lesen() throws LeerAusnahme{		
    		try{
    			return anker.verbindung.wert;	
    		}
    		catch(NullPointerException e){
    			throw new LeerAusnahme();
    		}
    	}
    
    	public void entfernen() throws LeerAusnahme{
    		if(istLeer()) throw new LeerAusnahme(); //eleganter
          //prüft, wieviele Objekte in der Liste hängen ## bei nur 1Obj: Referenz auf sich selbst 
    		if(anker.verbindung.verbindung != anker.verbindung)
             anker.verbindung = anker.verbindung.verbindung;
    		//wenn Referenz auf sich selbst
    		else anker = null;
    	}
    
    	public boolean istLeer(){
    		return anker == null;
    	}
    
    	public boolean istVoll(){
    		return false;
    	}
    }
    
    package liste;
    
    import lehrbuch.*;
    
    public interface WarteschlangeImpl<Element> {
    	public void entleeren(); // ensures istLeer()
    	public void eintragen(final Element element) throws VollAusnahme; // requires !istVoll() // ensures !istLeer()
    	public Element lesen() throws LeerAusnahme; // const // requires !istLeer()
    	public void entfernen() throws LeerAusnahme; // requires !istLeer() // ensures !istVoll()
    	public boolean istLeer(); // const
    	public boolean istVoll(); // const
    }
    
    package liste;
    
    import java.awt.*;
    import javax.swing.*;
    import java.awt.event.*;
    import lehrbuch.*;
    
    class WarteschlangeGUI
    {
    	private ListRing listInstanz;
    
    	private JFrame frame;
    	private Container content;
    
    //#########  Konstruktor  ##########
    	public WarteschlangeGUI()
    	{
    		listInstanz = new ListRing();
    //Frame erstellen
    		frame = new JFrame();
    		frame.setLayout(null);
    		content = frame.getContentPane();
    		frame.setSize(350,250);
    
    //TextField zur Eingabe erstellen
    		JTextField eingabeFeld = new JTextField("Text eingeben");
    		eingabeFeld.setBounds(10,72,100,20);
    
    //StatusLabel erstellen
    		JLabel status = new JLabel("Status:");
    		status.setBounds(10,200,240,20);
    
    //Listener für Buttons
    		KomponentenLauscher lauscher = new KomponentenLauscher(status,eingabeFeld);
    
    //Buttons erstellen
    		JButton eintragen = new JButton("eintragen");
    		eintragen.setBounds(10,10,100,20);
    		eintragen.addActionListener(lauscher);
    
    		JButton entfernen = new JButton("entfernen");
    		entfernen.setBounds(120,10,100,20);
    		entfernen.addActionListener(lauscher);
    
    		JButton entleeren = new JButton("entleeren");
    		entleeren.setBounds(10,40,100,20);
    		entleeren.addActionListener(lauscher);
    
    		JButton lesen = new JButton("lesen");
    		lesen.setBounds(120,40,100,20);
    		lesen.addActionListener(lauscher);
    
    //Komponenten hinzufügen
    		content.add(eintragen);
    		content.add(entfernen);
    		content.add(entleeren);
    		content.add(lesen);
    		content.add(eingabeFeld);
    		content.add(status);
    
    		frame.setVisible(true);
    	}
    
    	public static void main(String [] args)	{
    		WarteschlangeGUI instanzGUI = new WarteschlangeGUI();
    
    	}
    
    //############### ACTION ##########
    class KomponentenLauscher implements ActionListener
    
    	{
    		JLabel status;
    		JTextField eingabeFeld;
    
    		public KomponentenLauscher(JLabel status, JTextField eingabeFeld){
    			this.status = status;
    			this.eingabeFeld = eingabeFeld;
    		}
    
    		public void actionPerformed(ActionEvent e)
    		{
    			if (e.getActionCommand() == "eintragen"){
    				try{
    					listInstanz.eintragen(eingabeFeld.getText());
    					status.setText("<html>String-Objekt <font color=\"RED\"><i>'"+eingabeFeld.getText()+"'</i></font> hinzugefügt</html>");
    				}
    				catch(VollAusnahme voll){
    					status.setText("<html>Ausnahme - Warteschlange <font color=\"RED\">voll</font></html>");
    				}
    
    			}
    
    			if (e.getActionCommand() == "entfernen"){
    				try{
    					listInstanz.entfernen();
    					status.setText("<html>Ältestes String-Objekt entfernt!");
    					}
    				catch(LeerAusnahme leer){
    					status.setText("<html>Ausnahme - Warteschlange <font color=\"RED\">leer</font></html>");
    				}
    			}
    
    			if (e.getActionCommand() == "entleeren"){
    				listInstanz.entleeren();
    				status.setText("entleert");
    			}
    
    			if (e.getActionCommand() == "lesen"){
    				try{
    					status.setText("<html>Ältestes-Objekt <font color=\"RED\"><i>'"+listInstanz.lesen().toString()+"'</i></font></html>");
    				}
    				catch(LeerAusnahme leer){
    					status.setText("<html>Ausnahme - Warteschlange <font color=\"RED\">leer</font></html>");
    				}
    			}
    		}
    	}
    }
    

    😃


Anmelden zum Antworten