二叉树的基本操作及应用

mac2026-01-19  6

二叉树的基本操作实现

[问题描述] 建立一棵二叉树,试编程实现二叉树的如下基本操作:

按先序序列构造一棵二叉链表表示的二叉树T;对这棵二叉树进行遍历:先序、中序、后序以及层次遍历,分别输出结点的遍历序列;求二叉树的深度/结点数目/叶结点数目;(选做)将二叉树每个结点的左右子树交换位置。(选做) [基本要求] 从键盘接受输入(先序),以二叉链表作为存储结构,建立二叉树(以先序来建立), [测试数据] 如输入:ABCффDEфGффFффф(其中ф表示空格字符) ABC DE G F

则输出结果为

先序:ABCDEGF 中序:CBEGDFA 后序:CGEFDBA 层序:ABCDEFG

[选作内容] 采用非递归算法实现二叉树遍历。 CODE:

#include <iostream> #include <cstdio> using namespace std; typedef struct TNode { char data; struct TNode *l,*r; } TNode,*Tree; void CreatBiTree(Tree &t) { char ch; ch=getchar(); //注意字符可能是空格所以不能用cin if(ch==' ') t=NULL; else { t=new TNode; t->data=ch; CreatBiTree(t->l); CreatBiTree(t->r); } return; } void Preordering(Tree t) { if(t!=NULL) { cout<<t->data; Preordering(t->l); Preordering(t->r); } } void Middleorder(Tree t) { if(t!=NULL) { Middleorder(t->l); cout<<t->data; Middleorder(t->r); } } void Postorder(Tree t) { if(t!=NULL) { Postorder(t->l); Postorder(t->r); cout<<t->data; } } typedef struct QNode { Tree base; struct QNode *next; } QNode,*QueuePtr; typedef struct { QueuePtr f,r; } LinkQueue; void InitQueue(LinkQueue &q) { q.f=q.r=new QNode; q.f->next=NULL; return; } void Qpush(LinkQueue &q,Tree t) { QueuePtr p; p=new QNode; p->base=t; p->next=NULL; q.r->next=p; q.r=p; return; } bool Empty(LinkQueue q) { return q.f==q.r; } void arrangement(Tree t) { LinkQueue q; InitQueue(q); if(t) Qpush(q,t); while(!Empty(q)) { q.f=q.f->next; Tree k; k=new TNode; k=q.f->base; cout<<k->data; if(k->l) Qpush(q,k->l); if(k->r) Qpush(q,k->r); } cout<<endl; return; } int Deap(Tree t) { if(!t) return 0; int m,n; m=Deap(t->l); n=Deap(t->r); return m>n?m+1:n+1; } int Node(Tree t) { if(!t) return 0; else return Node(t->l)+Node(t->r)+1; } int Leaf(Tree t) { if(!t) return 0; else{ if(!t->l&&!t->r) return 1; else return Leaf(t->l)+Leaf(t->r); } } void Swap(Tree &t) { Tree root; root=t->l; t->l=t->r; t->r=root; if(t->l) Swap(t->l); if(t->r) Swap(t->r); } int main() { Tree t; CreatBiTree(t); cout<<"先序:"; Preordering(t); cout<<endl; cout<<"中序:"; Middleorder(t); cout<<endl; cout<<"后序:"; Postorder(t); cout<<endl; cout<<"层次:"; arrangement(t); cout<<"树的深度:"; cout<<Deap(t)<<endl; cout<<"结点数目:"; cout<<Node(t)<<endl; cout<<"叶结点数目:"; cout<<Leaf(t)<<endl; cout<<"左右子树交换位置后:"<<endl; Swap(t); cout<<"先序:"; Preordering(t); cout<<endl; cout<<"中序:"; Middleorder(t); cout<<endl; cout<<"后序:"; Postorder(t); cout<<endl; cout<<"层次:"; arrangement(t); return 0; }

哈夫曼树和哈夫曼编码

[问题描述]  一电文,有若干个不同字符,要求从终端输入这些不同字符及其出现的频率,然后对这些字符进行哈夫曼编码,并输出。 [测试数据] 利用教材P.139 例5.2中的数据调试程序 (可自己设定测试数据)。 [选作内容] 1、打印出该哈夫曼树 2、若从终端输入任意一段电文(假设仅为26个大小写英文字母),试编程高效地求出该段电文的哈夫曼编码。 提示:如何快速统计不同字符的出现频率 3、译码:将上述1的编码结果还原成电文。 样例输入:

aabbcdeffff

样例输出:

