一、树介绍
1)树的定义
树 (Tree) 是n(n≥0) 个结点的有限集。
若n = 0,称为空树;
若n > 0,则它满足如下两个条件:
(1)有且仅有一个特定的称为(Root)的结点;
(2)其余结点可分为m(m≥0)个互不相交的有限集 T1,T2,T3,…,Tm,其中每一个集合本身又是一棵树,并称为根的子树(SubTree)。
2)树的表示方式
3)树的基本术语
1、树的深度
2、有序树和无序树
3、森林
4)树结构于线性结构的比较
二、二叉树
1)二叉树的定义
为何要重点研究每结点最多只有两个 “又” 的树?
- 二叉树的结构最简单,规律性最强;
- 可以证明,所有树都能转为唯一对应的不失一般性。
普通树(多叉树)若不转化为二叉树,则运算很难实现。
二叉树在树结构的应用中起着非常重要的作用,因为对二叉的许多操作算法简单,而任何树都可以与二叉树相互转换,这样就解决了树的存储结构及其运算中存在的复杂性。
二叉树是 n(n≥0)个结点的有限集,它或者是空集(n =0),或者由一个根结点及两棵互不相交的分别称作这个根的左子树和右子树的二又树组成。
特点:
- 每个结点最多有俩孩子(二又树中不存在度大于 2 的结点)。
- 子树有左右之分,其次序不能颠倒。
- 二叉树可以是空集合,根可以有空的左子树或空的右子树。
注意:
二叉树不是树的特殊情况,它们是两个概念。
- 二叉树结点的子树要区分左子树和右子树,即使只有一棵子树行区分,说明它是左子树,还是右子树。
- 树当结点只有一个孩子时,就无须区分它是左还是右的次序。因此二者是不同的。这是二又树与树的最主要的差别。
(也就是二叉树每个结点位置或者说次序都是固定的,可以是空,但是不可以说它没有位置,而树的结点位置是相对于别的结点来说的,
没有别的结点时,它就无所谓左右了)
2)二叉树的5种基本形态
注意:虽然二叉树与树概念不同,但有关树的基本术语对二叉树都适用。
3)二叉树的抽象数据类型定义
4)二叉树的性质
1、性质1
第 i 层至少有1个结点
2、性质2
深度为k时至少有k个结点
3、性质3
三、二叉树的性质和存储结构
1)满二叉树
- 满二叉树在同样深度的二叉树中结点个数最多
- 满二叉树在同样深度的二叉树中叶子结点个数最多
2)完全二叉树
特点:
- 1.叶子只可能分布在层次最大的两层上。
- 2.对任一结点,如果其右子树的最大层次为i。
则其左子树的最大层次必为 i 或 i + 1。
3)完全二叉树性质
1、性质4
2、性质5
性质 5:如果对一棵有 ,个结点的完全二叉树(深度为 [log2n] + 1)的结点按层序编号(从第1层到第[log2n]+1层,每层从左到右),则对任一结点 i (1≤/n),有:
四、二叉树顺序存储结构
1)结构定义
#define MAXTSIZE 100
typedef TElemType SqBiTree[MAXSIZE]
SqBiTree bt;
2)总体代码实现
#include <iostream>
using namespace std;
#define MAXSIZE 100 // 数组的最大容量
// 二叉树节点的数据类型
typedef char TElemType;
// 顺序存储的二叉树
typedef TElemType SqBiTree[MAXSIZE];
// 初始化二叉树
void InitSqBiTree(SqBiTree bt) {
for (int i = 0; i < MAXSIZE; ++i) {
bt[i] = '#'; // 使用'#'表示空节点
}
}
// 创建二叉树
void CreateSqBiTree(SqBiTree& bt, const char* str) {
int i = 0;
while (str[i] != '\0') {
if (str[i] == '#') { // 如果是空节点
bt[++bt[0]] = '#';
}
else {
bt[++bt[0]] = str[i];
}
++i;
}
}
// 前序遍历
void PreOrder(SqBiTree bt, int index) {
if (index > bt[0] || bt[index] == '#') return;
cout << bt[index] << " "; // 访问当前节点
PreOrder(bt, 2 * index); // 递归访问左子树
PreOrder(bt, 2 * index + 1); // 递归访问右子树
}
// 中序遍历
void InOrder(SqBiTree bt, int index) {
if (index > bt[0] || bt[index] == '#') return;
InOrder(bt, 2 * index); // 递归访问左子树
cout << bt[index] << " "; // 访问当前节点
InOrder(bt, 2 * index + 1); // 递归访问右子树
}
// 后序遍历
void PostOrder(SqBiTree bt, int index) {
if (index > bt[0] || bt[index] == '#') return;
PostOrder(bt, 2 * index); // 递归访问左子树
PostOrder(bt, 2 * index + 1); // 递归访问右子树
cout << bt[index] << " "; // 访问当前节点
}
// 层次遍历
void LevelOrder(SqBiTree bt) {
for (int i = 1; i <= bt[0]; ++i) {
if (bt[i] != '#') {
cout << bt[i] << " ";
}
}
cout << endl;
}
int main() {
SqBiTree bt;
InitSqBiTree(bt);
// 创建二叉树,例如:"AB#C##D#E##F"
// 这里假设输入字符串中的'#'表示空节点
const char* treeStr = "AB#C##D#E##F";
bt[0] = 0; // 初始化根节点位置
CreateSqBiTree(bt, treeStr);
cout << "前序排序: ";
LevelOrder(bt);
cout << "中序排序: ";
PreOrder(bt, 1);
cout << endl;
cout << "后序排序: ";
InOrder(bt, 1);
cout << endl;
cout << "层次排序: ";
PostOrder(bt, 1);
cout << endl;
return 0;
}
五、二叉树链式存储结构
1)结构定义
typedef struct BiNode {
TElemType data;
struct BiNode* lchild, * rchild; //左右孩子指针
}BiNode, * BiTree;
2)总体代码实现
#include <iostream>
#include <queue>
using namespace std;
// 二叉树节点的数据类型
typedef char TElemType;
// 二叉树节点定义
typedef struct BiNode {
TElemType data;
struct BiNode* lchild, * rchild; // 左右孩子指针
} BiNode, * BiTree;
// 创建新节点
BiNode* CreateNode(TElemType data) {
BiNode* newNode = new BiNode;
newNode->data = data;
newNode->lchild = nullptr;
newNode->rchild = nullptr;
return newNode;
}
// 创建二叉树
BiTree CreateBiTree() {
// 创建根节点
BiTree A = CreateNode('A');
BiTree B = CreateNode('B');
BiTree C = CreateNode('C');
BiTree D = CreateNode('D');
BiTree E = CreateNode('E');
BiTree F = CreateNode('F');
BiTree G = CreateNode('G');
BiTree H = CreateNode('H');
BiTree I = CreateNode('I');
// 构建二叉树
A->lchild = B; A->rchild = C;
B->lchild = D; B->rchild = E;
C->lchild = F; C->rchild = G;
D->lchild = H; D->rchild = nullptr;
E->lchild = I; E->rchild = nullptr;
F->lchild = nullptr; F->rchild = nullptr;
G->lchild = nullptr; G->rchild = nullptr;
H->lchild = nullptr; H->rchild = nullptr;
I->lchild = nullptr; I->rchild = nullptr;
return A;
}
// 前序遍历(根 -> 左子树 -> 右子树)
void PreOrder(BiTree T) {
if (T == nullptr) return;
cout << T->data << " "; // 访问当前节点
PreOrder(T->lchild); // 递归访问左子树
PreOrder(T->rchild); // 递归访问右子树
}
// 中序遍历(左子树 -> 根 -> 右子树)
void InOrder(BiTree T) {
if (T == nullptr) return;
InOrder(T->lchild); // 递归访问左子树
cout << T->data << " "; // 访问当前节点
InOrder(T->rchild); // 递归访问右子树
}
// 后序遍历(左子树 -> 右子树 -> 根)
void PostOrder(BiTree T) {
if (T == nullptr) return;
PostOrder(T->lchild); // 递归访问左子树
PostOrder(T->rchild); // 递归访问右子树
cout << T->data << " "; // 访问当前节点
}
// 层次遍历(广度优先遍历)
void LevelOrder(BiTree T) {
if (T == nullptr) return;
queue<BiTree> q;
q.push(T);
while (!q.empty()) {
BiTree p = q.front();
q.pop();
cout << p->data << " "; // 访问当前节点
if (p->lchild != nullptr) {
q.push(p->lchild); // 将左子节点加入队列
}
if (p->rchild != nullptr) {
q.push(p->rchild); // 将右子节点加入队列
}
}
cout << endl;
}
// 递归删除二叉树
void DeleteTree(BiTree& T) {
if (T == nullptr) return;
DeleteTree(T->lchild);
DeleteTree(T->rchild);
delete T;
T = nullptr;
}
int main() {
// 创建二叉树
BiTree root = CreateBiTree();
// 输出前序遍历结果
cout << "前序遍历: ";
PreOrder(root);
cout << endl;
// 输出中序遍历结果
cout << "中序遍历: ";
InOrder(root);
cout << endl;
// 输出后序遍历结果
cout << "后序遍历: ";
PostOrder(root);
cout << endl;
// 输出层次遍历结果
cout << "层次遍历: ";
LevelOrder(root);
// 清理内存
DeleteTree(root);
return 0;
}
六、三叉链表
七、遍历二叉树
1)介绍
2)先序,中序,后序遍历介绍
若规定先左后右,则只有前三种情况:
- DLR --先(根)序遍历(中前后)
- LDR --中(根)序遍历(前中后)
- LRD --后(根)序遍历(前后中)
注意:
- 若二又树中各结点的值均不相同,则二又树结点的先序序列、中序序列和后序序列都是唯一的。
- 由二叉树的先序序列和中序序列,或由二叉树的后序序列和中序序列可以确定唯一棵二叉树。
案例:
1、由先序和中序求二叉树
2、由中序和后序求二叉树
3)先,中,后序递归算法实现
1、先序遍历
以上先序序列为:A B D C
Status PreOrderTraverse(BiTree T) {
if (T == NULL) return OK; // 空二叉树
else {
visit(T); // 访问根结点
PreOrderTraverse(T->lchild); // 递归遍历左子树
PreOrderTraverse(T->rchild); // 递归遍历右子树
}
}
2、中序遍历
Status InOrderTraverse(BiTree T) {
if (T == NULL) return OK; // 空二叉树
else {
InOrderTraverse(T->lchild); // 递归遍历左子树
visit(T); / /访问根结点;
InOrdenTraverse(T->rchild); // 递归遍历右子树
}
}
3、后序遍历
Status PostOrderTraverse(BiTree T) {
if (T == NULL) return OK; //空二叉树
else {
PostOrderTraverse(F->lchild); // 递归遍历左子树
PostOrderTraverse(T->rchild); // 递归遍历右子树
visit(T); // 访问根结点
}
}
4、总结
C语言代码实现
#include <stdio.h>
#include <stdlib.h>
// 二叉树节点定义
typedef struct BiTNode {
char data;
struct BiTNode* lchild, * rchild;
} BiTNode, * BiTree;
// 创建一个简单的二叉树
BiTree CreateBiTree() {
BiTree A, B, C, D, E, F, G, H, I;
A = (BiTree)malloc(sizeof(BiTNode));
B = (BiTree)malloc(sizeof(BiTNode));
C = (BiTree)malloc(sizeof(BiTNode));
D = (BiTree)malloc(sizeof(BiTNode));
E = (BiTree)malloc(sizeof(BiTNode));
F = (BiTree)malloc(sizeof(BiTNode));
G = (BiTree)malloc(sizeof(BiTNode));
H = (BiTree)malloc(sizeof(BiTNode));
I = (BiTree)malloc(sizeof(BiTNode));
A->data = 'A'; A->lchild = B; A->rchild = C;
B->data = 'B'; B->lchild = D; B->rchild = E;
C->data = 'C'; C->lchild = F; C->rchild = G;
D->data = 'D'; D->lchild = H; D->rchild = NULL;
E->data = 'E'; E->lchild = I; E->rchild = NULL;
F->data = 'F'; F->lchild = NULL; F->rchild = NULL;
G->data = 'G'; G->lchild = NULL; G->rchild = NULL;
H->data = 'H'; H->lchild = NULL; H->rchild = NULL;
I->data = 'I'; I->lchild = NULL; I->rchild = NULL;
return A;
}
// 先序遍历
void PreOrderTraverse(BiTree T) {
if (T == NULL) return;
printf("%c ", T->data); // 访问当前节点
PreOrderTraverse(T->lchild); // 递归访问左子树
PreOrderTraverse(T->rchild); // 递归访问右子树
}
// 中序遍历
void InOrderTraverse(BiTree T) {
if (T == NULL) return;
InOrderTraverse(T->lchild); // 递归访问左子树
printf("%c ", T->data); // 访问当前节点
InOrderTraverse(T->rchild); // 递归访问右子树
}
// 后序遍历
void PostOrderTraverse(BiTree T) {
if (T == NULL) return;
PostOrderTraverse(T->lchild); // 递归访问左子树
PostOrderTraverse(T->rchild); // 递归访问右子树
printf("%c ", T->data); // 访问当前节点
}
// 递归删除二叉树
void DeleteTree(BiTree T) {
if (T == NULL) return;
DeleteTree(T->lchild);
DeleteTree(T->rchild);
free(T);
}
int main() {
BiTree root = CreateBiTree();
printf("Preorder Traversal: ");
PreOrderTraverse(root);
printf("\n");
printf("Inorder Traversal: ");
InOrderTraverse(root);
printf("\n");
printf("Postorder Traversal: ");
PostOrderTraverse(root);
printf("\n");
// 清理内存
DeleteTree(root);
return 0;
}
C++代码实现
#include <iostream>
using namespace std;
// 二叉树节点定义
typedef struct BiTNode {
char data;
BiTNode* lchild, * rchild;
} BiTNode, * BiTree;
// 创建一个简单的二叉树
BiTree CreateBiTree() {
BiTree A = new BiTNode{ 'A', nullptr, nullptr };
BiTree B = new BiTNode{ 'B', nullptr, nullptr };
BiTree C = new BiTNode{ 'C', nullptr, nullptr };
BiTree D = new BiTNode{ 'D', nullptr, nullptr };
BiTree E = new BiTNode{ 'E', nullptr, nullptr };
BiTree F = new BiTNode{ 'F', nullptr, nullptr };
BiTree G = new BiTNode{ 'G', nullptr, nullptr };
BiTree H = new BiTNode{ 'H', nullptr, nullptr };
BiTree I = new BiTNode{ 'I', nullptr, nullptr };
A->lchild = B; A->rchild = C;
B->lchild = D; B->rchild = E;
C->lchild = F; C->rchild = G;
D->lchild = H; D->rchild = nullptr;
E->lchild = I; E->rchild = nullptr;
F->lchild = nullptr; F->rchild = nullptr;
G->lchild = nullptr; G->rchild = nullptr;
H->lchild = nullptr; H->rchild = nullptr;
I->lchild = nullptr; I->rchild = nullptr;
return A;
}
// 先序遍历
void PreOrderTraverse(BiTree T) {
if (T == nullptr) return;
cout << T->data << " "; // 访问当前节点
PreOrderTraverse(T->lchild); // 递归访问左子树
PreOrderTraverse(T->rchild); // 递归访问右子树
}
// 中序遍历
void InOrderTraverse(BiTree T) {
if (T == nullptr) return;
InOrderTraverse(T->lchild); // 递归访问左子树
cout << T->data << " "; // 访问当前节点
InOrderTraverse(T->rchild); // 递归访问右子树
}
// 后序遍历
void PostOrderTraverse(BiTree T) {
if (T == nullptr) return;
PostOrderTraverse(T->lchild); // 递归访问左子树
PostOrderTraverse(T->rchild); // 递归访问右子树
cout << T->data << " "; // 访问当前节点
}
// 递归删除二叉树
void DeleteTree(BiTree& T) {
if (T == nullptr) return;
DeleteTree(T->lchild);
DeleteTree(T->rchild);
delete T;
T = nullptr;
}
int main() {
BiTree root = CreateBiTree();
cout << "Preorder Traversal: ";
PreOrderTraverse(root);
cout << endl;
cout << "Inorder Traversal: ";
InOrderTraverse(root);
cout << endl;
cout << "Postorder Traversal: ";
PostOrderTraverse(root);
cout << endl;
// 清理内存
DeleteTree(root);
return 0;
}
4)先,中,后序非递归算法实现
用栈来实现
1、先序排序
Status PreOrderTraverse(BiTree T) {
BiTree p, q;
InitStack(S);
p = T;
while (p || !StackEmpty(S)) {
if (p) {
printf("%c", p->data); // 访问当前节点
Push(S, p);
p = p->lchild; // 向左子树走
} else {
Pop(S, q);
p = q->rchild; // 转向右子树
}
}
return OK;
}
2、中序排序
Status InOrderTraverse(BiTree T) {
BiTree p;
InitStack(S);
p = T;
while (p || !StackEmpty(S)) {
if (p) {
Push(S, p);
p = p->lchild;
}
else {
Pop(S, q);
printf("%c", q->data);
p = q->rchild;
}
}//while
return OK;
}
3、后序排序
Status PostOrderTraverse(BiTree T) {
BiTree p, q, r;
InitStack(S);
p = T;
r = NULL; // 用来记录最近一次访问的节点
while (p || !StackEmpty(S)) {
if (p) {
Push(S, p);
p = p->lchild; // 沿着左子树向下
} else {
GetTop(S, q);
// 如果右子树为空或者右子树已经被访问过
if (q->rchild == NULL || q->rchild == r) {
Pop(S, q);
printf("%c", q->data); // 访问当前节点
r = q; // 更新最近访问的节点
p = NULL; // 设置p为NULL,防止下一轮循环继续处理
} else {
p = q->rchild; // 转向右子树
}
}
}
return OK;
}
4、总结
C语言代码实现
#include <stdio.h>
#include <stdlib.h>
// 二叉树节点定义
typedef struct BiTNode {
char data;
struct BiTNode* lchild, * rchild;
} BiTNode, * BiTree;
// 栈的操作函数
#define MAXSIZE 100
typedef struct {
BiTree data[MAXSIZE];
int top;
} Stack;
void InitStack(Stack* S) {
S->top = -1;
}
int StackEmpty(Stack S) {
return S.top == -1;
}
int Push(Stack* S, BiTree e) {
if (S->top >= MAXSIZE - 1) return 0; // 栈满
S->data[++S->top] = e;
return 1;
}
int Pop(Stack* S, BiTree* e) {
if (S->top == -1) return 0; // 栈空
*e = S->data[S->top--];
return 1;
}
// 创建一个简单的二叉树
BiTree CreateBiTree() {
BiTree A, B, C, D, E, F, G, H, I;
A = (BiTree)malloc(sizeof(BiTNode));
B = (BiTree)malloc(sizeof(BiTNode));
C = (BiTree)malloc(sizeof(BiTNode));
D = (BiTree)malloc(sizeof(BiTNode));
E = (BiTree)malloc(sizeof(BiTNode));
F = (BiTree)malloc(sizeof(BiTNode));
G = (BiTree)malloc(sizeof(BiTNode));
H = (BiTree)malloc(sizeof(BiTNode));
I = (BiTree)malloc(sizeof(BiTNode));
A->data = 'A'; A->lchild = B; A->rchild = C;
B->data = 'B'; B->lchild = D; B->rchild = E;
C->data = 'C'; C->lchild = F; C->rchild = G;
D->data = 'D'; D->lchild = H; D->rchild = NULL;
E->data = 'E'; E->lchild = I; E->rchild = NULL;
F->data = 'F'; F->lchild = NULL; F->rchild = NULL;
G->data = 'G'; G->lchild = NULL; G->rchild = NULL;
H->data = 'H'; H->lchild = NULL; H->rchild = NULL;
I->data = 'I'; I->lchild = NULL; I->rchild = NULL;
return A;
}
// 先序遍历
void PreOrderTraverse(BiTree T) {
if (T == NULL) return;
Stack S;
InitStack(&S);
BiTree p = T;
while (p != NULL || !StackEmpty(S)) {
while (p != NULL) {
printf("%c ", p->data); // 访问当前节点
Push(&S, p);
p = p->lchild; // 向左子树走
}
if (!StackEmpty(S)) {
Pop(&S, &p);
p = p->rchild; // 转向右子树
}
}
printf("\n");
}
// 中序遍历
void InOrderTraverse(BiTree T) {
if (T == NULL) return;
Stack S;
InitStack(&S);
BiTree p = T;
while (p != NULL || !StackEmpty(S)) {
while (p != NULL) {
Push(&S, p);
p = p->lchild; // 向左子树走
}
if (!StackEmpty(S)) {
Pop(&S, &p);
printf("%c ", p->data); // 访问当前节点
p = p->rchild; // 转向右子树
}
}
printf("\n");
}
// 后序遍历
void PostOrderTraverse(BiTree T) {
if (T == NULL) return;
Stack S1, S2;
InitStack(&S1);
InitStack(&S2);
BiTree p = T;
Push(&S1, p);
while (!StackEmpty(S1)) {
Pop(&S1, &p);
Push(&S2, p);
if (p->lchild != NULL) Push(&S1, p->lchild); // 左子树入栈
if (p->rchild != NULL) Push(&S1, p->rchild); // 右子树入栈
}
while (!StackEmpty(S2)) {
Pop(&S2, &p);
printf("%c ", p->data); // 访问当前节点
}
printf("\n");
}
// 递归删除二叉树
void DeleteTree(BiTree T) {
if (T == NULL) return;
DeleteTree(T->lchild);
DeleteTree(T->rchild);
free(T);
}
int main() {
BiTree root = CreateBiTree();
printf("Preorder Traversal: ");
PreOrderTraverse(root);
printf("Inorder Traversal: ");
InOrderTraverse(root);
printf("Postorder Traversal: ");
PostOrderTraverse(root);
// 清理内存
DeleteTree(root);
return 0;
}
C++代码实现
#include <iostream>
#include <stack>
using namespace std;
// 二叉树节点定义
typedef struct BiTNode {
char data;
BiTNode* lchild, * rchild;
} BiTNode, * BiTree;
// 创建一个简单的二叉树
BiTree CreateBiTree() {
// 创建根节点
BiTree A = new BiTNode{ 'A', nullptr, nullptr };
BiTree B = new BiTNode{ 'B', nullptr, nullptr };
BiTree C = new BiTNode{ 'C', nullptr, nullptr };
BiTree D = new BiTNode{ 'D', nullptr, nullptr };
BiTree E = new BiTNode{ 'E', nullptr, nullptr };
BiTree F = new BiTNode{ 'F', nullptr, nullptr };
BiTree G = new BiTNode{ 'G', nullptr, nullptr };
BiTree H = new BiTNode{ 'H', nullptr, nullptr };
BiTree I = new BiTNode{ 'I', nullptr, nullptr };
// 构建二叉树
A->lchild = B; A->rchild = C;
B->lchild = D; B->rchild = E;
C->lchild = F; C->rchild = G;
D->lchild = H; D->rchild = nullptr;
E->lchild = I; E->rchild = nullptr;
F->lchild = nullptr; F->rchild = nullptr;
G->lchild = nullptr; G->rchild = nullptr;
H->lchild = nullptr; H->rchild = nullptr;
I->lchild = nullptr; I->rchild = nullptr;
return A;
}
// 先序遍历
void PreOrderTraverse(BiTree T) {
if (T == nullptr) return;
stack<BiTree> s;
BiTree p = T;
while (p != nullptr || !s.empty()) {
while (p != nullptr) {
cout << p->data << " "; // 访问当前节点
s.push(p);
p = p->lchild; // 向左子树走
}
if (!s.empty()) {
p = s.top();
s.pop();
p = p->rchild; // 转向右子树
}
}
cout << endl;
}
// 中序遍历
void InOrderTraverse(BiTree T) {
if (T == nullptr) return;
stack<BiTree> s;
BiTree p = T;
while (p != nullptr || !s.empty()) {
while (p != nullptr) {
s.push(p);
p = p->lchild; // 向左子树走
}
if (!s.empty()) {
p = s.top();
s.pop();
cout << p->data << " "; // 访问当前节点
p = p->rchild; // 转向右子树
}
}
cout << endl;
}
// 后序遍历
void PostOrderTraverse(BiTree T) {
if (T == nullptr) return;
stack<BiTree> s1, s2;
s1.push(T);
while (!s1.empty()) {
T = s1.top();
s1.pop();
s2.push(T);
if (T->lchild != nullptr) s1.push(T->lchild); // 左子树入栈
if (T->rchild != nullptr) s1.push(T->rchild); // 右子树入栈
}
while (!s2.empty()) {
T = s2.top();
s2.pop();
cout << T->data << " "; // 访问当前节点
}
cout << endl;
}
// 递归删除二叉树
void DeleteTree(BiTree& root) {
if (root == nullptr) return;
DeleteTree(root->lchild);
DeleteTree(root->rchild);
delete root;
root = nullptr;
}
int main() {
BiTree root = CreateBiTree();
cout << "Preorder Traversal: ";
PreOrderTraverse(root);
cout << "Inorder Traversal: ";
InOrderTraverse(root);
cout << "Postorder Traversal: ";
PostOrderTraverse(root);
// 清理内存
DeleteTree(root);
return 0;
}
5)二叉树层次遍历
1、层次遍历代码
// 层次遍历
void LevelOrder(BiTree b) {
BTNode* p;
SqQueue qu;
InitQueue(&qu); // 初始化队列
enQueue(&qu, b); // 根结点指针进入队列
while (!QueueEmpty(qu)) { // 队不为空,则循环
deQueue(&qu, &p); // 出队结点p
printf("%c ", p->data); // 访问结点p
if (p->lchild != NULL) {
enQueue(&qu, p->lchild); // 有左孩子时将其进队
}
if (p->rchild != NULL) {
enQueue(&qu, p->rchild); // 有右孩子时将其进队
}
}
printf("\n");
}
2、总体代码
C语言代码实现
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 100 // 队列的最大容量
// 二叉树节点定义
typedef struct BTNode {
char data;
struct BTNode* lchild, * rchild;
} BTNode, * BiTree;
// 顺序循环队列类型
typedef struct {
BTNode* data[MaxSize]; // 存放队中元素
int front, rear; // 队头和队尾指针
} SqQueue;
// 初始化队列
void InitQueue(SqQueue* qu) {
qu->front = qu->rear = 0;
}
// 判断队列是否为空
int QueueEmpty(SqQueue qu) {
return qu.front == qu.rear;
}
// 入队
int enQueue(SqQueue* qu, BTNode* e) {
if ((qu->rear + 1) % MaxSize == qu->front) { // 队满
return 0;
}
qu->data[qu->rear] = e;
qu->rear = (qu->rear + 1) % MaxSize;
return 1;
}
// 出队
int deQueue(SqQueue* qu, BTNode** e) {
if (qu->front == qu->rear) { // 队空
return 0;
}
*e = qu->data[qu->front];
qu->front = (qu->front + 1) % MaxSize;
return 1;
}
// 创建一个简单的二叉树
BiTree CreateBiTree() {
BiTree A = (BiTree)malloc(sizeof(BTNode));
BiTree B = (BiTree)malloc(sizeof(BTNode));
BiTree C = (BiTree)malloc(sizeof(BTNode));
BiTree D = (BiTree)malloc(sizeof(BTNode));
BiTree E = (BiTree)malloc(sizeof(BTNode));
BiTree F = (BiTree)malloc(sizeof(BTNode));
BiTree G = (BiTree)malloc(sizeof(BTNode));
BiTree H = (BiTree)malloc(sizeof(BTNode));
BiTree I = (BiTree)malloc(sizeof(BTNode));
A->data = 'A'; A->lchild = B; A->rchild = C;
B->data = 'B'; B->lchild = D; B->rchild = E;
C->data = 'C'; C->lchild = F; C->rchild = G;
D->data = 'D'; D->lchild = H; D->rchild = NULL;
E->data = 'E'; E->lchild = I; E->rchild = NULL;
F->data = 'F'; F->lchild = NULL; F->rchild = NULL;
G->data = 'G'; G->lchild = NULL; G->rchild = NULL;
H->data = 'H'; H->lchild = NULL; H->rchild = NULL;
I->data = 'I'; I->lchild = NULL; I->rchild = NULL;
return A;
}
// 层次遍历
void LevelOrder(BiTree b) {
BTNode* p;
SqQueue qu;
InitQueue(&qu); // 初始化队列
enQueue(&qu, b); // 根结点指针进入队列
while (!QueueEmpty(qu)) { // 队不为空,则循环
deQueue(&qu, &p); // 出队结点p
printf("%c ", p->data); // 访问结点p
if (p->lchild != NULL) {
enQueue(&qu, p->lchild); // 有左孩子时将其进队
}
if (p->rchild != NULL) {
enQueue(&qu, p->rchild); // 有右孩子时将其进队
}
}
printf("\n");
}
// 递归删除二叉树
void DeleteTree(BiTree T) {
if (T == NULL) return;
DeleteTree(T->lchild);
DeleteTree(T->rchild);
free(T);
}
int main() {
BiTree root = CreateBiTree();
printf("Level Order Traversal: ");
LevelOrder(root);
// 清理内存
DeleteTree(root);
return 0;
}
C++代码实现
#include <iostream>
#include <queue>
using namespace std;
// 二叉树节点定义
typedef struct BTNode {
char data;
BTNode *lchild, *rchild;
} BTNode, *BiTree;
// 创建一个简单的二叉树
BiTree CreateBiTree() {
BiTree A = new BTNode{ 'A', nullptr, nullptr };
BiTree B = new BTNode{ 'B', nullptr, nullptr };
BiTree C = new BTNode{ 'C', nullptr, nullptr };
BiTree D = new BTNode{ 'D', nullptr, nullptr };
BiTree E = new BTNode{ 'E', nullptr, nullptr };
BiTree F = new BTNode{ 'F', nullptr, nullptr };
BiTree G = new BTNode{ 'G', nullptr, nullptr };
BiTree H = new BTNode{ 'H', nullptr, nullptr };
BiTree I = new BTNode{ 'I', nullptr, nullptr };
A->lchild = B; A->rchild = C;
B->lchild = D; B->rchild = E;
C->lchild = F; C->rchild = G;
D->lchild = H; D->rchild = nullptr;
E->lchild = I; E->rchild = nullptr;
F->lchild = nullptr; F->rchild = nullptr;
G->lchild = nullptr; G->rchild = nullptr;
H->lchild = nullptr; H->rchild = nullptr;
I->lchild = nullptr; I->rchild = nullptr;
return A;
}
// 层次遍历
void LevelOrder(BiTree b) {
if (b == nullptr) return;
// 使用队列进行层次遍历
queue<BiTree> q;
q.push(b);
while (!q.empty()) {
BiTree p = q.front();
q.pop();
cout << p->data << " "; // 访问当前节点
// 将左子节点加入队列
if (p->lchild != nullptr) {
q.push(p->lchild);
}
// 将右子节点加入队列
if (p->rchild != nullptr) {
q.push(p->rchild);
}
}
cout << endl;
}
// 递归删除二叉树
void DeleteTree(BiTree &T) {
if (T == nullptr) return;
DeleteTree(T->lchild);
DeleteTree(T->rchild);
delete T;
T = nullptr;
}
int main() {
BiTree root = CreateBiTree();
cout << "Level Order Traversal: ";
LevelOrder(root); // 层次遍历
// 清理内存
DeleteTree(root);
return 0;
}
八、二叉树的创建
1)先序创建二叉树
Status CreateBiTree(BiTree &T) {
scanf(&ch);//cin>>ch;
if(ch== “#”) T= NULL
else {if (!(T =(BiTNode *)malloc(sizeof(BiTNode))))
exit(OVERFLOW); //T=new BiTNode;
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //构造左子树
CreateBiTree(T->rchild);//构造右子树
return OK;
}// CreateBiTree
2)总体代码实现
#include <iostream>
#include <queue>
using namespace std;
// 二叉树节点的数据类型
typedef char TElemType;
typedef int Status; //Status是函数的类型,其值是函数结果状态代码,如OK等
// 二叉树节点定义
typedef struct BiTNode {
TElemType data;
struct BiTNode* lchild, * rchild; // 左右孩子指针
} BiTNode, * BiTree;
// 状态码定义
#define OK 1
#define ERROR 0
#define OVERFLOW -2
// 创建新节点
Status CreateBiTree(BiTree& T) {
TElemType ch;
cin >> ch; // 读取一个字符
if (ch == '#') {
T = NULL; // 如果是 '#',表示空节点
}
else {
if (!(T = (BiTNode*)malloc(sizeof(BiTNode)))) {
exit(OVERFLOW); // 内存分配失败
}
T->data = ch; // 生成根节点
CreateBiTree(T->lchild); // 构造左子树
CreateBiTree(T->rchild); // 构造右子树
}
return OK;
}
// 前序遍历(根 -> 左子树 -> 右子树)
void PreOrder(BiTree T) {
if (T == NULL) return;
cout << T->data << " "; // 访问当前节点
PreOrder(T->lchild); // 递归访问左子树
PreOrder(T->rchild); // 递归访问右子树
}
// 中序遍历(左子树 -> 根 -> 右子树)
void InOrder(BiTree T) {
if (T == NULL) return;
InOrder(T->lchild); // 递归访问左子树
cout << T->data << " "; // 访问当前节点
InOrder(T->rchild); // 递归访问右子树
}
// 后序遍历(左子树 -> 右子树 -> 根)
void PostOrder(BiTree T) {
if (T == NULL) return;
PostOrder(T->lchild); // 递归访问左子树
PostOrder(T->rchild); // 递归访问右子树
cout << T->data << " "; // 访问当前节点
}
// 层次遍历(广度优先遍历)
void LevelOrder(BiTree T) {
if (T == NULL) return;
queue<BiTree> q;
q.push(T);
while (!q.empty()) {
BiTree p = q.front();
q.pop();
cout << p->data << " "; // 访问当前节点
if (p->lchild != NULL) {
q.push(p->lchild); // 将左子节点加入队列
}
if (p->rchild != NULL) {
q.push(p->rchild); // 将右子节点加入队列
}
}
cout << endl;
}
// 递归删除二叉树
void DeleteTree(BiTree& T) {
if (T == NULL) return;
DeleteTree(T->lchild);
DeleteTree(T->rchild);
free(T);
T = NULL;
}
int main() {
BiTree root = NULL;
// 创建二叉树
cout << "请输入先序遍历序列(使用 '#' 表示空节点): ";
CreateBiTree(root);
// 输出前序遍历结果
cout << "前序遍历: ";
PreOrder(root);
cout << endl;
// 输出中序遍历结果
cout << "中序遍历: ";
InOrder(root);
cout << endl;
// 输出后序遍历结果
cout << "后序遍历: ";
PostOrder(root);
cout << endl;
// 输出层次遍历结果
cout << "层次遍历: ";
LevelOrder(root);
// 清理内存
DeleteTree(root);
return 0;
}
九、复制二叉树
int Copy(BiTree T, BiTree& NewT) {
if (T == NULL) { //如果是空树返回0
NewT = NULL;
return O;
}
else {
NewT = new BiTNode;
NewT->data = T->data;
Copy(T->IChild, NewT->lchild);
Copy(T->rChild, NewT->rchild);
}
}
十、计算二叉树深度
int Depth(BiTree T) {
if (T == NULL) {
return 0;//如果是空树返回0
}
else {
m = Depth(T->IChild);
n = Depth(T->rChild);
if (m > n) return(m + 1);
else return(n + 1);
}
}
十一、计算二叉树结点总数
int NodeCount(BiTree T) {
if (T == NULL) return 0;
else
return NodeCount(T->lchild) + NodeCount(T->rchild) + 1;
}
十二、求叶子结点数
int LeadCount(BiTree T) {
if (T == NULL)
//如果是空树返回0
return 0;
if (T->Ichild == NULL && T->rchild == NULL)//如果是叶子结点返回1
return 1;
else
return LeafCount(T->lchild) + LeafCount(T->rchild);
}
十三、线序二叉树
1)介绍
提出的问题:
- 如何寻找特定遍历序列中二又树结点的前驱和后继???
解决的方法:
- 通过遍历寻找–费时间。
- 再增设前驱、后继指针域–增加了存储负担。
- 利用二叉链表中的空指针域。
利用二叉链表中的空指针域:
如果某个结点的左孩子为空,则将空的左孩子指针域改为指向其前驱,如果某结点的右孩子为空,则将空的右孩子指针域改为指向其后继
- ——这种改变指向的指针称为 “线索“
- 加上了线索的二又树称为线索二叉树(Threaded Binary Tree)
对二叉树按某种遍历次序使其变为线索二叉树的过程叫线索化
2)线索化过程
为区分lrchid和rchild指针到底是指向孩子的指针,还是指向前驱或者后继的指针,对二叉链表中每个结点增设
两个标志域 ltag 和 rtag ,并约定:
ltag = 0 lchild 指向该结点的左孩子
rtag = 0 rchild 指向该结点的右孩子
ltag = 1 lchild 指向该结点的前驱
rtag = 1 rchild 指向该结点的后继
typedef struct BiThrNode{
int data;
int ltag, rtag;
struct BiThrNode *lchild, rchild;
} BiThrNode, *BiThrTree ;