C++實現二叉樹的遞迴與非遞迴遍歷
阿新 • • 發佈:2019-02-07
#include<iostream>
#include<stdlib.h>
#include<stack>
#include<queue>
using namespace std;
typedef char ElemType;
//二叉樹的二叉連結串列結構,也就是二叉樹的儲存結構,1個數據域,2個指標域(分別指向左右孩子)
typedef struct BiTNode
{
ElemType data;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
//二叉樹的建立,按前序遍歷的方式建立二叉樹,當然也可以以中序或後序的方式建立二叉樹
void CreateBiTree(BiTree *T)
{
ElemType ch;
cin >> ch;
if (ch == '#')
*T = NULL; //保證是葉結點
else
{
*T = (BiTree)malloc(sizeof(BiTNode));
//if (!*T)
//exit(OVERFLOW); //記憶體分配失敗則退出。
(*T)->data = ch;//生成結點
CreateBiTree(&(*T)->lchild);//構造左子樹
CreateBiTree(&(*T)->rchild);//構造右子樹
}
}
//表示對遍歷到的結點資料進行的處理操作,此處操作是將樹結點前序遍歷輸出
void operation1(ElemType ch)
{
cout << ch << " ";
}
//此處在輸出的基礎上,並輸出層數
void operation2(ElemType ch, int level)
{
cout << ch << "在第" << level << "層" << " ";
}
//遞迴方式前序遍歷二叉樹
void PreOrderTraverse(BiTree T, int level)
{
if (T == NULL)
return;
/*此處表示對遍歷的樹結點進行的操作,根據你自己的要求進行操作,這裡只是輸出了結點的資料*/
operation1(T->data);
//operation2(T->data, level); //輸出了層數
PreOrderTraverse(T->lchild, level + 1);
PreOrderTraverse(T->rchild, level + 1);
}
//遞迴方式中序遍歷二叉樹
void InOrderTraverse(BiTree T,int level)
{
if(T==NULL)
return;
InOrderTraverse(T->lchild,level+1);
operation1(T->data);
//operation2(T->data, level); //輸出了層數
InOrderTraverse(T->rchild,level+1);
}
//遞迴方式後序遍歷二叉樹
void PostOrderTraverse(BiTree T,int level)
{
if(T==NULL)
return;
PostOrderTraverse(T->lchild,level+1);
PostOrderTraverse(T->rchild,level+1);
operation1(T->data);
//operation2(T->data, level); //輸出了層數
}
//非遞迴方式前序遍歷
/* 思路:將T入棧,遍歷左子樹;遍歷完左子樹返回時,棧頂元素應為T,出棧,再先序遍歷T的右子樹。*/
void PreOrder(BiTree T){
stack<BiTree> stack;
//p是遍歷指標
BiTree p = T;
//p不為空或者棧不空時迴圈
while (p || !stack.empty())
{
if (p != NULL)
{
//存入棧中
stack.push(p);
//對樹中的結點進行操作
operation1(p->data);
//遍歷左子樹
p = p->lchild;
}
else
{
//退棧
p = stack.top();
stack.pop();
//訪問右子樹
p = p->rchild;
}
}
}
//非遞迴中序遍歷
void InOrder(BiTree T)
{
stack<BiTree> stack;
//p是遍歷指標
BiTree p = T;
//p不為空或者棧不空時迴圈
while (p || !stack.empty())
{
if (p != NULL)
{
//存入棧中
stack.push(p);
//遍歷左子樹
p = p->lchild;
}
else
{
//退棧
p = stack.top();
operation1(p->data); //對樹中的結點進行操作
stack.pop();
//訪問右子樹
p = p->rchild;
}
}
}
//非遞迴後序遍歷
typedef struct BiTNodePost{
BiTree biTree;
char tag;
}BiTNodePost, *BiTreePost;
void PostOrder(BiTree T)
{
stack<BiTreePost> stack;
//p是遍歷指標
BiTree p = T;
BiTreePost BT;
//棧不空或者p不空時迴圈
while (p != NULL || !stack.empty())
{
//遍歷左子樹
while (p != NULL)
{
BT = (BiTreePost)malloc(sizeof(BiTNodePost));
BT->biTree = p;
//訪問過左子樹
BT->tag = 'L';
stack.push(BT);
p = p->lchild;
}
//左右子樹訪問完畢訪問根節點
while (!stack.empty() && (stack.top())->tag == 'R')
{
BT = stack.top();
//退棧
stack.pop();
BT->biTree;
cout<<BT->biTree->data<<" ";
}
//遍歷右子樹
if (!stack.empty())
{
BT = stack.top();
//訪問過右子樹
BT->tag = 'R';
p = BT->biTree;
p = p->rchild;
}
}
}
//層次遍歷
void LevelOrder(BiTree T)
{
BiTree p = T;
queue<BiTree> queue;
//根節點入隊
queue.push(p);
//佇列不空迴圈
// 迴圈使用入隊出隊操作
while (!queue.empty())
{
//對頭元素出隊
p = queue.front();
//訪問p指向的結點
operation1(p->data);
//退出佇列
queue.pop();
//左孩子不為空,將左孩子入隊
if (p->lchild != NULL)
{
queue.push(p->lchild);
}
//右孩子不空,將右孩子入隊
if (p->rchild != NULL)
{
queue.push(p->rchild);
}
}
}
int main()
{
int level = 1; //表層數
BiTree T = NULL;
cout << "請以前序遍歷的方式輸入擴充套件二叉樹:"; //類似輸入AB#D##C##
CreateBiTree(&T);// 建立二叉樹,沒有樹,怎麼遍歷
cout << "遞迴前序遍歷輸出為:" << endl;
PreOrderTraverse(T, level);//進行前序遍歷,其中operation1()和operation2()函式表示對遍歷的結點資料進行的處理操作
cout << endl;
cout << "遞迴中序遍歷輸出為:" << endl;
InOrderTraverse(T, level);
cout << endl;
cout << "遞迴後序遍歷輸出為:" << endl;
PostOrderTraverse(T, level);
cout << endl;
cout<<"非遞迴前序遍歷輸出為:"<<endl;
PreOrder(T);
cout<<endl;
cout<<"非遞迴前序遍歷輸出為:"<<endl;
InOrder(T);
cout<<endl;
cout<<"非遞迴前序遍歷輸出為:"<<endl;
PostOrder(T);
cout<<endl;
cout<<"層序遍歷輸出為:"<<endl;
LevelOrder(T);
cout<<endl;
return 0;
}