各个字母出现的次数为: a:2 b:2 c:1 d:1 e:1 f:4 1 a 2 0 0 0 2 b 2 0 0 0 3 c 1 0 0 0 4 d 1 0 0 0 5 e 1 0 0 0 6 f 4 0 0 0 每次连接的结点: 3 4 7 5 1 8 2 7 9 8 6 10 9 10 11 1 a 2 8 0 0 2 b 2 9 0 0 3 c 1 7 0 0 4 d 1 7 0 0 5 e 1 8 0 0 6 f 4 10 0 0 7 2 9 3 4 8 3 10 5 1 9 4 11 2 7 10 7 11 8 6 11 11 0 9 10 Huffman Code: a:101 b:00 c:010 d:011 e:100 f:11 String Huffman Code: 101101000001001110011111111 写一串由上面Huffman Code组成的编码,输入#结束: 1110001010101100 fecadb 1111 ff #

CODE:

#include <iostream> #include <algorithm> #include <cstring> #include <string> using namespace std; struct Huffman { char data; int s,w,p,l,r; }; Huffman h[60]; int b[1000]; void CreatHuffman(int e) { int i,j; Huffman m1,m2,m; for(j=e; j<=2*e-3; j++) //一共e个节点,所以要遍历e-1遍 { m1.w=0; m2.w=0; for(i=1; i<j; i++) //每次遍历选出两个权值最小的进行建立二叉树 { if(h[i].p==0) { if(m1.w==0) //先对m1进行赋值 { m1=h[i]; } else if(m2.w==0) //在对m2进行赋值 { m2=h[i]; if(m1.w>m2.w) //保证m1的权重小于m2的权重。 { m=m1; m1=m2; m2=m; } } else { if(m1.w>h[i].w) //保证m1是最小的 { m2=m1; m1=h[i]; } else if(m2.w>h[i].w) //如果不判断,到最后可能m1是最小的,但是m2不一定是次小的 m2=h[i]; } } } cout<<m1.s<<" "<<m2.s<<" "<<j<<endl; //输出两个最小的结点 h[j].w=m1.w+m2.w; //建立新的结点作为两个结点的双亲结点 h[j].s=j; h[j].l=m1.s; h[j].r=m2.s; h[m1.s].p=j; //对孩子节点的双亲节赋值 h[m2.s].p=j; } } int out(int t,int k) { if(h[t].p==0) //双亲结点为0则为哈夫曼树的根节点,返回搜索的长度,即字符的哈夫曼编码的长度 return k; if(h[h[t].p].l==t) //是左孩子就输出0,再看双亲 { b[k]=0; out(h[t].p,++k); } else if(h[h[t].p].r==t) //是右孩子就输出1,再看双亲 { b[k]=1; out(h[t].p,++k); } } int pop(int i,int n,int t) { while(h[t].l!=0||h[t].r!=0) //左右孩子都为0那么证明到了叶子节点,输出叶子节点代表的字符 { if(b[i]==0) { t=h[t].l; i++; } else if(b[i]==1) { t=h[t].r; i++; } } cout<<h[t].data; return i; } int main() { int a[60]; string str; while(cin>>str) { memset(a,0,sizeof(a)); memset(h,0,sizeof(h)); int i,j; for(i=0; i<str.length(); i++) //将输入的字符串统计各个字符出现的,区分大小写。用一个数组存储,前26个存储小写字母,后26个存储大写字母 { if(str[i]<='z'&&str[i]>='a') a[str[i]-'a']++; else if(str[i]<='Z'&&str[i]>='A') a[str[i]-'A'+26]++; } int e=1; cout<<"各个字母出现的次数为:"<<endl; for(i=0; i<26; i++) //将各个字母出现的次数输出,出现的次数为0就不需要输出了,同时记录次数不为0的字母的个数。将字母出现的次数作为该字母的权重。 { if(a[i]!=0) { cout<<(char)('a'+i)<<":"<<a[i]<<"\t"; h[e].w=a[i]; h[e].s=e; h[e++].data=(char)('a'+i); } } cout<<endl; for(i=26; i<52; i++) { if(a[i]!=0) { cout<<(char)('A'+i-26)<<":"<<a[i]<<"\t"; h[e].w=a[i]; h[e].s=e; h[e++].data=(char)('A'+i-26); } } cout<<endl; for(i=1; i<e; i++) //输出HT初态,包括节点、字符、权重、双亲节点、左右孩子节点 cout<<h[i].s<<" "<<h[i].data<<" "<<h[i].w<<" "<<h[i].p<<" "<<h[i].l<<" "<<h[i].r<<endl; cout<<"每次连接的结点:"<<endl; //建立哈夫曼树 CreatHuffman(e); cout<<endl; for(i=1; i<=2*e-3; i++) //输出HT的终态,包括节点、字符、权重、双亲节点、左右孩子节点 cout<<h[i].s<<" "<<h[i].data<<" "<<h[i].w<<" "<<h[i].p<<" "<<h[i].l<<" "<<h[i].r<<endl; cout<<endl; cout<<"Huffman Code:"<<endl; //输出各个字符的哈夫曼编码 for(i=1; i<e; i++) { cout<<h[i].data<<":"; for(int k=out(i,0); k>0; k--) //通过调用out()函数来获取编码长度,以及对数组赋值 cout<<b[k-1]; cout<<endl; } cout<<"String Huffman Code:"<<endl; //输出字符串的哈夫曼编码 for(i=0; i<str.length(); i++) { for(j=1; j<e; j++) { if(h[j].data==str[i]) //查找到字符所在位置 { memset(b,-1,sizeof(b)); for(int k=out(j,0); k>0; k--) cout<<b[k-1]; break; } } } cout<<endl; cout<<"写一串由上面Huffman Code组成的编码,输入#结束:"<<endl; //可以通过输入哈夫曼编码来翻译成字符串 while(cin>>str) { if(str[0]=='#') break; for(i=0; i<str.length(); i++) //字符数组转成整型数组 { b[i]=str[i]-'0'; } int t; for(i=1; i<=2*e-3; i++) //寻找根节点 { if(h[i].p==0) { t=h[i].s; break; } } for(i=0; i<str.length();) // { i=pop(i,str.length(),t); } cout<<endl; } } return 0; }

