Βρείτε αντάλλαξαν οι κόμβοι σε ένα BST

ψήφοι
6

Προσπαθώ να γράψω ένα πρόγραμμα που μπορεί να ανιχνεύσει και να εκτυπώσετε δύο κόμβους στο BST που έχουν ανταλλαγεί.

Σε ένα δέντρο τρία επίπεδα, έφτασα κοντά στη λύση, χρησιμοποιώντας αυτή την προσέγγιση.

If (!AllSubTreeAreValid())
{
//Nodes swapped on same side of main root node
}
else
{
  int max = getMax(root->left);
  int min = getMin(root->right);
  if(max > root->data || min < root->data )
  {
     //Nodes swapped on different sides of main root node
     //Print max and min values

  }
else 
{
 //No node swappped
}
}

//Helper functions
int GetMaxEle(TreeNode* tree)
{
    while(tree->right!=NULL)
    {
        tree=tree->right;
    }
    return tree->info;
}

int GetMinEle(TreeNode* tree)
{
    while(tree->left!=NULL)
    {
        tree=tree->left;
    }
    return tree->info;
}

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

             20

      15            30

   10    17       25     33

9  16  12  18  22  26  31  34

Όντας στο δεξί υποδέντρο ρίζα τον κόμβο 15, το 12 είναι ακόμα μεγαλύτερη (παραβίαση).

Όντας σε αριστερό υποδένδρο root κόμβο 15, το 16 είναι ακόμα μεγαλύτερη (παραβίαση).

Έτσι, 16, 12 είναι τα ανταλλαχθούν στοιχεία στο παραπάνω BST. Πώς μπορώ να τα βρω μέσα από το πρόγραμμα;

Δημοσιεύθηκε 31/08/2011 στις 17:30
πηγή χρήστη
Σε άλλες γλώσσες...                            


3 απαντήσεις

ψήφοι
0

Υποθέτω ότι σας getMin et getMax λειτουργεί witht τις υποθέσεις που το δέντρο είναι ένα BST, έτσι

T getMax(tree) {
  return tree -> right == null 
    ? tree -> value 
    : getMax(tree -> right);
}

(Ή το ισοδύναμο κώδικα με ένα βρόγχο). Αν ναι, κωδικό σας εξετάζει το πολύ τρεις τιμές στο δέντρο. Ακόμα κι αν getMax και getMin διασχίσει όλο το δέντρο για να πάρει την πραγματική max / min, θα εξακολουθούν να βασίζουν τη δοκιμή σας σε μόλις δύο συγκρίσεις. Αν θέλετε να βεβαιωθείτε ότι το δέντρο σας ικανοποιεί το ακίνητο BST, είναι προφανές ότι θα πρέπει να εξετάσει όλες τις τιμές. Είναι αρκετό για να συγκρίνει κάθε κόμβο με τη μητρική της.

void CheckIsBst(Tree *tree) {
  if (tree -> left != null) {
    if (tree -> left -> value > tree -> value) {
      // print violation
    }
    CheckIsBst(tree -> left);   
  }
  // same with -> right, reversing < to > in the test
}

Επεξεργασία : ότι ήταν λάθος, δείτε το σχόλιο. Πιστεύω ότι αυτό είναι εντάξει.

void checkIsBst(Tree *Tree, Tree *lowerBound, Tree *upperBound) {
  if(lowerBound!= null && lowerBound -> value > tree -> Value) {
    //violation
  }
  // same for upper bound, check with <
  if (tree -> left != null) {
    if (tree -> left -> value > tree -> value) {
      // print violation
     }
     CheckIsBst(tree -> left, lowerBound, tree);   
  }
  // same for right, reversing comparison 
  // setting lowerBound to tree instead of upperBound
}

Κλήση από τη ρίζα με μηδενική όρια

Απαντήθηκε 31/08/2011 στις 18:03
πηγή χρήστη

ψήφοι
8

Ένας τρόπος για να σκεφτεί για αυτό το πρόβλημα είναι να χρησιμοποιήσει το γεγονός ότι η inorder πόδια του δέντρου θα παράγει όλα τα στοιχεία σε ταξινομημένη σειρά. Εάν μπορείτε να εντοπίσετε αποκλίσεις από την ταξινομημένη σειρά κατά τη διάρκεια αυτής της διαδρομής, μπορείτε να προσπαθήσετε να εντοπίσετε τα δύο στοιχεία που είναι σε λάθος μέρος.

Ας δούμε πώς να το κάνουμε αυτό για έναν απλό ταξινομημένο πίνακα πρώτα, τότε θα χρησιμοποιήσει ο αλγόριθμος μας να οικοδομήσουμε κάτι που λειτουργεί στα δέντρα. Διαισθητικά, αν ξεκινήσετε με ένα ταξινομημένο πίνακα και στη συνέχεια να ανταλλάξουν δύο (μη-ίσα!) Στοιχεία, θα καταλήξουμε με κάποιο αριθμό των στοιχείων του πίνακα είναι εκτός τόπου. Για παράδειγμα, δίνεται η συστοιχία

1 2 3 4 5

Αν αλλάζετε 2 και 4, μπορούμε να καταλήξουμε σε αυτό το πίνακα:

1 4 3 2 5

Πώς θα διαπιστώσουμε ότι 2 και 4 μετατράπηκε εδώ; Λοιπόν, από τις 4 είναι η μεγαλύτερη από τις δύο στοιχεία και αντάλλαξαν προς τα κάτω, θα πρέπει να είναι μεγαλύτερη από ό, τι τα δύο από τα στοιχεία γύρω από αυτό. Παρομοίως, επειδή 2 ανταλλαχθούν πάνω, θα πρέπει να είναι μικρότερο από τα δύο από τα στοιχεία γύρω από αυτό. Από αυτό, θα μπορούσαμε να συμπεράνουμε ότι 2 και 4 αντάλλαξαν.

