Baumdurchquerungen (Inorder, Preorder & Postorder) mit Beispielen

Was ist Tree Traversal?

In der Baumdatenstruktur bedeutet Traversal, Knoten auf eine bestimmte Weise zu besuchen. Es gibt Knoten2-Arten von Durchquerungen. Im Allgemeinen basiert diese Art der Durchquerung auf dem Binรคrbaum. Ein Binรคrbaum bedeutet, dass jeder Knoten maximal 2 Knoten haben kann.

Ein Binรคrbaum ist eine bekannte Datenstruktur. Es gibt auch einen binรคren Suchbaum (BST). Diese Art der Durchquerung wird fรผr verschiedene Zwecke verwendet. Der Level-Order-Traversal wird zur Berechnung der Tiefe zwischen zwei Knoten verwendet. Es gibt eine andere Baumart namens โ€žAVLโ€œ, bei der die Berechnung der Hรถhe eines Knotens erforderlich ist. Wir kรถnnen einen Binรคrbaum im Array darstellen, aber zur Speicheroptimierung verwenden wir Struktur und Zeiger fรผr die Referenzierung des nรคchsten Knotens.

Arten der Baumdurchquerung

Wie wir besprochen haben binรคre Bรคume, diskutieren wir nun die einzelnen Arten von Durchquerungen. Je nach Typ gibt es zwei Arten der Durchquerung. Zuvor haben wir die Notwendigkeit der Ebenenreihenfolge oder der Breiten-zuerst-Durchquerung erwรคhnt. Jetzt Tiefendurchquerung So wird beispielsweise die Post-Order zum Lรถschen eines Knotens verwendet (darauf werden wir spรคter noch nรคher eingehen), die Pre-Order wird zum Kopieren eines Binรคrbaums verwendet und โ€žInorderโ€œ durchlรคuft den Baum in nicht abnehmender Reihenfolge.

  • Breite-Erste-Durchquerung
  • Tiefendurchquerung
  • Durchquerung der Vorbestellung
  • Post-Order-Traversal
  • In-Order-Traversal

Breite-Erste-Durchquerung

Es wird auch als Level-Order-Traversierung bezeichnet. Betrachten wir den folgenden Baum zur Demonstration der Level-Order-Traversierung.

Breite-Erste-Durchquerung

Wir beginnen also mit dem Wurzelknoten โ€ž1โ€œ. Es wird als Ebene 1 markiert. Dann geht der Algorithmus zu allen untergeordneten Knoten des aktuellen Knotens. Wir werden jetzt Knoten 2 und 3 besuchen. Sie werden als Level 2 gekennzeichnet.

Da wir danach 2 Knoten in Level 2 haben, werden wir auch deren Kinder besuchen. Also besuchen wir 5,6,8,7 und markieren sie als Level 3. Hier ist etwas, das nicht erwรคhnt wird:

Ebene des Knotens = Ebene des รผbergeordneten Knotens + 1

Stufe 1: 1

Stufe 2: 2 3

Stufe 3: 5 6 8 7

Ein รคhnlicher Algorithmus wird fรผr das BFS verwendet (Breitensuche).

Hier ist der Pseudocode fรผr das Durchlaufen der Ebenenreihenfolge:

level_order(node)
Q โ†’ Queue()
Q.push(node)
while !Q.empty():
    current_node = Q.pop()
    print current_node.value
# Checking if the current node have any child or not
if current_node.left is not NULL:
    Q.push(current_node.left)
if current_node.right is not NULL:
    Q.push(current_node.right)

Inorder Traversal Bianry Tree

Nehmen wir das gleiche Beispiel wie zuvor. Bei dieser Art der Durchquerung besuchen wir zuerst den linken Teilbaum, dann die Wurzel und danach den rechten Teilbaum. Um es leichter zu merken, kรถnnen wir sagen, dass die Reihenfolge wie folgt lautet: links-wurzel-rechts.

Inorder Traversal Bianry Tree

Nehmen wir fรผr den gesamten Baum an, dass die Wurzel 1 ist. Nun folgt der Algorithmus:

  • Besuchen Sie den linken Teilbaum von Knoten 1.
  • Der aktuelle Knoten ist 2 (da es sich um den linken Teilbaum von 1 handelt)

Inorder Traversal Bianry Tree

  • Besuchen Sie den linken Teilbaum von 2. Der aktuelle Knoten ist dieses Mal 5.
  • Beim รœbergang zu 5 gibt es keine untergeordneten Knoten, daher wird Knoten 5 als besucht markiert. Es kehrt zum รผbergeordneten Knoten zurรผck. Das ist 2.
  • Da der linke Teilbaum von 2 besucht wird, wird nun auch 2 besucht.
  • Die Algorithmus verschiebt den aktuellen Knoten in den rechten Teilbaum von Knoten 2, also Knoten 6. Nach dem Besuch von Knoten 6 wird er zu seinem รผbergeordneten Knoten 2 verschoben.
  • Da Knoten 2 besucht wird, besuchen wir nun den รผbergeordneten Knoten von Knoten 2; Das ist Knoten 1.
  • Danach besuchen wir den rechten Teilbaum.

