//好久不用C++许多语法细节都忘记了...费了九牛二虎之力还搞的那么复杂,Anyway,下午把二叉树的先序、中序、后序的非递归遍历给写出来了,还是有点成绩的。。。
//先序遍历,入栈的时候遍历。中序遍历,出栈的时候遍历元素。先序遍历和中序遍历真的就只有这么点区别
#include<iostream> #include<stack> using namespace std; typedef int dataType; typedef struct BiTree { dataType data; BiTree *lchild; BiTree *rchild; }BiTree,*treePoint; treePoint CreateTree(treePoint root) { dataType data; cin>>data; if(data==-1) { return NULL; } root=new BiTree; root->data=data; root->lchild=CreateTree(root->lchild); root->rchild=CreateTree(root->rchild); return root; }
int main() { treePoint root=NULL; root=CreateTree(root); cout<<"前序遍历方式。。。"<<endl; PreOrderTraverse(root); cout<<"\n中序遍历方式。。。"<<endl; InOrderTraverse(root); cout<<"\n后序遍历方式。。。"<<endl; PostOrderTraverse(root); system("pause"); return 0; }
首先将根节点不空,访问根节点元素,根节点入栈,若栈不空,首先将栈顶节点的所有左孩子入栈并访问左孩子的元素直至左子树为空。然后,若栈不为空,依次弹出栈里元素并判断,若弹出元素的右子树为空,接着弹出栈里面的元素,若弹出元素右子树不为空,访问弹出元素的数据,接着将弹出元素的左子树入栈,跳至开始。
void PreOrderTraverse(treePoint root) { treePoint bt; if(root==NULL) return; cout<<root->data<<'\t'; stack<treePoint>st; st.push(root); while(!st.empty()) { bt=st.top(); while(bt->lchild!=NULL) { st.push(bt->lchild); cout<<bt->lchild->data<<'\t'; bt=bt->lchild; } while(!st.empty()) { bt=st.top(); st.pop(); if(bt->rchild!=NULL) { cout<<bt->rchild->data<<'\t'; st.push(bt->rchild); break; } } } }
方法2:
void PreOrderTraverse(treePoint root) { if(root==NULL) return; treePoint bt; stack<treePoint>st; st.push(root); while(!st.empty()) { bt=st.top(); st.pop(); cout<<bt->data<<'\t'; if(bt->rchild!=NULL) st.push(bt->rchild); if(bt->lchild!=NULL) st.push(bt->lchild); } cout<<endl; }
若根节点不空,根节点入栈。若栈不空且其左子树不为空,依次将栈顶元素的所有左子树入栈直至左子树为空。然后,若栈不空,访问栈顶元素,栈顶元素的右子树不空时,将当前元素的右子树入栈并跳转到循环开始的地方。
void InOrderTraverse(treePoint root) { if(root==NULL) return; treePoint bt; stack<treePoint>st; st.push(root); while(!st.empty()) { bt=st.top(); while(bt->lchild!=NULL) { st.push(bt->lchild); bt=bt->lchild; } while(!st.empty()) { bt=st.top(); cout<<bt->data<<'\t'; st.pop(); if(bt->rchild!=NULL) { st.push(bt->rchild); break; } } } }
若根节点不空,根节点入栈。若栈不空,如果栈顶元素的左子树为空右子树为空,或者正在访问的节点是前一个访问节点的父节点,直接访问当前节点的元素,并将当前节点置为前一个节点。否则,如果当前栈顶元素的右子树不为空,将右子树入栈。如果左子树不为空,将左子树入栈,循环至栈不空的地方。。。
void PostOrderTraverse(treePoint root) { if(root==NULL) return; treePoint cur=root,pre=NULL; stack<treePoint>st; st.push(root); while(!st.empty()) { cur=st.top(); if((cur->lchild==NULL&&cur->rchild==NULL)||(pre!=NULL)&&(cur->lchild==pre||cur->rchild==pre)) { cout<<cur->data<<'\t'; st.pop(); pre=cur; }else { if(cur->rchild!=NULL) st.push(cur->rchild); if(cur->lchild!=NULL) st.push(cur->lchild); } } }
void StepOrderTraverse(treePoint root) { if(root==NULL) return; treePoint bt; queue<treePoint>qu; qu.push(root); while(!qu.empty()) { bt=qu.front(); qu.pop(); cout<<bt->data<<'\t'; if(bt->lchild!=NULL) qu.push(bt->lchild); if(bt->rchild!=NULL) qu.push(bt->rchild); } }