Ωστόσο, αυτό δεν λειτουργεί πάντα σωστά. Για παράδειγμα, ας υποθέσουμε ότι έχουμε ανταλλάξει 1 και 4:

4 2 3 1 5

Εδώ, τόσο 2 και 1 είναι μικρότερες από τις γειτονικές τους στοιχεία, και οι δύο 4 και 3 είναι μεγαλύτερα από τα δικά τους. Από αυτό μπορούμε να πούμε ότι δύο από τα τέσσερα αυτά με κάποιο τρόπο μετατράπηκε, αλλά δεν είναι σαφές ποια θα πρέπει να εναλλάσσονται. Ωστόσο, αν πάρουμε το μεγαλύτερο και το μικρότερο των τιμών αυτών (1 και 4, αντίστοιχα), καταλήγουμε να πάρει το ζευγάρι που αντάλλαξαν.

Γενικότερα, για να βρείτε τα στοιχεία που αντάλλαξαν με τη σειρά, που θέλετε να βρείτε

  • Το μεγαλύτερο τοπικό μέγιστο της συστοιχίας.
  • Το μικρότερο τοπικό ελάχιστο στη συστοιχία.

Αυτά τα δύο στοιχεία είναι εκτός τόπου και πρέπει να ανταλλαχθούν.

Τώρα, ας σκεφτούμε για το πώς να εφαρμόσουν αυτό σε δέντρα. Από την inorder πόδια του δέντρου θα παράγει το ταξινομημένη ακολουθία με τα δύο στοιχεία εκτός λειτουργίας, μια επιλογή θα ήταν να περπατήσει το δέντρο, καταγράφοντας την ακολουθία inorder των στοιχείων που έχουμε βρει, στη συνέχεια, χρησιμοποιώντας τον παραπάνω αλγόριθμο. Για παράδειγμα, σκεφτείτε την αρχική BST σας:

              20
         /         \
      15             30
     /   \         /   \ 
   10    17      25     33
  / |   /  \    /  \    |  \
9  16  12  18  22  26  31  34

Αν γραμμικοποίηση αυτό σε μια σειρά, παίρνουμε

9 10 16 15 12 17 18 20 22 25 26 30 31 33 34

Παρατηρήστε ότι 16 είναι μεγαλύτερη από περιβάλλοντα στοιχεία της και ότι 12 είναι μικρότερη από της. Αυτό μας λέει αμέσως ότι 12 και 16 αντάλλαξαν.

Ένας απλός αλγόριθμος για την επίλυση αυτού του προβλήματος, ως εκ τούτου, θα ήταν να κάνετε μια βόλτα inorder του δέντρου για να ευθυγραμμιστεί σε μια σειρά σαν vectorή deque, στη συνέχεια, να ανιχνεύσει ότι η ακολουθία για να βρούμε το μεγαλύτερο τοπικό μέγιστο και το μικρότερο τοπικό ελάχιστο. Αυτό θα τρέχει σε O (n) χρόνο, χρησιμοποιώντας O (n) χώρο. Μια πιο περίπλοκη, αλλά περισσότερο χώρο-αποδοτικός αλγόριθμος θα ήταν να διατηρηθεί μόνο κομμάτι των τριών κόμβων σε ένα χρόνο - το τρέχον κόμβο, τον προκάτοχό του, και ο διάδοχός του - το οποίο μειώνει τη χρήση της μνήμης σε O (1).

Η ελπίδα αυτό βοηθά!

Απαντήθηκε 31/08/2011 στις 21:22
πηγή χρήστη

ψήφοι
0

η διάσχιση δέντρου γίνεται από templatetypedef λειτουργεί εάν είστε βέβαιοι ότι υπάρχει μόνο ένα swap. Διαφορετικά, προτείνω μια λύση με βάση την αρχική κωδικό σας:

int GetMax(TreeNode* tree) {
    int max_right, max_left, ret;

    ret = tree->data;
    if (tree->left != NULL) {
        max_left = GetMax(tree->left);
        if (max_left > ret)
            ret = max_left;
    }
    if (tree->right != NULL) {
        max_right = GetMax(tree->right);
        if (max_right > ret)
            ret = max_right;
    }

    return ret;
}

int GetMin(TreeNode* tree) {
    int min_right, min_left, ret;

    ret = tree->data;
    if (tree->left != NULL) {
        min_left = GetMin(tree->left);
        if (min_left < ret)
            ret = min_left;
    }
    if (tree->right != NULL) {
        min_right = GetMin(tree->right);
        if (min_right < ret)
            ret = min_right;
    }

    return ret;
}

void print_violations(TreeNode* tree) {
    if ((tree->left != NULL) && (tree->right != NULL)) {
        int max_left = GetMax(tree->left);
        int min_right = GetMin(tree->right);
        if (max_left > tree->data && min_right < tree->data) {
            printf("Need to swap %d with %d\n", max_left, min_right);
        }
    }
    if (tree->left != NULL)
        print_violations(tree->left);
    if (tree->right != NULL)
        print_violations(tree->right);
}

Είναι πιο αργή, αλλά εκτυπώνει όλα τα swaps που προσδιορίζει. Μπορεί να αλλάξει για να εκτυπώσετε όλες τις παραβάσεις (π.χ. εάν (max_left> tree-> δεδομένα) παραβίαση εκτύπωσης). Μπορείτε να βελτιώσετε την απόδοση, αν μπορείτε να προσθέσετε δύο πεδία για την TreeNode με τη μέγιστη και ελάχιστη precomputed για αυτό το υποδένδρο.

Απαντήθηκε 01/09/2011 στις 08:43
πηγή χρήστη

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more