Puun läpikulku (järjestys, ennakkotilaus ja jälkitilaus) esimerkkeineen
Mikä on Tree Traversal?
Puutietorakenteessa läpikulku tarkoittaa solmuissa vierailemista jollakin tietyllä tavalla. Nodes2-tyyppisiä läpikulkuja on olemassa. Yleensä tällainen läpikulku perustuu binääripuuhun. Binääripuu tarkoittaa, että jokaisessa solmussa voi olla enintään 2 solmua.
Binääripuu on hyvin tunnettu tietorakenne. Siellä on myös binaarihakupuu (BST). Tämän tyyppistä läpikulkua käytetään useisiin tarkoituksiin. Tasojärjestyksen läpikulku, sitä käytetään kahden solmun välisen syvyyden laskemiseen. On olemassa toisenlainen puu nimeltä "AVL", jossa solmun korkeuden laskeminen on välttämätöntä. Voimme edustaa taulukossa binaaripuuta, mutta muistin optimoinnissa käytämme rakennetta ja osoitinta viittaamaan seuraavaan solmuun.
Puun läpikulkutyypit
Kuten keskustelimme binääripuut, nyt keskustelemme yksittäisistä läpikulkutyypeistä. Tyypistä riippuen on olemassa kahta tyyppiä läpikulkua. Aiemmin olemme maininneet tasojärjestyksen tai Breadth-First Traversalin välttämättömyyden. Nyt Syvyys-ensimmäinen läpikulku kuten jälkitilausta käytetään solmun poistamiseen (käsittelemme sitä myöhemmin), ennakkotilausta käytetään binaaripuun kopioimiseen, ja "inorder" kulkee puun läpi ei-laskevalla tavalla.
- Leveys - ensimmäinen läpikulku
- Syvyys-ensimmäinen läpikulku
- Ennakkotilaa läpikulku
- Tilauksen jälkeinen läpikulku
- Määräysten mukainen kulku
Leveys - ensimmäinen läpikulku
Se tunnetaan myös tasojärjestyksen läpikulkuna. Tarkastellaan seuraavaa puuta tasojärjestyksen läpikulun havainnollistamiseksi.
Joten aloitamme juurisolmusta "1". Se merkitään tasoksi 1. Sitten algoritmi menee kaikille nykyisen solmun lapsille. Vierailemme nyt solmuissa 2 ja 3. Ne merkitään tasoiksi 2.
Sen jälkeen, koska meillä on 2 solmua tasolla 2, vierailemme myös heidän lastensa luona. Joten käymme 5,6,8,7, 3, XNUMX, XNUMX ja merkitsemme ne tasoksi XNUMX. Tässä on asia, jota ei mainita,
Solmun taso = pääsolmun taso + 1
Taso 1: 1
Taso 2: 2 3
Taso 3: 5 6 8 7
Samanlaista algoritmia käytetään BFS:lle (Breadth-First-Search).
Tässä on pseudokoodi tasotilauksen läpikulkua varten:
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
Otetaan sama esimerkki kuin aiemmin. Tämän tyyppisessä läpikäymisessä käymme ensin vasemmassa alipuussa, sitten juuressa ja sen jälkeen oikeanpuoleisessa alipuussa. Muistamisen helpottamiseksi voimme sanoa, että järjestys menee kuten vasen-juuri-oikea.
Oletetaan, että koko puun juuri on 1. Nyt algoritmi seuraa:
- Käy solmun 1 vasemmassa alipuussa.
- Nykyinen solmu on 2 (koska se on 1:n vasen alipuu)
- Vieraile 2:n vasemmassa alipuussa. Nykyinen solmu on tällä kertaa 5.
- Siirretään kohtaan 5, sillä ei ole lapsia, joten solmu 5 merkitään vierailluksi. Se palaa pääsolmuun; joka on 2.
- Koska 2:n vasemmassa alipuussa vieraillaan, nyt käydään myös 2:ssa.
- - algoritmi siirtää nykyisen solmun solmun 2 oikeaan alipuuhun, joka on solmu 6. Vierailun jälkeen solmussa 6. Se siirtyy pääsolmuun 2.
- Koska solmussa 2 käydään, vierailemme nyt 2:n vanhemmassa; joka on solmu 1.
- Sen jälkeen vierailemme oikealla alipuulla.
Joten lopullinen läpikulku näyttää tältä:
Järjestys: 5 → 2 → 6 → 1 → 8 → 3 → 7
Tässä on Pseudokoodi tilauksen läpikäymiselle:
InOrder(node): if node is not null: InOrder(node.left) print node.value InOrder(node.right)
Tämä on rekursiivinen algoritmi järjestyksen läpikäymiselle. Varten Binäärihakupuu (BST), Inorder traversal antaa järjestetyn arvojen joukon.
Tilauksen jälkeinen läpikäynti
Tässä läpikäymisessä kuljemme ensin vasemmanpuoleisen alipuun poikki ja sitten juuren jälkeen oikeanpuoleisen alipuun. Kaikki matkat ovat jälkitilauksena. Esitetään esimerkki:
Tässä juuri = 1,
- Siirrymme ensin vasempaan alipuuhun. Joten juuresta tulee 2.
- Sitten 2 on jättänyt alipuun, joten siirrymme solmuun 5. Nyt juuri on 5.
- Sillä ei ole vasenta alipuuta, eikä sillä ole myöskään oikeaa alipuuta. Joten nyt merkitsemme solmun 5 vierailluksi ja siirrymme sen pääsolmuun.
- Nyt juuri on 2 ja sen vasemmassa alipuussa on käyty kokonaan. Siirrymme nyt sen oikeaan alipuuhun. Joten juuresta tulee 6.
- Koska solmussa 6 ei ole vasenta ja oikeaa alipuuta, merkitsemme solmun 6 vierailluksi ja siirrymme sen pääsolmuun 2.
- Nyt sekä vasemmalla että oikealla alipuulla käydään solmun 2 kohdalla. Myös se merkitään käydyksi.
- Siirrymme solmun 2 yläpäähän, joka on solmu 1.
- Vasemmassa alipuussa käydään juuri 1. Nyt käymme samalla tavalla oikeanpuoleisessa alipuussa.
Merkitty ympyrä on oikea alipuu. Nyt vierailemme oikeanpuoleisessa alipuussa, kuten vierailimme vasemmassa alipuussa. Sen jälkeen vierailemme solmussa. Lopullinen läpikulku on siis:
Jälkitilaus: 5 → 6 → 2 → 8 → 7 → 3 → 1
Tässä on pseudokoodi tilauksen jälkeiseen läpikäyntiin:
PostOrder(node): if node is not null: PostOrder(node.left) PostOrder(node.right) print node.value
Ennakkotilaa kulku
Ennakkotilauksen läpikäymisessä algoritmi vierailee ensin juurisolmussa, jonka jälkeen se siirtyy vasempaan ja oikeaan alipuuhun. Ymmärtämisen helpottamiseksi voimme ajatella ennakkotilauskäyntejä, kuten juuri → vasen-oikea.
Joten valitaan solmu 1 juureksi.
- Algoritmin mukaan juuri löydetään ensin, sitten vasen ja sitten oikea alipuu.
- Joten käymme juuri 1:ssä. Sitten siirrymme sen vasempaan alipuuhun. Juureksi tulee 2.
- Vierailemme solmussa 2 ja siirrymme sen vasempaan alipuuhun. Joten juuresta tulee 3.
- Vierailemme solmussa 3, sitten siirrymme sen pääsolmuun. Nyt käydään solmussa 2 ja sen vasemmassa alipuussa. Aika käydä oikealla alipuulla.
- Siirrymme oikeaan alipuuhun, juureksi tulee 4. Vierailemme kohdassa 4. Koska 4:llä ei ole alisolmua, siirrymme sen yläpuolelle.
- Nyt juuri on 2 ja siinä käydään yhdessä sen vasemman ja oikean alipuun kanssa. Joten siirrymme sen pääsolmuun. Nyt juuresta tulee 1.
- Samalla tavalla käymme oikeanpuoleisessa alipuussa.
Ennakkotilaus: 1 → 2 → 3 → 4 → 5 → 6 → 7
Tässä on pseudokoodi tilauksen jälkeiseen läpikäyntiin:
PreOrder(node): if node is not null: print node.value PreOrder(node.left) PreOrder(node.right)
Toteutus sisään 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)
lähtö:
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
Toteutus 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); }
Lähtö:
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
Toteutus C++ (Käytetään std:queue-tasojärjestystä)
#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