拼題A 二叉樹的非遞歸遍歷
題目描述:
本題要求用非遞歸的方法實現對給定二叉樹的 3 種遍歷。
函數接口定義:
void InorderTraversal( BinTree BT );
void PreorderTraversal( BinTree BT );
void PostorderTraversal( BinTree BT );
其中BinTree結構定義如下:
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
int flag;
};
要求 3 個函數分別按照訪問順序打印出結點的內容,格式爲一個空格跟着一個字符。
此外,裁判程序中給出了堆棧的全套操作,可以直接調用。
裁判測試程序樣例:
#include <stdio.h>
#include <stdlib.h>
typedef enum { false, true } bool;
typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
int flag;
};
/*------堆棧的定義-------*/
typedef Position SElementType;
typedef struct SNode *PtrToSNode;
struct SNode {
SElementType Data;
PtrToSNode Next;
};
typedef PtrToSNode Stack;
/* 裁判實現,細節不表 */
Stack CreateStack();
bool IsEmpty( Stack S );
bool Push( Stack S, SElementType X );
SElementType Pop( Stack S ); /* 刪除並僅返回S的棧頂元素 */
SElementType Peek( Stack S );/* 僅返回S的棧頂元素 */
/*----堆棧的定義結束-----*/
BinTree CreateBinTree(); /* 裁判實現,細節不表 */
void InorderTraversal( BinTree BT );
void PreorderTraversal( BinTree BT );
void PostorderTraversal( BinTree BT );
int main()
{
BinTree BT = CreateBinTree();
printf("Inorder:"); InorderTraversal(BT); printf("\n");
printf("Preorder:"); PreorderTraversal(BT); printf("\n");
printf("Postorder:"); PostorderTraversal(BT); printf("\n");
return 0;
}
/* 你的代碼將被嵌在這裏 */
輸入樣例:
如圖
輸出樣例:
Inorder: D B E F A G H C I
Preorder: A B D F E C G H I
Postorder: D E F B H G I C A
其實這題用遞歸也能過hhhh,但是既然題目讓用非遞歸,還是老老實實地用非遞歸寫叭~~
前序和中序遍歷看過浙大的慕課以後應該很容易就寫出來了,但是後序遍歷就要動點腦子辣~
難點在於根什麼時候輸出,觀察一下後序遍歷的特點可以發現,最先輸出的一定是葉子結點,即左右子樹都爲空的結點,那麼我們一旦輸出了一個結點, 就讓它的父結點的左或右子樹(是左還是右要判斷一下)爲空,這樣我們輸出的條件就只需判斷一下該結點的左右子樹是不是都爲空就行辣,當然,最開始我們要不停地遍歷左子樹~
可能說的不太清楚(表達能力太差啦555),還是看看代碼吧~
void InorderTraversal( BinTree BT ) // 中序遍歷
{
BinTree T = BT;
Stack S = CreateStack();
while(T || !IsEmpty(S))
{
while(T)
{
Push(S, T);
T = T->Left;
}
if(!IsEmpty(S))
{
T = Pop(S);
printf(" %c", T->Data);
T = T->Right;
}
}
}
void PreorderTraversal( BinTree BT ) // 前序遍歷
{
BinTree T = BT;
Stack S = CreateStack();
while(T || !IsEmpty(S))
{
while(T)
{
printf(" %c", T->Data);
Push(S, T);
T = T->Left;
}
if(!IsEmpty(S))
{
T = Pop(S);
T = T->Right;
}
}
}
void PostorderTraversal( BinTree BT ) // 後序遍歷
{
BinTree T = BT;
Stack S = CreateStack();
while(T || !IsEmpty(S))
{
while(T)
{
Push(S, T);
T = T->Left;
}
if(!IsEmpty(S))
{
T = Peek(S);
if(T->Left == NULL && T->Right == NULL) // 葉結點
{
T = Pop(S);
printf(" %c", T->Data);
if(!IsEmpty(S)) // 記得判斷一下棧是否爲空,剛開始忘了結果一直段錯誤。。
{
BinTree t = Peek(S);
// 判斷是讓左子樹爲空還是右子樹爲空
if(t->Left == T)
t->Left = NULL;
else if(t->Right == T)
t->Right = NULL;
}
}
T = T->Right;
}
}
}
沒仔細看題。。。。BinTree結構體裏面竟然還有一個flag,,,可能後序遍歷用一下這個flag會好寫一些???但我也還是沒想到怎麼用這個flag。。。反正不用也能過hhhhh