经过了三周的学习,树的内容终于告一段落了,三周的时长也说明了树与二叉树的重要性。
树是一种简单的非线性结构。在树这种数据结构中,所有数据元素之间的关系具有明显的层次特性。 在树结构中,每一个结点只有一个前件,称为父结点。没有前件的结点只有一个,称为树的根结点,简称树的根。每一个结点可以有多个后件,称为该结点的子结点。没有后件的结点称为叶子结点。 在树结构中,一个结点所拥有的后件的个数称为该结点的度,所有结点中的度称为树的度。树的层次称为树的深度。
而二叉树,是一种很有用的非线性结构,它具有以下两个特点:1)非空二叉树只有一个根结点;2)每一个结点最多有两棵子树,且分别称为该结点的左子树与右子树。
二叉树作为树中的重点学习内容,自然也有几点衍生内容。
满二叉树:除最后一层外,每一层上的所有结点都有两个子结点。
完全二叉树:除最后一层外,每一层上的结点数均达到值;在最后一层上只缺少右边的若干结点。
二叉树通常采用链式存储结构。
与线性链表类似,用于存储二叉树中各元素的存储结点也由两部分组成:数据域和指针域。但在二叉树中,由于每一个元素可以有两个后件(即两个子结点),因此,用于存储二叉树的存储结点的指针域有两个:一个用于指向该结点的左子结点的存储地址,称为左指针域;另一个用于指向该结点的右子结点的存储地址,称为右指针域。
针对二叉树的操作,比较重要同时也是我认为本章中比较有趣的就是二叉树的遍历了:
(1)前序遍历(DLR):若二叉树为空,则结束返回。否则:首先访问根结点,然后遍历左子树,最后遍历右子树;并且,在遍历左右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树。
(2)中序遍历(LDR):若二叉树为空,则结束返回。否则:首先遍历左子树,然后访问根结点,最后遍历右子树;并且,在遍历左、右子树时,仍然先遍历左子树,然后访问根结点,最后遍历右子树。
(3)后序遍历(LRD):若二叉树为空,则结束返回。否则:首先遍历左子树,然后遍历右子树,最后访问根结点,并且,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后访问根结点。
简要概括起来则是:
前序遍历:根左右
中序遍历:左根右
后序遍历:左右根
而本章题目中比较记忆深刻的就是天梯赛中的深入虎穴了:
1 #include <iostream>
2 #include <cstdio>
3 #include <queue>
4 using namespace std;
5
6 typedef struct{
7 int doors;//门的数量
8 int *p;//指向后面的门的编号序列
9 }node;
10
11 int input(node *a, int n);
12 int level(node *a, int r);
13
14 int main(){
15 node *a;//a用于存储整棵树
16 int i, j, k;
17 int n;
18 cin>>n;
19 int root;
20 a = new node[n+1];
21 root = input(a, n);
22 cout<<level(a, root)<<endl;
23 return 0;
24
25 }
26
27 int input(node *a, int n){//读入n扇门的信息给a数组,返回根所在的门牌号 下标
28 int i, j;
29 bool *vi;
30 vi = new bool[n+1];
31 for(i=0; i<n+1; ++i)//初始化vi数组的全部元素为false
32 vi[i] = false;
33
34
35 for(i=1; i<=n; ++i){//读入n扇门的信息
36 cin>>a[i].doors;
37 if(a[i].doors!=0){
38 a[i].p = new int [a[i].doors];//
39 for(j=0; j<a[i].doors; ++j){
40 cin>>a[i].p[j];
41 vi[a[i].p[j]] = true;
42 }//for
43 }//if
44 else//doors为零
45 a[i].p = NULL;
46 } //for
47
48 for(i=1; i<=n; ++i)//找根结点所在的下标
49 if(!vi[i]) return i;
50 }
51
52 int level(node *a, int r){//对a数组进行层次遍历,并返回遍历最后一个结点的编号
53 queue<int> q;
54 int t, i;
55 q.push(r);
56
57 while(!q.empty()){
58 t = q.front();
59 q.pop();
60
61 if(a[t].doors!=0){//t号门后面还有门,后面的门入队
62 for(i=0; i<a[t].doors; ++i)
63 q.push(a[t].p[i]);
64
65 }
66 }
67 return t;
68 }
本章内容较多也是更为重要,学习过程中遇到的问题相较于前几章也多了不少,但是平心而论,树的学习反倒是个人感觉颇为有趣的一章,同时也是学习了不少新知识,收获颇多,美中不足的就是最后一周因为五一假期的原因学习松散了许多。在接下来的一周要快速调整过来,尽快回复到平时的学习节奏来