樹的遍歷c/c++

  • 2021 年 2 月 27 日
  • 筆記

先序遍歷(遞歸)

1 void preOrderTraverase(TreeNode * r) 
2 {
3     if(r) 
4     { 
5         printf("%d\t",r->_data); 
6         preOrderTraverase(r->_left); 
7         preOrderTraverase(r->_right);
8     } 
9 }                

中序遍歷(遞歸)

1 void midOrderTraverase(TreeNode * r)
2 {
3     if(r)
4     {
5         midOrderTraverase(r->_left);
6         printf("%d\t",r->_data);
7         midOrderTraverase(r->_right);
8     }
9 }    

後序遍歷(遞歸)

1 void postOrderTraverase(TreeNode * r)
2 {
3     if(r)
4     {
5         postOrderTraverase(r->_left);
6         postOrderTraverase(r->_right);
7         printf("%d\t",r->_data);
8     }
9 }

層序遍歷(用到隊列)(遞歸)

 1 void levelOrderTraverse(TreeNode *root)
 2 {
 3     if(root) 
 4     {
 5         Queue q;
 6         initQueue(&q);
 7         enQueue(&q,root);
 8         while(!isQueueEmpty(&q)) 
 9         {
10             root = deQueue(&q);                    //根出隊
11             printf(" %d ",root->data);
12             if(root->left)enQueue(&q,root->left); //左子樹入隊
13             if(root->right)enQueue(&q,root->right);//右子樹入隊
14         }
15         printf("\n");
16     }
17 }

先序遍歷(非遞歸)

 1 void preOrderTraverase(TreeNode * r) 
 2 {
 3     if(r)
 4     {
 5         Stack s; 
 6         initStack(&s);
 7         while(r || !isStackEmpty(&s)) //第一次循環或者棧內不空
 8         {
 9             while(r)
10             {
11                 printf("%d\t",r->_data);//訪問結點
12                 push(&s,r);
13                 r = r->_left;          //一直向左並將沿途結點壓入堆棧
14             }
15             if(!isStackEmpty(&s))
16             {
17                 r = pop(&s);          //結點彈出堆棧
18                 r = r->_right;        //轉向右子樹
19             }
20         }
21     }
22 }                    

中序遍歷(非遞歸)

 1 void midOrderTraverase(TreeNode * r)
 2 {
 3     if(r)
 4     {
 5         Stack s;
 6         initStack(&s);
 7         while(r || !isStackEmpty(&s))
 8         {
 9             while(r)
10             {
11                 push(&s,r);
12                 r = r->_left;
13             }
14             if(!isStackEmpty(&s))
15             {
16                 r = pop(&s);
17                 printf("%d\t",r->_data);//訪問的時機變了
18                 r = r->_right;
19             }
20         }
21     }
22 }    

後序遍歷(非遞歸)

 
對於任一節點 P,
1.將節點 P 入棧;
2.若 P 不存在左孩子和右孩子,或者 P 存在左孩子或右孩子,但左右孩子已經被輸出,
則可以直接輸出節點 P,並將其出棧,將出棧節點 P 標記為上一個輸出的節點,再將此時的棧頂結點設為當前節點
3.若不滿足2中的條件,
則將 P 的右孩子和左孩子依次入棧當前節點重新置為棧頂結點,之後重複操作2;
4.直到棧空,遍歷結束。

 1 void postOrderTraverse(struct Tree *t) 
 2 {
 3     Stack s; initStack(&s);
 4     TreeNode *cur;          //當前結點
 5     TreeNode *pre=NULL; //前一次訪問的結點
 6     push(&s,t);
 7     while(!isStackEmpty(&s))
 8     {
 9         cur = pop(&s);
10         push(&s,cur);
11         if((cur->_left==NULL&&cur->_right==NULL)|| (pre!=NULL&&(pre==cur->_left||pre==cur->_right)))
12         { //如果當前結點沒有孩子結點或者孩子節點都已被訪問過
13             printf("%d\t",cur->_data);
14             pop(&s);
15             pre=cur;
16         }
17         else
18         {
19             if(cur->_right != NULL)
20                 push(&s,cur->_right);
21             if(cur->_left != NULL)
22                 push(&s,cur->_left);
23         }
24     }
25 }