计算机软件基础
课 程 设 计
报告
设计题目:    哈夫曼编\译码器       
      信息工程(系统工程方向)
      09系统1班         
      董健                 
      ***********         
指导教师   陈金辉               
     
一、设计题目
设计题目一 哈夫曼编\译码器
设计要求:
1.初始化,键盘输入字符集大小n,n个字符和n个权植,建立哈夫曼树。
2.编码,利用建好的huffman树生成huffman编码;
3.输出编码;
4.译码功能;
5.字符和频度如下:
字符 空格 A B C D E F G H I J K L M N O P Q
频度 186 64 13 22 32 103 21 15 47 57 1 2 32 20 57 63 15 1
字符 R S T U V W X Y Z
频度 48 51 80 23 8 18 1 16
1.1 问题分析
构造哈夫曼树时,首先将由n各字符形成的n个叶子节点存放到数组HTNode的前n个分量中,然后根据前面介绍的哈夫曼方法的基本思想,不断将两个小子树合并为一个较大的子树,每次构成的新子树,每次构成的新子树的根节点顺序放到HTNode数组中的前n个分量的后面。译码功能,假定电文中只使用A、B、C、D、E、F6种字符,若进行等长编码,它们分别需要3位二进制字符,可一次编码为000、001、010、011、100、101。
1.2 数据结构与算法设计
哈夫曼编\译码器的主要功能是先建立哈夫曼树,然后利用建好的哈夫曼树生成哈夫曼编码后进行译码 。
在数据通信中,经常需要将传送的文字转换成由二进制字符0、1组成的二进制串,称之为编码。构造一棵哈夫曼树,规定哈夫曼树中的左分之代表0,右分支代表1,则从根节点到每个叶子节点所经过的路径分支组成的0和1的序列便为该节点对应字符的编码,称之为哈夫曼编码。
最简单的二进制编码方式是等长编码。若采用不等长编码,让出现频率高的字符具有较短的编码,让出现频率低的字符具有较长的编码,这样可能缩短传送电文的总长度。哈夫曼树课用于构造使电文的编码总长最短的编码方案。
哈夫曼树编\译码器流程图
1.3 核心代码
哈夫曼编\译码器程序的主要代码如下所示:
#include <stdio.h>
#include <stdlib.h>          //要用system函数要调用的头文件
#include<conio.h>            //用getch()要调用的头文件
#include <string.h>
#define N 50                //义用N表示50叶节点数
#define M 2*N-1              //用M表示节点总数  当叶节点数位n时总节点数为2n-1
#define MAXSIZE 100
typedef struct
{
    char data;                  //结点值
    int weight;                //权值
    int parent;                //双亲结点
    int lchild;                //左孩子结点
    int rchild;                //右孩子结点
}HTNode;                   
typedef struct
{
    char cd[N];                //存放哈夫曼码
    int start;                  //从start开始读cd中的哈夫曼码
}HCode;
void CreateHT(HTNode ht[],int n)                      //调用输入的数组ht[],和节点数n
{
    int i,k,lnode,rnode;
    int min1,min2;
    for (i=0;i<2*n-1;i++)     
        ht[i].parent=ht[i].lchild=ht[i].rchild=-1;    //所有结点的相关域置初值-1
    for (i=n;i<2*n-1;i++)                            //构造哈夫曼树
    {
        min1=min2=32767;                              //int的范围是-32768—32767
        lnode=rnode=-1;                              //lnode和rnode记录最小权值的两个结点位置
        for (k=0;k<=i-1;k++)
        {
            if (ht[k].parent==-1)                    //只在尚未构造二叉树的结点中查
        {
if (ht[k].weight<min1)                //若权值小于最小的左节点的权值
                {
                    min2=min1;rnode=lnode;字符串转数组编码方式
                    min1=ht[k].weight;lnode=k;
                }
                else if (ht[k].weight<min2)
                {
                    min2=ht[k].weight;rnode=k;
                }
            }
        }
        ht[lnode].parent=i;ht[rnode].parent=i;                  //两个最小节点的父节点是i
        ht[i].weight=ht[lnode].weight+ht[rnode].weight;        //两个最小节点的父节点权值为两个最小节点权值之和
        ht[i].lchild=lnode;ht[i].rchild=rnode;                  //父节点的左节点和右节点
    }
}
void CreateHCode(HTNode ht[],HCode hcd[],int n)
{
int i,f,c;
HCode hc;
for (i=0;i<n;i++)                              //根据哈夫曼树求哈夫曼编码
{
  hc.start=n;c=i;
  f=ht[i].parent;
  while (f!=-1)                                  //循序直到树根结点结束循环
  {
  if (ht[f].lchild==c)                          //处理左孩子结点
    hc.cd[hc.start--]='0';
  else                                          //处理右孩子结点
    hc.cd[hc.start--]='1';
  c=f;f=ht[f].parent;
  }
  hc.start++;                                    //start指向哈夫曼编码hc.cd[]中最开始字符
  hcd[i]=hc;
}
}
void DispHCode(HTNode ht[],HCode hcd[],int n)    //输出哈夫曼编码的列表
{
int i,k;
printf("  输出哈夫曼编码:\n");
for (i=0;i<n;i++)                                //输出data中的所有数据,即A-Z
{
  printf("      %c:\t",ht[i].data);             

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。