本章我们学习了树与二叉树,树对于我来说是一种新的概念,虽然它本身的结构比较简单,但是在认清一些概念的时候还是要费上一点功夫,我们学习到的有树的基本术语,二叉树的定义这些概念性的东西,
而后主要学习的是二叉树。二叉树的3个性质一开始上课时会因为概念不清晰而觉得一下子有点难理解,过后认真回顾一下书本,并画了一下图来数一下,以小见大的方式来理解就不费吹灰之力。然后便是老生
常谈的存储结构。存储结构分为:顺序存储和链式存储。
然后学习到遍历二叉树和线索二叉树。
遍历二叉树的算法描述有三种:先序、中序、后序。
其中可能中序有点难理解,以下是我理解的过程:
分享一下上课时老师和我们讲解的深入虎穴的题目:
著名的王牌间谍 007 需要执行一次任务,获取敌方的机密情报。已知情报藏在一个地下迷宫里,迷宫只有一个入口,里面有很多条通路,每条路通向一扇门。每一扇门背后或者是一个房间,或者又有很多条路,同样是每条路通向一扇门…… 他的手里有一张表格,是其他间谍帮他收集到的情报,他们记下了每扇门的编号,以及这扇门背后的每一条通路所到达的门的编号。007 发现不存在两条路通向同一扇门。
内线告诉他,情报就藏在迷宫的最深处。但是这个迷宫太大了,他需要你的帮助 —— 请编程帮他找出距离入口最远的那扇门。
输入格式:
输入首先在一行中给出正整数 N(<),是门的数量。最后 N 行,第 i 行(1)按以下格式描述编号为 i 的那扇门背后能通向的门:
K D[1] D[2] ... D[K]
其中 K
是通道的数量,其后是每扇门的编号。
输出格式:
在一行中输出距离入口最远的那扇门的编号。题目保证这样的结果是唯一的。
输入样例:
13
3 2 3 4
2 5 6
1 7
1 8
1 9
0
2 11 10
1 13
0
0
1 12
0
0
输出样例:
12
代码分解如下:
老师是采用指针根据门的数量分配空间并指向其后跟着的门的方法,十分新颖。
typedef struct{ int doors;//门的数量 int*p;//指向后面的门的编号序列 }node;
而后则是读入门的数量以及门的信息
int input(node*a,int n) {//读入n扇门的信息给a数组,同时返回根所在的门牌号 (下标) int i,j; bool*vi; vi=new bool[n+1]; for(i=1;i<=n;i++)//初始化vi数组的全部元素为false vi[i]=false; for(i=1;i<=n;i++)//读入n扇门的信息 { cin>>a[i].doors; if(a[i].doors!=0) { a[i].p=new int[a[i].doors];//为a【i】.p申请空间 for(j=1;j<=a[i].doors;j++){ cin>>a[i].p[j-1]; vi[a[i].p[j-1]] =true; }//for }//if else//doors为0的情况 a[i].p=NULL; }//外for for(i=1;i<=n;i++) if(!vi[i]) return i;//找到根节点所在的下标 }
遍历过程
int level(node*a,int r) {//从a[r]开始对a数组进行层次遍历并返回遍历的最后一个结点的编号 queue<int> q; int t,i; q.push(r); while(!q.empty()){ t=q.front(); q.pop(); if(a[t].doors!=0){//t号门后面还有门,后面的门就入队 for(i=0;i<a[t].doors;i++) q.push(a[t].p[i]); } } return t; }
完整代码:
#include<iostream> #include<queue> using namespace std; typedef struct{ int doors;//门的数量 int*p;//指向后面的门的编号序列 }node; int input(node*a,int n) {//读入n扇门的信息给a数组,同时返回根所在的门牌号 (下标) int i,j; bool*vi; vi=new bool[n+1]; for(i=1;i<=n;i++)//初始化vi数组的全部元素为false vi[i]=false; for(i=1;i<=n;i++)//读入n扇门的信息 { cin>>a[i].doors; if(a[i].doors!=0) { a[i].p=new int[a[i].doors];//为a【i】.p申请空间 for(j=1;j<=a[i].doors;j++){ cin>>a[i].p[j-1]; vi[a[i].p[j-1]] =true; }//for }//if else//doors为0的情况 a[i].p=NULL; }//外for for(i=1;i<=n;i++) if(!vi[i]) return i;//找到根节点所在的下标 } int level(node*a,int r) {//从a[r]开始对a数组进行层次遍历并返回遍历的最后一个结点的编号 queue<int> q; int t,i; q.push(r); while(!q.empty()){ t=q.front(); q.pop(); if(a[t].doors!=0){//t号门后面还有门,后面的门就入队 for(i=0;i<a[t].doors;i++) q.push(a[t].p[i]); } } return t; } int main() { node *a;//存储整棵树 int i,j,k; int n,root; cin>>n; a=new node[n+1]; root=input(a,n); //cout<<root<<endl; cout<<level(a,root)<<endl; return 0; }
最后是哈夫曼树的构造
在森林中选两棵根节点权值最小的树作为左右子树构造一颗新的二叉树,新根的权值为左右子树根结点的和,在森林中删除这两棵树,重复操作
之后的目标:
还没有将哈夫曼树掌握的很好,只是了解到皮毛,我觉得这是我后面的增长点。而对于树的应用其实还不是很敏感,还没有去总结一下什么情况
下采用树的结构会比较好,这是一个可以进步的地方,还有就是打码的能力还需进一步提高,对书本上的东西还要更熟悉。看到自己的进步还是有
点欣慰的。