二叉树遍历
行文结构
- 递归方法(前中后)
- 非递归方法(前中后层)
- 微软面试题
二叉树遍历根据“根节点”遍历时相对的次序分为前序、中序、后序。图示为相对于根节点的次序,左右子树也是一样的规则。
前序遍历 中序遍历 后续遍历
1. 递归方法
前序遍历
void PreorderTraversal(BiTree T) { if(T != NULL) { cout << T->data << endl; PreorderTraversal(T->left); PreorderTraversal(T->right); } }
中序遍历
void InorderTraversal(BiTree T) { if(T != NULL) { InorderTraversal(T->left); cout << T->data << endl; InorderTraversal(T->right); } }
后续遍历
void PostorderTraversal(BiTree T) { if(T != NULL) { PostorderTraversal(T->left); PostorderTraversal(T->right); cout << T->data << endl; } }
整合参考程序
#include<iostream> #include<vector> using namespace std; typedef struct BiTNode { int data; BiTNode *left; BiTNode *right; }BiTNode, *BiTree; bool SearchBST(BiTree T, int val, BiTree f, BiTree &p) { if(!T) { p = f; return false; } else if(val == T->data) { p = T; return true; } else if(val < T->data) SearchBST(T->left, val, T, p); else SearchBST(T->right, val, T, p); } bool InsertBST(BiTree &T, int val) { BiTree p; if(!SearchBST(T, val, NULL, p)) { BiTree node = new BiTNode; node->data = val; node->left = node->right = NULL; if(!p) T = node; else if(val < p->data) p->left = node; else p->right = node; return true; } return false; } void PreorderTraversal(BiTree T) { if(T) { cout << T->data << endl; PreorderTraversal(T->left); PreorderTraversal(T->right); } } void InorderTraversal(BiTree T) { if(T) { InorderTraversal(T->left); cout << T->data << endl; InorderTraversal(T->right); } } void PostorderTraversal(BiTree T) { if(T) { PostorderTraversal(T->left); PostorderTraversal(T->right); cout << T->data << endl; } } int main() { int array[] = {5, 1, 0, 45, 10, 3, 8, 5}; int len_array = sizeof(array) / sizeof(*array); BiTree root = NULL; for(int i = 0; i< len_array; ++i) InsertBST(root, array[i]); cout << "PreorderTraversal" << endl; PreorderTraversal(root); cout << "----------------------" << endl; cout << "InorderTraversal" << endl; InorderTraversal(root); cout << "----------------------" << endl; cout << "PostorderTraversal" << endl; PostorderTraversal(root); cout << "----------------------" << endl; }
结果
2. 非递归方法
非递归方法借助于栈,“记忆”走过的结点。
前序遍历
“根-左孩子-右孩子”,对每一个结点看成是根节点,先输出,后入栈(到时返回访问右孩子),然后访问左孩子。当不能在往左走时,查询栈中的记忆,根据栈顶进入右孩子,重复上边的故事。
void PreorderTraversal(BiTree T) { stack<BiTree> s; while(T != NULL || !s.empty()) { while(T != NULL) { cout << T->data << endl; s.push(T); T = T->left; } T = s.top(); T = T->right; s.pop(); } }
中序遍历
“左孩子-根-右孩子”,对每一个结点看成是根节点,先入栈(到时返回访问自己和右孩子),然后访问左孩子。当不能在往左走时,查询栈中的记忆,根据栈顶访问自己并且进入右孩子,重复上边的故事。
void InorderTraversal(BiTree T) { stack<BiTree> s; while(T != NULL || !s.empty()) { while(T != NULL) { s.push(T); T = T->left; } T = s.top(); cout << T->data << endl; T = T->right; s.pop(); } }
后续遍历
“左孩子-右孩子-根”,为了达到这个效果,需要把把按“根-->右孩子-->左孩子”的顺序入栈,因为栈的特征是先进后出,所以访问时顺序相反。对于一个结点只有满足以下两个条件时,才访问,否则按“根-->右孩子-->左孩子”顺序入栈。
- 左右孩子全为NULL
- 前边访问的结点正好为当前结点的左孩子或右孩子(访问了左孩子必定已经访问了右孩子)
void PostorderTraversal(BiTree T) { stack<BiTree> s; BiTree cur = NULL, pre = NULL; s.push(T); while(!s.empty()) { cur = s.top(); if((cur->left != NULL && cur->right != NULL) || (pre != NULL && (pre == cur->left || pre == cur->right))) { cout << cur->data << endl; pre = cur; s.pop(); } else { if(cur->right) s.push(cur->right); if(cur->left) s.push(cur->left); } } }
整合参考程序
#include<iostream> #include<stack> using namespace std; typedef struct BiTNode { int data; BiTNode *left; BiTNode *right; }BiTNode, *BiTree; bool SearchBST(BiTree T, int val, BiTree f, BiTree &p) { if(!T) { p = f; return false; } else if(val == T->data) { p = T; return true; } else if(val < T->data) SearchBST(T->left, val, T, p); else SearchBST(T->right, val, T, p); } bool InsertBST(BiTree &T, int val) { BiTree p; if(!SearchBST(T, val, NULL, p)) { BiTree node = new BiTNode; node->data = val; node->left = node->right = NULL; if(!p) T = node; else if(val < p->data) p->left = node; else p->right = node; return true; } return false; } void PreorderTraversal(BiTree T) { stack<BiTree> s; while(T || !s.empty()) { while(T) { cout << T->data << endl; s.push(T); T = T->left; } T = s.top(); T = T->right; s.pop(); } } void InorderTraversal(BiTree T) { stack<BiTree> s; while(T || !s.empty()) { while(T) { s.push(T); T = T->left; } T = s.top(); cout << T->data << endl; T = T->right; s.pop(); } } void PostorderTraversal(BiTree T) { if (T == NULL) return; stack<BiTree> s; BiTree cur = NULL, pre = NULL; s.push(T); while(!s.empty()) { cur = s.top(); if((!cur->left && !cur->right) || (pre != NULL && (pre == cur->left || pre == cur->right))) { cout << cur->data << endl; pre = cur; s.pop(); } else { if(cur->right) s.push(cur->right); if(cur->left) s.push(cur->left); } } } int main() { int array[] = {5, 1, 0, 45, 10, 3, 8, 5}; int len_array = sizeof(array) / sizeof(*array); BiTree root = NULL; for(int i = 0; i< len_array; ++i) InsertBST(root, array[i]); cout << "PreorderTraversal" << endl; PreorderTraversal(root); cout << "----------------------" << endl; cout << "InorderTraversal" << endl; InorderTraversal(root); cout << "----------------------" << endl; cout << "PostorderTraversal" << endl; PostorderTraversal(root); cout << "----------------------" << endl; }
结果同递归遍历
层次遍历
详见http://www.cnblogs.com/kaituorensheng/p/3558645.html
3. 微软面试题
分析:由二叉遍历树变成有序的结构,不用说绝对是中序遍历。中序遍历分为两种方法——递归、非递归。递归不需要额外的空间,非递归需要额外空间(借助与栈)。现在用两种方法实现,其思路都是基本中序遍历的改进。
方法一(递归方法)
void BST2BLink(BiTree T, BiTree &pre) //&地址操作,所有递归使用同一个 { if(T) { BST2BLink(T->left, pre); if(pre) { pre->right = T; T ->left = pre; } pre = T; BST2BLink(T->right, pre); } }
执行程序
#include<iostream> #include<stack> using namespace std; typedef struct BiTNode { int data; BiTNode *left; BiTNode *right; }BiTNode, *BiTree; bool SearchBST(BiTree T, int val, BiTree f, BiTree &p) { if(!T) { p = f; return false; } else if(val == T->data) { p = T; return true; } else if(val < T->data) SearchBST(T->left, val, T, p); else SearchBST(T->right, val, T, p); } bool InsertBST(BiTree &T, int val) { BiTree p; if(!SearchBST(T, val, NULL, p)) { BiTree node = new BiTNode; node->data = val; node->left = node->right = NULL; if(!p) T = node; else if(val < p->data) p->left = node; else p->right = node; return true; } return false; } void BST2BLink(BiTree T, BiTree &pre) { if(T) { BST2BLink(T->left, pre); if(pre) { pre->right = T; T ->left = pre; } pre = T; BST2BLink(T->right, pre); } } int BST2BLink(BiTree &T) { stack<BiTree> s; BiTree cur = T, pre = NULL; while(cur || !s.empty()) { while(cur) { s.push(cur); cur = cur->left; } cur = s.top(); s.pop(); cout << cur->data << endl; if(!pre) T = cur; else { pre->right = cur; cur ->left = pre; } pre = cur; cur = cur->right; } } void BLinkTraversal(BiTree root) { while(root) { cout << root->data << endl; root = root->right; } } int main() { int array[] = {5, 8, 0, 3, 100, 45}; int len_array = sizeof(array) / sizeof(*array); BiTree root = NULL; for(int i = 0; i< len_array; ++i) InsertBST(root, array[i]); cout << "Recursion" << endl; BiTree pre = NULL; BST2BLink(root, pre); while(root->left) root = root->left; BLinkTraversal(root); /* cout << "\nNot Recursion" << endl; BST2BLink(root_copy); cout << "----------------------" << endl; BLinkTraversal(root); */ }
方法二(非递归方法)
int BST2BLink(BiTree &T) { stack<BiTree> s; BiTree cur = T, pre = NULL; while(cur || !s.empty()) { while(cur) { s.push(cur); cur = cur->left; } cur = s.top(); s.pop(); cout << cur->data << endl; if(!pre) T = cur; else { pre->right = cur; cur ->left = pre; } pre = cur; cur = cur->right; } }
执行程序
#include<iostream> #include<stack> using namespace std; typedef struct BiTNode { int data; BiTNode *left; BiTNode *right; }BiTNode, *BiTree; bool SearchBST(BiTree T, int val, BiTree f, BiTree &p) { if(!T) { p = f; return false; } else if(val == T->data) { p = T; return true; } else if(val < T->data) SearchBST(T->left, val, T, p); else SearchBST(T->right, val, T, p); } bool InsertBST(BiTree &T, int val) { BiTree p; if(!SearchBST(T, val, NULL, p)) { BiTree node = new BiTNode; node->data = val; node->left = node->right = NULL; if(!p) T = node; else if(val < p->data) p->left = node; else p->right = node; return true; } return false; } void BST2BLink(BiTree T, BiTree &pre) { if(T) { BST2BLink(T->left, pre); if(pre) { pre->right = T; T ->left = pre; } pre = T; BST2BLink(T->right, pre); } } int BST2BLink(BiTree &T) { stack<BiTree> s; BiTree cur = T, pre = NULL; while(cur || !s.empty()) { while(cur) { s.push(cur); cur = cur->left; } cur = s.top(); s.pop(); // cout << cur->data << endl; if(!pre) T = cur; else { pre->right = cur; cur ->left = pre; } pre = cur; cur = cur->right; } } void BLinkTraversal(BiTree root) { while(root) { cout << root->data << endl; root = root->right; } } int main() { int array[] = {5, 8, 0, 3, 100, 45}; int len_array = sizeof(array) / sizeof(*array); BiTree root = NULL; for(int i = 0; i< len_array; ++i) InsertBST(root, array[i]); /* cout << "Recursion" << endl; BiTree pre = NULL; BST2BLink(root, pre); while(root->left) root = root->left; BLinkTraversal(root); */ cout << "\nNot Recursion" << endl; BST2BLink(root); cout << "----------------------" << endl; BLinkTraversal(root); }