標籤:des blog http os io ar for 2014 div
今天學習到二叉樹的時候,看到了二叉樹的先序,後序,中序遍曆方法。然而二叉樹遍曆方法遞迴實現十分簡單,迭代版本實現起來些許複雜,就又上手試試二叉樹的各種遍曆方法以及實現版本,當是溫習一遍之前瞭解到的實現方法。
三種遍曆方法中遞迴實現難度相當,代碼相當簡略。
三種遍曆方法中利用棧實現的迭代版本中,先序和中序實現難度相對簡單,但是後序遍曆方法實現起來比較複雜,這裡實現思路也不同於之前先序和中序的版本。
另外一種O(1)空間複雜度實現先序,中序實現難度也相對簡單,後序相對複雜。
以下貼出完整測試代碼,main函數中輸入產生二叉樹的方法:
輸入節點數量,然後輸入二叉樹樹形結構1,2,3,#,4其中#代表空,則1,2,3,#,4代表以下結構:
1 / 2 3 \ 4
再舉一個例子,輸入7個節點數量,輸入1,2,3,4,5,6,7代表樹形結構如下:
1 / 2 3 / \ / 4 5 6 7
代碼:
其中_r尾碼的為遞迴實現,_s尾碼的為利用棧迭代實現,_m尾碼的為O(1)空間複雜度迭代實現。
其中_m迭代實現線程不安全,因為臨時的改變了樹的結構。
#include <iostream>#include <stack>#include <vector>using namespace std;struct TreeNode {int label;TreeNode *right;TreeNode *left;TreeNode(int temp):label(temp) {}};class Solution {public:void inordertraversal_r(TreeNode *root) {if(root == NULL) {return;}inordertraversal_r(root->left);cout<<root->label<<" ";inordertraversal_r(root->right);}void preordertraversal_r(TreeNode *root) {if(root == NULL) {return;}cout<<root->label<<" ";preordertraversal_r(root->left);preordertraversal_r(root->right);}void postordertraversal_r(TreeNode *root) {if(root == NULL) {return;}postordertraversal_r(root->left);postordertraversal_r(root->right);cout<<root->label<<" ";}void inordertraversal_s(TreeNode *root) {stack<TreeNode*> s;TreeNode *cur = root;while(!s.empty() || cur != NULL) {while(cur != NULL) {s.push(cur);cur = cur->left;}cur = s.top();s.pop();cout<<cur->label<<" ";cur = cur->right;}}void preordertraversal_s(TreeNode *root) {stack<TreeNode*> s;TreeNode *cur = root;while(!s.empty() || cur != NULL) {while(cur != NULL) {cout<<cur->label<<" ";s.push(cur);cur = cur->left;}cur = s.top();s.pop();cur = cur->right;}}//change thinking , it‘s too hardvoid postordertraversal_s(TreeNode *root) {//the original method/*We use a prev variable to keep track of the previously-traversed node. Let’s assume curr is the current node that’s on top of the stack. When prev is curr‘s parent, we are traversing down the tree. In this case, we try to traverse to curr‘s left child if available (ie, push left child to the stack). If it is not available, we look at curr‘s right child. If both left and right child do not exist (ie, curr is a leaf node), we print curr‘s value and pop it off the stack.If prev is curr‘s left child, we are traversing up the tree from the left. We look at curr‘s right child. If it is available, then traverse down the right child (ie, push right child to the stack), otherwise print curr‘s value and pop it off the stack.If prev is curr‘s right child, we are traversing up the tree from the right. In this case, we print curr‘s value and pop it off the stack.*/if(root == NULL) {return;}stack<TreeNode*> s;s.push(root);TreeNode *cur = NULL;TreeNode *pre = NULL;while( !s.empty() ) {cur = s.top();//left down or right downif( pre == NULL || pre->left == cur || pre->right == cur) {if(cur->left != NULL) {s.push(cur->left);}else if(cur->right != NULL) {s.push(cur->right);}else {cout<<cur->label<<" ";s.pop();}}//left upelse if(cur->left == pre) {if(cur->right != NULL) {s.push(cur->right);}else {cout<<cur->label<<" ";s.pop();}}//right upelse if(cur->right == pre) {cout<<cur->label<<" ";s.pop();}pre = cur;}/* the easy methodstack<TreeNode*> s;s.push(root);TreeNode *cur = NULL;TreeNode *pre = NULL;while( !s.empty() ) {cur = s.top();if(pre == NULL || pre->left == cur || pre->right == cur) {if(cur->left != NULL) {s.push(cur->left);}else if(cur->right != NULL) {s.push(cur->right);}}else if(cur->left == pre) {if(cur->right != NULL) {s.push(cur->right);}}else {cout<<cur->label<<" ";s.pop();}pre = cur;}*/}void inordertraversal_m(TreeNode *root) {TreeNode *cur = root;TreeNode *pre = NULL;while(cur != NULL) {if(cur->left == NULL) {cout<<cur->label<<" ";cur = cur->right;}else {pre = cur->left;while( pre->right != NULL && pre->right != cur ) {pre = pre->right;}if(pre->right == NULL) {pre->right = cur;cur = cur->left;}else {pre->right = NULL;cout<<cur->label<<" ";cur = cur->right;}}}}void preordertraversal_m(TreeNode *root) {TreeNode *cur = root;TreeNode *pre = NULL;while(cur != NULL) {if(cur->left == NULL) {cout<<cur->label<<" ";cur = cur->right;}else {pre = cur->left;while( pre->right != NULL && pre->right != cur ) {pre = pre->right;}if(pre->right == NULL) {pre->right = cur;cout<<cur->label<<" ";cur = cur->left;}else {pre->right = NULL;cur = cur->right;}}}}//this is the most difficult algorithmvoid reverse_out(TreeNode *from,TreeNode *to) {//first reverse from->to//reverseTreeNode *cur = from;TreeNode *post = cur->right;while(cur != to) {TreeNode *tmp = post->right;post->right = cur;cur = post;post = tmp;}//already reverse,output listTreeNode *traversal = cur;while( cur != from ) {cout<<cur->label<<" ";cur = cur->right;}cout<<cur->label<<" ";//reverse originalcur = to;post = cur->right;while(cur != from) {TreeNode *tmp = post->right;post->right = cur;cur = post;post = tmp;}//restore to‘s rightto->right = NULL;}void postordertraversal_m(TreeNode *root) {TreeNode *newroot = new TreeNode(0);newroot->left = root;newroot->right = NULL;TreeNode *cur = newroot;TreeNode *pre = NULL;while(cur != NULL) {if(cur->left == NULL) { cur = cur->right;}else {pre = cur->left;while(pre->right != NULL && pre->right != cur) {pre = pre->right;}if(pre->right == NULL) {pre->right = cur;cur = cur->left;} else {pre->right = NULL;reverse_out(cur->left,pre);cur = cur->right;}}}}};int main(void) {int nodecount;while( cin>>nodecount && nodecount != 0 ) {vector<TreeNode*> treenodes;while(nodecount) {nodecount--;int nodelabel;cin>>nodelabel;if( ((char)nodelabel) == ‘#‘ ) {treenodes.push_back( NULL );}else {treenodes.push_back( new TreeNode(nodelabel) );}}//construct the treefor(int i = 0;i < treenodes.size();i++) {if( treenodes[i] == NULL ) {continue;}else {//left child node 2n+1,right child node 2n+2if( 2*i + 1 < treenodes.size() ) {treenodes[i]->left = treenodes[2*i + 1];}else {treenodes[i]->left = NULL;}if( 2*i + 2 < treenodes.size() ) {treenodes[i]->right = treenodes[2*i + 2];}else {treenodes[i]->right = NULL;}}}Solution s;cout<<"inorder recursion :";s.inordertraversal_m(treenodes[0]);cout<<endl;cout<<"inorder stack :";s.inordertraversal_s(treenodes[0]);cout<<endl;cout<<"inorder morris :";s.inordertraversal_r(treenodes[0]);cout<<endl;cout<<"preorder recursion :";s.preordertraversal_m(treenodes[0]);cout<<endl;cout<<"preorder stack :";s.preordertraversal_s(treenodes[0]);cout<<endl;cout<<"preorder morris :";s.preordertraversal_r(treenodes[0]);cout<<endl;cout<<"postorder recursion:";s.postordertraversal_m(treenodes[0]);cout<<endl;cout<<"postorder stack :";s.postordertraversal_s(treenodes[0]);cout<<endl;cout<<"postorder morris :";s.postordertraversal_r(treenodes[0]);cout<<endl;for(int i = 0;i < treenodes.size();i++) {delete treenodes[i];}}}
關於morris的先序,中序思路圖解:
關於moriis的後序思路圖解:
二叉樹的遍曆方法