Die endgรผltige Durchquerung sieht also folgendermaรŸen aus:

InReihenfolge: 5 โ†’ 2 โ†’ 6 โ†’ 1 โ†’ 8 โ†’ 3 โ†’ 7

Hier ist der Pseudocode fรผr die Durchquerung in der richtigen Reihenfolge:

InOrder(node):
  if node is not null:
    InOrder(node.left)
  print node.value
    InOrder(node.right)

Dies ist der rekursive Algorithmus fรผr die Inorder-Traversierung. Fรผr die Binรคrer Suchbaum (BST), Inorder Traversal liefert das sortierte Array von Werten.

Post-Order-Traversal

Bei dieser Durchquerung durchlaufen wir zuerst den Teilbaum ganz links und dann den Teilbaum ganz rechts nach der Wurzel. Alle Durchquerungen erfolgen im Post-Order. Lassen Sie uns ein Beispiel demonstrieren:

Post-Order-Traversal

Hier gilt fรผr root = 1,

  • Wir gehen zuerst zum linken Teilbaum. Die Wurzel wird also 2.
  • Dann hat 2 den Teilbaum verlassen, also gehen wir zu Knoten 5. Jetzt ist die Wurzel 5.
  • Es gibt keinen linken Teilbaum und auch keinen rechten Teilbaum. Jetzt markieren wir Knoten 5 als besucht und gehen zu seinem รผbergeordneten Knoten.

Post-Order-Traversal

  • Jetzt ist die Wurzel 2 und ihr linker Teilbaum ist vollstรคndig besucht. Wir bewegen uns nun zu seinem rechten Unterbaum. Die Wurzel wird also 6.
  • Da Knoten 6 keinen linken und rechten Teilbaum hat, markieren wir den besuchten Knoten 6 und wechseln zu seinem รผbergeordneten Knoten 2.
  • Jetzt werden sowohl der linke als auch der rechte Teilbaum fรผr Knoten 2 besucht. Er wird ebenfalls als besucht markiert.
  • Wir wechseln zum รผbergeordneten Knoten von Knoten 2, also Knoten 1.
  • Der linke Teilbaum wird fรผr Wurzel 1 besucht. Jetzt besuchen wir auf รคhnliche Weise den rechten Teilbaum.

Post-Order-Traversal

Der markierte Kreis ist der rechte Teilbaum. Jetzt werden wir den rechten Teilbaum besuchen, so wie wir den linken Teilbaum besucht haben. Danach besuchen wir den Knoten. Die letzte Durchquerung wird also sein:

PostOrder: 5 โ†’ 6 โ†’ 2 โ†’ 8 โ†’ 7 โ†’ 3 โ†’ 1

Hier ist der Pseudocode fรผr Post-Order-Traversal:

PostOrder(node):
    if node is not null:
       PostOrder(node.left)
       PostOrder(node.right)
       print node.value

Traversal vorbestellen

Bei der Vorbestellungsdurchquerung besucht der Algorithmus zuerst den Wurzelknoten und bewegt sich dann zum linken bzw. rechten Teilbaum. Zum besseren Verstรคndnis kรถnnen wir uns beispielsweise vorbestellte Durchquerungsbesuche vorstellen Wurzel โ†’ links-rechts.

Traversal vorbestellen

Wรคhlen wir also Knoten 1 als Wurzel aus.

  • GemรครŸ dem Algorithmus wird zuerst die Wurzel, dann der linke und dann der rechte Teilbaum ermittelt.
  • Also besuchen wir Wurzel 1. Dann gehen wir zu seinem linken Unterbaum. Die Wurzel wird 2.
  • Wir besuchen Knoten 2 und wechseln zu seinem linken Unterbaum. Die Wurzel wird also zu 3.
  • Wir besuchen Knoten 3 und wechseln dann zu seinem รผbergeordneten Knoten. Nun wird Knoten 2 und sein linker Teilbaum besucht. Zeit, den richtigen Teilbaum zu besuchen.
  • Wir gehen zum rechten Teilbaum, die Wurzel wird zu 4. Wir besuchen 4. Da 4 keinen untergeordneten Knoten hat, gehen wir zu seinem รผbergeordneten Knoten.
  • Jetzt ist root 2 und wird zusammen mit seinem linken und rechten Teilbaum besucht. Wir wechseln also zum รผbergeordneten Knoten. Jetzt wird root zu 1.
  • Ebenso besuchen wir den rechten Teilbaum.

Vorbestellung: 1 โ†’ 2 โ†’ 3 โ†’ 4 โ†’ 5 โ†’ 6 โ†’ 7

Hier ist der Pseudocode fรผr Post-Order-Traversal:

PreOrder(node):
   if node is not null:
     print node.value
         PreOrder(node.left)
         PreOrder(node.right)

Umsetzung in Python

class Node:
    def __init__(self, item):
    self.left = None
self.right = None
self.val = item
# creating a tree data structure
def inorder(root):
#checking if the root is null or not
if root:
    inorder(root.left)
