霍夫码编码(笔记)

霍夫曼编码是一种无损数据压缩算法。其思想是为输入字符分配可变长度代码,分配代码的长度基于相应字符的频率。
代码实现

#include <cstdlib>
#include <iostream>
using namespace std;

#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;
	//查看右节点权重是否更小 更新smallest;
	if (right < minheap->size&&minheap->array[right]->freq <
		minheap->array[smallest]->freq)
		smallest = right;
	/*如果smallest索引发生了变化(表示左子节点或右子节点的频率更小),
	则使用你提供的swapMinHeapNode函数交换smallest和idx位置上的节点。
	这确保了最小频率的节点被移动到堆的顶部。
	最后,如果发生了交换,就递归调用minHeapify函数,
	在以smallest索引为根的子树上进行堆化操作。这样确保了整个堆中的最小堆属性得以保持。*/
	if (smallest!=idx){
		swapMinHeapNode(&minheap->array[smallest],&minheap->array[idx]);
		minHeapify(minheap, smallest);
	}

}
//堆大小是否为1
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)
	{
		//将父节点移到当前位置i 为待插入节点留出位置
		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) {
		cout << arr[i];
	}
	cout << "\n";
}
//检查是否叶子节点
int isLeaf(struct MinHeapNode* root) {

	return !(root->left)&&!(root->right);
}

//创建和构建最小堆(MinHeap)的函数
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)) {
		cout << 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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值