数据结构课程设计哈弗曼编码程序说明书一、使用手册:1、在字符里面输入字符(单个字符)以空格隔开,输入最大字符数量100;2、输入完成后点击哈弗曼编码按钮,然后再右边的列表控件中显示出字符、权值以及相应的哈弗曼代码。
3、运行完一次后点击清空按钮。
清空右边列表控件的内容,然后再测试下一组值。
可以用delete键删除二.可行性分析通过对输入编辑框中的字符进行分型,通过最这个字符进行遍历,获得每个字母的重复次数。
以此作为该字符的权值存入数组weight[]中,并与字符数组相对应,并将权值作为参数传入Status CHafumanDlg::HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n)中,利用对应的处理函数获得哈弗曼编码,最后输出在列表控件中。
二、概要设计在vc++6.0中生成的改程序1、建立基于对话框的程序,在类CHafumanDlg中添加构造哈弗曼树的代码;2、向对话框中添加静态文本控件(caption改为字符);接着添加编辑框并关联String类型的关联变量m_zifu,还有两个按钮(caption 分别改为清空和哈弗曼代码)以及一个列表控件,并关联一个CLisrCtrl类型的变量m_list;然后分别为清空和哈弗曼编码按钮添加相应的响应函数三、源代码1构造哈弗曼树的代码(1)// hafumanDlg.h : header file//头文件//#if !defined(AFX_HAFUMANDLG_H__ACA655FF_81FF_452A_855C_32381C74 3BB5__INCLUDED_)#defineAFX_HAFUMANDLG_H__ACA655FF_81FF_452A_855C_32381C743BB5__INC LUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000/////////////////////////////////////////////////////////////////////////////// CHafumanDlg dialog#define ok 1#define error 0typedef int Status;typedef struct{unsigned int weight;unsigned int parent,lchild,rchild;}HTNode, *HuffmanTree;//动态分配数组存储赫夫曼树typedef char * *HuffmanCode;//动态分配数组存储赫夫曼编码表class CHafumanDlg : public CDialog{// Constructionpublic:Status HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n);Status Select(HuffmanTree HT,int n,int &n1,int &n2);CHafumanDlg(CWnd* pParent = NULL); // standard constructor};(2)// hafumanDlg.cpp : implementation file//#include "stdafx.h"#include "hafuman.h"#include "hafumanDlg.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// CAboutDlg dialog used for App AboutStatus CHafumanDlg::Select(HuffmanTree HT, int n, int &n1, int &n2){// 在HT[i-1]中选择parent为0求weight最小的两个节点int i;for (i=1;i<=n && HT[i].parent!=0 ;i++);n1=i;for (i=1;i<=n;i++)if (HT[i].parent==0 && HT[i].weight<HT[n1].weight) n1=i;for (i=1; i<=n ; i++)if (HT[i].parent==0 && i!=n1) break;n2=i;for (i=1;i<=n;i++)if ( HT[i].parent==0 && i!=n1 && HT[i].weight<HT[ n2].weight) n2=i;return ok;(3)// hafumanDlg.cpp : implementation file//#include "stdafx.h"#include "hafuman.h"#include "hafumanDlg.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// CAboutDlg dialog used for App AboutStatus CHafumanDlg::HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int*w, int n){//w存放n个字符的权值,构造赫夫曼树HT,并求出n个字符的赫夫曼编码int m,s1,s2,i,start;unsigned int c,f;char *cd;if(n<=1)return error;m=2*n-1;//赫夫曼树的总节点数HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));//0号单元未用//初始化赫夫曼树for(i=1;i<=n;i++)//1到n号节点{HT[i].weight=w[i-1];HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;}for(i=n+1;i<=m;i++)//n+1号到m号节点{HT[i].weight=0;HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;}for(i=n+1;i<=m;i++){//构建赫夫曼树Select(HT,i-1,s1,s2);//选择weight最小的两个节点是s1,s2HT[s1].parent=i;HT[s2].parent=i;HT[i].lchild=s1;HT[i].rchild=s2;HT[i].weight=HT[s1].weight+HT[s2].weight;}//----从叶子节点到根逆向求每个字符的赫夫曼编码----HC=(HuffmanCode)malloc((n+1)*sizeof(char*));//分配n个字符编码的头指针向量cd=(char *)malloc(n*sizeof(char)); //分配求编码的工作空间cd[n-1]='\0';//编码结束符for(i=1;i<=n;i++){//逐个字符求赫夫曼编码start=n-1;//编码结束位置for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)//从叶子到根逆向求编码if(HT[f].lchild==c)cd[--start]='0';elsecd[--start]='1';HC[i]=(char *)malloc((n-start)*sizeof(char));//为第i个字符编码分配空间strcpy(HC[i],&cd[start]);//从cd复制编码(串)到HC }free(cd);//释放cdreturn ok;}2、构造可视化界面的代码(1)初始化列表控件BOOL CHafumanDlg::OnInitDialog(){CDialog::OnInitDialog();// Add "About..." menu item to system menu.// IDM_ABOUTBOX must be in the system command range.char *szItems[]={"字符","权值","哈弗曼代码"};int nWidths[]={100,100,100,100};//#define ITEMS(sizeof(szItems)/sizeof(char*))#define ITEMS (sizeof(szItems)/sizeof(char*))LV_COLUMN lc;memset(&lc,'\0',sizeof(LV_COLUMN));lc.mask=LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM;for (int sub=0;sub<ITEMS;++sub){lc.iImage=sub;lc.pszText=szItems[sub];lc.cx=nWidths[sub];m_list.InsertColumn(sub,&lc);}ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){CString strAboutMenu;strAboutMenu.LoadString(IDS_ABOUTBOX);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// Set the icon for this dialog. The framework does this automatically// when the application's main window is not a dialogSetIcon(m_hIcon, TRUE); // Set big iconSetIcon(m_hIcon, FALSE); // Set small icon// TODO: Add extra initialization herereturn TRUE; // return TRUE unless you set the focus to a control}(2)哈弗曼代码按钮控件的响应函数void CHafumanDlg::OnBianma(){// TODO: Add your control notification handler code hereUpdateData();char ZiFu[26]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};int number[26]={0},count=0,length,weight[26]={0},i;char ZiFu1[26],ZiFu2[100],ZiFU3[26][2];strcpy(ZiFu2,m_zifu);length=strlen(ZiFu2);if (length=1)MessageBox("请输入两个以上的字符");else{for(i=0;i<26;i++)strcpy(ZiFU3[i]," ");for(i=0;i<length;i++)if(ZiFu2[i]!=' '){switch(ZiFu2[i]){case 'a':number[0]++;if(number[0]!=0) ZiFu1[0]=ZiFu[0];break;case 'b':number[1]++;if(number[1]!=0) ZiFu1[1]=ZiFu[1];break;case 'c':number[2]++;if(number[2]!=0) ZiFu1[2]=ZiFu[2];break;case 'd':number[3]++;if(number[3]!=0) ZiFu1[3]=ZiFu[3];break;case 'e':number[4]++;if(number[4]!=0) ZiFu1[4]=ZiFu[4];break;case 'f':number[5]++;if(number[5]!=0) ZiFu1[5]=ZiFu[5];break;case 'g':number[6]++;if(number[6]!=0) ZiFu1[6]=ZiFu[6];break;case 'h':number[7]++;if(number[7]!=0) ZiFu1[7]=ZiFu[7];break;case 'i':number[8]++;if(number[8]!=0) ZiFu1[8]=ZiFu[8];break;case 'j':number[9]++;if(number[9]!=0) ZiFu1[9]=ZiFu[9];break;case 'k':number[10]++;if(number[10]!=0) ZiFu1[10]=ZiFu[10];break;case 'l':number[11]++;if(number[11]!=0) ZiFu1[11]=ZiFu[11];break;case 'm':number[12]++;if(number[12]!=0) ZiFu1[12]=ZiFu[12];break;case 'n':number[13]++;if(number[13]!=0) ZiFu1[13]=ZiFu[13];break;case 'o':number[14]++;if(number[14]!=0) ZiFu1[14]=ZiFu[14];break;case 'p':number[15]++;if(number[15]!=0) ZiFu1[15]=ZiFu[15];break;case 'q':number[16]++;if(number[16]!=0) ZiFu1[16]=ZiFu[16];break;case 'r':number[17]++;if(number[17]!=0) ZiFu1[17]=ZiFu[17];break;case 's':number[18]++;if(number[18]!=0) ZiFu1[18]=ZiFu[18];break;case 't':number[19]++;if(number[19]!=0) ZiFu1[19]=ZiFu[19];break;case 'u':number[20]++;if(number[20]!=0) ZiFu1[20]=ZiFu[20];break;case 'v':number[21]++;if(number[21]!=0) ZiFu1[21]=ZiFu[21];break;case 'w':number[22]++;if(number[22]!=0) ZiFu1[22]=ZiFu[22];break;case 'x':number[23]++;if(number[23]!=0) ZiFu1[23]=ZiFu[23];break;case 'y':number[24]++;if(number[24]!=0) ZiFu1[24]=ZiFu[24];break;case 'z':number[25]++;if(number[25]!=0) ZiFu1[25]=ZiFu[25];break;// case 'c':number[2]++;if(number[2]!=0) ZiFu1[2]=ZiFu[2];break;}}for(i=0;i<26;i++){if(number[i]!=0){weight[count]=number[i];ZiFU3[count][0]=ZiFu1[i];count++;}}}HuffmanTree HT;HuffmanCode HC;HuffmanCoding(HT, HC,weight,count);for (int e=0;e<count;e++){char a[20];itoa(weight[e],a,10);int index=m_list.InsertItem(m_list.GetItemCount(),&ZiFU3[e][0],e);m_list.SetItemText(index,1,a);m_list.SetItemText(index,2,HC[e+1]);}}(2)、清空按钮的响应函数void CHafumanDlg::OnButton1(){// TODO: Add your control notification handler code hereif (m_zifu.IsEmpty())MessageBox("请输入字符");m_zifu=" ";UpdateData(FALSE);m_list.DeleteAllItems();}四.测试结果1输入a n n n n n j j s t o l k w r s g g h s g结果:字符权值哈弗曼编码a 1 11110g 3 101h 1 11111j 2 1110k 1 0000l 1 00001n 5 01o 1 0010r 1 0011s 3 110t 1 1000w 1 10012测试结果二输入a m k m k字符权值哈弗曼编码a 1 10k 2 11m 2 0。