6-1 哈夫曼树及哈夫曼编码

这段内容介绍了如何实现哈夫曼树和哈夫曼编码,包括SelectTwoMin函数用于选取最小节点,以及HuffmanCoding函数用于构建哈夫曼树和计算编码。样例展示了输入叶子节点的权值后,如何输出对应的哈夫曼树结构和编码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

6-1 哈夫曼树及哈夫曼编码 (10 分)

函数SelectTwoMin(int upbound, HuffmanTree HT, int &s1, int &s2)是从1到upbound中找出father为0的节点赋给s1,s2,(为了保证答案唯一,请让s1的节点编号小于s2),函数HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n)是构造哈夫曼树以及计算哈夫曼编码。保证输入的权重值小于1000。
函数接口定义:
void SelectTwoMin(int upbound, HuffmanTree HT, int &s1, int &s2);
void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n);
其中 upbound 编号,HT是哈夫曼树,HC是哈夫曼编码,w是权值,n是叶子节点个数。
裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
int weight;
int parent;
int lchild;
int rchild;
} HTNode, *HuffmanTree;
typedef char ** HuffmanCode;

void SelectTwoMin(int upbound, HuffmanTree HT, int &s1, int &s2);
void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n);

int main() {
HuffmanTree ht;
HuffmanCode hc;

int n;
scanf("%d", &n);

int *w = (int *) malloc (n * sizeof(int));
for(int i = 0; i < n; ++ i)
    scanf("%d", &w[i]);

HuffmanCoding(ht, hc, w, n);

for (int i = 1; i <= 2 * n - 1; ++ i) {
    printf("%d %d %d %d\n", 
    ht[i].weight, ht[i].parent, ht[i].lchild, ht[i].rchild);
}

for (int i = 1; i <= n; ++ i)
    printf("%s\n", hc[i]);

free(w);
free(ht);
for (int i = 1; i <= n; ++ i)
    free(hc[i]);

return 0;

}
/* 你的代码将被嵌在这里 */
输入格式:
第一行输入一个数n,表示叶子节点的个数,接下去输入n个整数,表示每个节点的值
输出格式:
只要建树即可,输出已经确定了
输入样例:
4
1 2 3 4
输出样例:
1 5 0 0
2 5 0 0
3 6 0 0
4 7 0 0
3 6 1 2
6 7 3 5
10 0 4 6
110
111
10
0
代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    int weight;
    int parent;
    int lchild;
    int rchild;
} HTNode, *HuffmanTree;
typedef char ** HuffmanCode;

void SelectTwoMin(int upbound, HuffmanTree HT, int &s1, int &s2);
void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n);

void reverse(char *CH)
{
	int n=strlen(CH);
	int i;
	for (i=0; i<n/2;i++)
	{
		char temp;
		temp = CH[i];
		CH[i] = CH[n-i-1];
		CH[n-i-1] = temp;
	}
}

