🌺博客汇总:🌃Summary And Schedule🌠

🌸考研相关内容汇总:考研Schedule&&Summary

🌼408王道C督学课程目录:《王道C语言督学班目录》

🌺先画图,后再实战代码

本章需要掌握:

  • 1、树、二叉树、满二叉树、完全二叉树
  • 2、层次建树、先序遍历、中序遍历、后序遍历、层序遍历
  • 3、真题

1、树(Tree)

树是一种逻辑结构,也是一种分层结构。n(n>=0)个结点的有限集。当n=0是空树;当n>0时①有且仅有一个根节点②n>1其余结点可分为m(m>0)个互不相交的有限集T1,T2,…,Tm,每个集合又是一颗二叉树,称为跟的子树。

2、二叉树(BiTree)

满二叉树(是除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树。)

完全二叉树(除最后一 层外,其它各层的结点数都达到最大个数。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// function.h
// Created by 41507 on 2022/11/9.
//

#ifndef INC_1_TREE_FUNCTION_H
#define INC_1_TREE_FUNCTION_H
#include <stdio.h>
#include <stdlib.h>

typedef char BiElemType;
typedef struct BiTNode{
BiElemType c;//c就是书籍上的data
struct BiTNode *lchild;
struct BiTNode *rchild;
}BiTNode,*BiTree;

//tag结构体是辅助队列使用的
typedef struct tag{
BiTree p;//树的某一个结点的地址值
struct tag *pnext;
}tag_t,*ptag_t;
#endif //INC_1_TREE_FUNCTION_H

3、层次建树

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
#include "function.h"

int main() {
BiTree pnew;//用来指向新申请的树结点
BiTree tree=NULL;//tree是指向树根的,代表树
char c;
ptag_t phead=NULL,ptail=NULL,listpnew=NULL,pcur;
//abcdefghij
while(scanf("%c",&c))
{
if(c=='\n')
{
break;//读取到换行就结束
}
//calloc申请的空间大小是两个参数直接相乘,并对空间进行初始化,赋值为0
pnew= (BiTree)calloc(1,sizeof(BiTNode));
pnew->c=c;
listpnew= (ptag_t)calloc(1,sizeof(tag_t));//给队列结点申请空间
listpnew->p=pnew;
//如果是树的第一个结点
if(NULL==tree)
{
tree=pnew;//tree指向树的根结点
phead=listpnew;//第一个结点即是队列头,也是队列尾
ptail=listpnew;
pcur=listpnew;//pcur要指向要进入树的父亲元素
}else{
//让元素先入队列
ptail->pnext=listpnew;
ptail=listpnew;
//接下来把结点放入树中
if(NULL==pcur->p->lchild)
{
pcur->p->lchild=pnew;//pcur->p左孩子为空,就放入左孩子
}else if(NULL==pcur->p->rchild)
{
pcur->p->rchild=pnew;//pcur->p右孩子为空,就放入右孩子
pcur=pcur->pnext;//当前结点左右孩子都有了,pcur就指向下一个
}
}
}
return 0;
}

4、二叉树的前序、中序、后序、层次遍历

一些定义

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
// function.h
//
// Created by 41507 on 2022/11/9.
//

#ifndef INC_1_TREE_FUNCTION_H
#define INC_1_TREE_FUNCTION_H
#include <stdio.h>
#include <stdlib.h>

typedef char BiElemType;
typedef struct BiTNode{
BiElemType c;//c就是书籍上的data
struct BiTNode *lchild;
struct BiTNode *rchild;
}BiTNode,*BiTree;

//tag结构体是辅助队列使用的
typedef struct tag{
BiTree p;//树的某一个结点的地址值
struct tag *pnext;
}tag_t,*ptag_t;

//队列的结构体
typedef BiTree ElemType;
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct{
LinkNode *front,*rear;//链表头 链表尾,也可以称为队头,队尾
}LinkQueue;//先进先出
void InitQueue(LinkQueue &Q);
bool IsEmpty(LinkQueue Q);
void EnQueue(LinkQueue &Q,ElemType x);
bool DeQueue(LinkQueue &Q,ElemType &x);

#endif //INC_1_TREE_FUNCTION_H

链队列 操作代码

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
// queue.cpp
// Created by 41507 on 2022/11/9.
//
#include "function.h"

//队列的初始化,使用的是带头结点的链表来实现的
void InitQueue(LinkQueue &Q)
{
Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));
Q.front->next=NULL;
}
//判断队列是否为空
bool IsEmpty(LinkQueue Q)
{
return Q.rear==Q.front;
}
//入队
void EnQueue(LinkQueue &Q,ElemType x)
{
LinkNode *pnew=(LinkNode*)malloc(sizeof(LinkNode));
pnew->data=x;
pnew->next=NULL;//要让next为NULL
Q.rear->next=pnew;//尾指针的next指向pnew,因为从尾部入队
Q.rear=pnew;//rear要指向新的尾部
}
//出队
bool DeQueue(LinkQueue &Q,ElemType &x)
{
if(Q.rear==Q.front)//队列为空
{
return false;
}
LinkNode* q=Q.front->next;//拿到第一个结点,存入q
x=q->data;//获取要出队的元素值
Q.front->next=q->next;//让一个结点断链
if(Q.rear==q)//链表只剩余一个结点时,被删除后,要改变rear
{
Q.rear=Q.front;
}
free(q);
return true;
}