# recursively calling left subtree
print(str(root.val) + " ", end = '')
inorder(root.right)
# recursively calling right subtree
def postorder(root):
    if root:
    postorder(root.left)
postorder(root.right)
print(str(root.val) + " ", end = '')
def preorder(root):
    if root:
    print(str(root.val) + " ", end = '')
preorder(root.left)
preorder(root.right)
def levelOrder(root):
    queue = list()
queue.append(root)
while len(queue) & gt;
0:
    current = queue[0]
queue = queue[1: ]
print(str(current.val) + " ", end = "")
if current.left:
    queue.append(current.left)
if current.right:
   queue.append(current.right)
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.left.right = Node(5)
root.right.left = Node(6)
root.right.right = Node(7)
print("\nLevelOrder traversal:\t", end = " ")
levelOrder(root)
print("\nInorder traversal:\t", end = " ")
inorder(root)
print("\nPreorder traversal:\t", end = " ")
preorder(root)
print("\nPostorder traversal:\t", end = " ")
postorder(root)

Ausgang:

LevelOrder traversal:  1 2 3 4 5 6 7
Inorder traversal:     4 2 5 1 6 3 7
Preorder traversal:    1 2 4 5 3 6 7
Postorder traversal:   4 5 2 6 7 3 1

Implementierung in C

#include <stdio.h>
#include <stdlib.h>
struct node {
   int value;
   struct node* left;
   struct node* right;
};
// Inorder traversal
void InOrder(struct node* root) {
   if (root == NULL) return;
   InOrder(root->left);
   printf("%d ", root->value);
   InOrder(root->right);
}
// PreOrder traversal
void PreOrder(struct node* root) {
  if (root == NULL) return;
  printf("%d ", root->value);
  PreOrder(root->left);
  PreOrder(root->right);
}
// PostOrder traversal
void PostOrder(struct node* root) {
  if (root == NULL) return;
  PostOrder(root->left);
  PostOrder(root->right);
  printf("%d ", root->value);
}
// Create a new Node
struct node* createNode(int value) {
  struct node* newNode = malloc(sizeof(struct node));
  newNode->value = value;
  newNode->left = NULL;
  newNode->right = NULL;
  return newNode;
}
int main() {
  struct node* root = createNode(1);
  root->left = createNode(2);
  root->right = createNode(3);
  root->left->left = createNode(4);
  root->left->right = createNode(5);
  root->right->left = createNode(6);
  root->right->right = createNode(7);
  printf("Inorder traversal:\t");
  InOrder(root);
  printf("\PreOrder traversal:\t");
  PreOrder(root);
  printf("\nPostOrder traversal:\t");
  PostOrder(root);
}

Ausgang:

Inorder traversal: 4 2 5 1 6 3 7
Preorder traversal: 1 2 4 5 3 6 7
Postorder traversal: 4 5 2 6 7 3 1

Implementierung von C++ (Verwenden von std:queue fรผr die Ebenenreihenfolge)

#include <stdio.h>
#include <stdlib.h>
#include<queue>
typedef struct node {
  int value;
  struct node* left;
  struct node* right;
}node;
// Inorder traversal
void InOrder(struct node* root) {
  if (root == NULL) return;
  InOrder(root->left);
  printf("%d ", root->value);
  InOrder(root->right);
}
// PreOrder traversal
void PreOrder(struct node* root) {
  if (root == NULL) return;
  printf("%d ", root->value);
  PreOrder(root->left);
  PreOrder(root->right);
}
// PostOrder traversal
void PostOrder(struct node* root) {
  if (root == NULL) return;
  PostOrder(root->left);
  PostOrder(root->right);
  printf("%d ", root->value);
}
void LevelOrder(struct node* root){
   std::queue<struct node*> Q;
   Q.push(root);
   while(!Q.empty()){
   struct node* current = Q.front();
   Q.pop();
   printf("%d ",current->value);
 if(current->left)
   Q.push(current->left);
 if(current->right)
   Q.push(current->right);
  }
}
// Create a new Node
struct node* createNode(int value) {
  struct node* newNode = new node();
  newNode->value = value;
  newNode->left = NULL;
  newNode->right = NULL;
  return newNode;
}
int main() {
  struct node* root = createNode(1);
  root->left = createNode(2);
  root->right = createNode(3);
  root->left->left = createNode(4);
  root->left->right = createNode(5);
  root->right->left = createNode(6);
  root->right->right = createNode(7);
  printf("Level Order traversal:\t");
  LevelOrder(root);
  printf("\nInorder traversal:\t");
  InOrder(root);
  printf("\nPreOrder traversal:\t");
  PreOrder(root);
  printf("\nPostOrder traversal:\t");
  PostOrder(root);
}
LevelOrder traversal:  1 2 3 4 5 6 7
Inorder traversal:     4 2 5 1 6 3 7
Preorder traversal:    1 2 4 5 3 6 7
Postorder traversal:   4 5 2 6 7 3 1

Fassen Sie diesen Beitrag mit folgenden Worten zusammen: