Περιστροφές δένδρων BST (Δομές Δεδομένων)

Συζητήσεις για γλώσσες προγραμματισμού και θέματα σχετικά με προγραμματισμό.
Post Reply
User avatar
Zifnab
Venus Former Team Member
Posts: 7581
Joined: Tue Nov 15, 2005 2:42 am
Academic status: MSc
Gender:
Location: Connecticut
Contact:

Περιστροφές δένδρων BST (Δομές Δεδομένων)

Post by Zifnab » Wed Jan 24, 2007 3:02 am

Παιδιά έχω ένα πρόβλημα! Στις σημειώσεις για τις Δομές δεδομένων(βασισμένες στου Princeton) περιγράφονται οι συναρτήσεις για περιστροφή Binary-Search-Trees... Όμως απ'ότι φαίνεται αυτές οι δύο μέθοδοι ούτε καν περιστρέφουν το δέντρο με το γνωστό αλγόριθμο. Συγκεκριμένα όταν γίνεται π.χ RotR για κάποια ρίζα υπόδενδρου μπλέκει και τον πατέρα του και τον παππού του, κάτι που αυτές οι μέθοδοι δεν κάνουν... Απ' ότι κατάλαβα οι μέθοδοι χρησιμοποιούνται από τον Sedgewick αναδρομικά για να κάνουμε εισαγωγή στοιχείου στη ρίζα και ΜΟΝΟ....

Code: Select all

class bst<Item extends Comparable> {
	private class Node{
		Node left;
		Node right;
		Item item;
		private Node(Item item) {
			this.item=item;
		}
	}
	Node root;
	public void insert(Item item) {
		root=insert(root,item);
	}
	public void insert(Item[] items) {
		for (int i=0; i<items.length; i++) 
			insert(items[i]);
		
	}
	private Node insert(Node x,Item item) {
		if (x==null)
			return new Node(item);
		else if(item.compareTo(x.item)<0) 
			x.left = insert(x.left,item);
		else
			x.right = insert(x.right,item);
		return x;
	}
	public Node protL(Node h) { //aristeri peristrofi
		Node x=h.right;
		h.right=x.left;
		x.left=h;
		return x;
	}
	public Node protR(Node h) { //dexia peristrofi
		Node x=h.left;
		h.left=x.right;
		x.right=h;
		return x;
	}
	public static void main(String args[]) {
		bst<Character> searchtree=new bst<Character>(); 
		Character[] chars={'A','S','E','R','C','H','I','N','G','X','M','P','L'};
		searchtree.insert(chars);
		//dokimes
		System.out.println(searchtree.root.item);
		System.out.println(searchtree.root.right.item);
		System.out.println(searchtree.root.right.left.item);
		System.out.println(searchtree.root.right.left.right.item);
		searchtree.rotR(searchtree.root.right);
		System.out.println("After Right Rotation");
		System.out.println(searchtree.root.item);
		System.out.println(searchtree.root.right.item);
		System.out.println(searchtree.root.right.left.item);
		System.out.println(searchtree.root.right.left.left.item);	
	}			
}


Ο σωστός κώδικας που βρήκα είναι κάτι σαν αυτό:

Code: Select all

void rotate( node c ) {

    node p = c.parent;		// parent of c
    node gp = p.parent;		// grandparent of c (might be null)

    // Update the lower edge which switches sides

    if (c == p.left) {
      p.left = c.right;
      if (p.left != null)
	p.left.parent = p;
      c.right = p;
      p.parent = c;
    } else {
      p.right = c.left;
      if (p.right != null)
	p.right.parent = p;
      c.left = p;
      p.parent = c;
    }

    // Update the upper edge which switches sides

    if (gp == null)
      root = c;
    else if (p == gp.left)
      gp.left = c;
    else
      gp.right = c;
    
    c.parent = gp;
  }
}

Επίσης ο τελευταίος κώδικας μας προστατεύει να μην περιστρέψουμε κάποιο κόμβο δένδρου που δεν επιτρέπεται....

Να και ένα ωραίο link που βρίκα για τις περιστροφές με applet
http://www.cs.queensu.ca/~jstewart/appl ... ation.html

Εσείς τι γνώμη έχετε ? thx ;)
User avatar
cactus
Mbyte level
Mbyte level
Posts: 959
Joined: Tue Apr 25, 2006 7:14 pm
Academic status: N>4
Gender:

Post by cactus » Wed Jan 24, 2007 5:12 pm

Δεν καταλαβαίνω πιο είναι το πρόβλημα...
"Έτρεξα"(=με το χέρι) τις protL(Node), protR(Node) και δεν βρήκα πρόβλημα.
Μήπως επειδή η 1η υλοποίηση δεν χρησιμοποιεί σε κάθε κόμβο πεδίο που να αναφέρεται στον κόμβο-πατέρα του κόμβου όπως κάνει η 2η;

Α,ακόμα μία διαφορά είναι:

--στις protL(Node) & protR(Node) περιστρέφεις το όρισμα και το παιδί του.
--στη rotare(node) περιστρέφεις το όρισμα κια τον πατέρα του.

Αν δες σε κάλυψα πες μου...ίσως να μην κατάλαβα το πρόβλημα.
Ζifnab wrote:Επίσης ο τελευταίος κώδικας μας προστατεύει να μην περιστρέψουμε κάποιο κόμβο δένδρου που δεν επιτρέπεται....
Μπορείς να μου το εξηγήσεις λίγο;; δηλ ένα παράδειγμα ενός κόμβου που δεν μπορούμε να περιστρέψουμε, ή κάτι άλλο, δεν το κατάλαβα
laikedelic !
User avatar
Zifnab
Venus Former Team Member
Posts: 7581
Joined: Tue Nov 15, 2005 2:42 am
Academic status: MSc
Gender:
Location: Connecticut
Contact:

Post by Zifnab » Wed Jan 24, 2007 5:23 pm

Απλά είπα πως οι δύο μέθοδοι επάνω δεν μπορούν να χρησιμοποιηθούν έτσι χύμα για ένα δένδρο...παρά μόνο αναδρομικά όταν κάνουμε εισαγωγή στη ρίζα...Γενικά δεν δουλεύουν μόνες τους,αφού δεν αλλάζουν την σύνδεση της νέας υπορίζας με τον πατέρα και τον παππού...τέλος πάντων.

Αυτές οι δύο μέθοδοι έχουν και το άλλο πρόβλημα:
Αν έχω το δένδρο

Code: Select all

    B
  /   \
 A     C
δεν μπορώ να κάνω περιστροφή ως προς το A ή το C, γιατί αυτά δεν έχουν παιδιά. Σύμφωνα με το βιβλίο του Sedgewick π.χ για την δεξιά περιστροφή ο κόμβος που περιστρέφεται γίνεται δεξιό παιδί του αριστερού του παιδιού...
User avatar
cactus
Mbyte level
Mbyte level
Posts: 959
Joined: Tue Apr 25, 2006 7:14 pm
Academic status: N>4
Gender:

Post by cactus » Wed Jan 24, 2007 5:30 pm

Σωστός σε όλα!
laikedelic !
User avatar
Zifnab
Venus Former Team Member
Posts: 7581
Joined: Tue Nov 15, 2005 2:42 am
Academic status: MSc
Gender:
Location: Connecticut
Contact:

Post by Zifnab » Wed Jan 24, 2007 5:54 pm

cactus έχει νόημα να περιστρέφουμε κόμβο που είναι ήδη στην κεντρική ρίζα (επίπεδο 1)?
Δες λίγο το link επάνω - και παίξε με τα applets...Παρατήρησε ότι η rotate που παραθέτω στο δεύτερο κομμάτι κώδικα (προέρχεται από το applet) δεν έχει left και right... Δηλαδή ένας κόμβος είτε θα μπορεί να περιστραφεί αριστερά είτε δεξιά (ποτέ και τα δύο μαζί), είτε καθόλου?
User avatar
cactus
Mbyte level
Mbyte level
Posts: 959
Joined: Tue Apr 25, 2006 7:14 pm
Academic status: N>4
Gender:

Post by cactus » Wed Jan 24, 2007 6:38 pm

EDIT: Zifnab, δεν είδα το τελευταίο post σου όταν postaρα το παρακάτω...το κοιτάζω τώρα αυτό που λές...