前序遍历、中序遍历、后序遍历、层次遍历

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
104
105
106
// main.cpp
#include "function.h"

//前序遍历,也叫先序遍历,也是深度优先遍历
void PreOrder(BiTree p)
{
if(p!=NULL)
{
printf("%c", p->c);
PreOrder(p->lchild);//打印左子树
PreOrder(p->rchild);//打印右子树
}
}
//中序遍历
void InOrder(BiTree p)
{
if(p!=NULL)
{
InOrder(p->lchild);//打印左子树
printf("%c", p->c);
InOrder(p->rchild);//打印右子树
}
}
//后序遍历
void PostOrder(BiTree p)
{
if(p!=NULL)
{
PostOrder(p->lchild);//打印左子树
PostOrder(p->rchild);//打印右子树
printf("%c", p->c);
}
}

//层序遍历
//层次遍历,层序遍历,广度优先遍历
void LevelOrder(BiTree T)
{
LinkQueue Q;
InitQueue(Q);
BiTree p;//存储出队的结点
EnQueue(Q,T);//把根入队
while(!IsEmpty(Q))
{
DeQueue(Q,p);
putchar(p->c);//等价于printf("%c",c);
if(p->lchild)
{
EnQueue(Q,p->lchild);//左孩子不为空,就入队左孩子
}
if(p->rchild)
{
EnQueue(Q,p->rchild);//右孩子不为空,就入队右孩子
}
}
}

int main() {
BiTree pnew;//用来指向新申请的树结点
BiTree tree=NULL;//tree是指向树根的,代表树
char c;
ptag_t phead=NULL,ptail=NULL,listpnew=NULL,pcur;
//abcdefghij
while(scanf("%c",&c))
{
if(c=='\n')
{
break;//读取到换行就结束
}
//calloc申请的空间大小是两个参数直接相乘,并对空间进行初始化,赋值为0
pnew= (BiTree)calloc(1,sizeof(BiTNode));
pnew->c=c;
listpnew= (ptag_t)calloc(1,sizeof(tag_t));//给队列结点申请空间
listpnew->p=pnew;
//如果是树的第一个结点
if(NULL==tree)
{
tree=pnew;//tree指向树的根结点
phead=listpnew;//第一个结点即是队列头,也是队列尾
ptail=listpnew;
pcur=listpnew;//pcur要指向要进入树的父亲元素
}else{
//让元素先入队列
ptail->pnext=listpnew;
ptail=listpnew;
//接下来把结点放入树中
if(NULL==pcur->p->lchild)
{
pcur->p->lchild=pnew;//pcur->p左孩子为空,就放入左孩子
}else if(NULL==pcur->p->rchild)
{
pcur->p->rchild=pnew;//pcur->p右孩子为空,就放入右孩子
pcur=pcur->pnext;//当前结点左右孩子都有了,pcur就指向下一个
}
}
}
printf("--------PreOrder----------\n");//也叫先序遍历,先打印当前结点,打印左孩子,打印右孩子
PreOrder(tree);
printf("\n--------InOrder------------\n");//先打印左孩子,打印父亲,打印右孩子
InOrder(tree);
printf("\n--------PostOrder------------\n");//先打印左孩子,打印右孩子,最后打印父亲
PostOrder(tree);
printf("\n--------LevelOrder------------\n");
LevelOrder(tree);
return 0;
}

