記錄一下關於二叉樹的非遞歸遍歷
阿新 • • 發佈:2017-12-07
printf order type typedef print 課本 pos else if post
利用棧的非遞歸先序遍歷二叉樹:
額,這個是我自己寫的,可能算法有點啰嗦……
/********** 【題目】試利用棧及其基本操作寫出二叉樹T的非遞歸 的先序遍歷算法。 二叉鏈表類型定義: typedef struct BiTNode { TElemType data; struct BiTNode *lchild,*rchild; } BiTNode, *BiTree; 可用棧類型Stack的相關定義: typedef BiTree SElemType; // 棧的元素類型 Status InitStack(Stack &S); Status StackEmpty(Stack S); Status Push(Stack &S, SElemType e); Status Pop(Stack &S, SElemType &e); Status GetTop(Stack S, SElemType &e); **********/ /*思路:先訪問根節點,然後向左一直走下去,每走一個都是先訪問根節點,並沿途把右子樹入棧。向左走完後,開始搞棧裏面的元素, 對棧裏面的元素,先看它的右子樹存不存在,若存在則入棧,然後再對這個元素的右子樹也進行向左走操作*/ void traverseLeft(BiTree T, Stack &S, void (*visit)(TElemType)); Stack S; void PreOrder(BiTree T, void (*visit)(TElemType)) /* 使用棧,非遞歸先序遍歷二叉樹T, */ /* 對每個結點的元素域data調用函數visit */ { InitStack(S); BiTree tree2= T; BiTree treeTemp = tree2; while(treeTemp && treeTemp->data!=‘#‘) { //好吧做了後面的題後發現好像可以不用這個data=‘#‘,但懶得改了 visit(treeTemp->data); printf("visit the root:%c\n",treeTemp->data); traverseLeft(treeTemp->lchild, S, visit);//遍歷左邊的節點,並沿途將他們的右子樹入棧,遍歷後treeTemp指向最左邊那個子樹while(!StackEmpty(S)) { printf("get into the stack\n"); Pop(S, treeTemp); visit(treeTemp->data); printf("visit the stack of the rchild:%c\n",treeTemp->data); if(treeTemp->rchild && treeTemp->rchild->data!=‘#‘) { Push(S, treeTemp->rchild); } traverseLeft(treeTemp->lchild, S, visit); } treeTemp = tree2->rchild; tree2 = tree2->rchild; } } void traverseLeft(BiTree T, Stack &S, void (*visit)(TElemType)) { while(T && T->data!=‘#‘) { visit(T->data); printf("visit the lchild:%c\n",T->data); if(T->rchild && T->data!=‘#‘) { Push(S, T->rchild); if(!StackEmpty(S)) { printf("push %c into the stack\n",T->rchild->data); } } T = T->lchild; } }
利用棧實現非遞歸後序遍歷二叉樹:
這個是網上找的實現算法:
/********** 【題目】試利用棧及其基本操作寫出二叉樹T的非遞歸 的後序遍歷算法(提示:為分辨後序遍歷時兩次進棧的 不同返回點,需在指針進棧時同時將一個標誌進棧)。 二叉鏈表類型定義: typedef struct BiTNode { TElemType data; struct BiTNode *lchild,*rchild; } BiTNode, *BiTree; 可用棧類型Stack的相關定義: typedef struct { struct BiTNode *ptr; // 二叉樹結點的指針類型 int tag; // 0..1 } SElemType; // 棧的元素類型 Status InitStack(Stack &S); Status StackEmpty(Stack S); Status Push(Stack &S, SElemType e); Status Pop(Stack &S, SElemType &e); Status GetTop(Stack S, SElemType &e); **********/ void PostOrder(BiTree T, void (*visit)(TElemType)) /* 使用棧,非遞歸後序遍歷二叉樹T, */ /* 對每個結點的元素域data調用函數visit */ { SElemType a,b; //a可以說是主要遍歷這個樹的一個指針這樣的,b是主要用來處理從棧出來的東西 Stack s; a.ptr=T; while(a.ptr){ if(a.ptr->lchild&&a.ptr->rchild){ //如果有兩個孩子的話 a.tag=1; Push(s,a); //屬於1號 a.ptr=a.ptr->lchild; //走左孩子 } else if(a.ptr->lchild&&!a.ptr->rchild){ //如果只有左孩子的話 a.tag=0; //屬於0號 Push(s,a); a.ptr=a.ptr->lchild; //走左孩子 } else if(!a.ptr->lchild&&a.ptr->rchild){ //如果只有右孩子的話 a.tag=0; //屬於0號 Push(s,a); a.ptr=a.ptr->rchild; //走右孩子 } else if(!a.ptr->lchild&&!a.ptr->rchild) { //如果是葉子結點的話 (*visit)(a.ptr->data); //先訪問這個葉子結點 Pop(s,b); //然後就開始訪問棧裏面的東西了,出棧,用b來裝 if(b.tag==1) //如果棧裏面遲來的是個有兩個孩子的東西,說明剛剛它走的是左孩子,然後現在要走它的右孩子並把它變成tag為0 { b.tag=0; a.ptr=b.ptr->rchild; //走右孩子 Push(s,b); } else if(b.tag==0) //如果從棧出來的這個是只有一個孩子的,說明它的孩子已經訪問過了,因為棧裏的已經是往回走了嘛,它進去的時候如果只有一個孩子,那 //回去就說明它的孩子都被訪問過了 { a=b; //依然用a來走遍歷 while(a.tag==0&&!StackEmpty(s)) //如果棧未空且出來的元素都是tag為0的 { (*visit)(a.ptr->data); Pop(s,a); } if(a.tag==0&&StackEmpty(s)){ //如果棧裏面已經沒有元素了,就指向NULL,也就是遍歷結束 (*visit)(a.ptr->data); a.ptr=NULL; } else if(a.tag==1){ b=a; a.ptr=b.ptr->rchild; b.tag=0; Push(s,b); } } } } } //網上的答案:寫在函數體裏面就行了 /* SElemType a,b; Stack s; a.ptr=T; while(a.ptr){ if(a.ptr->lchild&&a.ptr->rchild){ //如果有兩個孩子的話 a.tag=1; Push(s,a); //屬於1號 a.ptr=a.ptr->lchild; //走左孩子 } else if(a.ptr->lchild&&!a.ptr->rchild){ //如果只有左孩子的話 a.tag=0; //屬於0號 Push(s,a); a.ptr=a.ptr->lchild; //走左孩子 } else if(!a.ptr->lchild&&a.ptr->rchild){ //如果只有右孩子的話 a.tag=0; //屬於0號 Push(s,a); a.ptr=a.ptr->rchild; //走右孩子 } else if(!a.ptr->lchild&&!a.ptr->rchild) { //如果是葉子結點的話 (*visit)(a.ptr->data); //先訪問這個葉子結點 Pop(s,b); //出棧,用b來裝 if(b.tag==1) //有兩個孩子的話 { b.tag=0; a.ptr=b.ptr->rchild; Push(s,b); } else if(b.tag==0) { a=b; while(a.tag==0&&!StackEmpty(s)) { (*visit)(a.ptr->data); Pop(s,a); } if(a.tag==0&&StackEmpty(s)){ (*visit)(a.ptr->data); a.ptr=NULL; } else if(a.tag==1){ b=a; a.ptr=b.ptr->rchild; b.tag=0; Push(s,b); } } } }
利用棧的非遞歸終須遍歷二叉樹在數據結構課本的p135上
記錄一下關於二叉樹的非遞歸遍歷