哈夫曼树课程设计

时间:2024.3.31

数据结构课程设计

                   ---哈夫曼树编码

       

哈夫曼树编码

一、实现功能

   给出一串字符,根据每个字符出现的频数进行编码,将文字转化为二进制的字符组成的字符串,即加密。加密过程根据频数生成哈夫曼树,然后进行遍历,得到二进制编码。

二、 哈夫曼算法叙述

(1).根据给定的n个权值{w1,w2,…,wn}构成n棵二叉树的集合F={T1,T2,…,Tn},其中每棵二叉树Ti中只有一个带权值为Wi的根结点,其左右子树均为空。

(2).在F中选取两棵根结点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为其左右子树上根结点的权值之和

(3).在F中删除这两棵树,同时将新得到的二叉树加入F中。

(4).重复(2)和(3),直到F中只含一棵二叉树为止,即哈夫曼树。

三、根据书上算法介绍进行代码编写(VC++编写)

1、哈夫曼树的建立、初始化和遍历

void CHFMDlg::CrtHuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w,int n)

{

   int m,i,s1,s2;

   m=2*n-1;

   HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));

   for(i=1; i<=n; ++i) //1--n号存放叶子结点,初始化

   {

      HT[i].weight=*w;

      HT[i].LChild=0;

      HT[i].parent=0;

      HT[i].RChild=0;

   }

   for(i=n+1; i<=m; i++)

   {

      HT[i].weight=0;

      HT[i].LChild=0;

      HT[i].parent=0;

      HT[i].RChild=0;

   }

   //非叶子结点初始化

   for(i=n+1; i<=m; i++) //创建非叶子结点,建哈夫曼树

   {

      Select(HT,i-1,&s1,&s2);

      HT[s1].parent=i;

      HT[s2].parent=i;

      HT[i].LChild=s1;

      HT[i].RChild=s2;

      HT[i].weight=HT[s1].weight+HT[s2].weight;

   }

      char *cd;

      int j,start,p;

      unsigned int c;

      HC=(HuffmanCode)malloc((n+1)*sizeof(char *)); //分配n个编码的头指针

      cd=(char *)malloc(n*sizeof(char));    //分配求当前编码的工作空间

      cd[n-1]='\0';

      //从右向左逐位存放编码,首先存放编码结束符

      for(j=1; j<=n; j++)   //求n个叶子结点对应的哈夫曼编码

      {

       start=n-1;   //初始化编码起始指针

       for(c=j,p=HT[j].parent; p!=0;c=p,p=HT[p].parent)

        //从叶子到根结点遍历求编码

        if( HT[p].LChild==c)

           cd[--start]='0';   //左分支标0

        else

           cd[--start]='1';   //右分支标1

      HC[j]=(char *)malloc((n-start)*sizeof(char));

//为第i个编码分配空间

        strcpy(HC[j],&cd[start]);

      }

   free(cd);

}

2、

void CHFMDlg::Select(HuffmanTree HT, int n, int *s1, int *s2)

//在HT[1]~HT[i-1]的范围内选择两个parent为0

//且weight最小的结点,其序号分别赋值给s1、s2

{

    int i,min;

   for(i=1; i<=n; i++)

   {

      if(HT[i].parent==0)

      { min=i; break; }

   }

   for(i=1; i<=n; i++)

   {

      if(HT[i].parent==0)

      {

        if(HT[i].weight<HT[min].weight)

           min=i;

      }

   }

   *s1=min;

   for(i=1; i<=n; i++)

   {

      if(HT[i].parent==0 && i!=(*s1))

      { min=i; break; }

   }

   for(i=1; i<=n; i++)

   {

      if(ht[i].parent==0 && i!=(*s1))

      {

        if(HT[i].weight<HT[min].weight)

           min=i;

      }

   }

   *s2=min;

}

四、 在MFC中进行代码编译

添加列表框显示每个字符的编码

界面如下:CHFMDlg对话框

void CHFMDlg::SetCtrlStyle(HWND hWnd, DWORD dwNewStyle)

//设置列表控件风格

{

   DWORD  dwOldStyle;

   dwOldStyle=GetWindowLong(hWnd,GWL_STYLE);

   if ((dwOldStyle&LVS_TYPEMASK)!=dwNewStyle)

   {

      dwOldStyle&=~LVS_TYPEMASK;

      dwNewStyle|=dwOldStyle;

      SetWindowLong(hWnd,GWL_STYLE,dwNewStyle);

   }

}

BOOL CHFMDlg::OnInitDialog()//初始化列表控件

