二叉樹的基本操作實現(建立、先序、中序、後序、層序)
[問題描述]
建立一棵二叉樹,試程式設計實現二叉樹的如下基本操作: 1. 按先序序列構造一棵二叉連結串列表示的二叉樹T; 2. 對這棵二叉樹進行遍歷:先序、中序、後序以及層次遍歷,分別輸出結點的遍歷序列;
[基本要求]
從鍵盤接受輸入(先序),以二叉連結串列作為儲存結構,建立二叉樹(以先序來建立),
[測試資料]
如輸入:ABC##DE#G##F###(其中#表示空格字元)則輸出結果為:
先序:ABCDEGF
中序:CBEGDFA
後序:CGEFDBA
層序:ABCDEFG
----------------------------------------------------------------我是分割線--------------------------------------------------------------------------------
【二叉樹定義】
二叉樹是n(n>=0)個結點所構成的集合,n=0時為空樹,n>0為非空樹。對於非空樹T:
1.有且僅有一個稱為 根 的結點;
2.除根節點外其餘結點分為兩個互不相交的子集T1,T2,分別稱為T的左子樹,右子樹
二叉樹與樹一樣具有遞迴性質,二叉樹每個結點至多兩顆子樹,子樹有左右之分,次序不可顛倒。
【儲存結構】
1.順序儲存結構
#define MAXSIZE 100
typedef TElemType SqBiTree[MAXSIZE];//0號單元儲存根節點,TElemType可換成自己需要的型別如char
SqBiTree bt;
2.鏈式儲存結構
typedef struct BiTNode { char data;//結點資料域 BiTNode *lchild, *rchild;//左右孩子指標 }BiTNode,*BiTree;
順序儲存結構只適用完全二叉樹,一般採用鏈式。
【先序建立二叉連結串列】
void CreateBiTree(BiTree&T)//先序遍歷的順序建立二叉表 { char ch; cin >> ch;//輸入的字串會進入緩衝區, if (ch == '#')//ch為字元型,(ch=="#")錯誤 T = NULL;//遞迴結束,建立空樹 else//遞迴建立二叉樹 { T = new BiTNode;//生成根節點 T->data = ch;//將ch賦值給資料域 CreateBiTree(T->lchild);//遞迴建立左子樹 CreateBiTree(T->rchild);//遞迴建立右子樹 } }
【先序遍歷】
void PreOrderTraverse(BiTree T)//先序遍歷
{
if (T)//若二叉樹非空
{
cout << T->data;//訪問根節點
PreOrderTraverse(T->lchild);//先序遍歷左子樹
PreOrderTraverse(T->rchild);//先序遍歷右子樹
}
}
先中後序類似,先序是根左右,中序左根右,後序左右根,只要改變訪問根節點順序就行,具體程式碼在下面。
【層序遍歷】
void SeqOrderTraverse(BiTree T)//層序遍歷
{
SqQueue q;
InitQueue(q);
EnQueue(q, T);
while (q.rear!=q.front)
{
BiTree root = OutQueue(q);
cout << root->data << " ";
if (root->lchild)
EnQueue(q, root->lchild);
if (root->rchild)
EnQueue(q, root->rchild);
}
cout << endl;
}
層序遍歷順序:ABCDEFG
每個結點遍歷都是 根-左-右 的順序,
A入隊後出隊,出隊時其左右孩子入隊,判斷左右孩子是否為空,如果非空,則入隊。其他結點類似。
-------------------------------------------------------------------我是分割線----------------------------------------------------------------------------------
【程式碼】
#include<iostream>
#define MAXSIZE 100
using namespace std;
typedef struct BiTNode
{
char data;
BiTNode *lchild, *rchild;
}BiTNode,*BiTree;
typedef struct SqQueue
{
BiTree*base;//儲存空間的基地址
int front;
int rear;
};
void InitQueue(SqQueue&q)//構造空佇列
{
q.base = new BiTree[MAXSIZE];
if (!q.base) exit(OVERFLOW);
q.front = q.rear = 0;
}
void EnQueue(SqQueue&q,BiTree&T)//入隊
{
q.base[q.rear] = T;
q.rear++;
}
BiTree OutQueue(SqQueue&q)
{
BiTree T;
T = q.base[q.front];
q.front++;
return T;
}
void CreateBiTree(BiTree&T)//先序遍歷的順序建立二叉表
{
char ch;
cin >> ch;//輸入的字串會進入緩衝區,
if (ch == '#')//ch為字元型,(ch=="#")錯誤
T = NULL;//遞迴結束,建立空樹
else//遞迴建立二叉樹
{
T = new BiTNode;//生成根節點
T->data = ch;//將ch賦值給資料域
CreateBiTree(T->lchild);//遞迴建立左子樹
CreateBiTree(T->rchild);//遞迴建立右子樹
}
}
void PreOrderTraverse(BiTree T)//先序遍歷
{
if (T)//若二叉樹非空
{
cout << T->data << " ";//訪問根節點
PreOrderTraverse(T->lchild);//先序遍歷左子樹
PreOrderTraverse(T->rchild);//先序遍歷右子樹
}
}
void InOrderTraverse(BiTree T)//中序遍歷
{
if (T)
{
InOrderTraverse(T->lchild);
cout << T->data << " ";
InOrderTraverse(T->rchild);
}
}
void PostOrderTraverse(BiTree T)//後序遍歷
{
if (T)
{
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
cout << T->data << " ";
}
}
void SeqOrderTraverse(BiTree T)//層序遍歷
{
SqQueue q;
InitQueue(q);
EnQueue(q, T);
while (q.rear!=q.front)
{
BiTree root = OutQueue(q);
cout << root->data << " ";
if (root->lchild)
EnQueue(q, root->lchild);
if (root->rchild)
EnQueue(q, root->rchild);
}
cout << endl;
}
int main()
{
BiTree T;
cout << "請輸入字串,#表空樹" << endl;
CreateBiTree(T);
cout << "先序輸出:";
PreOrderTraverse(T);
cout << endl;
cout << "中序輸出:";
InOrderTraverse(T);
cout << endl;
cout << "後序輸出:" ;
PostOrderTraverse(T);
cout << endl;
cout << "層序輸出:";
SeqOrderTraverse(T);
return 0;
}
【執行結果】