第五章小结
第五章学习了非线性结构树,数据元素之间存在一对多的关系。二叉树是一种最常用的树形结构,满二叉树和完全二叉树又是两种特殊形态的二叉树。
一、本章知识小结
二叉树的二叉链表存储表示:
1 typedef struct BiTNode 2 { 3 TElemType data; 4 struct BiTNode *lchild, *rchild; 5 }BiTNode, *BiTree;
中序遍历的递归算法:
viod InOrderTraverse(BiTree T) { if(T == NULL) return ; InOrderTraverse(T->lchild); cout<<T->data; InOrderTraverse(T->rchild); }
先序和后序遍历的递归算法与中序类似,只是cout语句的位置不一样。对含有n个结点的二叉树,遍历算法的时间复杂度都为O(n),空间复杂度都为O(n).
基于二叉链表的层次遍历:
viod level(BiTree T) { queue<BiTree> q; BiTree p; q.init(); q.push(T); while(!q.empty()) { p=q.front(); q.pop(); if(p!=NULL){ cout<<p->data<<' '; q.push(p->lchild); q.push(p->rchild); } } }
遍历结点的顺序是自上而下,自左向右。在队列里排队的是指针(结点的首地址),所以queue<BiTree> q;
但是理论与实际是有很大差别的,下面是我对于深入虎穴这道题的一些心得体会
二、深入虎穴
这道题已经不能再使用二叉树了,结点数目不再仅限于两个,而是多个,所以我们需要用到新的存储结构,
typedef struct node { int doors;//门的数量 int *p;//p指向具体门的编号,把p看作一个整型数组 }node;
根据实际的数据输入形式,我们需要一个input()函数建立树且返回根结点,还需要一个查找函数find()返回最远那扇门的编号,因此main()函数是
int main() { node *a;//定义一个动态的整型数组 int root; root = input(a); //返回根所在的下标 cout<<find(a,root); return 0; }
input函数
int input(node *&a) { int n,i; cin>>n; bool *vi; a=new node[n+1]; vi=new bool[n+1]; for(i=1;i<=n;i++) { //将vi数组初始化为false vi[i]=false; } for(i=1;i<=n;i++) { int x; cin>>x; a[i].doors=x; a[i].p=new int[x];//x的有效下标是从0到x-1,下面的循环j不能从1开始 for(int j=0;j<x;j++) { cin>>a[i].p[j]; vi[a[i].p[j]]=true; } } //找出根在数组的下标 for(i=1;i<=n;i++) { if(!vi[i]) break; } return i; }
这里采用的是创建动态数组的方法,虽然只有n扇门,但使用new的时候,创建的数组空间大小为n+1,这是为了数组下标能从1到n,能直接对应第几扇门。
数组的空间大小就决定了下标的有效范围,大小为n的数组,下标只能从0到n-1,在循环中要注意下标的取值。
find函数
int find(node *a,int root) {//从a数组的root下标开始往下搜索,层次遍历的最后一个结点就是最远的 int x=0; queue<int> q;//定义用于存放的带访问的门编号队列 q.push(root);//根编号入队 //当队列不为空 //x = 出队 //x后面的门号入队 while(!q.empty()) { x=q.front(); q.pop(); for(int i=0;i<a[x].doors;i++) { q.push(a[x].p[i]); } } return x;//答案就是x }
队列里排队的是门编号,是int类型,在定义一个队列时,首先要确定其中元素的类型!
这道题是老师带着我们一起完成的,一道题可以用多种的存储结构,但有一些基本的标准,是否能方便大量的数据操作,它的时间复杂度和空间复杂度;要基于这两点来选择合适的存储结构。如这道题还可以选用二维数组实现,但是N的数量是10的5次方,如果使用数组,是不能通过的,所以需要选用别的存储结构。
我认为能将数据正确存储并找到根结点编号,这道题已经成功了一半,理论与实际是有很大差别的,必须实际问题实际分析。遍历算法是解决树问题的基础,只有掌握了遍历算法,才能完成更多的实践。
上次的目标是多做编程题,但树的问题确实是不容易解决,所以没有很好的完成目标;接下来的目标是好好学习图这种更难的数据结构,多打代码。