数据结构哈夫曼树和哈夫曼编码 适合新手学习因为本人也是新手,嘻嘻嘻

哈夫曼树和哈夫曼编码

给大家两句口诀 “选择两小造新树,删除两小造新人”
先看懂图这里有篇代码 大家可以对照一下 都是大同小异
大家要先看懂这两张图

第二张

#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;



猜你喜欢

转载自blog.csdn.net/jiahuiandxuehui/article/details/110200699