5、201441 题真题讲解

41.(13 分)二叉树的带权路径长度(WPL)是二叉树中所有叶结点的带权路径长度之和。给定一棵二叉树 T,采用二叉链表存储,结点结构如下:

截屏2024-05-02 20.26.24

其中叶结点的 weight 域保存该结点的非负权值。设 root 为指向 T 的根结点的指针,请设计 求 T 的 WPL 的算法,要求:

(1)给出算法的基本设计思想。

(2)使用 C 或 C++语言,给出二叉树结点的数据类型定义。

(3)根据设计思想,采用 C 或 C++语言描述算法,关键之处给出注释。

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
#include <stdio.h>
#include <stdlib.h>

typedef int BiElemType;
typedef struct BiTNode{
BiElemType weight;//用字符的ASCII值作为weight值
struct BiTNode *lchild;
struct BiTNode *rchild;
}BiTNode,*BiTree;

//tag结构体是辅助队列使用的
typedef struct tag{
BiTree p;//树的某一个结点的地址值
struct tag *pnext;
}tag_t,*ptag_t;
//前序遍历,也叫先序遍历,也是深度优先遍历
//deep代表路径长度,就是有几条路径

int wpl_PreOrder(BiTree p,int deep)
{
static int wpl=0;//静态局部变量和全局变量类似,只会初始化1次,区别是只在函数内有效
if(p!=NULL)
{
//判断当为叶子结点时,将对应叶子结点weight和deep相乘,加到wpl上
if(p->lchild==NULL && p->rchild==NULL)
{
wpl+=p->weight*deep;
}
wpl_PreOrder(p->lchild,deep+1);//递归左子树,路径长度要加1
wpl_PreOrder(p->rchild,deep+1);//递归右子树,路径长度也要加1
}
return wpl;
}

int WPL(BiTree tree)
{
return wpl_PreOrder(tree,0);
}

int main() {
BiTree pnew;//用来指向新申请的树结点
BiTree tree=NULL;//tree是指向树根的,代表树
char c;
ptag_t phead=NULL,ptail=NULL,listpnew=NULL,pcur;
//abcdefghij
while(scanf("%c",&c))
{
if(c=='\n')
{
break;//读取到换行就结束
}
//calloc申请的空间大小是两个参数直接相乘,并对空间进行初始化,赋值为0
pnew= (BiTree)calloc(1,sizeof(BiTNode));
pnew->weight=c;
listpnew= (ptag_t)calloc(1,sizeof(tag_t));//给队列结点申请空间
listpnew->p=pnew;
//如果是树的第一个结点
if(NULL==tree)
{
tree=pnew;//tree指向树的根结点
phead=listpnew;//第一个结点即是队列头,也是队列尾
ptail=listpnew;
pcur=listpnew;//pcur要指向要进入树的父亲元素
}else{
//让元素先入队列
ptail->pnext=listpnew;
ptail=listpnew;
//接下来把结点放入树中
if(NULL==pcur->p->lchild)
{
pcur->p->lchild=pnew;//pcur->p左孩子为空,就放入左孩子
}else if(NULL==pcur->p->rchild)
{
pcur->p->rchild=pnew;//pcur->p右孩子为空,就放入右孩子
pcur=pcur->pnext;//当前结点左右孩子都有了,pcur就指向下一个
}
}
}
printf("%d\n",WPL(tree));
return 0;
}