寻求最佳判断

[问题描述] 试设计一个算法,用最少的比较,尽快地将N个随机的百分制成绩转换成五级分制. 0~59 ———————————————————— bad 60~69 ———————————————————— pass 70~79 ———————————————————— general 80~89 ———————————————————— good 90~100 ———————————————————— excellent [设计要求] 输入n个任意的百分制分数,要求输出对应的等级

非标准正确答案 CODE:

#include <iostream> #include <string> using namespace std; struct grade { double data; int node,score; string str; }; grade a[1100]; int e; void per() { cout<<"90~100:"; cin>>a[e].data; a[e].node=e; a[e].score=90; a[e].str="excellent"; e++; cout<<"80~89:"; cin>>a[e].data; a[e].score=80; a[e].str="good"; e++; cout<<"70~79:"; cin>>a[e].data; a[e].score=70; a[e].str="general"; e++; cout<<"60~69:"; cin>>a[e].data; a[e].score=60; a[e].str="pass"; e++; cout<<"0~59:"; cin>>a[e].data; a[e].score=0; a[e].str="bad"; e++; } int main() { cout<<"输入各分数段的百分制:"<<endl; e=1; per(); double sum=0; int i,t,n; for(i=1; i<e; i++) { sum+=a[i].data; if(sum>=0.5) break; } cout<<"以"<<a[i].score<<"为根"; cout<<"输入任意的百分制分数,输入其他结束:"<<endl; while(cin>>n) { t=i; if(n<0||n>100) break; if(n>a[t].score) { int j=1; while(j<=t) { if(a[j].score<=n) { cout<<a[j].str<<endl; break; } else { j++; } } } else { while(t<=5) { if(a[t].score<=n) { cout<<a[t].str<<endl; break; } else { t++; } } } } return 0; }

果子合并

[问题描述] n堆果子, 每堆果子数量任意,试设计一种最佳方案,将这n堆果子合并为一堆,使得合并工作量最小。 注:规定合并两堆果子的工作量是这两堆果子的数量之和。 [标准输入] M,N M表示M组测试数据,N表示每组测试数据数量不超过N个,每堆果子数量不超过10000。随后的M行是测试数据。 [标准输出] M行数据表示对应果子的合并工作量

[输入样例]:

2 6 7, 5, 2, 4 5,6,2,9,7

【输出样例】:

35 65

CODE:

#include <iostream> #include <cstdio> #include <cstring> using namespace std; struct fruit { int w,s; }; int main() { int n,m; while(cin>>m>>n) { while(m--) { fruit a[11000]; memset(a,0,sizeof(a)); int e=1,i,j; char ch=','; while(ch==',') { a[e].s=e; cin>>a[e++].w; ch=getchar(); } int sum=0; fruit m1,m2,m3; for(i=e; i<2*e-2; i++) { cout<<i<<','; m1.w=m2.w=-1; for(j=1; j<i; j++) { if(a[j].s!=-1) { if(m1.w==-1) { m1=a[j]; } else if(m2.w==-1) { m2=a[j]; if(m1.w>m2.w) { m3=m1; m1=m2; m2=m3; } } else { if(m1.w>=a[j].w) { m2=m1; m1=a[j]; } else if(m2.w>=a[j].w) m2=a[j]; } } } a[m1.s].s=-1; a[m2.s].s=-1; a[i].w=m1.w+m2.w; a[i].s=i; sum+=a[i].w; } cout<<sum<<endl; } } return 0; }
最新回复(0)