首页 > 代码库 > 二叉树的创建、遍历

二叉树的创建、遍历

二叉树的创建。这里采用最简单的情况,创建完全二叉树,用数组来保存:

 1 struct TreeNode 2 { 3     int val; 4     TreeNode *left, *right; 5     TreeNode(int x): val(x), left(NULL), right(NULL) {}; 6 }; 7  8 void CreatTree(TreeNode *root, int idx, int A[], int n)   //root结点已分配,idx为根结点的编号 9 {10     if(2 * idx <= n)   //左儿子11     {12         root->left = new TreeNode(A[2 * idx - 1]);13         CreatTree(root->left, 2 * idx, A, n);14     }15     if(2 * idx + 1 <= n)  //右儿子16     {17         root->right = new TreeNode(A[2 * idx]);18         CreatTree(root->right, 2 * idx + 1, A, n);19     }20 }

 

二叉树的销毁:

1 void DestroyTree(TreeNode *root)2 {3     if(root == NULL)4         return;5     DestroyTree(root->left);    //先递归删除子树6     DestroyTree(root->right);7     delete root;8 }

 

二叉树的层次遍历:

 1 //层次遍历 2 void BreadthFirstPrint(TreeNode *root) //BFS, 用队列 3 { 4     if(root == NULL) 5         return; 6     queue<TreeNode *> que; 7     que.push(root); 8  9     TreeNode *current = NULL;10     while(!que.empty())11     {12         current = que.front();13         que.pop();14         15         cout << current->val <<  ;16 17         if(current->left != NULL)18             que.push(current->left);19         if(current->right != NULL)20             que.push(current->right);21     }22 }

 

二叉树的递归遍历:

 1 //先序遍历,递归 2 void PreorderRe(TreeNode *root)  3 { 4     if(root == NULL) 5         return; 6     cout << root->val <<  ; 7     PreorderRe(root->left); 8     PreorderRe(root->right); 9 }10 11 //中序遍历,递归12 void InorderRe(TreeNode *root)13 {14     if(root == NULL)15         return;16     InorderRe(root->left);17     cout << root->val <<  ;18     InorderRe(root->right);19 }20 21 //后序遍历,递归版22 void PostorderRe(TreeNode *root)23 {24     if(root == NULL)25         return;26     PostorderRe(root->left);27     PostorderRe(root->right);28     cout << root->val <<  ;29 }

 

 

二叉树的非递归遍历,用栈:

 1 //先序遍历,非递归,用栈;也是DFS算法 2 void PreorderStk(TreeNode *root)  3 { 4     if(root == NULL) 5         return; 6     stack<TreeNode *> stk; 7     stk.push(root); 8  9     TreeNode *current = NULL;10     while(!stk.empty())11     {12         current = stk.top();13         stk.pop();14 15         cout << current->val <<  ;16 17         if(current->right != NULL)18             stk.push(current->right);19         if(current->left != NULL)20             stk.push(current->left);21     }22 }23 24 //中序遍历,用栈,非递归25 void InorderStk(TreeNode *root)26 {27     if(root == NULL)28         return;29     stack<TreeNode *> stk;30     stk.push(root);31 32     TreeNode *current = root->left;33     while(!stk.empty() || current != NULL)  //中序遍历,左子树访问完后栈为空,所以同时检测current,此时它指向右子树根34     {35         if(current != NULL)     //向左遍历到底36         {37             stk.push(current);38             current = current->left;39         }40         else    //左子树为空,访问元素后遍历其右子树41         {42             cout << stk.top()->val <<  ;43             current = stk.top()->right;44             stk.pop();45         }46     }47 }48 49 //后序遍历,非递归版,用栈50 void PostorderStk(TreeNode *root)51 {52     stack<TreeNode *> ndStk;53     TreeNode *cur = root, *prev = NULL;     //维持一个prev指针,指向上一次访问的结点54 55     while(cur != NULL)      //先向左遍历到底,入栈56     {57         ndStk.push(cur);58         cur = cur->left;59     }60 61     while(!ndStk.empty())62     {63         cur = ndStk.top();64         if(cur->right == prev)  //右子树的根已访问,说明右子树访问完;或者右子树为空,则访问当前结点65         {66             cout << cur->val <<  ;67             ndStk.pop();68             prev = cur;69         }70         else    //访问右子树71         {72             cur = cur->right;73             while(cur != NULL)  //与处理根节点时的情况相同,向左遍历到底入栈,prev赋空值74             {75                 ndStk.push(cur);76                 cur = cur->left;77             }78             prev = NULL;79         }80     }//while81 }

 

二叉树的非递归遍历,O(1)空间,Morris遍历:

  1 //先序遍历,非递归,O(1)空间。Morris遍历  2 void PreorderMrs(TreeNode *root)   3 {  4     TreeNode *p = root;  5     while(p != NULL)  6     {  7         if(p->left != NULL)   //找中序遍历的前驱结点  8         {  9             TreeNode *tmp = p->left; 10             while(tmp->right != NULL && tmp->right != p) 11                 tmp = tmp->right; 12             if(tmp->right == NULL)  //前驱还未做标记,说明当前结点还没访问 13             { 14                 tmp->right = p;     //标记前驱结点,使其右儿子为当前结点 15                 cout << p->val <<  ; 16                 p = p->left;        //访问当前节点后访问左子树 17             } 18             else                    //前驱已做标记,说明当前结点与左子树已访问过 19             { 20                 tmp->right = NULL; 21                 p = p->right; 22             } 23         } 24         else        //左子树为空,访问当前节点后访问右子树 25         { 26             cout << p->val <<  ; 27             p = p->right; 28         } 29     } 30 } 31  32 //中序遍历,非递归,O(1)空间。Morris遍历。 33 void InorderMrs(TreeNode *root) 34 { 35     TreeNode *p = root; 36     while(p != NULL) 37     { 38         if(p->left != NULL) 39         { 40             TreeNode *tmp = p->left; 41             while(tmp->right != NULL && tmp->right != p) 42                 tmp = tmp->right; 43             if(tmp->right == NULL) 44             { 45                 tmp->right = p; 46                 p = p->left; 47             } 48             else 49             { 50                 cout << p->val <<  ;      //和先序Morris的唯一不同点,访问元素的位置不同。当左子树访问完之后再访问当前结点。 51                 p = p->right; 52                 tmp->right = NULL; 53             } 54         } 55         else 56         { 57             cout << p->val <<  ; 58             p = p->right; 59         } 60     } 61 } 62  63 //后序遍历,非递归,O(1)空间。Morris遍历。需要两个辅助函数 64 void reverse(TreeNode *start, TreeNode *stop) 65 { 66     TreeNode *prev = start, *cur = start->right, *next; 67     while(prev != stop) 68     { 69         next = cur->right; 70         cur->right = prev; 71         prev = cur; 72         cur = next; 73     } 74 } 75 void printReverseList(TreeNode *start, TreeNode *stop) 76 { 77     TreeNode *p = stop; 78     reverse(start, stop); 79     while(true) 80     { 81         cout << p->val <<  ; 82         if(p == start) 83             break; 84         p = p->right; 85     } 86     reverse(stop, start); 87 } 88 void PostorderMrs(TreeNode *root) 89 { 90     TreeNode dummy(-1), *p = &dummy; 91     dummy.left = root;  //新建一个结点,把root作为左儿子,方便统一处理 92  93     while(p != NULL) 94     { 95         if(p->left != NULL)     //找中序遍历的前驱结点 96         { 97             TreeNode *tmp = p->left; 98             while(tmp->right != NULL && tmp->right != p) 99                 tmp = tmp->right;100             if(tmp->right == NULL)101             {102                 tmp->right = p;103                 p = p->left;104             }105             else106             {107                 printReverseList(p->left, tmp); //与中序遍历的不同点,逆序输出当前结点的左儿子到前驱之间的路径108 109                 tmp->right = NULL;110                 p = p->right;111             }112         }113         else114         {115             p = p->right;116         }117     }//while118 }