1. 程式人生 > >資料結構-----後序遍歷二叉樹非遞迴演算法(利用堆疊實現)

資料結構-----後序遍歷二叉樹非遞迴演算法(利用堆疊實現)

一、非遞迴後序遍歷演算法思想

後序遍歷的非遞迴演算法中節點的進棧次數是兩個,即每個節點都要進棧兩次,第二次退棧的時候才訪問節點。

第一次進棧時,在遍歷左子樹的過程中將"根"節點進棧,待左子樹訪問完後,回溯的節點退棧,即退出這個"根"節點,但不能立即訪問,只能藉助於這個"根"去找該"根"的右子樹,並遍歷這棵右子樹,直到該右子樹全部遍歷以後,再退出該"根"節點,並訪問它。

           所以為了記錄節點是第一次還是第二次進棧,就在堆疊資料元素的結構中增加一個數據項:進棧標誌。

                 (1)當節點非空時或堆疊非空時,執行(2),否則結束演算法;

           (2)

當節點指標非空時,節點的進棧標誌設為false,節點指標及進棧標誌進棧,然後將節點指向進棧節點的左子樹的根,重複(2),知道指標為空(最後一個進棧的是最左子樹),節點指標為空時,轉(3);

           (3)堆疊非空時,從堆疊中退出一個節點的指標。如果退出的節點的進棧標誌為true,說明該節點是第二次退棧,訪問該接點,並將指標強制設為空,準備下一次退棧,並轉(3),如果進棧標誌為false,說明該節點是第一次退棧,將進棧標誌設為true,然後將該節點指標及進棧標誌進棧,再將指標指向它的右子樹,轉(1)。

二、程式碼實現

#include<stdio.h>
#include<stdlib.h>

typedef char EType; 

struct BinaryTreeNode
{
	EType data;
	struct BinaryTreeNode *LChild;
	struct BinaryTreeNode *RChild;
};
typedef BinaryTreeNode BinaryTree;

typedef struct SType
{
	BinaryTreeNode *ptr;
	bool status;//進棧標誌
}SType;

typedef struct Stack
{
	SType *element;
	int top;
	int MaxSize;
}Stack;

void CreatStack(Stack &S,int MaxStackSize);
bool IsEmpty(Stack &S);
bool IsFull(Stack &S);
bool GetTop(Stack &S,SType &result);
bool Pop(Stack &S,SType &result);
bool Push(Stack &S,SType &x);
void CreatBiTree(BinaryTreeNode **BT);
void PostOrderNoRecursive(BinaryTreeNode *BT);

int main()
{
    BinaryTreeNode *BT = NULL;
	CreatBiTree(&BT);
	printf("後序遍歷二叉樹非遞迴演算法輸出為:");
	PostOrderNoRecursive(BT);
	printf("\n");
	return 0;
}

void CreatStack(Stack &S,int MaxStackSize)
{
	S.MaxSize = MaxStackSize;
	S.element = new SType[S.MaxSize];
	S.top = -1;
}

bool IsEmpty(Stack &S)
{
	if(S.top == -1)
		return true;
	return false;
}

bool IsFull(Stack &S)
{
	if(S.top >= S.MaxSize-1)
		return true;
	return false;
}

bool GetTop(Stack &S,SType &result)
{
	if(IsEmpty(S))
		return false;
	result = S.element[S.top];
	return true;
}

bool Pop(Stack &S,SType &result)
{
	if(IsEmpty(S))
		return false;
	result = S.element[S.top];
	S.top--;
	return true;
}

bool Push(Stack &S,SType &x)
{
    if(IsFull(S))
		return false;
	S.top++;
	S.element[S.top] = x;
	return true;
}

void CreatBiTree(BinaryTreeNode **BT)
{
	EType tem;
	
	scanf("%c",&tem);
	if(' ' == tem)
	{
	    *BT = NULL;
	}
	else
	{
		*BT = new BinaryTreeNode;
		(*BT)->data = tem;
		CreatBiTree(&(*BT)->LChild);
        CreatBiTree(&(*BT)->RChild);
	}
}

void PostOrderNoRecursive(BinaryTreeNode *BT)
{
	Stack S;
	SType temp;
	BinaryTreeNode *p = BT;
	int MaxStackSize = 50;
	CreatStack(S,MaxStackSize);

	while(p || !IsEmpty(S))
	{
		if(p)//找最左子樹
		{
			temp.status = false;//設定該節點是第一次進棧
			temp.ptr = p;
			Push(S,temp);
			p = p->LChild;
		}
		else
		{
			if(!IsEmpty(S))
			{
				Pop(S,temp);
				p = temp.ptr;
				if(temp.status)//若該節點是第二次退棧,就訪問,並設定p=0繼續退棧
				{
                    printf("%c\t",p->data);
					p = NULL;
				}	
			    else
				{
					temp.status = true;//設定該節點是第二次進棧
					Push(S,temp);
					p = p->RChild;//遍歷該節點的右子樹
				}
			}
		}
	}
}

三、效果展示

建立這樣一顆二叉樹


所以按照前序遍歷輸入應該是:“AB_D_ _CE_ _ _”(其中“_”代表空格)

那麼執行結果為: