数据结构--我的哈夫曼编译系统

这是一个使用C语言实现的哈夫曼编码编译系统,能够创建哈夫曼树,进行中序遍历,并根据哈夫曼树对输入字符串进行编码和解码。用户可以通过文件或键盘输入字符串进行操作。
摘要由CSDN通过智能技术生成
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node//每个树的节点至少包含3个内容,节点的权值,左子树,右子树的地址
{
    int element;
    char ch;
    char u[100];
    int num;
    struct node *Lchild,*Rchild;
}node;
typedef struct tree
{
   struct node *root;
}tree;//每一棵树都是由一个个节点构成的
tree start;
void Maketree(tree *bt,int x,char c,tree *Lt,tree *Rt)//该函数的目的是传入x的值,建立一棵左子树是Lt,右子树是Rt的树bt(创建方法就是先申请一个空间保存权值,然后记录下左子树右子树的地址,此时注意访问子树有两种方式:
//1直接通过左子树Lt->root来访问2通过p->Lchild来访问,而事实上,我们希望的是第二种方式,即这时左子树已经成为整体的一部分,所以都要清零( Lt->root=Rt->root=NULL;)
{

    node *p=(node*)malloc(sizeof(node));
    p->ch=c;
    p->element=x;
    p->Lchild=Lt->root;
    p->Rchild=Rt->root;
    Lt->root=Rt->root=NULL;
    bt->root=p;//最后把先建立的节点赋值给bt(我们就是通过bt传递的)

}
tree CreatHFMtree(int w[],char s[],int n)//传入两个参数,一个是数组w,一个是节点的数量n
{
    tree zero,h[1000];
    int i,k,k1,k2;
    tree *p;
    p=&zero;
    p->root=NULL;
    for (i=0;i<n;i++)
    Maketree(&h[i],w[i],s[i],p,p);//先建成n个树,再进行合并
    for (k=n-1;k>0;k--)//n棵树合并,进行n-1次
    {
    Fmin(h,&k1,&k2,k);//在已经建成的n棵树中,找出最小值的下标k1,次小值得下标k2,最小值每次只会在前k个值(每一次找出两个值都会在数组中忽略最小值)
    Maketree(&h[k1],h[k1].root->element+h[k2].root->element,'#',&h[k1],&h[k2]);//这步可以说是哈夫曼树的核心代码,把找到的两个小值求和h[k1]+h[k2],作为h[k2]的树,而他的子树就是h[k1],h[k2]
    h[k2]=h[k];//每一次把最小值换成队尾的那个,此时最小值就没有了,而有了两个队尾元素,然后由于k--,队尾元素相当于被删除了一个,所以只剩下了除了最小数的全部元素(如果最小值就是队尾元素,那也是成立,可以自己思考一下)
    }
    return h[0];
}
void makecode(node *t)//得出译码(每一个子节点的译码都是从父节点那继承来的)
{
    int i,l;
    if (t==start.root)
    {
        for (i=0;i<100;i++)
        start.root->u[i]='\0';
        start.root->num=0;
    }
   if ((t->Lchild==NULL)&&(t->Rchild==NULL))
   {
       printf("%c:",t->ch);
       for (i=0;i<t->num;i++)
       printf("%c",t->u[i]);
       printf("\n");
       return;
   }
    if (t->Lchild!=NULL)
    {
        for (i=0;i<t->num;i++)
        t->Lchild->u[i]=t->u[i];
        t->Lchild->u[t->num]='0';
        t->Lchild->num=t->num+1;
        makecode(t->Lchild);
      }
    if (t->Rchild!=NULL)
    {
        for (i=0;i<t->num;i++)
        t->Rchild->u[i]=t->u[i];
        t->Rchild->u[t->num]='1';
        t->Rchild->num=t->num+1;
        makecode(t->Rchild);
    }
}
void  translate(node *t,char p[])//翻译,先记录下来,因为不知道是否符合规范
{
    char s[100];
    node *q=t;
    int l,i,k=0,max;
    l=strlen(p);
    for (i=0;i<l;i++)
    {
    if (p[i]=='0')
        if (q->Lchild)
        q=q->Lchild;
        else
            printf("请输入正确的字符串\n");
    else
    {
    if (p[i]=='1')
        if (q->Rchild)
        q=q->Rchild;
        else
            printf("请输入正确的字符串\n");
    }
    if ((q->Lchild==NULL)&&(q->Rchild==NULL))
    {
     s[k++]=q->ch;
     max=i;
     q=t;
    }
    }
    if (max!=l-1)
        printf("请输入正确的字符串\n");
    else
    {
        for (i=0;i<k;i++)
        printf("%c",s[i]);
    }
   printf("\n");
}
void Fmin(tree h[],int *k1,int *k2,int k)//k1是最小值的下标,k2是次小值的下标(这一部分其实就是维护由两个元素组成的堆)
{

    int i,min1,min2;
    if (h[0].root->element<h[1].root->element)
    {
    *k1=0;
    *k2=1;
    min1=h[0].root->element;
    min2=h[1].root->element;
    }
    else
    {
      *k1=1;
      *k2=0;
      min1=h[1].root->element;
      min2=h[0].root->element;
    }
    for (i=2;i<=k;i++)
    if (h[i].root->element<min1)//如果比最小值还小
    {
        *k2=*k1;//先更新次小值的为原来的最小值,原来的最小值更新为h[i].root->element
        *k1=i;
         min2=min1;
         min1=h[i].root->element;
    }
    else
        if (h[i].root->element<min2)
    {

        *k2=i;
        min2=h[i].root->element;//直接更新次小值
    }
}
void PreOrd(node *t)
{

    if (t)
    {
        printf("%d %c  ",t->element,t->ch);
        PreOrd(t->Lchild);
        PreOrd(t->Rchild);
    }
}
void menu()
{
    printf("**********************************************************\n");
    printf("*****欢迎使用B14040312宋宇通的小小哈夫曼编译系统**********\n");
    printf("*********创建新的哈夫曼的编译系统请按1***************\n");
    printf("*********从文件输入待编译的字符串请按2***************\n");
    printf("*********从键盘输入待编译的字符串请按3***************\n");
    printf("*********如果你残忍地想退出本系统请按4*******************\n");
}
  int main()
  {
      FILE *fp;
      int w[1000];
      char s[1000];
      char p[1000];
      char cha;
      int i,n,ok=1;
      fp=fopen("d://1.txt","r");
      menu();
      cha=getchar();
     while(cha!='4')
    {
    switch (cha)
    {
    case '1':
      printf("请输入树节点的个数\n");
      scanf("%d",&n);
      printf("请输入节点(格式为频率 对应的字母)\n");
      for (i=0;i<n;i++)
      scanf("%d %c",&w[i],&s[i]);
      start=CreatHFMtree(w,s,n);
      printf("建成的哈夫曼树的中序遍历结果为:");
      PreOrd(start.root);
      printf("\n");
      makecode(start.root);
      printf("*********从文件输入待编译的字符串请按2(文本保存在D://1.txt)***************\n");
      printf("*********从键盘输入待编译的字符串请按3***************\n");
      break;
    case '2':
      if (start.root==NULL)
      printf("你还没给我创建哈夫曼编译系统呢,过分了!\n");
    else
    {
      printf("注意文件是保存在d下的1.txt下的哦,亲~~\n");
      fscanf(fp,"%s",p);
      printf("你在文件中保存的字符串是:");
      printf("%s\n",p);
      printf("翻译结果为:");
      translate(start.root,p);
      printf("\n");
    }
      printf("*********从文件输入待编译的字符串请按2***************\n");
      printf("*********从键盘输入待编译的字符串请按3***************\n");
      printf("*********如果你残忍地想退出本系统请按4*******************\n");
      break;
    case '3':
        if (start.root==NULL)
        printf("你还没给我创建哈夫曼编译系统呢,过分了!\n");
        else
    {
      printf("请输入待翻译的字符串\n");
      scanf("%s",p);
      printf("翻译结果为:");
      translate(start.root,p);
    }
      printf("*********从文件输入待编译的字符串请按2***************\n");
      printf("*********从键盘输入待编译的字符串请按3***************\n");
      printf("*********如果你残忍地想退出本系统请按4*******************\n");
      break;
    default:printf("请输入正确的数字,不然人家要生气了~~\n");
            ok=0;
    }
   if (ok) getchar();
    cha=getchar();
    }
    printf("谢谢使用\n");
      fclose(fp);
      return 0;
  }











评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值