5678: 数据结构实验:哈夫曼树和编码

描述

当用 n 个结点(都做叶子结点且都有各自的权值)试图构建一棵树时,如果构建的这棵树的带权路径长度最小,称这棵树为“最优二叉树”,有时也叫“赫夫曼树”或者“哈夫曼树”。

现给定若干权值,请构建一棵哈夫曼树,并输出各个权值对应的哈夫曼编码长度。

哈夫曼树中的结点定义如下:

//哈夫曼树结点结构

typedef struct

{

int weight;//结点权重

int parent, left, right;//父结点、左孩子、右孩子在数组中的位置下标

}HTNode, *HuffmanTree;

//动态二维数组,存储哈夫曼编码

typedef char ** HuffmanCode;

部分代码已完成,请补充完整,提交时请勿包含给定代码。

//打印哈夫曼编码的函数
void PrintHuffmanCode(HuffmanCode htable, int *w, int n)
{
    printf("Huffman code:\n");
    for(int i = 1; i <= n; i++)
        printf("%d(%d)\n",w[i-1], strlen(htable[i]));
}
int main()
{
    int w[100], n, i;
    scanf("%d", &n);
    for(i=0;i<n;i++)
        scanf("%d", &w[i]);
    HuffmanTree htree;
    HuffmanCode htable;
    CreateHuffmanTree(htree, w, n);
    HuffmanCoding(htree, htable, n);
    PrintHuffmanCode(htable,w, n);
    return 0;
}

输入

输入数据第一行为n(不超过100),接下来有n个正整数,表示权值。

输出

按照输入权值顺序输出相应的哈夫曼编码的长度,格式见样例。

样例输入

5
2 8 7 6 5

样例输出

Huffman code:
2(3)
8(2)
7(2)
6(2)
5(3)

