Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4662
  • 博文数量: 6
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 51
  • 用 户 组: 普通用户
  • 注册时间: 2014-08-31 23:39
文章分类
文章存档

2014年(6)

我的朋友
最近访客

分类: C/C++

2014-09-01 00:07:42


点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define N 7


  4. //-------------------------双亲孩子表(存储huffman树)--------------------------//
  5. typedef struct
  6. {
  7.     int weight;
  8.     int parent,lchild,rchild;
  9. }Huffmantree;



  10. //-------------------------存储最后得出的huffman编码---------------------------//
  11. typedef struct
  12. {
  13.     char ch;
  14.     char bits[N+1];//由于huffman得出的编码的长度不会超过N+1(叶节点个数加‘\0’)
  15. } CodeNode;

  16. //--------------------------------定义链表结构----------------------------------//

  17. typedef struct Node
  18. {
  19.     int data;
  20.     struct Node *next;
  21. }Node,*LinkedList;

  22. LinkedList L;
  23. /*由于是全局变量,所以下面不能对L直接进行赋值操作,而要间接操作,不然L就不是指向
  24. 正确的连表了如L=L->next是错误的,P=L ,P=P->next才是正确的*/

  25. void LinkedListInit()
  26. {

  27.     L=(Node *)malloc(sizeof(Node));
  28.     if(L==NULL)
  29.     {
  30.         printf("申请聊表失败!");
  31.         exit(0);
  32.     }
  33.     L->next=NULL;

  34. }


  35. //---------------------------------构造一个从大到小的链表------------------------------------//
  36. void LinkListIn(int i,Huffmantree tree[])//链表中按节点数据大小顺序插入
  37. {


  38.         LinkedList P,I,T;
  39.         P=L;

  40.         while( (P->next != NULL)&&(tree[i].weight > tree[P->next->data].weight) )
  41. //两个条件不能调换,P->next!=NULL是tree[P->next->data].weight)正常运行的前提,不然会出现指针越界错误(自动退出程序的后果)
  42.         {
  43.             P = P->next;
  44.         }
  45.         I=(Node *)malloc(sizeof(Node));//以下是插入节点的操作
  46.         I->data = i;
  47.         T = P->next;
  48.         P->next = I;
  49.         I->next = T;

  50. }

  51. //--------------------------从链表中取最小的两个数---------------------------//
  52. int LinkListInOut()//由于链表已经从小到大排好,直接取L->next,就是最小的数,
  53. {
  54.     int i;
  55.     LinkedList P;
  56.     i = L->next->data;
  57.     P=L->next;
  58.     L->next=P->next;
  59.     free(P); //取出来后一定要记得 删除
  60.     return i;//一定要放在最后return,因为return是结束和带回返回值的标志

  61. }
  62. //-----------------------------构造huffman树---------------------------------//
  63. void CreatHuffmanTree(Huffmantree tree[],int n)
  64. {
  65.     int i,j,d,x,f;
  66.     LinkedListInit();

  67.     for(i=0;i<n;i++)//初始化tree数组,因为下面没有操作到得数组内容都为NULL也就是0
  68.     {
  69.         tree[i].weight=0;
  70.         tree[i].parent=0;
  71.         tree[i].lchild=0;
  72.         tree[i].rchild=0;
  73.     }
  74.     printf("输入权重(A,B,C,D,E,F,G):");
  75.     for(i=0; i < N; i++)
  76.     {
  77.         scanf("%d",&f);//scanf的数字输入不用当心缓冲区问题
  78.         tree[i].weight = f;
  79.         LinkListIn( i, tree );//插入链表
  80.     }

  81.    for( j = N; j < 2*N-1; j++ )//由于这个过程会产生N-1个新节点,而且每个新节点都要放到链表中,所以构建是N-1次
  82.    {
  83.         d=LinkListInOut();//从链表中取出最小的两个数
  84.         x=LinkListInOut();
  85.         tree[j].weight = tree[d].weight + tree[x].weight;//新节点的权重
  86.         tree[d].parent=j;//以下是填写新节点的左右孩子,以及他的左右孩子的父母(就是这个新节点)
  87.         tree[x].parent=j;
  88.         tree[j].rchild=d;
  89.         tree[j].lchild=x;
  90.         LinkListIn(j,tree);
  91.     }
  92. }
  93. //-----------------------------------编码阶段------------------------------------//
  94. void Huffman(Huffmantree tree[])
  95. {
  96.     char cd[N];
  97.     char ch[7]={'A','B','C','D','E','F','G'};
  98.     int i,j,p;

  99.     for( i = 0; i < N; i++)
  100.     {
  101.         int start=N;//最后得出的结果要反序,在这里使用了从数组最后向前填写,在最终输出时从前读到后(从start读到数组尾部)
  102.         int c=i;
  103.        while( p = tree[c].parent )//读取路径,左为0,右为1,可以其他的(以至于答案不唯一)
  104.         {
  105.         if( tree[p].lchild == c )
  106.             cd[--start] ='0';//从末尾往开头写
  107.         else
  108.             cd[--start] ='1';
  109.         c=p;
  110.         }
  111.         printf("%c:",ch[i]);
  112.         for(j=start;j<N;j++)//从开头往末尾读
  113.             printf("%c",cd[j]);
  114.         printf(" ");
  115.     }



  116. }



  117. //-------------------------------------------------------------------------------//
  118. main()
  119. {
  120.     Huffmantree tree[2*N-1];//一共有2*N-1个节点

  121.     CreatHuffmanTree(tree,2*N-1);//构造哈弗曼树
  122.     Huffman(tree);//哈弗曼编码

  123.     return 0;
  124. }
        运行时输入自己定义的权重(或可以自己实现统计计算权重,这里就不说了)。
        在此只有a,b,c,d,e,f四个数,可与根据要就改写ch[]数组和N。

        最后得出权重越大(一般为重复出现次数越多权重越大),编码越短。。。这就是哈弗曼编码的精辟。














阅读(52) | 评论(0) | 转发(0) |
1

上一篇:没有了

下一篇:回溯法实现八皇后问题

给主人留下些什么吧!~~