c语言实现哈夫曼树的创建与中序遍历以及哈夫曼编码(附详细代码)

任务描述

本关任务:编写能对给定n个叶子结点,构建哈夫曼树,给出每个叶子结点对应编码的程序。

相关知识

哈夫曼编码和译码的基本原理

  1. 首先要构造一棵哈夫曼树。哈夫曼树的结点结构包括权值,双亲,左右孩子;假如由n个字符来构造一棵哈夫曼树,则共有结点2n-1个;在构造前,先初始化,初始化操作是把双亲,左右孩子的下标值都赋为0;然后依次输入每个结点的权值。

  2. 第二步是通过n-1次循环,每次先找输入的权值中最小的两个结点,把这两个结点的权值相加赋给一个新结点,并且这个新结点的左孩子是权值最小的结点,右孩子是权值第二小的结点;鉴于上述找到的结点都是双亲为0的结点,为了下次能正确寻找到剩下结点中权值最小的两个结点,每次循环要把找的权值最小的两个结点的双亲赋值不为0i)。就这样通过n-1循环下、操作,创建了一棵哈夫曼树,其中,前n个结点是叶子(输入的字符结点)后n-1个是度为2的结点。

  3. 编码的思想是逆序编码,从叶子结点出发,向上回溯,如果该结点是回溯到上一个结点的左孩子,则在记录编码的数组里存“0”,否则存“1”,注意是倒着存;直到遇到根结点(结点双亲为0),每一次循环编码到根结点,把编码存在编码表中,然后开始编码下一个字符(叶子)

测试说明

平台会对你编写的代码进行测试:

测试输入:5 2 7 4 5 19

预期输出:(对哈夫曼树按中序遍历输出对应叶子的哈夫曼编码)

 
  1. 7 00
  2. 5 010
  3. 2 0110
  4. 4 0111
  5. 19 1
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
# include<malloc.h>
#include <iostream> 
using namespace std;
#define max 1000;
struct HtNode {
	int ww;//结点的权值
	int parent, lch, rch;
	char codes[10];//存放哈夫曼编码
};
struct HtTree {
	int m;//叶子结点的个数
	int root;//哈夫曼树根在数组的下标
	struct HtNode ht[1000];//存放2m-1个节点的数组
};
typedef struct HtTree* HtTreee;

HtTreee creathuffman(int m, int* w)//创建哈弗曼树
{
	int num = 2 * m - 1;
	HtTreee huf;
	int i, j, x1, x2, m1, m2;
	huf = (HtTreee)malloc(sizeof(struct HtTree));;
	//huf->ht = (struct HtNode*)malloc(sizeof(struct HtNode) * num);//分配空间

	for (i = 0; i < num; i++) {
		huf->ht[i].lch = huf->ht[i].parent = huf->ht[i].rch = -1;

		if (i < m) {
			huf->ht[i].ww = w[i];
		}
		else {
			huf->ht[i].ww = -1;
		}
	}//初始化哈弗曼树
	for (i = 0; i < m-1; i++) {
		m1 = m2 = max;
		x1 = x2 = -1;
		for (j = 0; j < m + i; j++) {//寻找两个最小权的无父节点的结点
			if (huf->ht[j].ww < m1 && huf->ht[j].parent == -1) {//x1存放最小的下标
				m2 = m1; x2 = x1;
				m1 = huf->ht[j].ww;x1 = j;
			}
			else if(huf->ht[j].ww < m2 && huf->ht[j].parent == -1) {//x1存放次小的下标
				m2 = huf->ht[j].ww; x2 = j;
			}
		}
		huf->ht[x1].parent = huf->ht[x2].parent = m + i;
		huf->ht[m + i].ww = m1 + m2;
		huf->ht[m + i].lch = x1; huf->ht[m + i].rch = x2;//默认右大左小
	}
	huf->root = 2 * m - 2;
	return huf;
}

