(数据结构)哈夫曼编码实现(C语言)

news/2025/3/13 14:43:16/

(数据结构)哈夫曼编码实现(C语言)

哈夫曼的编码:从一堆数组当中取出来最小的两个值,按照左下右大的进行绘制,将两个权值之和,放入队列当中,然后再进行取出两个小的,以此类推,直到全部结束,在根据图根节点,到叶子节点,每一个分支来得出编码,向左0,向右1,即可得到一个结果。

#include <stdio.h>
#include <stdlib.h>// 定义哈夫曼树结点的结构
struct Node {int frequency;char data;struct Node* left;struct Node* right;
};// 创建一个新的哈夫曼树结点
struct Node* newNode(int frequency, char data) {struct Node* node = (struct Node*)malloc(sizeof(struct Node));node->frequency = frequency;node->data = data;node->left = NULL;node->right = NULL;return node;
}struct MinHeap {int size;int capacity;struct Node** array;
};// 创建最小堆
struct MinHeap* createMinHeap(int capacity) {struct MinHeap* minHeap = (struct MinHeap*)malloc(sizeof(struct MinHeap));minHeap->size = 0;minHeap->capacity = capacity;minHeap->array = (struct Node**)malloc(capacity * sizeof(struct Node*));return minHeap;
}// 交换两个结点的位置
void swapNode(struct Node** a, struct Node** b) {struct Node* temp = *a;*a = *b;*b = temp;
}// 维护最小堆的性质
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]->frequency < minHeap->array[smallest]->frequency) {smallest = left;}if (right < minHeap->size && minHeap->array[right]->frequency < minHeap->array[smallest]->frequency) {smallest = right;}if (smallest != idx) {swapNode(&minHeap->array[smallest], &minHeap->array[idx]);minHeapify(minHeap, smallest);}
}// 检查最小堆是否只有一个元素
int isSizeOne(struct MinHeap* minHeap) {return minHeap->size == 1;
}// 检查结点是否是叶子结点
int isLeaf(struct Node* root) {return !(root->left) && !(root->right);
}// 从最小堆中提取最小值(即频率最小的结点)
struct Node* extractMin(struct MinHeap* minHeap) {struct Node* 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 Node* node) {++minHeap->size;int i = minHeap->size - 1;while (i && node->frequency < minHeap->array[(i - 1) / 2]->frequency) {minHeap->array[i] = minHeap->array[(i - 1) / 2];i = (i - 1) / 2;}minHeap->array[i] = node;
}// 构建哈夫曼树
struct Node* buildHuffmanTree(char data[], int frequency[], int size) {struct Node *left, *right, *top;// 创建一个最小堆并初始化struct MinHeap* minHeap = createMinHeap(size);// 向最小堆中插入结点for (int i = 0; i < size; i++) {insertMinHeap(minHeap, newNode(frequency[i], data[i]));}// 构建哈夫曼树while (!isSizeOne(minHeap)) {// 从最小堆中取出最小的两个结点作为左子树和右子树left = extractMin(minHeap);right = extractMin(minHeap);// 创建一个新的结点作为父结点top = newNode(left->frequency + right->frequency, '-');top->left = left;top->right = right;// 将父结点插入最小堆中insertMinHeap(minHeap, top);}// 最后剩下的结点就是哈夫曼树的根结点return extractMin(minHeap);
}// 打印哈夫曼编码
void printHuffmanCodes(struct Node* root, int arr[], int top) {// 叶子结点是存有字符的结点if (root->left) {arr[top] = 0;printHuffmanCodes(root->left, arr, top + 1);}if (root->right) {arr[top] = 1;printHuffmanCodes(root->right, arr, top + 1);}// 如果是叶子结点(没有左右子结点),则打印编码if (!root->left && !root->right) {printf("%c: ", root->data);for (int i = 0; i < top; i++) {printf("%d", arr[i]);}printf("\n");}
}int main() {char data[] = { 'a', 'b', 'c', 'd', 'e' };int frequency[] = { 5, 9, 12, 13, 16 };int size = sizeof(data) / sizeof(data[0]);struct Node* root = buildHuffmanTree(data, frequency, size);int arr[100], top = 0;printHuffmanCodes(root, arr, top);return 0;
}

http://www.ppmy.cn/news/974424.html

相关文章

opencv 之 外接多边形(矩形、圆、三角形、椭圆、多边形)使用详解

opencv 之 外接多边形&#xff08;矩形、圆、三角形、椭圆、多边形&#xff09;使用详解 本文主要讲述opencv中的外接多边形的使用&#xff1a; 多边形近似外接矩形、最小外接矩形最小外接圆外接三角形椭圆拟合凸包 将重点讲述最小外接矩形的使用 1. API介绍 #多边形近似 v…

视频的行为识别

1. 概述 使用DL方法解决视频中行为识别/动作识别的问题解决思路有三个分支&#xff1a;分别是two-stream(双流)方法&#xff0c;C3D方法以及CNN-LSTM方法。本文将从算法介绍、算法架构、参数配置、训练集预处理、算法优势及原因、运行结果六个方面对每种算法进行阐释&#xff…

人脸图片及视频识别

import cv2 cap cv2.VideoCapture(0) cap.set(3,640)#改变高度 cap.set(4,480)#改变宽度 cap.set(10,100)#改变亮度 def Face_Detect_Pic(image):gray cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)cv2.imshow("gray", gray)face_detector cv2.CascadeClassifier(&quo…

ChatGPT在舆情分析和情感监测中的应用如何?

ChatGPT在舆情分析和情感监测领域的应用具有广泛的潜力。舆情分析是指通过对社交媒体、新闻、论坛等渠道中的文本数据进行分析&#xff0c;了解公众对特定事件、产品或品牌的态度和情感。情感监测是一种文本情感分析任务&#xff0c;旨在识别文本中所表达的情感&#xff0c;如喜…

视频理解多模态大模型(大模型基础、微调、视频理解基础)

转眼就要博0了&#xff0c;导师开始让我看视频理解多模态方向的内容&#xff0c;重新一遍打基础吧&#xff0c;从Python&#xff0c;到NLP&#xff0c;再到视频理解&#xff0c;最后加上凸优化&#xff0c;一步一步来&#xff0c;疯学一个暑假。写这个博客作为我的笔记以及好文…

Vue数据劫持源码分析

Vue.js 3.0 中的数据劫持是通过 Proxy 实现的&#xff0c;而不是使用 Vue.js 2.x 中的 Object.defineProperty。Proxy 是 ES6 中引入的一个新特性&#xff0c;它提供了更强大的拦截和自定义操作对象的能力。 以下是 Vue.js 3.0 中数据劫持的简化版源码分析&#xff1a; 创建 …

进程信号的理解

进程信号 1. 信号的概念2. 信号的产生3. 信号的保存1. 信号其他相关常见概念2. 在内核中的表示3.信号集操作函数 4. 信号的处理&#xff08;捕捉&#xff09; 1. 信号的概念 信号的一生&#xff0c;进程信号从产生到被处理所经历的过程一共分成了三步&#xff1a;信号产生、信…

【Git】—— 分⽀的基本操作

目录 &#xff08;一&#xff09;理解分⽀ &#xff08;二&#xff09;创建分⽀ &#xff08;三&#xff09;切换分⽀ &#xff08;四&#xff09;合并分⽀ &#xff08;五&#xff09;删除分⽀ 总结 &#xff08;一&#xff09;理解分⽀ 本章开始介绍 Git 的杀⼿级功能之…