{

   CDialog::OnInitDialog();

……………

   SetCtrlStyle(m_ListCtrl.m_hWnd,LVS_REPORT);

   CString strHeader[2]={"字符","编码"};

   int nWidth[2]={80,100};

   for (int nCol=0;nCol<2;nCol++)

   {

m_ListCtrl.InsertColumn(nCol,strHeader[nCol],LVCFMT_LEFT,nWidth[nCol]);

   }

   return TRUE; 

}

 void CHFMDlg::OnOK()//编译按钮

{

   // TODO: Add extra validation here

   UpdateData();

   CString strContent,str,strValue;

strContent=m_strContent;//获取编辑框中的字符串并赋//strContent

int size=strContent.GetLength();//获得字符串长度

str=strContent.GetAt(0);

for (int i=0;i<size;i++)//将不同的字符存入str中

   {

      int m=0;

      for (int j=0;j<str.GetLength();j++)

        if (strContent.GetAt(i)==str.GetAt(j))

           m++;

      if (m==0)  str=str+strContent.GetAt(i);

   }

   int n=str.GetLength();

   int *strnum=new int(n);

for (int k=0;k<n;k++)//计算str中字符出现的次数,即权值,存//入strnum数组中

   {

      int num=0;

      for (int j=0;j<size;j++)

        if (strContent.GetAt(j)==str.GetAt(k))

           num++;

      strnum[k]=num;

   }

   HuffmanTree HT;

   HuffmanCode HC;

   CrtHuffmanCoding(HT,HC,strnum,n);

   CString  strShow="";

    for (int m=0;m<size;m++)

    {

      for (int t=0;t<n;t++)

        if(strContent.GetAt(m)==str.GetAt(t))

           strShow=strShow+"*"+HC[t+1];

    }

   SetDlgItemText(IDC_EDIT2,strShow);

   for (int x=0;x<n;x++)

   {

     CString  s=str.GetAt(x);

      Int nIndex=m_ListCtrl.InsertItem(m_ListCtrl.GetItemCount(),s);

      m_ListCtrl.SetItemText(nIndex,1,HC[nIndex+1]);

   }

}

void CHFMDlg::SetCtrlStyle(HWND hWnd, DWORD dwNewStyle)

{

   DWORD  dwOldStyle;

   dwOldStyle=GetWindowLong(hWnd,GWL_STYLE);

   if ((dwOldStyle&LVS_TYPEMASK)!=dwNewStyle)

   {

      dwOldStyle&=~LVS_TYPEMASK;

      dwNewStyle|=dwOldStyle;

      SetWindowLong(hWnd,GWL_STYLE,dwNewStyle);

   }

}

四、编译结果如下:


第二篇:课程设计构造哈夫曼树


中国矿业大学徐海学院计算机系

《软件认知实践》报告

姓    名:学  号     

专    业:                

设计题目:                    

指导教师:                               

              

 

20##12


目    录

第1章  题目概述. 1

第1.1节  题目要求... 1

第1.2节  主要难点... 1

第2章 系统流程图. 1

第3章 数据结构和算法. 1

第4章 核心代码分析. 1

第5章 实验小结. 1

参考文献. 1


第1章  题目概述

设计程序以实现构造哈夫曼树的哈夫曼算法

                        

第1.1节  题目要求

(1)可以使用实验工具的有关功能。

(2)要能演示构造过程。

(3)求解出所构造的哈夫曼树的带权路径长度。

                         

第1.2节  主要难点

(1)构造哈夫曼树:根据给定的权值构成二叉树集合,其中每棵二叉树中只有一个带权的根节点,其左右子树均为空;在二叉树集合中选取两棵根节点权值最小的树作为左右子树构造一棵新的二叉树,且新的二叉树的根节点的权值为其左、右子树上根节点的权值之和;在二叉树集合中删除这两棵树,并将得到的二叉树加入集合中;重复上述步骤,直至二叉树集合中只含一棵树为止。

(2)求带权路径长度:先求每个叶子结点到树根之间的路径长度与该叶子结

点所带权值之积,在将所得之积求和。

第2章 系统流程图

第3章 数据结构和算法

使用树TREE的结构,编造最优二叉树(即哈夫曼树),涉及到主要函数有Inithuffmantree,Destoryhuffmantree,huffmancodeing,Visithuffmantree等,用于在一定时间复杂度内寻找到最佳(最短)路径,节约比较次数。

1.Init huffmantree(&T)

      操作结果:构造一个已知结点和权值的huffmantree.

2.Destory huffmantree(&T)

      条件:huffmantree已经存在

      结果:销毁huffmantree.

3.huffman coding(&T)

     条件:huffmantree已经存在

     结果:输出huffman code.

4.Visit huffmantree(&T)

            条件:huffmantree已经存在

     结果:显示 huffman tree.

代码运行结果

 

第4章 核心代码分析

(1)   定义

int s1=0,s2=0;//定义两个全局变量

typedef struct//  定义/结构体

