Data structure Huffman tree and Huffman coding are suitable for novices to learn because I am also a novice, hee hee

Huffman tree and Huffman coding


Let me give you two mantras "Choose two small trees to make new trees, delete two small ones to make new trees". First understand the picture. Here is a code for you to compare it. They are all the same.
Everyone must understand these two pictures first

the second one

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#define MAX  17
typedef struct
{
    
    
	unsigned int weight;
	unsigned int parent, lchild, rchild;
}HTnode, *Huffmantree;
typedef char * *Huffmancode;
void select(Huffmantree HT, int n, int *s1, int *s2)
{
    
    
	int i, t;
	t = 1000;
	for (i = 1; i <= n; i++)
		if (HT[i].parent == 0 && HT[i].weight < t)
		{
    
    
			t = HT[i].weight;
			*s1 = i;
		}
	t = 1000;
	for (i = 1; i <= n; i++)
		if (HT[i].parent == 0 && HT[i].weight < t&&i!= *s1)
		{
    
    
			t = HT[i].weight;
			*s2 = i;
		}
}
void Huffmancoding(Huffmantree HT, Huffmancode HC, int *w, int n)
{
    
    
	int p1, q2;
	int *s1, *s2;
	int m, i, f, start, c;
	char *cd;
	Huffmantree p;
	s1 = &p1;
	s2 = &q2;
	if (n <= 1)  return;
	m = 2 * n - 1;     w = w + 1;
	HT = (Huffmantree)malloc((m + 1) * sizeof(HTnode));
	for (p = HT + 1, i = 1; i <= n; ++i, ++p, ++w)
	{
    
    
		p->weight = *w;  p->parent = 0;  p->lchild = 0;   p->rchild = 0;
	}
	for (; i <= m; ++i, ++p)
	{
    
    
		p->weight = 0;   p->parent = 0;  p->lchild = 0;   p->rchild = 0;
	}
	for (i = n + 1; i <= m; ++i)
	{
    
    
		select(HT, i - 1, s1, s2);
		HT[p1].parent = i;
		HT[q2].parent = i;
		HT[i].lchild = p1;
		HT[i].rchild = q2;
		HT[i].weight = HT[p1].weight + HT[q2].weight;
	}
	HC = (Huffmancode)malloc((n + 1) * sizeof(char *));
	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';
			else cd[--start] = '1';
		HC[i] = (char *)malloc((n - start) * sizeof(char));
		strcpy(HC[i], &cd[start]);
	}
	free(cd);
	printf("Print the Huffmantree:\n");
	printf("  weight  parent  lchild  rchild\n");
	for (i = 1; i <= 2 * n - 1; i++)
	{
    
    
		printf("%2d  %3d     %3d", i, HT[i].weight, HT[i].parent);
		printf("     %3d     %3d\n", HT[i].lchild, HT[i].rchild);
	}
	printf("Print the Humancode :\n");
	for (i = 1; i < n + 1; i++)
		printf("the code of %2d is %s\n", i, HC[i]);
}
void main()
{
    
    
	Huffmantree HT = NULL;
	Huffmancode HC = NULL;
	int n = 1, data, i, w[MAX];
	printf("Please input the weight of the elements of huffmantree (input -1 to exit)\n");
	scanf_s("%d", &data);
	while (data != -1)
	{
    
    
		w[n] = data;
		n++;
		scanf_s("%d", &data);
	}
	n = n - 1;
	Huffmancoding(HT, HC, w, n);
	_getch();
}


#include<stdio.h>
#include<iostream>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>//算法,头文件包含求最大最小等
#define MAX_NUM 100//最大数字个数为100
#define inf 2000000000 //最大值为
using namespace std;
using namespace std;
typedef struct {
    
    
	unsigned int weight;//权值 数字无符号
	unsigned int parent, lchild, rchild;//父节点,孩子结点的权值 
}HTNode, *HuffmanTree;
typedef char * * HuffmanCode;//二维字符数组 
int s1, s2;//最小的两个结点 

void Select(HuffmanTree &HT, int x) 
{
    
    //选出无父结点,并且权值最小的两个结点,赋值给s1,s2 
	int i, min1 = inf, min2 = inf;
	for (i = 1; i <= x; i++) {
    
    //找最小 
		if (HT[i].weight < min1&&HT[i].parent == 0)
		 {
    
     
			 min1 = HT[i].weight; 
			 s1 = i;//选出该权值是第几个
		  }
	for (i = 1; i <= x; i++) {
    
    //找次小 
		if (HT[i].weight < min2&&i != s1 && HT[i].parent == 0) 
		{
    
    
			min2 = HT[i].weight; 
			s2 = i;
		}
  }

void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n)
 {
    
    //根据输入的结点的权值和个数来构建赫夫曼树 //创建数 和编码的地址
	if (n <= 1)return;
	int m = 2 * n - 1;//n个叶子,有2*n-1个结点 
	int i;
	HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode));//0号单元未用 开辟空间
	HuffmanTree p;
	for (p = HT + 1, i = 1; i <= n; i++, p++, w++) 
	{
    
    //叶子结点赋值 
		p->weight = *w; p->parent = 0; p->lchild = 0; p->rchild = 0;
	}
	for (; i <= m; i++, p++) 
	{
    
    //非叶子结点初始化 
		p->weight = 0; p->parent = 0; p->lchild = 0; p->rchild = 0;
	}
	for (i = n + 1; i <= m; i++)
    {
    
    
		Select(HT, i - 1);//选出最小的两个无父节点的结点 
		HT[s1].parent = i; //找到第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 *));//申请一段以HC为首地址的内存,可以看成二维字符数组 ,这里先申请了第一维 
	char *cd = (char *)malloc(n * sizeof(char));//申请一段临时工作空间 
	cd[n - 1] = '\0';//编码结束符 
	for (i = 1; i <= n; i++) {
    
    
		int start = n - 1, c, f;
		for (c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent) {
    
    //从叶子到根逆向求编码 
			if (HT[f].lchild == c)
			cd[--start] = '0';//如果当前结点是父节点的左孩子,则存一个1 
			else 
			cd[--start] = '1';//反之 
		}
		HC[i] = (char *)malloc((n - start) * sizeof(char));//申请第二维 
		strcpy(HC[i], &cd[start]);//将编码从工作空间存入赫夫曼编码表中 
	}
	free(cd); //释放临时空间 
}

int main() {
    
    
	HuffmanTree HT;//自定义结构体  ht
	HuffmanCode HC;
	int w[MAX_NUM], n;
	int i;
	printf("输入结点的个数:\n");
	scanf_s("%d", &n);
	printf("输入每个结点的权值:\n");
	for (i = 0; i < n; i++)
		scanf_s("%d", &w[i]);
	HuffmanCoding(HT, HC, w, n);
	for (i = 1; i <= n; i++)
		printf("%d的赫夫曼编码为:%s\n", HT[i].weight, HC[i]);
	return 0;



Guess you like

Origin blog.csdn.net/jiahuiandxuehui/article/details/110200699