1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
#include <iostream>
#include <cstdio> #include <stack> #include <vector> #include "BinaryTree.h" using namespace std; void preorder(TreeNode *root, vector< int> &path) { if(root != NULL) { path.push_back(root->val); preorder(root->left, path); preorder(root->right, path); } } vector< int> preorderTraversal(TreeNode *root) { vector< int> path; preorder(root, path); return path; } // 树中结点含有分叉, // 8 // / \ // 6 1 // / \ // 9 2 // / \ // 4 7 int main() { TreeNode *pNodeA1 = CreateBinaryTreeNode( 8); TreeNode *pNodeA2 = CreateBinaryTreeNode( 6); TreeNode *pNodeA3 = CreateBinaryTreeNode( 1); TreeNode *pNodeA4 = CreateBinaryTreeNode( 9); TreeNode *pNodeA5 = CreateBinaryTreeNode( 2); TreeNode *pNodeA6 = CreateBinaryTreeNode( 4); TreeNode *pNodeA7 = CreateBinaryTreeNode( 7); ConnectTreeNodes(pNodeA1, pNodeA2, pNodeA3); ConnectTreeNodes(pNodeA2, pNodeA4, pNodeA5); ConnectTreeNodes(pNodeA5, pNodeA6, pNodeA7); PrintTree(pNodeA1); vector< int> ans = preorderTraversal(pNodeA1); for ( int i = 0; i < ans.size(); ++i) { cout << ans[i] << " "; } cout << endl; DestroyTree(pNodeA1); return 0; } |
2.非递归实现(迭代实现)
根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。因此其处理过程如下:
对于任一结点P:
1)访问结点P,并将结点P入栈;
2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;
3)直到P为NULL并且栈为空,则遍历结束。
test.cpp:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
#include <iostream>
#include <cstdio> #include <stack> #include <vector> #include "BinaryTree.h" using namespace std; /** * Definition for binary tree * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ vector< int> rootRLTraversal(TreeNode *root) { stack<TreeNode *> s; vector< int> ans; TreeNode *tmp; s.push(root); while (!s.empty()) { tmp = s.top(); s.pop(); if (!tmp) { continue; } //注意这里tmp不为空的时候才可以把他放进去 ans.push_back(tmp->val); s.push(tmp->right); s.push(tmp->left); } return ans; } // 树中结点含有分叉, // 6 // / \ // 7 2 // / \ // 1 4 // / \ // 3 5 int main() { TreeNode *pNodeA1 = CreateBinaryTreeNode( 6); TreeNode *pNodeA2 = CreateBinaryTreeNode( 7); TreeNode *pNodeA3 = CreateBinaryTreeNode( 2); TreeNode *pNodeA4 = CreateBinaryTreeNode( 1); TreeNode *pNodeA5 = CreateBinaryTreeNode( 4); TreeNode *pNodeA6 = CreateBinaryTreeNode( 3); TreeNode *pNodeA7 = CreateBinaryTreeNode( 5); ConnectTreeNodes(pNodeA1, pNodeA2, pNodeA3); ConnectTreeNodes(pNodeA2, pNodeA4, pNodeA5); ConnectTreeNodes(pNodeA5, pNodeA6, pNodeA7); vector< int> ans = rootRLTraversal(pNodeA1); for ( int i = 0; i < ans.size(); ++i) { cout << ans[i] << " "; } cout << endl; DestroyTree(pNodeA1); return 0; } |
复杂一点但是代码风格和中序和后序一致,
test.cpp:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
#include <iostream>
#include <cstdio> #include <stack> #include <vector> #include "BinaryTree.h" using namespace std; //非递归前序遍历 vector< int> preorderTraversal(TreeNode *root) { stack<TreeNode *> s; vector< int> path; TreeNode *p = root; while(p != NULL || !s.empty()) { while(p != NULL) { path.push_back(p->val); s.push(p); p = p->left; } if(!s.empty()) { p = s.top(); s.pop(); p = p->right; } } return path; } // 树中结点含有分叉, // 8 // / \ // 6 1 // / \ // 9 2 // / \ // 4 7 int main() { TreeNode *pNodeA1 = CreateBinaryTreeNode( 8); TreeNode *pNodeA2 = CreateBinaryTreeNode( 6); TreeNode *pNodeA3 = CreateBinaryTreeNode( 1); TreeNode *pNodeA4 = CreateBinaryTreeNode( 9); TreeNode *pNodeA5 = CreateBinaryTreeNode( 2); TreeNode *pNodeA6 = CreateBinaryTreeNode( 4); TreeNode *pNodeA7 = CreateBinaryTreeNode( 7); ConnectTreeNodes(pNodeA1, pNodeA2, pNodeA3); ConnectTreeNodes(pNodeA2, pNodeA4, pNodeA5); ConnectTreeNodes(pNodeA5, pNodeA6, pNodeA7); PrintTree(pNodeA1); vector< int> ans = preorderTraversal(pNodeA1); for ( int i = 0; i < ans.size(); ++i) { cout << ans[i] << " "; } cout << endl; DestroyTree(pNodeA1); return 0; } |
输出结果:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
#include <iostream>
#include <cstdio> #include <stack> #include <vector> #include "BinaryTree.h" using namespace std; void inorder(TreeNode *root, vector< int> &path) { if(root != NULL) { inorder(root->left, path); path.push_back(root->val); inorder(root->right, path); } } vector< int> inorderTraversal(TreeNode *root) { vector< int> path; inorder(root, path); return path; } // 树中结点含有分叉, // 8 // / \ // 6 1 // / \ // 9 2 // / \ // 4 7 int main() { TreeNode *pNodeA1 = CreateBinaryTreeNode( 8); TreeNode *pNodeA2 = CreateBinaryTreeNode( 6); TreeNode *pNodeA3 = CreateBinaryTreeNode( 1); TreeNode *pNodeA4 = CreateBinaryTreeNode( 9); TreeNode *pNodeA5 = CreateBinaryTreeNode( 2); TreeNode *pNodeA6 = CreateBinaryTreeNode( 4); TreeNode *pNodeA7 = CreateBinaryTreeNode( 7); ConnectTreeNodes(pNodeA1, pNodeA2, pNodeA3); ConnectTreeNodes(pNodeA2, pNodeA4, pNodeA5); ConnectTreeNodes(pNodeA5, pNodeA6, pNodeA7); PrintTree(pNodeA1); vector< int> ans = inorderTraversal(pNodeA1); for ( int i = 0; i < ans.size(); ++i) { cout << ans[i] << " "; } cout << endl; DestroyTree(pNodeA1); return 0; } |
输出结果:
2.非递归实现
根据中序遍历的顺序,对于任一结点,优先访问其左孩子,而左孩子结点又可以看做一根结点,然后继续访问其左孩子结点,直到遇到左孩子结点为空的结点才进行访问,然后按相同的规则访问其右子树。因此其处理过程如下:
对于任一结点P,
1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;
2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;
3)直到P为NULL并且栈为空则遍历结束
test.cpp:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
#include <iostream>
#include <cstdio> #include <stack> #include <vector> #include "BinaryTree.h" using namespace std; //非递归中序遍历 vector< int> inorderTraversal(TreeNode *root) { stack<TreeNode *> s; vector< int> path; TreeNode *p = root; while(p != NULL || !s.empty()) { while(p != NULL) { s.push(p); p = p->left; } if(!s.empty()) { p = s.top(); path.push_back(p->val); s.pop(); p = p->right; } } return path; } // 树中结点含有分叉, // 8 // / \ // 6 1 // / \ // 9 2 // / \ // 4 7 int main() { TreeNode *pNodeA1 = CreateBinaryTreeNode( 8); TreeNode *pNodeA2 = CreateBinaryTreeNode( 6); TreeNode *pNodeA3 = CreateBinaryTreeNode( 1); TreeNode *pNodeA4 = CreateBinaryTreeNode( 9); TreeNode *pNodeA5 = CreateBinaryTreeNode( 2); TreeNode *pNodeA6 = CreateBinaryTreeNode( 4); TreeNode *pNodeA7 = CreateBinaryTreeNode( 7); ConnectTreeNodes(pNodeA1, pNodeA2, pNodeA3); ConnectTreeNodes(pNodeA2, pNodeA4, pNodeA5); ConnectTreeNodes(pNodeA5, pNodeA6, pNodeA7); PrintTree(pNodeA1); vector< int> ans = inorderTraversal(pNodeA1); for ( int i = 0; i < ans.size(); ++i) { cout << ans[i] << " "; } cout << endl; DestroyTree(pNodeA1); return 0; } |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
#include <iostream>
#include <cstdio> #include <stack> #include <vector> #include "BinaryTree.h" using namespace std; /** * Definition for binary tree * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ void postorder(TreeNode *root, vector< int> &path) { if(root != NULL) { postorder(root->left, path); postorder(root->right, path); path.push_back(root->val); } } vector< int> postorderTraversal(TreeNode *root) { vector< int> path; postorder(root, path); return path; } // 树中结点含有分叉, // 8 // / \ // 6 1 // / \ // 9 2 // / \ // 4 7 int main() { TreeNode *pNodeA1 = CreateBinaryTreeNode( 8); TreeNode *pNodeA2 = CreateBinaryTreeNode( 6); TreeNode *pNodeA3 = CreateBinaryTreeNode( 1); TreeNode *pNodeA4 = CreateBinaryTreeNode( 9); TreeNode *pNodeA5 = CreateBinaryTreeNode( 2); TreeNode *pNodeA6 = CreateBinaryTreeNode( 4); TreeNode *pNodeA7 = CreateBinaryTreeNode( 7); ConnectTreeNodes(pNodeA1, pNodeA2, pNodeA3); ConnectTreeNodes(pNodeA2, pNodeA4, pNodeA5); ConnectTreeNodes(pNodeA5, pNodeA6, pNodeA7); PrintTree(pNodeA1); vector< int> ans = postorderTraversal(pNodeA1); for ( int i = 0; i < ans.size(); ++i) { cout << ans[i] << " "; } cout << endl; DestroyTree(pNodeA1); return 0; } |
9 4 7 2 6 1 8运行结果:
2.非递归实现
后序遍历的非递归实现是三种遍历方式中最难的一种。因为在后序遍历中,要保证左孩子和右孩子都已被访问并且左孩子在右孩子前访问才能访问根结点,这就为流程的控制带来了难题。下面介绍两种思路。
第一种思路:对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问, 因此其右孩子还为被访问。所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就 保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是 否是第一次出现在栈顶。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
#include <iostream>
#include <cstdio> #include <stack> #include <vector> #include "BinaryTree.h" using namespace std; /** * Definition for binary tree * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ //中介节点 struct TempNode { TreeNode *btnode; bool isFirst; }; //非递归后序遍历-迭代 vector< int> postTraversal(TreeNode *root) { stack<TempNode *> s; vector< int> path; TreeNode *p = root; TempNode *temp; while(p != NULL || !s.empty()) { while(p != NULL) //沿左子树一直往下搜索,直至出现没有左子树的结点 { TempNode *tempNode = new TempNode; tempNode->btnode = p; tempNode->isFirst = true; s.push(tempNode); p = p->left; } if(!s.empty()) { temp = s.top(); s.pop(); if(temp->isFirst == true) //表示是第一次出现在栈顶 { temp->isFirst = false; s.push(temp); p = temp->btnode->right; } else //第二次出现在栈顶 { path.push_back(temp->btnode->val); p = NULL; } } } return path; } // 树中结点含有分叉, // 8 // / \ // 6 1 // / \ // 9 2 // / \ // 4 7 int main() { TreeNode *pNodeA1 = CreateBinaryTreeNode( 8); TreeNode *pNodeA2 = CreateBinaryTreeNode( 6); TreeNode *pNodeA3 = CreateBinaryTreeNode( 1); TreeNode *pNodeA4 = CreateBinaryTreeNode( 9); TreeNode *pNodeA5 = CreateBinaryTreeNode( 2); TreeNode *pNodeA6 = CreateBinaryTreeNode( 4); TreeNode *pNodeA7 = CreateBinaryTreeNode( 7); ConnectTreeNodes(pNodeA1, pNodeA2, pNodeA3); ConnectTreeNodes(pNodeA2, pNodeA4, pNodeA5); ConnectTreeNodes(pNodeA5, pNodeA6, pNodeA7); PrintTree(pNodeA1); vector< int> ans = postTraversal(pNodeA1); for ( int i = 0; i < ans.size(); ++i) { cout << ans[i] << " "; } cout << endl; DestroyTree(pNodeA1); return 0; } |
【二叉树遍历模版】层次遍历
count 记录的是当前遍历的层次当中的结点个数。
depth记录的是当前遍历过的层次数。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
#include <iostream>
#include <cstdio> #include <stack> #include <vector> #include "BinaryTree.h" using namespace std; /** * Definition for binary tree * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ vector<vector< int> > levelOrder(TreeNode *root) { vector<vector< int> > matrix; if(root == NULL) { return matrix; } vector< int> temp; temp.push_back(root->val); matrix.push_back(temp); vector<TreeNode *> path; path.push_back(root); int count = 1; while(!path.empty()) { TreeNode *tn = path.front(); if(tn->left) { path.push_back(tn->left); } if(tn->right) { path.push_back(tn->right); } path.erase(path.begin()); count--; if(count == 0) { vector< int> tmp; vector<TreeNode *>::iterator it = path.begin(); for(; it != path.end(); ++it) { tmp.push_back((*it)->val); } if(tmp.size() > 0) { matrix.push_back(tmp); } count = path.size(); } } return matrix; } // 树中结点含有分叉, // 8 // / \ // 6 1 // / \ // 9 2 // / \ // 4 7 int main() { TreeNode *pNodeA1 = CreateBinaryTreeNode( 8); TreeNode *pNodeA2 = CreateBinaryTreeNode( 6); TreeNode *pNodeA3 = CreateBinaryTreeNode( 1); TreeNode *pNodeA4 = CreateBinaryTreeNode( 9); TreeNode *pNodeA5 = CreateBinaryTreeNode( 2); TreeNode *pNodeA6 = CreateBinaryTreeNode( 4); TreeNode *pNodeA7 = CreateBinaryTreeNode( 7); ConnectTreeNodes(pNodeA1, pNodeA2, pNodeA3); ConnectTreeNodes(pNodeA2, pNodeA4, pNodeA5); ConnectTreeNodes(pNodeA5, pNodeA6, pNodeA7); PrintTree(pNodeA1); vector<vector< int> > ans = levelOrder(pNodeA1); for ( int i = 0; i < ans.size(); ++i) { for ( int j = 0; j < ans[i].size(); ++j) { cout << ans[i][j] << " "; } } cout << endl; DestroyTree(pNodeA1); return 0; } |
【二叉树遍历模版】Root->Right->Left遍历
先遍历根节点,然后在遍历这个根节点的右子树的根节点,然后递归对右子树做遍历,
遍历完事儿之后再递归遍历左子树。注意这种遍历方法很常用。本质上是一种DFS。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
#include <iostream>
#include <cstdio> #include <stack> #include <vector> #include "BinaryTree.h" using namespace std; /** * Definition for binary tree * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ vector< int> rootRLTraversal(TreeNode *root) { stack<TreeNode *> s; vector< int> ans; TreeNode *tmp; s.push(root); while (!s.empty()) { tmp = s.top(); s.pop(); if (!tmp) { continue; } //注意这里tmp不为空的时候才可以把他放进去 ans.push_back(tmp->val); s.push(tmp->left); s.push(tmp->right); } return ans; } // 树中结点含有分叉, // 6 // / \ // 7 2 // / \ // 1 4 // / \ // 3 5 int main() { TreeNode *pNodeA1 = CreateBinaryTreeNode( 6); TreeNode *pNodeA2 = CreateBinaryTreeNode( 7); TreeNode *pNodeA3 = CreateBinaryTreeNode( 2); TreeNode *pNodeA4 = CreateBinaryTreeNode( 1); TreeNode *pNodeA5 = CreateBinaryTreeNode( 4); TreeNode *pNodeA6 = CreateBinaryTreeNode( 3); TreeNode *pNodeA7 = CreateBinaryTreeNode( 5); ConnectTreeNodes(pNodeA1, pNodeA2, pNodeA3); ConnectTreeNodes(pNodeA2, pNodeA4, pNodeA5); ConnectTreeNodes(pNodeA5, pNodeA6, pNodeA7); vector< int> ans = rootRLTraversal(pNodeA1); for ( int i = 0; i < ans.size(); ++i) { cout << ans[i] << " "; } cout << endl; DestroyTree(pNodeA1); return 0; } |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#ifndef _BINARY_TREE_H_
#define _BINARY_TREE_H_ struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode( int x) : val(x), left( NULL), right( NULL) {} }; TreeNode *CreateBinaryTreeNode( int value); void ConnectTreeNodes(TreeNode *pParent, TreeNode *pLeft, TreeNode *pRight); void PrintTreeNode(TreeNode *pNode); void PrintTree(TreeNode *pRoot); void DestroyTree(TreeNode *pRoot); #endif /*_BINARY_TREE_H_*/ |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
#include <iostream>
#include <cstdio> #include "BinaryTree.h" using namespace std; /** * Definition for binary tree * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ //创建结点 TreeNode *CreateBinaryTreeNode( int value) { TreeNode *pNode = new TreeNode(value); return pNode; } //连接结点 void ConnectTreeNodes(TreeNode *pParent, TreeNode *pLeft, TreeNode *pRight) { if(pParent != NULL) { pParent->left = pLeft; pParent->right = pRight; } } //打印节点内容以及左右子结点内容 void PrintTreeNode(TreeNode *pNode) { if(pNode != NULL) { printf( "value of this node is: %d\n", pNode->val); if(pNode->left != NULL) printf( "value of its left child is: %d.\n", pNode->left->val); else printf( "left child is null.\n"); if(pNode->right != NULL) printf( "value of its right child is: %d.\n", pNode->right->val); else printf( "right child is null.\n"); } else { printf( "this node is null.\n"); } printf( "\n"); } //前序遍历递归方法打印结点内容 void PrintTree(TreeNode *pRoot) { PrintTreeNode(pRoot); if(pRoot != NULL) { if(pRoot->left != NULL) PrintTree(pRoot->left); if(pRoot->right != NULL) PrintTree(pRoot->right); } } void DestroyTree(TreeNode *pRoot) { if(pRoot != NULL) { TreeNode *pLeft = pRoot->left; TreeNode *pRight = pRoot->right; delete pRoot; pRoot = NULL; DestroyTree(pLeft); DestroyTree(pRight); } } |