一,前序走訪非遞迴:
根據前序走訪訪問的順序,優先訪問根結點,然後再分別訪問左孩子和右孩子。即對於任一結點,其可看做是根結點,因此可以直接存取,訪問完之後,若其左孩子不為空白,按相同規則訪問它的左子樹;當訪問其左子樹時,再訪問它的右子樹。因此其處理過程如下:
對於任一結點P:
1)訪問結點P,並將結點P入棧;
2)判斷結點P的左孩子是否為空白,若為空白,則取棧頂結點並進行出棧操作,並將棧頂結點的右孩子置為當前的結點P,迴圈至1);若不為空白,則將P的左孩子置為當前的結點P;
3)直到P為NULL並且棧為空白,則遍曆結束。
void preOrder2(node *root) //非遞迴前序走訪
{
stack<node*> s;
node *p=root;
while(p!=NULL||!s.empty())
{
while(p!=NULL)//向左遍曆直到葉子
{
cout<<p->data<<" ";
s.push(p);
p=p->lchild;
}
if(!s.empty())
{
p=s.top();
s.pop();
p=p->rchild;
}
}
cout<<endl;
}
二,中序遍曆非遞迴
根據中序遍曆的順序,對於任一結點,優先訪問其左孩子,而左孩子結點又可以看做一根結點,然後繼續訪問其左孩子結點,直到遇到左孩子結點為空白的結點才進行訪問,然後按相同的規則訪問其右子樹。因此其處理過程如下:
對於任一結點P,
1)若其左孩子不為空白,則將P入棧並將P的左孩子置為當前的P,然後對當前結點P再進行相同的處理;
2)若其左孩子為空白,則取棧頂元素並進行出棧操作,訪問該棧頂結點,然後將當前的P置為棧頂結點的右孩子;
3)直到P為NULL並且棧為空白則遍曆結束
void inOrder2(node *root) //非遞迴中序遍曆
{
stack<node*> s;
node *p=root;
while(p!=NULL||!s.empty())
{
while(p!=NULL)//記錄訪問過的根節點
{
s.push(p);
p=p->lchild;
}
if(!s.empty())
{
p=s.top();
cout<<p->data<<" "; //訪問棧頂
s.pop();
p=p->rchild; //將當前訪問的元素的右孩子入棧
}
}
}
要保證根結點在左孩子和右孩子訪問之後才能訪問,因此對於任一結點P,先將其入棧。如果P不存在左孩子和右孩子,則可以直接存取它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被訪問過了,則同樣可以直接存取該結點。若非上述兩種情況,則將P的右孩子和左孩子依次入棧,這樣就保證了每次取棧頂元素的時候,左孩子在右孩子前面被訪問,左孩子和右孩子都在根結點前面被訪問。
void postOrder3(node *root) //非遞迴後序遍曆
{
stack<node*> s;
node *cur; //當前結點
node *pre=NULL; //前一次訪問的結點
s.push(root);
while(!s.empty())
{
cur=s.top();
if((cur->lchild==NULL&&cur->rchild==NULL)||
(pre!=NULL&&(pre==cur->lchild||pre==cur->rchild)))
{
cout<<cur->data<<" "; //如果當前結點沒有孩子結點或者孩子節點都已被訪問過
s.pop();
pre=cur;
}
else
{
if(cur->rchild!=NULL)
s.push(cur->rchild);
if(cur->lchild!=NULL)
s.push(cur->lchild);
}
}
}
綜合程式附錄
#include "stdio.h"#include "stdlib.h" #include "stack.h"int count;//統計葉子節點個數 struct node{int data;//二叉樹的節點值node *lchild,*rchild;//左右孩子節點 };/*不知道為什麼 建立的時候需要傳回值才 建立有效*/node *createTree(){node *root;int data;printf("input data:");scanf("%d",&data);//printf("output data:%d\n",data);if(data==0) root=NULL; else/*根左右 前序建立二叉樹*/ { root=(node*)malloc(sizeof(node)); root->data=data; root->lchild=createTree(); root->rchild=createTree(); }return root;} void preOrder(node *root){if(root==NULL) return;else//不是空{printf("%d\n",root->data);preOrder(root->lchild);preOrder(root->rchild); } }void inOrder(node *root){if(root==NULL) return;else//不是空{inOrder(root->lchild);printf("%d\n",root->data);inOrder(root->rchild); } }void postOrder(node *root){if(root==NULL) return;else//不是空{postOrder(root->lchild);postOrder(root->rchild);printf("%d\n",root->data); } }void CountLeaves(node *root){if(root==NULL) return;else//不是空{if(root->lchild==NULL&&root->rchild==NULL) count++;CountLeaves(root->lchild);CountLeaves(root->rchild); } } int deepLength(node *root){int deep1,deep2;if(root==NULL) return 0; else { deep1=deepLength(root->lchild); deep2=deepLength(root->rchild); if(deep1>deep2) return deep1+1;//這個地方一定是返回+1 else return deep2+1; }}void CountNodes(node *root){if(root==NULL) return;else//不是空{ count++;CountNodes(root->lchild);CountNodes(root->rchild); } } void exchange(node *root){if(root==NULL) return; else { exchange(root->lchild); exchange(root->rchild); node *temp=root->lchild; root->lchild=root->rchild; root->rchild=temp; }}void search(node *root,int x){if(root==NULL) return ; else { if(root->data==x) { count++; printf("has\n"); } search(root->lchild,x); search(root->rchild,x); }}void preOrder2(node *root) //非遞迴前序走訪 { stack<node*> s; node *p=root; while(p!=NULL||!s.empty()) { while(p!=NULL)//向左遍曆 直到葉子 { cout<<p->data<<" "; s.push(p); p=p->lchild; } if(!s.empty()) { p=s.top(); s.pop(); p=p->rchild; } } cout<<endl; }void inOrder2(node *root) //非遞迴中序遍曆{ stack<node*> s; node *p=root; while(p!=NULL||!s.empty()) { while(p!=NULL) { s.push(p); p=p->lchild; } if(!s.empty()) { p=s.top(); cout<<p->data<<" "; s.pop(); p=p->rchild; } } }void postOrder3(node *root) //非遞迴後序遍曆{ stack<node*> s; node *cur; //當前結點 node *pre=NULL; //前一次訪問的結點 s.push(root); while(!s.empty()) { cur=s.top(); if((cur->lchild==NULL&&cur->rchild==NULL)|| (pre!=NULL&&(pre==cur->lchild||pre==cur->rchild))) { cout<<cur->data<<" "; //如果當前結點沒有孩子結點或者孩子節點都已被訪問過 s.pop(); pre=cur; } else { if(cur->rchild!=NULL) s.push(cur->rchild); if(cur->lchild!=NULL) s.push(cur->lchild); } } }/*一定要記住直接輸入1 2 3 0 0 0 0 建立的是 左二叉樹 平衡的應該是 1 2 0 0 3 0 0*/int main(){node *root;//=(node*)malloc(sizeof(node));//這裡不要初始化了 因為建立的時候要初始化 printf(" Please select what you want do\n");printf("----------------------------------------------\n");printf(" 1.前序建立二叉樹\n");printf(" 2.遞迴前序走訪二叉樹\n");printf(" 3.遞迴中序遍曆二叉樹\n");printf(" 4.遞迴後序遍曆二叉樹\n");printf(" 5.求分葉節點個數\n");printf(" 6.求樹的高度\n");printf(" 7.求二叉樹節點個數\n");printf(" 8.交換左右子樹\n");printf(" 9.尋找有無某個節點\n");printf(" 10.非遞迴前序走訪二叉樹\n");printf(" 11.非遞迴前序走訪二叉樹\n");printf(" 12.非遞迴前序走訪二叉樹\n");printf(" 15.退出\n"); int i;while(true){scanf("%d",&i); switch(i) { case 1: root=createTree(); printf("create tree is finished please select what you want do next:\n");break; case 2:printf("Now outPut data in PreOrder:\n"); preOrder(root); printf("output is over please select again\n");break; case 3: printf("Now outPut data in inOrder:\n"); inOrder(root);printf("output is over please select again\n");break; case 4: printf("Now outPut data in postOrder:\n"); postOrder(root);printf("output is over please select again\n");break; case 5: count=0; CountLeaves(root); printf("The leaves's count is:%d\n",count);printf("output is over please select again\n");break;//葉子節點的個數 case 6: int deep=deepLength(root); printf("The tree's deepLength is:%d\n",deep);printf("output is over please select again\n");break; case 7: count=0; CountNodes(root); printf("The leaves's count is:%d\n",count);printf("output is over\n"); break;//求二叉樹節點個數 case 8: exchange(root); break; case 9: printf("please input what you want search\n"); int x; scanf("%d",&x); count=0; search(root,x);if(count!=0) { printf("The tree has this root\n"); printf("output is over please select again\n"); } else { printf("The tree not has this root\n"); printf("output is over please select again\n"); } break; case 10:printf("Now outPut data in PreOrder:\n"); preOrder2(root); printf("output is over please select again\n");break; case 11:printf("Now outPut data in PreOrder:\n"); inOrder2(root); printf("output is over please select again\n");break; case 12:printf("Now outPut data in PreOrder:\n"); postOrder3(root); printf("output is over please select again\n");break; case 15: exit(0); break;//包含在stdlib.h當中 } } return 0;}