代码:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3
  4 typedef struct
  5 {
  6     int weight;//结点权重
  7     int parent, left, right;//父结点、左孩子、右孩子在数组中的位置下标
  8 }HTNode, *HuffmanTree;
  9 typedef char ** HuffmanCode;
 10
 11 void select(HuffmanTree htree,int n, int *s1,int *s2){
 12     int minn;
 13     for(int i=1;i<=n;i++){
 14         if((htree)[i].parent==0){ //如果此结点的父亲没有,那么把结点号赋值给 min,跳出循环
 15             minn=i;
 16             break;
 17         }
 18     }
 19     for(int i=1;i<=n;i++){   //找出权值最小的
 20         if((htree)[i].parent==0){
 21             if((htree)[i].weight<(htree)[minn].weight){
 22                 minn=i;
 23             }
 24         }
 25     }
 26     *s1=minn;  //编号
 27     for(int i=1;i<=n;i++){
 28         if((htree)[i].parent==0&&i!=(*s1)){ //如果此结点的父亲没有,那么把结点号赋值给 min,跳出循环
 29             minn=i;
 30             break;
 31         }
 32     }
 33     for(int i=1;i<=n;i++){
 34         if((htree)[i].parent==0&&i!=(*s1)){
 35             if((htree)[i].weight<(htree)[minn].weight){
 36                 minn=i;
 37             }
 38         }
 39     }
 40     *s2=minn;   //找出两个编号最小的
 41 }
 42
 43 void CreateHuffmanTree(HuffmanTree &htree,int w[],int n){
 44     if(n<=1) return; // 如果只有一个编码就相当于 0
 45     int m=2*n-1;  //哈夫曼树度为2或为0 总结点树为2*n-1;
 46     int s1,s2; //s1 和 s2 为两个当前结点里,要选取的最小权值的结点
 47     htree=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
 48     for(int i=1;i<=n;i++){     //1--n号存放叶子结点,初始化叶子结点,结构数组来初始化每个叶子结点
 49         (htree)[i].weight=w[i-1];
 50         (htree)[i].parent=0;
 51         (htree)[i].left=0;
 52         (htree)[i].right=0;
 53     }
 54     for(int i=n+1;i<=m;i++){  //非叶子结点的初始化
 55         (htree)[i].weight=0;
 56         (htree)[i].parent=0;
 57         (htree)[i].left=0;
 58         (htree)[i].right=0;
 59     }
 60     for(int i=n+1;i<=m;i++){   //创建非叶子结点,建哈夫曼树
 61         select(htree, i-1, &s1, &s2);  //再前面有权值里面选出两个最小的构建二叉树
 62         (htree)[s1].parent=i;
 63         (htree)[s2].parent=i;
 64         (htree)[i].left=s1;
 65         (htree)[i].right=s2;
 66         (htree)[i].weight=(htree)[s1].weight+(htree)[s2].weight;
 67     }
 68 }
 69
 70 void HuffmanCoding(HuffmanTree &htree,HuffmanCode &htable,int n){
 71     htable=(HuffmanCode)malloc((n+1)*sizeof(char*));
 72     char *cd = (char *)malloc(n*sizeof(char));
 73     cd[n-1]=‘\0‘;
 74     for(int i=1;i<=n;i++){   //从叶子节点开始
 75         //从叶子结点出发,得到的哈夫曼编码是逆序的,需要在字符串数组中逆序存放
 76         int start=n-1;
 77         int c=i;
 78         int j=htree[i].parent;
 79         while(j!=0){
 80             // 如果该结点是父结点的左孩子则对应路径编码为 0,否则为右孩子编码为 1
 81             if(htree[j].left==c){
 82                 cd[--start]=‘0‘;
 83             }
 84             else cd[--start]=‘1‘;
 85             c=j;
 86             j=htree[j].parent;
 87         }
 88         //跳出循环后,cd 数组中从下标 start 开始,存放的就是该结点的哈夫曼编码
 89         htable[i] = (char *)malloc((n-start)*sizeof(char));
 90         strcpy(htable[i],&cd[start]);
 91     }
 92     free(cd);
 93 }
 94
 95 void PrintHuffmanCode(HuffmanCode htable, int *w, int n)
 96 {
 97     printf("Huffman code:\n");
 98     for(int i = 1; i <= n; i++)
 99         printf("%d(%d)\n",w[i-1], strlen(htable[i]));
100 }
101
102 int main()
103 {
104     int w[100], n, i;
105     scanf("%d", &n);
106     for(i=0;i<n;i++)
107         scanf("%d", &w[i]);
108     HuffmanTree htree;
109     HuffmanCode htable;
110     CreateHuffmanTree(htree, w, n);
111     HuffmanCoding(htree, htable, n);
112     PrintHuffmanCode(htable,w, n);
113     return 0;
114 }

原文地址:https://www.cnblogs.com/qq-1585047819/p/10841113.html

时间: 2024-10-17 23:44:09

5678: 数据结构实验:哈夫曼树和编码的相关文章

【数据结构】哈夫曼树实现编码译码

根据一段字符串中字符的个数 作为该字符的权值生成哈夫曼树. 然后根据生成的哈夫曼编码,对任意字符串实现编码,对任意二进制串实现译码. 程序运行结果: 1.程序主界面: 2.根据字符串 创建哈夫曼树及编码: 3.生成的编码表如下: 4.根据生成的哈夫曼编码对字符串编码: 5.生成的编码保存在文件中: 6.对二进制串译码: 结果: 代码: 哈夫曼树的生成和编码的常见,以及编码和译码函数 //_HuffmanTree_H #ifndef _HuffmanTree_H #define _HuffmanT

哈夫曼树的编码实验

Java哈夫曼编码实验--哈夫曼树的建立,编码与解码 建树,造树,编码,解码 一.哈夫曼树编码介绍 1.哈夫曼树: (1)定义:假设有n个权值{w1, w2, ..., wn},试构造一棵含有n个叶子结点的二叉树,每个叶子节点带权威wi,则其中带权路径长度WPL最小的二叉树叫做最优二叉树或者哈夫曼树. (2)特点:哈夫曼树中没有度为1的结点,故由n0 = n2+1以及m= n0+n1+n2,n1=0可推出m=2*n0-1,即一棵有n个叶子节点的哈夫曼树共有2n-1个节点. 2.哈夫曼编码步骤:

