二叉树的创建。这里采用最简单的情况,创建完全二叉树,用数组来保存:
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 }//while 81 }
二叉树的非递归遍历,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 else 106 { 107 printReverseList(p->left, tmp); //与中序遍历的不同点,逆序输出当前结点的左儿子到前驱之间的路径 108 109 tmp->right = NULL; 110 p = p->right; 111 } 112 } 113 else 114 { 115 p = p->right; 116 } 117 }//while 118 }
时间: 2024-08-02 06:40:44