int main() {
    HuffmanTree ht;
    HuffmanCode hc;

    int n;
    scanf("%d", &n);
	
    int *w = (int *) malloc (n * sizeof(int));
    for(int i = 0; i < n; ++ i)
        scanf("%d", &w[i]);

    HuffmanCoding(ht, hc, w, n);
	
    for (int i = 1; i <= 2 * n - 1; ++ i) {
        printf("%d %d %d %d\n", 
        ht[i].weight, ht[i].parent, ht[i].lchild, ht[i].rchild);
    }

    for (int i = 1; i <= n; ++ i)
        printf("%s\n", hc[i]);

    free(w);
    free(ht);
    for (int i = 1; i <= n; ++ i)
        free(hc[i]);
	
    return 0;
}
//其中 upbound 编号,HT是哈夫曼树,HC是哈夫曼编码,w是权值,n是叶子节点个数
void SelectTwoMin(int upbound, HuffmanTree HT, int &s1, int &s2)
{
    int x1=0,x2=0;
    int m1= 1000;
    int m2= 1000;
    for(int i=1; i<=upbound; i++)
    {
        if(HT[i].parent == 0&& HT[i].weight < m1)
        {
            m2= m1;
            x2 = x1;
            m1 = HT[i].weight;
            x1 = i;
        }
        else if(HT[i].parent == 0 && HT[i].weight <m2)
        {
            m2 = HT[i].weight;
            x2 = i;
        }
    }
    s1 = x1;
    s2 = x2;
}
void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n)
{
    int s1=0;
    int s2=0;
    HT = (HuffmanTree)malloc(sizeof(HTNode)*(2*n));
    HC = (char **)malloc(sizeof(char *)*(n+1));
    for(int i=1;i<=n;i++)
    {
    	HC[i] = (char *)malloc(sizeof(char)*(n+1));
		memset(HC[i],0,sizeof(char)*(n+1));
	}
    for (int i = 0; i <n ; ++i) {
        HT[i+1].weight = w[i];
    }//给结构体赋值
    for(int i=1;i<=2*n-1;i++)
    {
		HT[i].parent = 0;
		HT[i].lchild = 0;
		HT[i].rchild = 0;
	}
    for (int i = 0; i <n-1 ; ++i) {
        SelectTwoMin(n+i,HT,s1,s2);
        HT[i+n+1].lchild = s1;
        HT[i+n+1].rchild = s2;
        HT[i+n+1].weight = HT[s1].weight+HT[s2].weight;
        HT[s1].parent = i+n+1;
        HT[s2].parent = i+n+1;
    }
    //
    for (int i = 1; i <= n ; ++i) {
        int c = i;
        int parent = HT[c].parent;
        while (parent!=0)
        {
            if(HT[parent].lchild==c)
            {
                strncat(HC[i],"0",1);
            }
            else
                strncat(HC[i],"1",1);
        c = parent;
        parent = HT[parent].parent;
    }
    reverse(HC[i]);
    }
}

输出样例:
在这里插入图片描述
该代码随难度不大到有很多细节需要注意:

  1. 初始化叶节点以及非叶节点使他们的父亲结点儿子结点全部初始化为0.
  2. 申请字符串数组内存注意形式。
  3. 在申请过程中要保证每一个字符串都应该被初始化否则会出现乱码(亲测)。
  4. 注意得到的哈夫曼编码是从叶节点到根结点,需要将它逆序。
### 哈夫曼哈夫曼编码概述 哈夫曼是一种特殊的二叉,用于实现最优前缀编码方案。这种编码方式能够有效地压缩数据,在通信领域有着广泛的应用。 #### 构建哈夫曼的原则 构建哈夫曼遵循以下原则: - 将给定的一组具有不同权重(通常代表字符出现频率)的叶子节点组成森林; - 每次从未加入到当前中的最小两个权值结点创建一个新的父节点,并将其作为这两个子节点的父亲节点; - 把新建立起来的这个内部节点重新放回未处理集合中继续参与后续操作直到只剩下一个根节点为止[^1]。 #### 哈夫曼编码的特点 哈夫曼编码具备如下特性: - **唯一可解性**:由于采用的是前缀性质的编码规则,即任何一个字符对应的编码都不是其他任何字符编码串的前缀,因此可以确保译码过程不会产生歧义。 - **最短路径优先**:对于频繁使用的符号赋予较短长度的编码序列,而较少见的情况则分配较长位数表示,以此达到整体上减少传输量的目的[^2]。 #### PTA平台下的具体应用实例 在PTA平台上关于哈夫曼哈夫曼编码的任务描述指出,当构造此类特殊形式的二叉查找表时需满足特定条件——左孩子结点权值不大于右孩子结点权值;如果遇到相同情况,则依据先进先出原则选取最先被移除的那个元素来进行组合形成新的双亲节点。此外还明确了左右分支分别对应'0'和'1'[^3]。 ```python from heapq import heappush, heappop def huffman_tree(frequencies): heap = [[weight, [symbol, ""]] for symbol, weight in frequencies.items()] while len(heap) > 1: lo = heappop(heap) hi = heappop(heap) for pair in lo[1:]: pair[1] = '0' + pair[1] for pair in hi[1:]: pair[1] = '1' + pair[1] heappush(heap, [lo[0]+hi[0]] + lo[1:] + hi[1:]) return sorted(heappop(heap)[1:], key=lambda p: (len(p[-1]), p)) frequencies = {'a': 45, 'b': 13, 'c': 12, 'd': 16, 'e': 9, 'f': 5} huff_code = dict(huffman_tree(frequencies)) print("Symbol".ljust(10) + "Frequency".ljust(10) + "Huffman Code") for symbl in frequencies.keys(): print(symbl.ljust(10), str(frequencies[symbl]).ljust(10), huff_code[symbl]) ```
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值