{

    int c;//字符域

    int w;//权值域

    int p,l,r;/双亲域/左孩子域右孩子域,

}HT,*HuffmanTree;//动态分配数组存储赫夫曼树

typedef char * *HuffmanCode;//动态分配数组存储赫夫曼编码

HT *HTree;

(2) 找出两个最小权值s1,s2

void Select(HT *HTree,int b)

{

    int i,j,t;

for(i=1;i<=b;i++)

    if(!HTree[i].p)

    {

       s1 = i;

       break;

    }

    for(j=i+1;j<=b;j++)

    if(!HTree[j].p)

    {

       s2 = j;

       break;

    }

    for(i=1;i<=b;i++)

    if((HTree[s1].w>HTree[i].w)&&(!HTree[i].p)&&(s2!=i))

       s1=i;

    for(j=1;j <= b;j++)

    if((HTree[s2].w>HTree[j].w)&&(!HTree[j].p)&&(s1!=j))

       s2=j;

    if(s1>s2)//令s1小于s2

    {

        t=s1;

        s1=s2;

        s2=t;

    }

}

HuffmanCode HCode

(3)  输出状态图

void pr(HT *HTree,int m)

{

    int i;

    HT *h;

    printf("\n输出状态图\n字符\t权值\t双亲\t左孩子\t右孩子");

    h=HTree+1;

    for(i=1;i<=m;i++,h++)

    {

       printf("\n%c\t%d\t%d\t%d\t%d",h->c,h->w,h->p,h->l,h->r);

    }

(4) 逐个字符求赫夫曼编码

void Strcpy(char *p1,char *p2,int i,int j)

 {

    int k;

    for(k=0;i<=j;k++,i++)

       *(p1+k)=*(p2+i);

}

(5) 逐个字符求赫夫曼编码

void bm(HT *HTree,int n,char *code)

{

    int i,start,t,P;

    for(i=1;i<=n;i++)

    {  

       start=n-1;//编码结束符位置

       for(t=i,P=HTree[i].p;P!=0;t=P,P=HTree[P].p)//从叶子到根逆向求编码

       {

           if (HTree[P].l==t)

              code[--start]='0';//左孩子编码为0

           else

              code[--start]='1';//有孩子编码为1

       }

        HCode[i]=(char *)malloc((n-start)*sizeof(char));//为第i个字符编码分配空间

      

       Strcpy(HCode[i],code,start,n-1);//把code占到hcode上

    }

}

(6) 输出赫夫曼编码函数

void Print(HuffmanTree HTree,HuffmanCode HCode,int n)

{  

    int i;

    for(i=1;i<=n;i++)

    {

       printf("%c--",HTree[i].c);

        printf("%d--",HTree[i].w);

        printf("%s",HCode[i]);

        printf("\n");

    }

}

(7)  带权路径长度

dq(HT *HTree,int n)

{

    int i,l,P,WPL;

    int wpl[100];

    for(i=1;i<=n;i++)

    {  

       for(l=0,P=HTree[i].p;P!=0;P=HTree[P].p)  

           l+=1;//l是路径个数

       wpl[i]=HTree[i].w*l;

    }

    for(i=1,WPL=0;i<=n;i++)

       WPL+=wpl[i];

    return WPL;

}

(8) 主函数

void main()

{

    int n,m,i,C,W,WPL;

    HT *h;

    printf("赫夫曼树应用!");

    printf("\n输入叶子节点个数:");

    scanf("%d",&n);

    m=2*n-1;

    HTree=(HT *)malloc((m+1)*sizeof(HT));//0号单元未用,初始化赫夫曼树

    h=HTree+1;

    printf("\n输入%d个字符的Asc码(97-133)和权值:",n);

    //叶子结点初始化

    for(i=1;i<=n;i++,h++)

    {

       scanf("%d",&C);

        scanf("%d",&W);    

       h->c=C;

       h->w=W;

       h->p=0;

       h->l=0;

       h->r=0;

    }

    //中间结点初始化

    for(i=n+1;i<=m;i++,h++)

    {

        h->c=' ';

       h->w=0;

       h->p=0;

       h->l=0;

       h->r=0;

    }

    printf("\n初始\n");

    pr(HTree,m);//输出初始状态图

    //建赫夫曼树

    for(i=n+1;i<=m;i++)

    {

        Select(HTree,i-1);

        HTree[s1].p=i;

        HTree[s2].p=i;

        HTree[i].l=s1;

        HTree[i].r=s2;

        HTree[i].w=HTree[s1].w+HTree[s2].w;

    }

    //输出终结状态图

    printf("\n终结\n");

    pr(HTree,m);

    //从叶子到根逆向求赫夫曼树编码

    char *code;

    HCode=(HuffmanCode)malloc((n+1)*sizeof(char));//0号单元未用,分配n个字符编码的头指针向量

    code=(char *)malloc(n*sizeof(char));//分配求编码的公用工作空间

    code[n-1]='\0';//编码结束符

    bm(HTree,n,code);

    printf("\n赫夫曼编码为:\n");

    Print(HTree,HCode,n);

    //带权路径长度

    WPL=dq(HTree,n);

    printf("\n带权路径长度:%d\n",WPL);

}

第5章 实验小结

通过这一段时间的课程设计,我通过查找资料,仔细思考,运行修改,编出赫夫曼树应用这个程序。

在编程序的过程中,也遇到了很多困难:检查没有错误却无法得出想要的结果,语句也和书上的一样却无法连接结点,又或是想达到的效果编不出来等等。这说明我们掌握的知识不够完整,不够扎实,需要加深巩固。我们一点点地摸索、求证、询问、查找,虽然还有不完美的地方,终于将程序完成,也对树的知识有了更深的理解。

这一周的课程设计让我收获颇丰,也感谢老师平时上课的教导。

参考文献

严蔚敏 吴伟民编.《数据结构(c语言版)》. 清华大学出版社

谭浩强编.《C程序设计》.清华大学出版社

更多相关推荐:
哈夫曼树课程设计报告

闽江学院课程设计说明书题目哈夫曼编译码器院系计算机科学系专业班级学号学生姓名指导教师20xx年12月30日课程设计需求分析报告一分析问题和确定解决方案1分析问题利用哈夫曼编码进行通信可以大大提高信道利用率缩短信...

哈夫曼树课程设计报告

数据结构课程设计报告设计题目哈夫曼树应用专业软件工程班级软件学生学号指导教师罗作民张翔起止时间20xx070420xx0708目录一具体任务21功能22分步实施23要求2二哈夫曼编码21问题描述22基本要求33...

哈夫曼树课程设计

中南林业科技大学课程设计报告设计名称数据结构课程设计姓名王昆学号20xx4282专业班级20xx级软件工程系院计算机与信息工程学院设计时间20xx20xx学年第二学期设计地点电子信息楼机房1数据结构课程设计报告...

哈夫曼树课程设计论文

课程论文题目哈夫曼树及其应用课程设计报告学号20xx30210115姓名黄文宣班级1232101专业信息安全课程名称数据结构课程老师王晓燕二零一肆年一月1目录1课程设计的题目及简介32实验目的33设计说明44总...

哈夫曼树编码课程设计实验报告

武汉工程大学计算机科学与工程学院综合设计报告设计题目学生学号1005080228专业班级学生姓名张建雄学生成绩指导教师职称刘黎志副教授课题工作时间至说明1报告中的第一二三项由指导教师在综合设计开始前填写并发给每...

哈夫曼编码课程设计报告

数据结构课程设计报告基于哈夫曼树的文件压缩解压程序专业班级信科2班姓名徐爱娟谢静学号20xx161431005120xx161431005020xx1231一需求分析1课题要求实现文件的压缩与解压并计算压缩率A...

哈夫曼编码课程设计报告

数据结构课程设计报告课题专业班级学号姓名指导教师1课程设计的目的和意义在当今信息爆炸时代如何采用有效的数据压缩技术来节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视哈夫曼编码正是一种应用广泛且...

哈夫曼树的应用 课程设计任务书

课程设计任务书20xx20xx学年第1学期学生姓名专业班级10级计科1班指导教师邓丹君工作部门计算机学院一课程设计题目哈夫曼树的应用二课程设计内容1从终端读入字符集大小n以及n个字符和n个权值建立哈夫曼树并将它...

数据结构课程设计模——哈夫曼编码译码器

数据结构课程设计报告设计题目专业班级姓名学号完成日期目录1问题描述第2页2系统设计第2页3数据结构与算法描述第5页4测试结果与分析第6页5总结第10页6参考文献第10页附录程序源代码第11页共22页第页课程设计...

哈夫曼树课程设计

计算机学院信息管理与信息系统专业数据结构课程设计题目哈夫曼树的应用班级信管09101班姓名赵林芬学号20xx17020xx4同组人姓名陈立芳王红起迄日期20xx03010304课程设计地点系办公楼E3A513指...

JAVA_课程设计报告

JAVA程序设计课程设计报告设计题目学院名称专业班级姓名学号1目录一需求分析3二概要设计3三详细设计331数据库设计332模块及窗体设计3321数据库模块设计3322用户登录识别模块5323用户信息管理模块61...

软件课程设计报告

中南民族大学软件课程设计报告电子信息工程09级题目学生吴雪学号指导教师王锦程电子工程0907100220xx年4月25日简易网络聊天系统摘要计算机网络通信技术已经深入我们的生活并给我们即使通信带来了很大的方随着...

哈夫曼树课程设计报告(20篇)