练习46

 
  1. /**********************************************************************************
  2.   46. 设有一个字符串,长度小于 100,且全部以英文字母组成。对字串中的每个字
  3.  母可用 0,1,2 三个数字进行编码,且数字可以重复使用。
  4.  程序要求:(1) 输入字符串,并能判断输入是否有错;
  5.            (2) 输出对应的编码表及码长,要求字串的编码总长度为最短;
  6.            (3) 根据上述编码表,给出一些编码,然后求出其原字符串。
  7.  例如:输入的字符为:ABCBAAADDEF
  8.      其对应的编码表为:
  9.          A:   2                B:  10
  10.          C:  11                D:  12
  11.          E:  00                F:  01
  12.  对应的编码为:210111022212120001       总码长为:18
  13.  根据该编码,给出编码:010001121110222   则输出字串:FEFDCBAAA.
  14.   *******************************************************************************/
  15. #include <stdio.h>
  16. #include <malloc.h>
  17. //英文字母的个数
  18. #define LETTER_NUM 26
  19. //编码树节点
  20. typedef struct
  21. {
  22.     int weight;
  23.     int parent;
  24.     int child0;
  25.     int child1;
  26.     int child2;
  27. }   TreeNode;
  28. char *Letters;//字母
  29. int *Weights;//权值(字母使用的个数)
  30. int LetterNum;//字母个数
  31. TreeNode *Tree;//编码树节点集(数组指针)
  32. int NodeNum;//节点个数
  33. int CodeLen;//码长
  34. //统计字母个数
  35. int CountLetter(char *str)
  36. {
  37.     int i,k;
  38.     static int Counter[LETTER_NUM];
  39.     LetterNum = 0;
  40.     for(i=0; str[i] != '/0'; i++)
  41.     {
  42.         //如果含有非字母,返回错误
  43.         if(str[i]<0x61 || str[i]>0x7A)
  44.             return 0;
  45.         if(Counter[str[i]-0x61] == 0)
  46.             LetterNum ++;
  47.         Counter[str[i]-0x61] ++;
  48.     }
  49.     //为字母和统计个数分配空间
  50.     Letters = (char*)malloc(LetterNum*sizeof(char));
  51.     Weights = (int*)malloc(LetterNum*sizeof(int));
  52.     for(i=0,k=0; i<LETTER_NUM; i++)
  53.     {
  54.         if(Counter[i] > 0)
  55.         {
  56.             Letters[k] = (char)(i+0x61);
  57.             Weights[k++] = Counter[i];
  58.         }
  59.     }
  60.     return 1;
  61. }
  62. //创建编码树
  63. void CreateTree()
  64. {
  65.     int i,j;
  66.     int min1,min2,min3;
  67.     NodeNum = LetterNum + LetterNum/2;
  68.     Tree = (TreeNode*)malloc(NodeNum*sizeof(TreeNode));
  69.     for(i=0; i<LetterNum; i++)
  70.     {
  71.         Tree[i].weight = Weights[i];
  72.         Tree[i].parent = -1;
  73.         Tree[i].child0 = -1;
  74.         Tree[i].child1 = -1;
  75.         Tree[i].child2 = -1;
  76.     }
  77.     if(LetterNum % 2 == 0)
  78.     {
  79.         min1 = 0;
  80.         min2 = 1;
  81.         if(Tree[min1].weight > Tree[min2].weight)
  82.         {
  83.             int tmp;
  84.             tmp = min1;
  85.             min1 = min2;
  86.             min2 = tmp;
  87.         }
  88.         for(i=2; i<LetterNum; i++)
  89.         {
  90.             if(Tree[i].weight<Tree[min1].weight)
  91.             {
  92.                 min2 = min1;
  93.                 min1 = i;
  94.             }
  95.             else if(Tree[i].weight<Tree[min2].weight)
  96.             {
  97.                 min2 = i;
  98.             }
  99.         }
  100.         Tree[i].weight = Tree[min1].weight + Tree[min2].weight;
  101.         Tree[i].parent = -1;
  102.         Tree[i].child0 = min1;
  103.         Tree[i].child1 = min2;
  104.         Tree[i].child2 = -1;
  105.         Tree[min1].parent = i;
  106.         Tree[min2].parent = i;
  107.         i++;
  108.     }
  109.     //此处从最新生成的树开始搜索最小树根的树,树高比较大
  110.     /*
  111.     for(; i<NodeNum; i++)
  112.     {
  113.         j = i-1;
  114.         while(Tree[j].parent != -1) j--;
  115.         min1 = j--;
  116.         while(Tree[j].parent != -1) j--;
  117.         min2 = j--;
  118.         while(Tree[j].parent != -1) j--;
  119.         min3 = j--;
  120.         if(Tree[min1].weight > Tree[min2].weight)
  121.         {
  122.             int tmp;
  123.             tmp = min1;
  124.             min1 = min2;
  125.             min2 = tmp;
  126.         }
  127.         if(Tree[min1].weight > Tree[min3].weight)
  128.         {
  129.             int tmp;
  130.             tmp = min1;
  131.             min1 = min3;
  132.             min3 = tmp;
  133.         }
  134.         if(Tree[min2].weight > Tree[min3].weight)
  135.         {
  136.             int tmp;
  137.             tmp = min2;
  138.             min2 = min3;
  139.             min3 = tmp;
  140.         }
  141.         for(; j>=0; j--)
  142.         {
  143.             if(Tree[j].parent == -1)
  144.             {
  145.                 if(Tree[j].weight < Tree[min1].weight)
  146.                 {
  147.                     min3 = min2;
  148.                     min2 = min1;
  149.                     min1 = j;       
  150.                 }
  151.                 else if(Tree[j].weight < Tree[min2].weight)
  152.                 {
  153.                     min3 = min2;
  154.                     min2 = j;
  155.                 }
  156.                 else if(Tree[j].weight < Tree[min3].weight)
  157.                 {
  158.                     min3 = j;
  159.                 }
  160.             }
  161.         }*/
  162.     for(; i<NodeNum; i++)
  163.     {
  164.         j = 0;
  165.         while(Tree[j].parent != -1) j++;
  166.         min1 = j++;
  167.         while(Tree[j].parent != -1) j++;
  168.         min2 = j++;
  169.         while(Tree[j].parent != -1) j++;
  170.         min3 = j++;
  171.         if(Tree[min1].weight > Tree[min2].weight)
  172.         {
  173.             int tmp;
  174.             tmp = min1;
  175.             min1 = min2;
  176.             min2 = tmp;
  177.         }
  178.         if(Tree[min1].weight > Tree[min3].weight)
  179.         {
  180.             int tmp;
  181.             tmp = min1;
  182.             min1 = min3;
  183.             min3 = tmp;
  184.         }
  185.         if(Tree[min2].weight > Tree[min3].weight)
  186.         {
  187.             int tmp;
  188.             tmp = min2;
  189.             min2 = min3;
  190.             min3 = tmp;
  191.         }
  192.         for(; j<=i-1; j++)
  193.         {
  194.             if(Tree[j].parent == -1)
  195.             {
  196.                 if(Tree[j].weight < Tree[min1].weight)
  197.                 {
  198.                     min3 = min2;
  199.                     min2 = min1;
  200.                     min1 = j;       
  201.                 }
  202.                 else if(Tree[j].weight < Tree[min2].weight)
  203.                 {
  204.                     min3 = min2;
  205.                     min2 = j;
  206.                 }
  207.                 else if(Tree[j].weight < Tree[min3].weight)
  208.                 {
  209.                     min3 = j;
  210.                 }
  211.             }
  212.         }
  213.         Tree[i].weight = Tree[min1].weight + Tree[min2].weight + Tree[min3].weight;
  214.         Tree[i].child0 = min1;
  215.         Tree[i].child1 = min2;
  216.         Tree[i].child2 = min3;
  217.         Tree[i].parent = -1;
  218.         Tree[min1].parent = i;
  219.         Tree[min2].parent = i;
  220.         Tree[min3].parent = i;
  221.     }
  222. }
  223. //释放空间
  224. void DestroyTree()
  225. {
  226.     if(Letters)
  227.         free(Letters);
  228.     if(Weights)
  229.         free(Weights);
  230.     if(Tree)
  231.         free(Tree);
  232. }
  233. //打印生成树
  234. void PrintTree()
  235. {
  236.     int i;
  237.     printf("/n----CodeTree----/n");
  238.     for(i=0; i<NodeNum; i++)
  239.     {
  240.         printf("%4d",Tree[i].weight);
  241.         printf("%4d",Tree[i].parent);
  242.         printf("%4d",Tree[i].child0);
  243.         printf("%4d",Tree[i].child1);
  244.         printf("%4d/n/n",Tree[i].child2);
  245.     }
  246. }
  247. //显示字母编码表
  248. void EncodeLetters()
  249. {
  250.     int i,j,k,t;
  251.     char *code;
  252.     char tmp;
  253.     printf("/n其对应的编码表为:/n");
  254.     code = (char*)malloc(LetterNum*sizeof(char));
  255.     for(t=0; t<LetterNum; t++)
  256.     {
  257.         j = i = t; k = 0;
  258.         while(Tree[j].parent != -1)
  259.         {
  260.             j = Tree[j].parent;
  261.             if(Tree[j].child0 == i)
  262.                 code[k++] = '0';
  263.             else if(Tree[j].child1 == i)
  264.                 code[k++] = '1';
  265.             else code[k++] = '2';
  266.             i = j;
  267.         }
  268.         code[k] = '/0';//结束符
  269.         for(i=0; i<k/2; i++)//头尾置换
  270.         {
  271.             tmp = code[i];
  272.             code[i] = code[k-i-1];
  273.             code[k-i-1] = tmp;
  274.         }
  275.         printf("%c : %s/n",Letters[t],code);
  276.     }
  277.     free(code);
  278. }
  279. //编码
  280. void Encode(char *lets)
  281. {
  282.     int i,j,k,t;
  283.     char *code;
  284.     char tmp;
  285.     code = (char*)malloc(LetterNum*sizeof(char));
  286.     CodeLen = 0;
  287.     
  288.     for(t = 0; lets[t] != '/0'; t++)
  289.     {
  290.         for(i=0; i<LetterNum; i++)
  291.         {
  292.             if(Letters[i] == lets[t])
  293.                 break;
  294.         }
  295.         j = i; k = 0;
  296.         while(Tree[j].parent != -1)
  297.         {
  298.             j = Tree[j].parent;
  299.             if(Tree[j].child0 == i)
  300.                 code[k++] = '0';
  301.             else if(Tree[j].child1 == i)
  302.                 code[k++] = '1';
  303.             else code[k++] = '2';
  304.             i = j;
  305.             CodeLen++;
  306.         }
  307.         code[k] = '/0';//结束符
  308.         for(i=0; i<k/2; i++)//头尾置换
  309.         {
  310.             tmp = code[i];
  311.             code[i] = code[k-i-1];
  312.             code[k-i-1] = tmp;
  313.         }
  314.         printf(code);
  315.     }
  316.     free(code);
  317.     printf("/n");
  318. }
  319. //译码
  320. void Decode(char *codes)
  321. {
  322.     int i,j,k=0;
  323.     int ch;
  324.     do
  325.     {
  326.         i = NodeNum-1;
  327.         while(Tree[i].child0 != -1 && Tree[i].child1 != -1)
  328.         {
  329.             ch = codes[k++];
  330.             if(ch == '/0')
  331.                 break;
  332.             if(ch == '0')
  333.                 j = Tree[i].child0;
  334.             else if(ch == '1')
  335.                 j = Tree[i].child1;
  336.             else j = Tree[i].child2;
  337.             i = j;
  338.         }
  339.         //写入Decode
  340.         printf("%c",Letters[i]);
  341.     }while(ch != '/0');
  342.     printf("/n");
  343. }
  344. //main
  345. void main()
  346. {
  347.     char str[100];
  348.     char code[100];
  349.     printf("请输入要编码的字母串(长度小于100):/n");
  350.     scanf("%s",str);
  351.     if(!CountLetter(str))
  352.     {
  353.         printf("The string has error!/n");
  354.         return ;
  355.     }
  356.     CreateTree();
  357. //  PrintTree();
  358.     EncodeLetters();
  359.     printf("对应的编码为:");
  360.     Encode(str);
  361.     printf("总码长为: %d/n", CodeLen);
  362.     printf("根据该编码,给出编码:");
  363.     scanf("%s",code);
  364.     printf("则输出字串:");
  365.     Decode(code);
  366. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值