Επαναποστάρω...(μ'αρέσουν οι δομές :) )

Λοιπόν το λάθος που επισήμανες,σωστός μεν αλλά μου φένεται πολύ χοντρό για να του ξέφυγε...

Παρατήρησα από τα σχόλια στη main ότι εσύ τα έγραψες σωστά;; Επίσης παρατήρησα ότι η κάθε αντικέιμενο τις τάξης είναι ένα BST. Οι κόμβοι είναι αντικέιμενα εσωτερικής τάξης private, άρα μία τάξη πελάτης δεν έχει πρόσβαση σε αυτά. Οι public μέθοδοι έχουν ορίσματα Nodes που δεν έχουμε πρόσβαση αρα ο κώδικας είχε μια getRoot() ή κάτι τέτοιο, σωστα;
(αν αυτες οι υποθέσεις ήταν σωστές, τότε αυτό που ακολουθεί έχει νόημα, αλλιώς δεν νομιζω να αξίζει τον κόπο...)

Οπότε κάνω μια υπόθεση ότι ίσως δεν είναι σκοπός της τάξης να κάνεις ποτέ rotare ένα κόμβο τυχαία, παρα μόνο τη ρίζα, απλά και μόνο για να ισορροπείς το δέντρο...(Μήπως η rotare δεν ήταν καν public αλλά μια άλλη τη χρησιμοπιούσε, (άλλη μία παρακινδυνεμένη υπόθεση))

Έψαξα στα .pdf στο eclass αλλα δεν την πλήρη βρήκα την υλοποίηση, φαντάστηκα ότι είναι από το βιβλίο και ότι δεν τη μετέφερες όλη για ευνόητους λόγους.

Γενικά, πιστεύω καλύτερα είναι ν αδοκιμ'αζεις μια τάξη-βιβλιοθήκη με μία τάξη πελάτη σε άλλο πακέτο ώστε να βλέπεις και το λόγω επιλογής της συγγεκριμένης υλοποίησης.

no offence taken, just shooting ideas
laikedelic !
User avatar
cactus
Mbyte level
Mbyte level
Posts: 959
Joined: Tue Apr 25, 2006 7:14 pm
Academic status: N>4
Gender:

Post by cactus » Wed Jan 24, 2007 7:20 pm

Ζifnab wrote:cactus έχει νόημα να περιστρέφουμε κόμβο που είναι ήδη στην κεντρική ρίζα (επίπεδο 1)?
Δες λίγο το link επάνω - και παίξε με τα applets...Παρατήρησε ότι η rotate που παραθέτω στο δεύτερο κομμάτι κώδικα (προέρχεται από το applet) δεν έχει left και right... Δηλαδή ένας κόμβος είτε θα μπορεί να περιστραφεί αριστερά είτε δεξιά (ποτέ και τα δύο μαζί), είτε καθόλου?
Στο βιβλίο του Συντιχάκη βρήκα το εξης:
Η αριστερή περιστροφή ενός κόμβου p εμπλέκει τον ίδιο κια το δεξί του παιδί, έστω r. To αριστερό υπόδεντρο του κόμβου r γίνεται δεξί παιδί του κόμβου p και ο p γίνεται αριστερό παιδί του κόμβου r.
Η δεξιά περιστροφή ενός κόμβου p εμπλέκει τον p και το αριστερό του παιδί έστω l. Το δεξί υπόδεντρο του l γίνεται αριστερού παιδί του p και ο p γίνεται δεξί παιδί του l.
Πρόσεξε ότι οι protL(Node) και protR(Node) περιστρέφουν το δεξί παιδί του ορίσματος, κια το αριστερό αντίστοιχα, ενώ ο η rotare(node) περιστρέφει το όρισμα ανάλογα με το αν είναι δεξί ή αριστερό πιαδί του πατέρα του.

Δηλ όλες περιστρέφουν το παιδί ανάλογα με τη θέση του ως προς τον πατέρα.

Αυτά ως ενδείξεις...επανέρχομαι σύντομα...

Στο χω ξαναπεί, μου αρέσουν οι ιδέες σου. (ποτέ δεν το χα σκεφτει αυτό...ωραίος!!!)
Last edited by cactus on Wed Jan 24, 2007 7:43 pm, edited 1 time in total.
laikedelic !
User avatar
cactus
Mbyte level
Mbyte level
Posts: 959
Joined: Tue Apr 25, 2006 7:14 pm
Academic status: N>4
Gender:

Post by cactus » Wed Jan 24, 2007 7:34 pm

Όντως έχεις δίκιο. Έστω το δέντρο:

Code: Select all

                     20   
                  /       \
               15          26
              /   \       /    \
            4      17    23     30
Oι τιμές είναι τα πεδία των κόμβων που τους καθιστούν διαταξιμους.
Προφανώς είναι BST.
Μπορέις να περιστρέψεις αριστερά τον 20 ως προς τον 26, αλλά έστω πως θες να περιστρέψεις τον 20 δεξιά ώς προς τον 26.
Οκ, μπορέι να γίνει, αλλά δεν βλέπω κανονικότητα ούτε ως προς τις κινήσεις που θα κάνεις ούτε ως προς το αποτέλεσμα που θα έχεις στο δέντρο. Δηλ αν και εφικτό δεν βλέπω κέρδος... εσύ τι λές;;;
Last edited by cactus on Wed Jan 24, 2007 7:35 pm, edited 1 time in total.
laikedelic !
The Punisher
Venus Former Team Member
Posts: 7561
Joined: Thu Oct 27, 2005 1:43 pm
Academic status: Alumnus/a
Gender:
Location: Boston, MA

Post by The Punisher » Wed Jan 24, 2007 7:35 pm

κοινώς o Node στις protL και protR είναι ο πατέρας, ενώ στη rotate το παιδί ... νομίζω
User avatar
Zifnab
Venus Former Team Member
Posts: 7581
Joined: Tue Nov 15, 2005 2:42 am
Academic status: MSc
Gender:
Location: Connecticut
Contact:

Post by Zifnab » Wed Jan 24, 2007 7:49 pm

Ευχαριστώ cactus και Punisher που ασχολείστε... ;)
Βασικά και ο Συντιχάκης λέει τα ίδια με τον Sedgewick....Αυτά όμως ισχύουν για την αναδρομική περιστροφή και όχι για μια τυχαία περιστροφή κάποιου κόμβου που οπωσδήποτε μπλέκουν τουλάχιστον τον πατέρα...Θα το ψάξω και εγώ και θα γράψω στα συμπεράσματα στα οποία κατέληξα...
Post Reply

Return to “Προγραμματισμός”