標籤:des blog ar io on 資料 div log ef
/**********************************************************************二叉樹的基本操作(1)二叉樹的資料結構(2)二叉樹的構造(3)二叉樹遍曆 :先序,中序,後序************************************************************************/#include <cstdio>#include <cstdlib>const int MAX=20;//二叉樹的結構 利用雙鏈表實現typedef struct Node{char ch; // 資料域struct Node *plchild; //左子樹指標struct Node *prchild;//右子樹指標}BiTreeNode;//構造二叉樹 //1.按照先序遍曆法構造 利用遞迴構造// ABD#G##EH##I##CF#J###void CreateBiTree_PreOrder(BiTreeNode * &T) //注意這裡傳入的是指標的引用{char ch;scanf("%c",&ch);if(‘#‘==ch)T=NULL;else {T=new BiTreeNode;if(NULL==T)exit(-1);T->ch=ch;CreateBiTree_PreOrder(T->plchild); // 構造左子樹CreateBiTree_PreOrder(T->prchild); // 構造右子樹}}//2.按照帶括弧的字串建立二叉樹結構/*思路:a(b(c,d),e(f(,g),h(i)))‘(‘: 表明已建立的節點為雙親節點,入棧。將要建立左孩子節點,用flag=1標記‘,‘: 表明將要建立右孩子節點。用flag=2標記‘)‘: 表明左右孩子節點建立和連結完畢,父節點出棧。default: 建立節點,並且賦值,判斷連結情況 */void CreateBiTree_ByString(BiTreeNode* &T, char str[]){BiTreeNode* Stack[MAX];// 棧用於儲存父節點int top=0,flag=0;BiTreeNode* p=NULL;//用於臨時指標while(*str){switch(*str){case ‘(‘:Stack[top++]=p;flag=1;//表示即將要建立的是 左孩子節點break;case ‘,‘:flag=2; //表明將要建立右孩子節點break;case ‘)‘:--top;//將父節點出棧break;default:{p=new BiTreeNode;if(NULL==p)return ;if(T==NULL)T=p;p->ch=*str;p->plchild=NULL;p->prchild=NULL;switch(flag) //此時 flag要初始化 不然非法訪問{case 1:Stack[top-1]->plchild=p; //將父節點與左孩子節點連結break;case 2:Stack[top-1]->prchild=p; //將父節點與右孩子節點連結break;}break;}}++str;}}// 遞迴先序遍曆void PreOrderTraverse_Recur(BiTreeNode *T){if(T) {printf("%2c",T->ch);PreOrderTraverse_Recur(T->plchild);PreOrderTraverse_Recur(T->prchild);}}// 非遞迴先序遍曆/* 思路: 先訪問父節點,列印。然後壓入棧中,然後訪問左孩子節點,訪問列印壓棧。將左孩子一個個壓入棧中,直到NULL.然後在訪問右孩子節點。同理按前 */void PreOrderTraverse_NoRecur(BiTreeNode *T){BiTreeNode* Stack[MAX]; //利用數組構造棧 先進後出int top=0;BiTreeNode *p=T;while( p || top >0){while(p){printf("%2c",p->ch);//先訪問Stack[top++]=p;//將 父節點壓棧p=p->plchild;//訪問左孩子節點}if(top>0)//top 代表棧中有多個節點{ //開始訪問 右孩子節點p=Stack[--top];//如果某個父節點的左孩子節點為NULL 那麼出棧該父節點。p=p->prchild;//然後又跳入到 訪問該右孩子的左子樹}}}// 遞迴中序遍曆void InOrderTraverse_Recur(BiTreeNode *T){if(T) //如果節點不為NULL {InOrderTraverse_Recur(T->plchild); //先放問 左孩子樹printf("%2c",T->ch); //然後在 訪問根節點InOrderTraverse_Recur(T->prchild); // 然後在訪問 右孩子樹}}// 非遞迴中序遍曆 /* 思路:相比於先序而言(一直將父節點壓棧,父節點出棧的時候就是要訪問該節點的右孩子樹) 所以中序遍曆,一直壓入左孩子節點,直到NULL.在出棧的時候列印父節點值。 */void InorderTraverse_NoRecur(BiTreeNode *T){BiTreeNode* Stack[MAX];int top=0;BiTreeNode *p=T;while( p || top>0 ){while(p){Stack[top++]=p; //直接將父節點入棧p=p->plchild;// 然後訪問左子樹}if(top>0){p=Stack[--top]; //將父節點處棧printf("%2c",p->ch); //列印父節點值p=p->prchild; //訪問右孩子子樹}}}// 遞迴後序遍曆void AfterOrderTraverse_Recur(BiTreeNode *T){if(T){AfterOrderTraverse_Recur(T->plchild);AfterOrderTraverse_Recur(T->prchild);printf("%2c",T->ch);}}// 非遞迴後序遍曆/*思路:依舊是將父節點依次壓棧。直到左節點為NULL,此時不出棧父節點,而是直接存取右孩子節點同時設定q用於檢測是否已經訪問過右孩子節點。 */void AfterOrderTraverse_NoRecur(BiTreeNode *T){BiTreeNode* Stack[MAX];int top=0;BiTreeNode *p=T,*q=NULL; // q用於判斷右節點是否訪問過while(p || top>0){while(p) //直到沒有左孩子節點{Stack[top++]=p;p=p->plchild; }if(top>0){p=Stack[top-1]; //不出棧 直接存取右子樹if(p->prchild==NULL || p->prchild == q) //沒有右節點或者右節點已經訪問過{printf("%2c",p->ch);q=p;p=NULL;top--;}else //有右節點 且沒被訪問過p=p->prchild;}}}//銷毀二叉樹void DestoryBiTree(BiTreeNode* &T){if(T){if(T->plchild)DestoryBiTree(T->plchild);if(T->prchild)DestoryBiTree(T->prchild);delete T;T=NULL;}}int main(){//ABD#G##EH##I##CF#J###BiTreeNode *T=NULL;CreateBiTree_PreOrder(T);puts("遞迴先序遍曆:");PreOrderTraverse_Recur(T);puts("");puts("非遞迴先序遍曆:");PreOrderTraverse_NoRecur(T);puts("");puts("遞迴中序遍曆:");InOrderTraverse_Recur(T);puts("");puts("非遞迴中序遍曆:");InorderTraverse_NoRecur(T);puts("");puts("遞迴後序遍曆:");AfterOrderTraverse_Recur(T);puts("");puts("非遞迴後序遍曆:");AfterOrderTraverse_NoRecur(T);puts("");DestoryBiTree(T);//銷毀二叉樹puts("\n--按照帶括弧的字串輸入------------");BiTreeNode *T2=NULL;char str[]="a(b(c,d),e(f(,g),h(i)))";CreateBiTree_ByString(T2,str);puts("遞迴先序遍曆:");PreOrderTraverse_Recur(T2);puts("");puts("非遞迴先序遍曆:");PreOrderTraverse_NoRecur(T2);puts("");puts("遞迴中序遍曆:");InOrderTraverse_Recur(T2);puts("");puts("非遞迴中序遍曆:");InorderTraverse_NoRecur(T2);puts("");puts("遞迴後序遍曆:");AfterOrderTraverse_Recur(T2);puts("");puts("非遞迴後序遍曆:");AfterOrderTraverse_NoRecur(T2);puts("");//DestoryBiTree(T2);//銷毀二叉樹}
[轉]資料結構 二叉樹的遍曆