哈夫曼编码(数据结构)源程序

来源:互联网 发布:淘宝配货员工资多少 编辑:程序博客网 时间:2024/05/08 04:09
构造思想:哈夫曼树 1:由给定的n个权值构造n棵树只有一个叶子结点的二叉树,得到一个二叉树的合F; 2:再F中选取根结点的权值最小和次小的二棵二叉树作为左,右子树构造一棵新的二叉树,这棵树的根结点的权值为左右子树根结点权值之和。 3:在集合F中删除作为左右子树的二棵二叉树,并将新建的二叉树加入到集合F中。 4:重复2 ,3两步,当F中只剩下一棵二叉树时,便建立好一棵哈夫曼树
/********************************/
/*编写者:小黎                                */
/*目的:给数据结构初学者一点点帮助      */
/********************************/


#include<conio.h>
#include<stdio.h>
#include<alloc.h>
#define n  100
int h[50],m[50];
int i=0,j=0,v=1,t=1;  
/*用来标记huffman树的深度*/
int k=195,K=192,chp=179,chr=27; /*输出huffman时用到的字符*/
int huffrecod=0;         /*用于记录huffman的编码与字符的个数*/
typedef struct Lnode{            /*用来记录字符的个数*/
char code;
int  values;
struct Lnode *next;
}Lnode,*listnode;

typedef struct charhuffman{   /*用来记录字符的huffman编码序列*/
char code;
int huffuman[15];
int count; /*记录编码的个数*/
}charhuffman,*huffmanchar;

typedef struct treenode{ /*二叉树的构造体*/
char code;
int values;
struct treenode *lchild;
struct treenode *rchild;
}treenode,*ntree;

typedef struct queuenode/*队列的构造体*/
{
  int values;
  struct treenode *pntree;
  struct queuenode *next;
}queuenode,*listqueue;

huffmanchar huff;

listqueue returnroot(listnode heap)
{
 listqueue s,t,k;
 ntree p;
 s=(listqueue)malloc(sizeof(queuenode)); /*建立队列的头结点*/
 k=s;
 s->values=0; s->pntree=NULL; s->next=NULL;
 while(heap!=NULL)
 {
  p=(ntree)malloc(sizeof(treenode));
  p->code=heap->code;
  p->values=heap->values;p->lchild=NULL;p->rchild=NULL;
  t=(listqueue)malloc(sizeof(queuenode));
  t->values=heap->values;
  t->pntree=p; s->next=t; t->next=NULL;
  s=s->next;
  heap=heap->next;
 }
return k;
}

listnode creatleaflist(char s[])  /*输入字符序列,确定叶子结点及权值*/
{listnode heap,p,r;
 int i,j=0;
 p=(listnode)malloc(sizeof(Lnode));
 heap=p;
 p->next=NULL;p->code=s[0];p->values=1;
  while(s[j]!=NULL)
 {for(i=0;i<j;i++)
  { if(s[i]==s[j])
    { r=heap;
      while(s[i]!=r->code)
      r=r->next;
      if(s[i]==r->code)
         r->values++;
      break;   
      }/*if(s[i]==s[j])*/
     else
      {  if(i==(j-1))
        {
         r=(listnode)malloc(sizeof(Lnode));
         p->next=r;r->next=NULL;
         p=p->next;p->code=s[j];p->values=1;
         break;
        }/*if(i==(j-1))*/
      }
    }/*for(i=0;i<j;i++)*/
  j++;
 } /*while(s[j]!=NULL)*/
return heap;
}

listqueue heaplistqueue(listqueue heapqueue) /*确定哈曼树*/
{listqueue pk,pks,rs,rss,freep;
  int a,b,i,j;
  ntree pa,pb,ps;
  pk=heapqueue;
  pks=heapqueue;
  while(pk->next->next!=NULL)
  { i=0,j=0; /*用来确定是否删除最小两权植的结点*/
    pks=pks->next;
    a=pks->values;
    b=pks->next->values;
    while(pks->next!=NULL) /*找到最小两个权值*/
    {pks=pks->next;
     if(a>pks->values){b=a;a=pks->values;}
     else{if(b>pks->values) b=pks->values;}
    }
    rs=pk;
    heapqueue=rs->next;
    while(heapqueue!=NULL)
    { if(heapqueue->values==a&&i==0)
        {pa=heapqueue->pntree;
          rs->next=heapqueue->next;
          freep=heapqueue;
          free(freep);
          heapqueue=rs->next;
          i=1;      
        }else
         {if(heapqueue->values==b&&j==0)
          {pb=heapqueue->pntree;
           rs->next=heapqueue->next;
           freep=heapqueue;
           free(freep);
           heapqueue=rs->next;
           j=1;
          }else
             {rs=heapqueue;
              heapqueue=heapqueue->next;
             }
         }
    }/*while(heapqueue!=NULL)*/
    heapqueue=rs;
    ps=(ntree)malloc(sizeof(treenode));
    ps->code='';ps->lchild=pa;ps->rchild=pb;ps->values=a+b;
    rss=(listqueue)malloc(sizeof(queuenode));
    rss->values=a+b;
    rss->pntree=ps;
    heapqueue->next=rss;
    rss->next=NULL;
    pks=pk;
   }
 return pk;
}

