1,概述

树:

  • 树是一个n个结点的有限集,如果n=0称之为空树。
  • 树的定义是递归的,树中又调用了自身。
  • 树的根节点没有前驱,除了根节点,其他所有节点有且只有一个前驱
  • 树中所有节点可以有0个或者多个后驱。

二叉树:

  • 特殊的树结构

  • 每个结点至多只有两个子树

遍历方式:

  • 前中后 根节点遍历

前序:根->左->右

中序:左->根->右

后序:左->右->根

如图所示:

image-20231120123206399

在这里需要注意的是,根是相对的,左右也是相对的,以A为根,左右为B,C。以B为根,左右为D,F。

  • 前序时,开始根为A然后是A-B-D,此时根为B,所以退出D进入E。
  • 中序时,开始从D开始,然后根为B,所以是D-B-E,然后退出E进入A。
  • 后序时,开始从D开始,然后去E,再去根B,然后进入F-G-C最后到A。

2. 树的创建

树的创建中我们每次都会调用相同的结构体,所以我们使用递归来重复定义和写入预设代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <time.h>
#include <Windows.h>
#include <string.h>
#include <malloc.h>

//二叉树的结构定义
typedef struct TREECREAT {
char name;
struct TREECREAT* LEFT;
struct TREECREAT* RIGHT;
}TREE;

//二叉树的逻辑
void TREERE(TREE** t) {
char name;
//name = getchar();
scanf(" %c",&name);
if (name=='#') {
//此时为空节点
*t = NULL;
return;
}
else
{
//此时不为空
*t = (TREE*)malloc(sizeof(TREE));
(*t)->name = name;
//左子树
TREERE(&((*t)->LEFT));
//右子树
TREERE(&((*t)->RIGHT));
}
}

int main() {
TREE* t ;
TREERE(&t);
system("pause");
return 0;
}

再上述过程中,我们将结构重复使用,避免了每次定义的繁杂过程。我们传入二级指针来修改指向。这时我们的录入得到顺序为根->左->右,并且是层级递增。如果需要先录入右侧,只需要更改两条代码的位置即可。

3.树的遍历

3.1普通遍历

树的遍历有前序,中序,后续三种。其区别并不大==仅仅需要改变代码优先执行的顺序即可==

前序如下:

1
2
3
4
5
6
7
8
9
10
11
12
//树的遍历
void printtree1(TREE* p) {
if (p == NULL) {
return;
}
else {
//前序
printf("%c\n", p->name);
printtree1(p->LEFT);
printtree1(p->RIGHT);
}
}

中序如下:

1
2
3
4
5
6
7
8
9
10
11
12
//树的遍历
void printtree2(TREE* p) {
if (p == NULL) {
return;
}
else {
//中序
printtree2(p->LEFT);
printf("%c\n", p->name);
printtree2(p->RIGHT);
}
}

后序如下:

1
2
3
4
5
6
7
8
9
10
11
12
//树的遍历
void printtree3(TREE* p) {
if (p == NULL) {
return;
}
else {
//后序
printtree3(p->LEFT);
printtree3(p->RIGHT);
printf("%c\n", p->name);
}
}

其本质在于printf的位置,即根的输出与左右分枝的执行顺序。

3.2 层次遍历

层次遍历相当于树的同级结构的遍历,如图:

image-20231120123206399

层次遍历就相当于是A->B->C->D->E->F->G的顺序进行遍历,这里b和c是同一级,defg为同一级。这里由于我们用递归定义的树结构,这里层级遍历就需要用到队的结构去实现。

由于层次遍历,我们可以改变一下录入规则去使用它

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <time.h>
#include <Windows.h>
#include <string.h>
#include <malloc.h>

//树模块
typedef struct TREE {
int data;
struct TREE* left;
struct TREE* right;
}TREE;

//队列模块
typedef struct QUEUE {
TREE* arr[10];
int front;
int bottom;//用整形计数
}QUEUE;

void initqueue(QUEUE* q) {
(*q).front = (*q).bottom = 0;
}

void put(QUEUE* q1, TREE* p2) {
(*q1).arr[(*q1).front++] = p2;
}

TREE* pop(QUEUE* q) {
if ((*q).front == (*q).bottom)
return NULL;
return ((*q).arr[(*q).bottom++]);
}

//匹配是否符合条件
TREE* search(TREE* tr) {
QUEUE* q;
TREE* p;
initqueue(&q);
if (tr->left == NULL || tr->right == NULL) {
return tr;
}
put(&q, tr);
while (1) {
p = pop(&q);
if (p->left != NULL) {
put(&q, p->left);
}
else {
return p;
}
if (p->right != NULL) {
putqueue(&q, p->right);
}
else {
return p;
}
}
}

//初始化树
TREE* inittree(TREE**p) {
TREE* pp = *p;
char data;
scanf("%c", &data);
pp = (TREE*)malloc(sizeof(TREE));
pp->left = NULL;
pp->right = NULL;
pp->data = data;
*p = pp;
return *p;
}

//插入
void insert() {
TREE* p, * q;
char ch;
q = (TREE*)malloc(sizeof(TREE));
q->left = NULL;
q->right = NULL;
printf("请输入节点字母:\n");
ch = getchar();
q->data = ch;
p = search(&q);
if (p->left) {
p->left = q;
}
else {
p->right = q;
}
}

int main() {
TREE* p;
inittree(&p);
system("pause");
return 0;
}

在上述代码中,我么能用整形数来计算和存储队列,我们每次输入树的根时都会进行判定,左右,如果左没有就填充左,然后判定右边,不同的时,每次录入都会判定左右的根是否为空,然后按层次录入。从而每次录入时进行队列的录入,于是完成了层次遍历的存储条件。


3. 资料参考

【UP从0到1带你手撕数据结构全集(C语言版)】https://www.bilibili.com/video/BV1W64y1z7jh?p=13&vd_source=602097138258a0057a732e44579de1ed

【数据结构上机-通过层次遍历演示完全二叉树的建立与遍历-C语言上机代码完整实现】https://www.bilibili.com/video/BV1PF411E7ja?vd_source=602097138258a0057a732e44579de1ed

【层次遍历C语言实现】https://www.bilibili.com/video/BV1HM4y1u7fV?vd_source=602097138258a0057a732e44579de1ed