20172303 2018-2019-1《程序设计与数据结构》哈夫曼树编码与解码

20172303 2018-2019-1<程序设计与数据结构>哈夫曼树编码与解码 哈夫曼树简介 定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree).哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近. 带权路径长度(Weighted Path Length of Tree,简记为WPL) 结点的权:在一些应用中,赋予树中结点的一个有某种意义的实数. 结点的带权路径长度:结点到树根之间的路径长度与

20172304 蓝墨云实验哈夫曼树

20172304 蓝墨云实验哈夫曼树 实验要求 设有字符集:S={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}. 给定一个包含26个英文字母的文件,统计每个字符出现的概率,根据计算的概率构造一颗哈夫曼树. 并完成对英文文件的编码和解码. 要求: (1) 准备一个包含26个英文字母的英文文件(可以不包含标点符号等),统计各个字符的概率 (2) 构造哈夫曼树 (3) 对英文文件进行编码,输出一个编码后的文件 (4) 对编码文件进行解码,输出

数据结构例程——哈夫曼树

本文是数据结构基础系列(6):树和二叉树中第15课时哈夫曼树的例程. #include <stdio.h> #include <string.h> #define N 50 //叶子结点数 #define M 2*N-1 //树中结点总数 //哈夫曼树的节点结构类型 typedef struct { char data; //结点值 double weight; //权重 int parent; //双亲结点 int lchild; //左孩子结点 int rchild; //右孩

【数据结构】赫夫曼树的实现和模拟压缩(C++)

赫夫曼(Huffman)树,由发明它的人物命名,又称最优树,是一类带权路径最短的二叉树,主要用于数据压缩传输. 赫夫曼树的构造过程相对比较简单,要理解赫夫曼数,要先了解赫夫曼编码. 对一组出现频率不同的字符进行01编码,如果设计等长的编码方法,不会出现混淆的方法,根据规定长度的编码进行翻译,有且只有一个字符与之对应.比如设计两位编码的方法,A,B,C,D字符可以用00-11来表示,接收方只要依次取两位编码进行翻译就可以得出原数据,但如果原数据只由n个A组成的,那发出的编码就是2n个0组成,这样的

数据结构_哈夫曼树

基本概念 路径:在一棵树中,从任意一个结点到达另一个结点的通路 路径长度:该路径所需经过的边的个数 带权路径长度:从根结点到达该节点的路径长度再乘以该结点权值的结果 带权路径长度和:树所有的叶子结点的带权路径长度和 哈夫曼树:给定n个带权值结点,以它们为叶子结点构造的一棵带权路径和最小的二叉树 哈夫曼树的求法 将所有结点放入集合 K. 若集合 K 中剩余结点大于 2 个,则取出其中权值最小的两个结点,构造他们同时为某个新节点的左右儿子,该新节点是他们共同的双亲结点,设定它的权值为其两个儿子结点的

数据结构知识点——哈夫曼树

7.哈夫曼树 7.1.哈夫曼树的概述 哈夫曼树,也称最优二叉树,它是n个带权叶子结点构成的所有二叉树中,带权路径长度最小的二叉树. 所谓树的带权路径长度,就是树中所有的叶节点的权值乘上其到根结点的路径长度. 权值越大的结点离根结点越近的二叉树才是最优二叉树. 树的带权路径路径长度(WPL)是从树根到每一结点的路径长度之和,记为WPL=(W1*L1+W2*L2+W3*L3+...+Wn*Ln),N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,

数据结构之哈夫曼树

#include <iostream> #include <iomanip> #include <string> using namespace std; typedef struct { string name; int weight; int parent, lchild, rchild; int visited; //设置visited选项来表示每次查找最小权值后的删除,0代表未删除,1表示删除 }HTNode,*HuffmanTree; int Min(Huff