练习46

来源:互联网 发布:java中double转string 编辑:程序博客网 时间:2024/05/16 19:18
/*********************************************************************************   46. 设有一个字符串,长度小于 100,且全部以英文字母组成。对字串中的每个字 母可用 0,1,2 三个数字进行编码,且数字可以重复使用。 程序要求:(1) 输入字符串,并能判断输入是否有错;           (2) 输出对应的编码表及码长,要求字串的编码总长度为最短;           (3) 根据上述编码表,给出一些编码,然后求出其原字符串。 例如:输入的字符为:ABCBAAADDEF     其对应的编码表为:         A:   2                B:  10         C:  11                D:  12         E:  00                F:  O1 对应的编码为:210111022212120001       总码长为:18 根据该编码,给出编码:010001121110222   则输出字串:FEFDCBAAAA.  ********************************************************************************/#include <iostream.h>#include <string.h>typedef struct{int w;char let;int parent;int child[3];}TreeNode;typedef struct{TreeNode* pNode;int root;}Tree;#define MaxBit 26typedef struct{char bit[MaxBit];int start;} CodeBit;Tree tree;CodeBit cb[MaxBit];void Build2BTree(int n,int count[],char letters[]){int i,s,t;//初始化节点树tree.pNode = new TreeNode[2*n-1];t=2*n-1;for(i=0; i<n; i++){tree.pNode[i].w = count[i];tree.pNode[i].let = letters[i];tree.pNode[i].parent = -1;tree.pNode[i].child[0] = -1;tree.pNode[i].child[1] = -1;tree.pNode[i].child[2] = -1;}while(i<t){int min1,min2;min1 = -1; min2 = -1;//找出权值最小的树for(s=0; s<i; s++){if(tree.pNode[s].parent == -1){if(min1 == -1)min1 = s;elseif(tree.pNode[s].w < tree.pNode[min1].w)min1 = s;}}//找出权值次小的树for(s=0; s<i; s++){if(tree.pNode[s].parent == -1 && s != min1){if(min2 == -1)min2 = s;elseif(tree.pNode[s].w < tree.pNode[min2].w)min2 = s;}}//生成新的树tree.pNode[i].w = tree.pNode[min1].w + tree.pNode[min2].w;tree.pNode[i].let = '\0';tree.pNode[i].parent = -1;tree.pNode[i].child[0] = min1;tree.pNode[i].child[1] = min2;tree.pNode[i].child[2] = -1;tree.pNode[min1].parent = i;tree.pNode[min2].parent = i;i++;}tree.root = t-1;}//返回树的节点类型int NodeType(int i){if(i == -1)//非节点return 2;if(tree.pNode[i].child[0] == -1)//叶子节点return 1;return 0;//非叶子节点}void Convert3BTree(Tree& tree,int n){int s,t,cur;//引入循环队列int* q = new int[n];s = t = 0;//树根入列if(NodeType(tree.root) == 0){q[t] = tree.root;t = (t+1)%n;}//遍历队列while(s!=t){int select = -1;int child0,child1;cur = q[s];s = (s+1)%n;child0 = tree.pNode[cur].child[0];child1 = tree.pNode[cur].child[1];if(NodeType(child0) == 0)select = child0;if(NodeType(child1) == 0){if(select == -1)select = child1;else{if(tree.pNode[select].w < tree.pNode[child1].w)select = child1;}}if(select != -1){int c0,c1,p;c0 = tree.pNode[select].child[0];c1 = tree.pNode[select].child[1];p = tree.pNode[select].parent;tree.pNode[c0].parent = p;tree.pNode[c1].parent = p;tree.pNode[p].child[2] = c1;if(select == child0)tree.pNode[p].child[0] = c0;elsetree.pNode[p].child[1] = c0;}//将类型为非叶子节点的子节点加入队列if(NodeType(tree.pNode[cur].child[0]) == 0){q[t] = tree.pNode[cur].child[0];t = (t+1)%n;}if(NodeType(tree.pNode[cur].child[1]) == 0){q[t] = tree.pNode[cur].child[1];t = (t+1)%n;}if(NodeType(tree.pNode[cur].child[2]) == 0){q[t] = tree.pNode[cur].child[2];t = (t+1)%n;}}delete []q;}void CodeLetter(Tree& tree,int n){for(int i=0; i<n; i++){int c = i;int p = tree.pNode[c].parent;char let = tree.pNode[c].let;int idx = (int)(let-0x41);cb[idx].bit[MaxBit-1] = '\0';cb[idx].start = MaxBit-1;while(p!=-1){if(tree.pNode[p].child[2] == c)cb[idx].bit[--(cb[idx].start)] = '2';else if(tree.pNode[p].child[1] == c)cb[idx].bit[--(cb[idx].start)] = '1';else if(tree.pNode[p].child[0] == c)cb[idx].bit[--(cb[idx].start)] = '0';c=p;p = tree.pNode[p].parent;}}}void Code(char *str,char *code){int i;for(i=0; str[i]!='\0'; i++){int idx;idx = str[i]-0x41;strcat(code,cb[idx].bit+cb[idx].start);}}void Decode(char *code,char *str){int i = 0;int j = 0;while(code[i]!='\0'){int p = tree.root;while(NodeType(p) == 0){p = tree.pNode[p].child[code[i]-0x30];i++;}str[j++] = tree.pNode[p].let;}str[j] = '\0';}void ShowLetterCode(int n,char letters[]){int i;for(i=0; i<n; i++){int idx = (int)(letters[i]-0x41);cout<<letters[i]<<": "<<cb[idx].bit+cb[idx].start<<endl;}}void FreeTreeNode(){delete []tree.pNode;}void main(){char str[101] = {'\0'};char code[500] = {'\0'};int i,n;int count[26]={0};char letters[26];//输入编码字符串cout<<"请输入字符串(全部以英文字母组成):"<<endl;cin>>str;//排错和统计字符出现频率for(i=0; str[i]!='\0'; i++){if(str[i]<0x41 || (str[i]>=0x5B && str[i]<=0x60) || str[i]>=0x7B){cout<<"输入有误:请输入英文字母!"<<endl;return;}else if(str[i]>0x60){str[i] = str[i] - 0x20;}count[str[i]-0x41]++;}for(i=0,n=0; i<26; i++){if(count[i]>0){count[n] = count[i];letters[n] = (char)(i+0x41);n++;}}//输出字母的出现频率for(i=0; i<n; i++)cout<<letters[i]<<":"<<count[i]<<" ";cout<<endl;cout<<"输入的字符为:"<<endl<<str<<endl;//建立最小权二叉树Build2BTree(n,count,letters);//转换为权值最小的三叉树Convert3BTree(tree,n);//显示字母对应的编码CodeLetter(tree,n);ShowLetterCode(n,letters);//编码Code(str,code);cout<<"字符串对应编码为:"<<code<<"   总码长为:"<<strlen(code)<<endl;//译码cout<<"请输入代码:";cin>>code;cout<<"译码为:";Decode(code,str);cout<<str<<endl;FreeTreeNode();}

 
原创粉丝点击