#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