第五章学习了树
学习树的时候感觉树很乱,其实主要是存储结构问题,我理清了一下思路
就树的存储结构而言
链式结构一般是二叉链表和三叉链表,不过这仅局限于二叉树
顺式存储的本质是一维数组,每个结点的具体存储结构需要根据应用场景来决定
在这章的实践和作业,用到的存储结构都是顺序存储,在数据的读入,用到的手法几乎一致
以下给出例子
1 int CreatTree(node t[]) 2 { 3 int N; 4 5 cin >> N; 6 7 bool check[100]={false}; 8 9 for(int i=0;i<N;i++) 10 { //将数据存入数组,并寻找根节点 11 12 cin >> t[i].lch >> t[i].rch ; //输入两个节点 13 14 if(t[i].lch>='0' && t[i].lch<='9') 15 { 16 17 t[i].lch=t[i].lch-'0'; 18 check[t[i].lch]=true; 19 } 20 else 21 t[i].lch=-1; //将字符换为-1存储起来 22 23 24 if(t[i].rch>='0' && t[i].rch<='9') 25 { 26 27 t[i].rch=t[i].rch-'0'; 28 check[t[i].rch]=true; 29 } 30 else 31 t[i].rch=-1; 32 } 33 34 for(int i=0;i<N;i++) 35 if(!check[i]) 36 return i; 37 } //函数结束
然后作业题还用到层次遍历
void level(node t[],int x) { int tmp=0; queque<int> q; q.push(x); //将根节点的序号入队 int flag=0; while(!q.empty()) { tmp=q.front(); q.pop(); if(tmp!=-1) { q.push(t[tmp].lch); q.push(t[tmp].rch); } if(t[tmp].lch==-1 && t[tmp].rch==-1) { if(flag==0) { cout << tmp <<" "; //先输出第一个 flag++; } else cout<< " " <<tmp; //从第二个开始后的输出 }
实践题的深入虎穴和作业题用到的手法类似,在树的同构里,我觉得很容易被忽略的是两颗树都为空的情形,一般边界情况最容易写,但往往最容易被忽略
感觉分析问题还是要从浅入深。而且在学习过程中,还感受到了递归的“魅力”,只要把表层写好,后面的就不会出问题。以下是递归的一个函数
int Isomorphic(int root1,int root2) { //用递归结构判断 if(root1==-1 && root2==-1) return 1; //若都为空树,则同构 if((root1==-1 && root2!=-1) || (root1!=-1 && root2==-1)) return 0; //一颗为空,一颗不为空则不同构 if(t1[root1].name!=t2[root2].name) return 0; //第一层数据不相等,不同构 if(t1[root1].lch==-1 && t2[root2].rch==-1) //如果左孩子都为空 return( Isomorphic(t1[root1].rch,t2[root2].rch)); //判断右孩子是否为空,数据是否相等,是否一个有右孩子,一个没有 if((t1[root1].lch!=-1) && (t2[root2].lch!=-1) && (t1[t1[root1].lch].name==t2[t2[root2].lch].name)) return ( Isomorphic(t1[root1].lch,t2[root2].lch) && Isomorphic(t1[root1].rch,t2[root2].rch ) ) ; else return( Isomorphic( t1[root1].lch,t2[root2].rch ) && Isomorphic( t1[root1].rch,t2[root2].lch ) ) ;}