二叉樹的遍歷操作

#include<iostream>
#include<queue>
#include<stack>
using namespace std;

//定義二叉樹的節點數據類型
struct BTNode{
	char data;
	BTNode *left_child;
	BTNode *right_child;
};

class BinaryTree
{
private:
	BTNode *BT;
public:
	BinaryTree(){BT = NULL;}//構造函數,將根節點置空
	~BinaryTree();//銷燬二叉樹

	void CreateBTree(){	cout<<"輸入數據,以‘#'代表空指針:"<<endl;Create(BT);}
	void Create(BTNode* &ptNode);//遞歸創建二叉樹

	void DisplayLevelBTree();//層次遍歷二叉樹

	void PreTraBTree(){cout<<"遞歸先序遍歷:";PreTraBTree(BT);cout<<endl;}
	void InTraBTree(){cout<<"遞歸中序遍歷:";InTraBTree(BT);cout<<endl;}
	void PostTraBTree(){cout<<"遞歸後序遍歷:";PostTraBTree(BT);cout<<endl;}
	void PreTraBTree(BTNode* ptNode);//遞歸算法:先序遍歷
	void InTraBTree(BTNode* ptNode);//遞歸算法:中序遍歷
	void PostTraBTree(BTNode* ptNode);//遞歸算法:後序遍歷

	void PreTraBTree_N();//非遞歸算法:先序遍歷
	void InTraBTree_N();//非遞歸算法:中序遍歷
	void PostTraBTree_N();//非遞歸算法:後序遍歷

};

//遞歸創建二叉樹
void BinaryTree::Create(BTNode* &ptNode)
{
	char data;
	cin>>data;
	if(data == '#')
		ptNode = NULL;
	else
	{
		ptNode = new BTNode;
		if(ptNode == NULL)
			cout<<"申請內存失敗!"<<endl;
		ptNode->data = data;
		Create(ptNode->left_child);
		Create(ptNode->right_child);
	}
}

//層次遍歷二叉樹
/*
	** 算法概述
	層次遍歷二叉樹,關鍵要用到隊列,
	父結點一出,就要判斷子結點是否爲空,非空則馬上進入隊列
*/
void BinaryTree::DisplayLevelBTree()
{
	cout<<"層次遍歷二叉樹:"<<endl;
	queue<BTNode *> que;
	if(BT!=NULL)
		que.push(BT);
	else
		cout<<"樹爲空!"<<endl;
	BTNode *pnode;
	while(!que.empty())
	{
		pnode = que.front();
		cout<<pnode->data<<' ';
		que.pop();
		if(pnode->left_child)
			que.push(pnode->left_child);
		if(pnode->right_child)
			que.push(pnode->right_child);
	}
	cout<<endl;

}

//遞歸算法:先序遍歷
void BinaryTree::PreTraBTree(BTNode* ptNode)
{
	if(ptNode)
	{
		cout<<ptNode->data<<' ';
		PreTraBTree(ptNode->left_child);
		PreTraBTree(ptNode->right_child);
	}
}
//遞歸算法:中序遍歷
void BinaryTree::InTraBTree(BTNode* ptNode)
{
	if(ptNode)
	{
		InTraBTree(ptNode->left_child);
		cout<<ptNode->data<<' ';
		InTraBTree(ptNode->right_child);
	}
}
//遞歸算法:後序遍歷
void BinaryTree::PostTraBTree(BTNode* ptNode)
{
	if(ptNode)
	{
		PostTraBTree(ptNode->left_child);
		PostTraBTree(ptNode->right_child);
		cout<<ptNode->data<<' ';
	}
}

//非遞歸算法:先序遍歷
/*
	** 算法概述
	對於任一節點P,
	1)輸出節點P,然後將其入棧,再看P的左孩子是否爲空;
	2)若P的左孩子不爲空,則置P的左孩子爲當前節點,重複1)的操作;
	3)若P的左孩子爲空,則將棧頂節點出棧,但不輸出,
	   並將出棧節點的右孩子置爲當前節點,看其是否爲空;
	4)若不爲空,則循環至1)操作;
	5)如果爲空,則繼續出棧,但不輸出,
	   同時將出棧節點的右孩子置爲當前節點,
	   看其是否爲空,重複4)和5)操作;
	6)直到當前節點P爲NULL並且棧空,遍歷結束。
*/
void BinaryTree::PreTraBTree_N()
{
	cout<<"非遞歸先序遍歷:";
	stack<BTNode *> bt_stack;//利用棧來實現
	BTNode* p_cur = BT;//當前節點,開始的時候指向根節點
	while( p_cur || !bt_stack.empty())//當前節點P爲NULL並且棧空,遍歷結束
	{
		cout<<p_cur->data<<' ';//首先輸出當前數據
		bt_stack.push(p_cur);//當前節點入棧
		p_cur = p_cur->left_child;//入棧的時候操作左孩子
		while(!p_cur && !bt_stack.empty())//當前節點爲空
		{
			p_cur = bt_stack.top();
			bt_stack.pop();
			p_cur = p_cur->right_child;//出棧的時候操作右孩子
		}

	}
	cout<<endl;
}
//非遞歸算法:中序遍歷
/*
	** 算法概述
	對於任一節點P,
	1)若P的左孩子不爲空,則將P入棧並將P的左孩子置爲當前節點,
	   然後再對當前節點進行相同的處理;
	2)若P的左孩子爲空,則輸出P節點,而後將P的右孩子置爲當前節點,
	   看其是否爲空;
	3)若不爲空,則重複1)和2)的操作;
	4)若爲空,則執行出棧操作,輸出棧頂節點,
	   並將出棧的節點的右孩子置爲當前節點,看其是否爲空,
	   重複3)和4)的操作;
	5)直到當前節點P爲NULL並且棧爲空,則遍歷結束。
*/
void BinaryTree::InTraBTree_N()
{
	cout<<"非遞歸中序遍歷:";
	stack<BTNode *> bt_stack;
	BTNode* p_cur = BT;
	while(p_cur || !bt_stack.empty())
	{
		if(p_cur->left_child)
		{
			bt_stack.push(p_cur);
			p_cur = p_cur->left_child;
		}
		else
		{
			cout<<p_cur->data<<' ';
			p_cur = p_cur->right_child;
			while(!p_cur && !bt_stack.empty())
			{
				p_cur = bt_stack.top();
				cout<<p_cur->data<<' ';
				bt_stack.pop();
				p_cur = p_cur->right_child;
			}
		}
	}
	cout<<endl;
}
//非遞歸算法:後序遍歷
void BinaryTree::PostTraBTree_N()
{
}

int main()
{
	BinaryTree *b_tree = new BinaryTree();
	b_tree->CreateBTree();
	b_tree->DisplayLevelBTree();
	b_tree->PreTraBTree();
	b_tree->InTraBTree();
	b_tree->PostTraBTree();
	b_tree->PreTraBTree_N();
	b_tree->InTraBTree_N();
	return 0;
}

顯然,對一個含有n個節點的二叉樹進行遍歷,其時間複雜度爲O(n),所需輔助空間爲遍歷過程中棧的最大容量,即樹的深度,最壞情況爲n,因此其空間複雜的也爲O(n)。

參考博文:http://blog.csdn.net/pi9nc/article/details/13008511


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章