数据结构-C语言代码 day12-哈夫曼树

一、哈夫曼树的概念

给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,则称该二叉树为哈夫曼树,也被称为最优二叉树。

1、路径—从树中一个结点到另一个结点之间的分支构成这两个结点间的路径  

结点路径长度—两结点间路径上的分支数

树的路径长度—根节点到每个结点路径长度之和(TL)

TL = 1+1+2+2+3+3+4+4 = 20

2、权—结点所赋的值

结点带权路径长度—从根节点到该结点间路径长度和权的乘积

树的带权路径长度—结点之和(WPL)

WPL = 7*2+5*2+2*2+4*2 = 36

(构造哈夫曼树时首先选择权值小的叶子结点,权越大离根越近)

3、哈夫曼编码

利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。树中从根到每个叶子节点都有一条路径,对路径上的各分支约定指向左子树的分支表示”0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为各个叶子节点对应的字符编码,即是哈夫曼编码。

二、代码展示

#include<stdio.h>
#define MAX_SIZE 1000

typedef struct NODE Node;
struct NODE
{
	int weight;//结点权值
	int parent,lchild,rchild; 
};

//初始化结点
void initNode(Node &node,int weight,int parent,int lchild,int rchild)
{
	node.weight = weight;
	node.parent = parent;
	node.lchild = lchild;
	node.rchild = rchild;
 } 

/*
1、n个结点,需分配n*2-1个内存空间,前n个表示新输入的结点,后n-1表示结点的父结点;
2、初始化数组,给权赋值; 
3、遍历数组,标记最小结点;
4、将新结点插入最后;
5、重复3、4,最后一个结点即为根结点。
*/
void createHuffmanTree(Node *node,int *a,int n)
//n为叶子结点个数 
{
	int i,j,m1,m2,x1,x2,total;
	for(i = 0;i < n;i++)
	{
		initNode(node[i],a[i],-1,-1,-1);
	}
	total = n*2-1;//哈夫曼树所有结点的个数
	for(i = n;i < total;i++)
	{
		m1 = 100;
		m2 = m1;
		x1 = x2 =0;
		for(j = 0;j < i;j++)
		{
			if(node[j].parent == -1)
			{
				if(node[j].weight < m1)
				{
					m2 = m1;
					x2 = x1;
					m1 = node[j].weight;
					x1 = j;
				}
				else if(node[j].weight < m2)
				{
					m2 = node[j].weight;
					x2 = j;
				}
			}
		}
		node[x1].parent = i;
		node[x2].parent = i;
		initNode(node[i],m1+m2,-1,x1,x2);
	 } 
}

//哈夫曼编码 
void huffmanCode(Node *node,int child,int *str)
{
	int i,parent,j = 0,e;
	parent = node[child].parent;//父结点 
	while(parent != -1)
	{
		if(node[parent].lchild == child)//若此结点为该父结点的左子结点,0入数组,否则1入数组 
		{
			str[j++] = 0;
		}
		else 
		{
			str[j++] = 1;
		}
		child  = parent;
		parent = node[child].parent;
	}
	e = j;
	for(j = e-1;j >= 0;j--)
		printf("%d",str[j]);
	printf("\n");
}

int main()
{
	Node node[MAX_SIZE];
	int a1[MAX_SIZE];//存放权值
	int a2[MAX_SIZE];//存放哈夫曼编码
	int n,i,j,e;
	printf("请输入叶子结点的个数:");
	scanf("%d",&n);
	for(i = 0;i < n;i++)
	{
		scanf("%d",&a1[i]);
	}
	createHuffmanTree(node,a1,n);
	
	for(i = 0;i < n;i++)
	{
		huffmanCode(node,i,a2);
	}
	return 0;
}
请输入叶子结点的个数:8
15 14 1 25 6 24 26 12
101
100
11000
00
11001
111
01
1101

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个求哈夫曼树C语言代码,包括哈夫曼编码: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_TREE_HT 100 struct MinHeapNode { char data; unsigned freq; struct MinHeapNode *left, *right; }; struct MinHeap { unsigned size; unsigned capacity; struct MinHeapNode **array; }; struct MinHeapNode *newNode(char data, unsigned freq) { struct MinHeapNode *temp = (struct MinHeapNode *)malloc(sizeof(struct MinHeapNode)); temp->left = temp->right = NULL; temp->data = data; temp->freq = freq; return temp; } struct MinHeap *createMinHeap(unsigned capacity) { struct MinHeap *minHeap = (struct MinHeap *)malloc(sizeof(struct MinHeap)); minHeap->size = 0; minHeap->capacity = capacity; minHeap->array = (struct MinHeapNode **)malloc(minHeap->capacity * sizeof(struct MinHeapNode *)); return minHeap; } void swapMinHeapNode(struct MinHeapNode **a, struct MinHeapNode **b) { struct MinHeapNode *t = *a; *a = *b; *b = t; } void minHeapify(struct MinHeap *minHeap, int idx) { int smallest = idx; int left = 2 * idx + 1; int right = 2 * idx + 2; if (left < minHeap->size && minHeap->array[left]->freq < minHeap->array[smallest]->freq) smallest = left; if (right < minHeap->size && minHeap->array[right]->freq < minHeap->array[smallest]->freq) smallest = right; if (smallest != idx) { swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]); minHeapify(minHeap, smallest); } } int isSizeOne(struct MinHeap *minHeap) { return (minHeap->size == 1); } struct MinHeapNode *extractMin(struct MinHeap *minHeap) { struct MinHeapNode *temp = minHeap->array[0]; minHeap->array[0] = minHeap->array[minHeap->size - 1]; --minHeap->size; minHeapify(minHeap, 0); return temp; } void insertMinHeap(struct MinHeap *minHeap, struct MinHeapNode *minHeapNode) { ++minHeap->size; int i = minHeap->size - 1; while (i && minHeapNode->freq < minHeap->array[(i - 1) / 2]->freq) { minHeap->array[i] = minHeap->array[(i - 1) / 2]; i = (i - 1) / 2; } minHeap->array[i] = minHeapNode; } void buildMinHeap(struct MinHeap *minHeap) { int n = minHeap->size - 1; int i; for (i = (n - 1) / 2; i >= 0; --i) minHeapify(minHeap, i); } void printArr(int arr[], int n) { int i; for (i = 0; i < n; ++i) printf("%d", arr[i]); printf("\n"); } int isLeaf(struct MinHeapNode *root) { return !(root->left) && !(root->right); } struct MinHeap *createAndBuildMinHeap(char data[], int freq[], int size) { struct MinHeap *minHeap = createMinHeap(size); for (int i = 0; i < size; ++i) minHeap->array[i] = newNode(data[i], freq[i]); minHeap->size = size; buildMinHeap(minHeap); return minHeap; } struct MinHeapNode *buildHuffmanTree(char data[], int freq[], int size) { struct MinHeapNode *left, *right, *top; struct MinHeap *minHeap = createAndBuildMinHeap(data, freq, size); while (!isSizeOne(minHeap)) { left = extractMin(minHeap); right = extractMin(minHeap); top = newNode('$', left->freq + right->freq); top->left = left; top->right = right; insertMinHeap(minHeap, top); } return extractMin(minHeap); } void printCodes(struct MinHeapNode *root, int arr[], int top) { if (root->left) { arr[top] = 0; printCodes(root->left, arr, top + 1); } if (root->right) { arr[top] = 1; printCodes(root->right, arr, top + 1); } if (isLeaf(root)) { printf("%c: ", root->data); printArr(arr, top); } } void HuffmanCodes(char data[], int freq[], int size) { struct MinHeapNode *root = buildHuffmanTree(data, freq, size); int arr[MAX_TREE_HT], top = 0; printCodes(root, arr, top); } int main() { char arr[] = {'a', 'b', 'c', 'd', 'e', 'f'}; int freq[] = {5, 9, 12, 13, 16, 45}; int size = sizeof(arr) / sizeof(arr[0]); HuffmanCodes(arr, freq, size); return 0; } ``` 这个代码可以求出哈夫曼树,并输出每个字符的哈夫曼编码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值