void printdata(ntree heaptree)  /*输出哈夫曼编码及输出哈夫曼树*/
{
 int j;
 if(heaptree->code!='')
  {printf("%d",heaptree->values);
   printf(" %c",chr);
   printf("%c",heaptree->code);
   printf("--(");
   huff[huffrecod].code=heaptree->code;
   huff[huffrecod].count=i;
   for(j=0;j<i;j++){
     huff[huffrecod].huffuman[j]=h[j];
     printf("%d",h[j]);
     }
   printf(")/n");
   huffrecod++;
   i--;
  }
  else
  {h[i++]=0;
   v=i;
   printf("%d/n",heaptree->values);
   while(--v)
   printf("%c ",chp);
   printf("%c ",k);
   printdata(heaptree->lchild);
   h[i++]=1;
   t=i;
   while(--t)
   printf("%c ",chp);
   printf("%c ",K);
   printdata(heaptree->rchild);
   i--;
  }
}

void encode(char s[],huffmanchar huff)
{ int nt=0;
  int hfcount;
  int ihuff;
  while(s[nt]!=NULL)
  { for(ihuff=0;ihuff<50;ihuff++)
    { if(s[nt]==huff[ihuff].code)
      {for(hfcount=0;hfcount<huff[ihuff].count;hfcount++)
        {printf("%d",huff[ihuff].huffuman[hfcount]);
        }
        break;
      }
    }
    nt++;
  }
}

void main()
{
 int i=0,j=0;
 char s[n],c;
 listnode heap; /*确定叶子结点*/ 
 ntree heaptree; /*确定哈夫曼树*/
 listqueue heapqueue,pk;
 huff=(huffmanchar)malloc(50*sizeof(charhuffman));
 gotoxy(30+wherex(),wherey());
 textcolor(BLACK);
 textbackground(WHITE);
 cprintf("This huffman program/r/n");
 printf("please input char list and in Enter of end!:/n/n");
 c=getchar();
 if(c=='/n')
 exit(0);
 while(c!='/n')
 {s[i++]=c;
  c=getchar();
  }
 heap=creatleaflist(s);
 heapqueue=returnroot(heap);
 printf("/nthe chars appear of frequency:/n");
 while(heap!=NULL)
 {printf("%c%d/t",heap->code,heap->values);
  heap=heap->next;
  }
 printf("/n");
 pk=heaplistqueue(heapqueue);
 printf("/nthe huffman:/n");
 printdata(pk->next->pntree);
 printf("/nthe char coding:/n");
 for(j=0;j<huffrecod;j++)
 { printf("%c-",huff[j].code);
   for(i=0;i<huff[j].count;i++)
   {printf("%d",huff[j].huffuman[i]);}
   printf("/t");
  }
 printf("/nthe chars encode:/nSTART--<");
 encode(s,huff);
 printf(">--END");
 getch();
}

                              This huffman program
please input char list and in Enter of end!:

sdklfjkslr

the chars appear of frequency:
s2      d1      k2      l2      f1      j1      r1

the huffman:
10
├ 4
│ ├ 2 ←l--(00)
│ └ 2
│ │ ├ 1 ←d--(010)
│ │ └ 1 ←f--(011)
└ 6
│ ├ 2
│ │ ├ 1 ←j--(100)
│ │ └ 1 ←r--(101)
│ └ 4
│ │ ├ 2 ←s--(110)
│ │ └ 2 ←k--(111)

the char coding:
l-00    d-010   f-011   j-100   r-101   s-110   k-111
the chars encode:
START--<1100101110001110011111000101>--END