void huffmancodes(HtTreee huf,int n) {
	char* temp;
	temp = new char[n];
	temp[n - 1] = '\0';
	int start, pos, parent;
	for (int i = 0; i < n; i++) {
		start = n - 1;
		pos = i;
		parent = huf->ht[i].parent;
		while (parent != -1) {
			if (huf->ht[parent].lch == pos) {
				temp[--start] = '0';
			}
			else
			{
				temp[--start] = '1';
			}
			pos = parent;
			parent = huf->ht[parent].parent;
		}
		strcpy(&huf->ht[i].codes[0], &temp[start]);
	}
	delete temp;

}

void inOrderhuffman(HtTreee huf)
{    
	int i = huf->root;
	if (huf->ht[i].lch==-1) {
		cout << huf->ht[i].ww<<" " << huf->ht[i].codes << endl;
		return;
	}

    huf->root = huf->ht[i].lch;
	inOrderhuffman(huf);

	huf->root = huf->ht[i].rch;
	inOrderhuffman(huf);

}
int main() {

	int m,ww;
	cin >> m;//输入叶子结点个数
	HtTreee huf;
	int w[100];//存放权值
	for (int i = 0; i < m; i++) {
		cin >> ww;
		w[i] = ww;
	}
	huf = creathuffman(m,w);
	huffmancodes(huf, m);
	inOrderhuffman(huf);
}

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C语言实现哈夫曼编码代码,其中包含注释: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 1000 // 定义最大编码长度 typedef struct { int weight; // 权值 int parent, lchild, rchild; // 双亲和左右孩子结点 } HTNode, *HuffmanTree; typedef char **HuffmanCode; void Select(HuffmanTree HT, int n, int *s1, int *s2) { // 在前n个结点中选择权值最小的两个结点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 && 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 && HT[i].weight < HT[min].weight && i != *s1) { min = i; } } *s2 = min; } void CreateHuffmanTree(HuffmanTree *HT, int n) { // 由n个权值为w的结点构建哈夫曼树HT if (n <= 1) { return; } int m = 2 * n - 1; *HT = (HuffmanTree) malloc((m + 1) * sizeof(HTNode)); int i; for (i = 1; i <= m; i++) { (*HT)[i].parent = 0; (*HT)[i].lchild = 0; (*HT)[i].rchild = 0; } for (i = 1; i <= n; i++) { scanf("%d", &((*HT)[i].weight)); } int s1, s2; 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; } } void CreateHuffmanCode(HuffmanTree HT, HuffmanCode *HC, int n) { // 根据哈夫曼树HT求出n个字符的哈夫曼编码HC *HC = (HuffmanCode) malloc((n + 1) * sizeof(char *)); char *cd = (char *) malloc(n * sizeof(char)); cd[n - 1] = '\0'; int i, c, f; for (i = 1; i <= n; i++) { int 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'; } else { cd[--start] = '1'; } } (*HC)[i] = (char *) malloc((n - start) * sizeof(char)); strcpy((*HC)[i], &cd[start]); } free(cd); } void HuffmanCoding(HuffmanTree HT, HuffmanCode HC, int n) { // 输入n个字符的权值,建立哈夫曼树HT,并求出n个字符的哈夫曼编码HC CreateHuffmanTree(&HT, n); CreateHuffmanCode(HT, &HC, n); } void HuffmanDecoding(HuffmanTree HT, int n) { // 将01序列翻译成原来的文本字符 printf("请输入01序列:\n"); char str[MAX]; scanf("%s", str); int i, c = 2 * n - 1; for (i = 0; str[i] != '\0'; i++) { if (str[i] == '0') { c = HT[c].lchild; } else { c = HT[c].rchild; } if (HT[c].lchild == 0 && HT[c].rchild == 0) { printf("%d", c); c = 2 * n - 1; } } } int main() { int n; printf("请输入字符的个数n:\n"); scanf("%d", &n); HuffmanTree HT; HuffmanCode HC; HuffmanCoding(HT, HC, n); int i; printf("各字符的哈夫曼编码如下:\n"); for (i = 1; i <= n; i++) { printf("%d %s\n", i, HC[i]); } HuffmanDecoding(HT, n); return 0; } ``` 以上是C语言实现哈夫曼编码代码,可以根据输入的字符权值构建哈夫曼树,并输出各字符对应的哈夫曼编码。同时,可以将传输的文本转换成对应的哈夫曼编码01序列,并将哈夫曼编码01序列翻译成原来的文本字符。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值