樹和二叉樹1——鏈式二叉樹基礎
阿新 • • 發佈:2018-12-09
本文程式碼基於【資料結構】【嚴蔚敏】【清華大學】
包含了大多數二叉樹的基本操作
1.準備部分的程式碼:
用c++其實就是用了個max()函式
#include <stdio.h>
#include <stdlib.h>//malloc和exit函式所需標頭檔案
#include <iostream>
using namespace std;
#define MaxSize 100
typedef char ElemType;
當然也可以改成C,記得加上一個自定義max函式
#include <stdio.h>
#include <stdlib.h>//malloc和exit函式所需標頭檔案
#define MaxSize 100
typedef char ElemType;
int max(int a,int b)
{
return a>b?a:b;
}
2.構造二叉樹結點
包括資料域和左右孩子指標
typedef struct BiTNode {
ElemType data;
struct BiTNode *lchild, *rchild; // 左右孩子指標
} BiTNode, *BiTree;
3.先序輸入二叉樹中結點的值
一些必要的註解:
①TheBinaryTree為結構體指標,指向結構體
BiTree TheBinaryTree=BiTNode *TheBinaryTree
②T為TheBinaryTree的引用,是結構體指標
BiTree &T= BiTNode *&T
③BT是結構指標TheBinaryTree的指標,BT指向結構體指標
BiTNode **BT=BiTree *BT
所有有兩種 CreateBiTree寫法:
void CreateBiTree(BiTNode* &T)//BiTree &T== BiTNode* &T
{
// 按先序次序輸入二叉樹中結點的值
// 構造二叉連結串列表示的二叉樹T。
ElemType ch;
static int i = 0;
char pch[] = "ABC$$DE$G$$F$$$"; // 欲產生的 先序序列。圖6.8(b)
ch = pch[i++];
if(ch == '$') // 空樹
T = NULL;
else {
T = (BiTree)malloc(sizeof(BiTNode));
if(!T) // 檢測是否申請結點成功
exit(-1);
T->data = ch; // 生成根結點
CreateBiTree(T->lchild); // 構造左子樹
CreateBiTree(T->rchild); // 構造右子樹
}
}
void CreateBiTree_Pointer(BiTNode **BT)//BiTree *BT BT此時為指標的指標, BiTNode* *BT==BiTree *BT
{
// 按先序次序輸入二叉樹中結點的值
// 構造二叉連結串列表示的二叉樹BT。
ElemType ch;
static int i = 0;
char pch[] = "AB D C "; // 欲產生的二叉樹 先序序列
ch = pch[i++];
//scanf("%c",&ch);
if(ch == ' ') // 空樹
*BT = NULL;
else {
*BT = (BiTree)malloc(sizeof(BiTNode));
if(!*BT) // 檢測是否申請結點成功
exit(-1);
(*BT)->data = ch; // 生成根結點
CreateBiTree_Pointer(&(*BT)->lchild); // 構造左子樹
CreateBiTree_Pointer(&(*BT)->rchild); // 構造右子樹
}
}
4.三種遍歷(遞迴)
// 中序遍歷
void InOrderTraversal(BiTree BT)
{
if(BT) {
InOrderTraversal(BT->lchild);
printf("%c ", BT->data);
InOrderTraversal(BT->rchild);
}
}
//先序遍歷
void PreOrderTraversal(BiTree BT)
{
if(BT) {
printf("%c ", BT->data);
PreOrderTraversal(BT->lchild);
PreOrderTraversal(BT->rchild);
}
}
// 後序遍歷
void PostOrderTraversal(BiTree BT)
{
if(BT) {
PostOrderTraversal(BT->lchild);
PostOrderTraversal(BT->rchild);
printf("%c ", BT->data);
}
}
5.中序遍歷非遞迴遍歷演算法(關於其他遍歷演算法之後還會寫文章提到)
// 中序遍歷非遞迴遍歷演算法
//利用壓棧
void InOrderTraversal_NoRecursion(BiTNode *T)
{
BiTNode *Stack[MaxSize];//BiTree Stack[MaxSize]
int top = -1;
while(T || (top != -1)) {
while(T) { // 一直向左並將沿途結點壓入堆疊
Stack[++top] = T;
T = T->lchild;
}
if(top != -1) {
T = Stack[top--]; // 結點彈出堆疊
printf("%c ", T->data); //(訪問)列印結點
T = T->rchild; // 轉向右子樹
}
}
}
6.輸出葉子結點值
// 輸出二叉樹中的葉子結點。
void PreOrderPrintLeaves(BiTree BT)
{
if(BT) {
if(BT->lchild == NULL && BT->rchild == NULL)
printf("%c ", BT->data);
PreOrderPrintLeaves(BT->lchild);
PreOrderPrintLeaves(BT->rchild);
}
}
7.輸出深度
// 求二叉樹的深度
int Binary_tree_Deepness(BiTNode *T)
{
if(T == NULL)
return 0;
else
if(T->lchild == NULL && T->rchild == NULL)
return 1;
else
return 1 + max(Binary_tree_Deepness(T->lchild), Binary_tree_Deepness(T->rchild));
}
//表示形式2
int Binary_tree_Deepness_Post(BiTNode *T)
{
int h1, h2;
if(T == NULL)
return 0;
h1 = Binary_tree_Deepness_Post(T->lchild);
h2 = Binary_tree_Deepness_Post(T->rchild);
if(T->lchild == NULL && T->rchild == NULL)
return 1;
else
return 1 + max(h1, h2);
}
8.求度為 2 的結點數
//求二叉樹的度為 2 的結點數演算法
int BT_CountDegree2(BiTNode *T)
{
int n1, n2;
if (T == NULL)
return 0;
else {
n1 = BT_CountDegree2(T->lchild);
n2 = BT_CountDegree2(T->rchild);
if (T->lchild != NULL && T->rchild != NULL)
return 1 + n1 + n2;
else
return n1 + n2;
}
}
9.構造和銷燬
PS:完整程式碼中沒用到構造和銷燬,Init某種意義上可有可無,destroy最好還是加一下
Status InitBiTree(BiTree &T)
{
// 操作結果: 構造空二叉樹T
T = NULL;
return OK;
}
void DestroyBiTree(BiTree &T)
{
// 初始條件: 二叉樹T存在。操作結果: 銷燬二叉樹T
if(T) { // 非空樹
if(T->lchild) // 有左孩子
DestroyBiTree(T->lchild); // 銷燬左孩子子樹
if(T->rchild) // 有右孩子
DestroyBiTree(T->rchild); // 銷燬右孩子子樹
free(T); // 釋放根結點
T = NULL; // 空指標賦0
}
}
10.主函式
int main()
{
BiTree TheBinaryTree;//BiTNode *TheBinaryTree
printf("\n建立二叉樹,請輸入結點值系列:\n");
CreateBiTree(TheBinaryTree);//TheBinaryTree為結構體指標
printf("\n先序遍歷序列:\n");
PreOrderTraversal(TheBinaryTree);
printf("\n中序遍歷序列:\n");
InOrderTraversal(TheBinaryTree);
printf("\n中序遍歷序列 - 中序遍歷非遞迴演算法:\n");
InOrderTraversal_NoRecursion(TheBinaryTree);
printf("\n後序遍歷序列:\n");
PostOrderTraversal(TheBinaryTree);
printf("\n二叉樹的深度為:\n");
//printf("%d",Binary_tree_Deepness_Post(TheBinaryTree));
printf("%d", Binary_tree_Deepness(TheBinaryTree));
printf("\n葉子結點為:\n");
PreOrderPrintLeaves(TheBinaryTree);
printf("\n度為2的結點個數為:\n");
printf("%d", BT_CountDegree2(TheBinaryTree));
return 1;
}
便於複製完整原始碼如下:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
#define MaxSize 100
typedef char ElemType;
typedef struct BiTNode {
ElemType data;
struct BiTNode *lchild, *rchild; // 左右孩子指標
} BiTNode, *BiTree;
//TheBinaryTree為結構體指標,指向結構體
//BiTree TheBinaryTree==BiTNode *TheBinaryTree
//BiTree &T== BiTNode* &T T為TheBinaryTree的引用,是結構體指標
//BiTNode **BT==BiTree *BT BT是結構指標TheBinaryTree的指標, BT指向結構體指標
void CreateBiTree(BiTNode* &T)//BiTree &T== BiTNode* &T
{
// 按先序次序輸入二叉樹中結點的值
// 構造二叉連結串列表示的二叉樹T。
ElemType ch;
static int i = 0;
char pch[] = "ABC$$DE$G$$F$$$"; // 欲產生的 先序序列。圖6.8(b)
ch = pch[i++];
if(ch == '$') // 空樹
T = NULL;
else {
T = (BiTree)malloc(sizeof(BiTNode));
if(!T) // 檢測是否申請結點成功
exit(-1);
T->data = ch; // 生成根結點
CreateBiTree(T->lchild); // 構造左子樹
CreateBiTree(T->rchild); // 構造右子樹
}
}
void CreateBiTree_Pointer(BiTNode **BT)//BiTree *BT BT此時為指標的指標, BiTNode* *BT==BiTree *BT
{
// 按先序次序輸入二叉樹中結點的值
// 構造二叉連結串列表示的二叉樹BT。
ElemType ch;
static int i = 0;
char pch[] = "AB D C "; // 欲產生的二叉樹 先序序列
ch = pch[i++];
//scanf("%c",&ch);
if(ch == ' ') // 空樹
*BT = NULL;
else {
*BT = (BiTree)malloc(sizeof(BiTNode));
if(!*BT) // 檢測是否申請結點成功
exit(-1);
(*BT)->data = ch; // 生成根結點
CreateBiTree_Pointer(&(*BT)->lchild); // 構造左子樹
CreateBiTree_Pointer(&(*BT)->rchild); // 構造右子樹
}
}
// 中序遍歷
void InOrderTraversal(BiTree BT)
{
if(BT) {
InOrderTraversal(BT->lchild);
printf("%c ", BT->data);
InOrderTraversal(BT->rchild);
}
}
//先序遍歷
void PreOrderTraversal(BiTree BT)
{
if(BT) {
printf("%c ", BT->data);
PreOrderTraversal(BT->lchild);
PreOrderTraversal(BT->rchild);
}
}
// 後序遍歷
void PostOrderTraversal(BiTree BT)
{
if(BT) {
PostOrderTraversal(BT->lchild);
PostOrderTraversal(BT->rchild);
printf("%c ", BT->data);
}
}
// 中序遍歷非遞迴遍歷演算法
//利用壓棧
void InOrderTraversal_NoRecursion(BiTNode *T)
{
BiTNode *Stack[MaxSize];//BiTree Stack[MaxSize]
int top = -1;
while(T || (top != -1)) {
while(T) { // 一直向左並將沿途結點壓入堆疊
Stack[++top] = T;
T = T->lchild;
}
if(top != -1) {
T = Stack[top--]; // 結點彈出堆疊
printf("%c ", T->data); //(訪問)列印結點
T = T->rchild; // 轉向右子樹
}
}
}
// 輸出二叉樹中的葉子結點。
void PreOrderPrintLeaves(BiTree BT)
{
if(BT) {
if(BT->lchild == NULL && BT->rchild == NULL)
printf("%c ", BT->data);
PreOrderPrintLeaves(BT->lchild);
PreOrderPrintLeaves(BT->rchild);
}
}
// 求二叉樹的深度
int Binary_tree_Deepness(BiTNode *T)
{
if(T == NULL)
return 0;
else
if(T->lchild == NULL && T->rchild == NULL)
return 1;
else
return 1 + max(Binary_tree_Deepness(T->lchild), Binary_tree_Deepness(T->rchild));
}
int Binary_tree_Deepness_Post(BiTNode *T)
{
int h1, h2;
if(T == NULL)
return 0;
h1 = Binary_tree_Deepness_Post(T->lchild);
h2 = Binary_tree_Deepness_Post(T->rchild);
if(T->lchild == NULL && T->rchild == NULL)
return 1;
else
return 1 + max(h1, h2);
}
//求二叉樹的度為 2 的結點數演算法
int BT_CountDegree2(BiTNode *T)
{
int n1, n2;
if (T == NULL)
return 0;
else {
n1 = BT_CountDegree2(T->lchild);
n2 = BT_CountDegree2(T->rchild);
if (T->lchild != NULL && T->rchild != NULL)
return 1 + n1 + n2;
else
return n1 + n2;
}
}
int main()
{
BiTree TheBinaryTree;//BiTNode *TheBinaryTree
printf("\n建立二叉樹,請輸入結點值系列:\n");
CreateBiTree(TheBinaryTree);//TheBinaryTree為結構體指標
printf("\n先序遍歷序列:\n");
PreOrderTraversal(TheBinaryTree);
printf("\n中序遍歷序列:\n");
InOrderTraversal(TheBinaryTree);
printf("\n中序遍歷序列 - 中序遍歷非遞迴演算法:\n");
InOrderTraversal_NoRecursion(TheBinaryTree);
printf("\n後序遍歷序列:\n");
PostOrderTraversal(TheBinaryTree);
printf("\n二叉樹的深度為:\n");
//printf("%d",Binary_tree_Deepness_Post(TheBinaryTree));
printf("%d", Binary_tree_Deepness(TheBinaryTree));
printf("\n葉子結點為:\n");
PreOrderPrintLeaves(TheBinaryTree);
printf("\n度為2的結點個數為:\n");
printf("%d", BT_CountDegree2(TheBinaryTree));
return 1;
}