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

(数据结构)哈夫曼编码实现(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.mzph.cn/news/7176.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VuePress在生产环境跳转子页报错 Failed to execute ‘appendChild‘ on ‘Node‘

记录一个使用VuePress时遇到的问题 使用VuePress做了一个文档网页&#xff0c;在开发环境的时候一切正常&#xff0c;但是发布到生产环境后&#xff0c;直接跳转二级页面会报错Failed to execute appendChild on Node 比如主页是http://sun/docs/.vuepress/dist/index.html#/…

SwiftUI-基础

应用入口 Main函数与App结构体的绑定&#xff0c;遵循App协议 main struct BaseApp: App {var body: some Scene {WindowGroup {ContentView()}} } 兼容UIApplicationDelegate main struct BasicApp: App {UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate…

【C语言项目】三子棋

文章目录 项目思路一、分文件进行创建二、进入游戏前的目录2.1 目录的功能&#xff1a;2.2 目录界面&#xff1a;2.3 选择进入或退出游戏2.4 多次重玩功能 三、画出棋盘3.1 写出棋子3.2 初始化棋盘3.2 画出棋盘的框架3.3 代码实现 四、玩家落子4.1 落子逻辑4.2具体情况分类讨论…

抖斗音直播间评论引流助手,支持直播间喊话+视频评论区喊话=到指定直播间引流精准粉丝【永久脚本+详细教程】

如果你觉得直播间发言手动太麻烦了&#xff0c;或许这个自动工具能帮到你&#xff01; 1.开始运行前&#xff0c;需要手动去打开打开直播间或者视频评论区&#xff0c;再运行脚本。 2.脚本就是模拟人工操作&#xff0c;在相应的APP里进行评论&#xff0c;无突破APP限制功能。…

[USACO14DEC] Marathon G

洛谷[USACO14DEC] Marathon G 题目大意 Bessie \text{Bessie} Bessie设计了一条马拉松路线&#xff0c;有 N N N个点。 Bessie \text{Bessie} Bessie有 q q q次操作&#xff0c;每次操作是修改或询问。每次修改会修改一个点的坐标&#xff0c;每次询问是选手跑过一条子路径的时…

阿里云ACK的etcd证书过期手工升级操作

一.问题现象 阿里云ACK的etcd证书过期&#xff0c;通过图形化界面升级提示升级失败&#xff0c;考虑通过脚本的方式升级ETCD相关的证书。由于在前期做类似的升级ETCD证书失败导致整个集群业务出现访问异常&#xff0c;所有在升级之前做好对应的备份操作是很有必要的 二.前期准…

【Kubernetes运维篇】ingress-nginx实现业务灰度发布详解

文章目录 一、理论&#xff1a;实现灰度发布的几种场景1、场景一&#xff1a;将新版本灰度给部分用户2、场景二&#xff1a;按照比例流程给新版本3、实现灰度发布字段解释 二、实践&#xff1a;1、实验前提环境2、基于Request Header(请求头)进行流量分割3、基于Cookie进行流量…

93.qt qml-自定义Table优化(新增:水平拖拽/缩放自适应/选择使能/自定义委托)

之前我们更新了90.qt qml-Table表格组件(支持表头表尾固定/自定义颜色/自定义操作按钮/排序)_qml 表格_诺谦的博客-CSDN博客 但是一直没出源码,是因为该demo还存在问题,那就是表头表尾固定下,如果是半透明状态下,会看到表头表尾固定后的内容,所以只能重构代码,不能使用重…

Vue3组合式API+TypeScript写法入门

文章目录 前言1.reactive2.ref3.props4.computed5.emit6.watch总结 前言 参考Vue3官网. 本篇以组合式API为例, 但不包含setup语法糖式写法. 原本打算结合class-component, Vue3不推荐就不用了: OverView|Vue Class Component. 而且是不再推荐基于类的组件写法, 推荐单文件组件…

Android App 持续集成性能测试:启动流量

目录 前言&#xff1a; get app UID 获取流量数据 获得启动流量数据 总结 前言&#xff1a; Jenkins 是一种开源的持续集成工具&#xff0c;可以帮助我们更加方便地进行软件开发和测试工作。通过 API 远程管理 Jenkins 可以帮助我们更加方便地进行 Jenkins 的配置和管理工…

react实现路由跳转动画

下载插件 npm i react-transition-group 配置路由 import { createBrowserRouter as ReactRouter,Navigate } from "react-router-dom";import App from ../App.js import Login from "../view/login.js"; import Home from "../home.js"; co…

了解 3DS MAX 3D摄像机跟踪设置:第 4 部分

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 1. 项目设置 步骤 1 打开“后效”。 打开后效果 步骤 2 转到合成>新合成以创建新合成。 将“宽度”和“高度”值分别设置为 1280 和 720。将帧速率设置为 25&#xff0c;将持续时间设置为 12 秒。单…

Go基本数据类型及内置函数(一文稳定基础)

文章目录 1. 基础数据类型2.内置函数3.函数4.列表操作及for循环5.原子性操作6.通道7.协程与并发安全8.定时器 1. 基础数据类型 1. bool&#xff1a;布尔类型&#xff0c;只有 true 和 false 两个值。var test2 bool true2. string&#xff1a;字符串类型&#xff0c;表示一组字…

微服务网关

1.网关是如何演化来的&#xff0c;在微服务中有什么作用&#xff1f; 随着单体架构转化为微服务架构的时候&#xff0c;由一个后台服务由一个单一的服务变成了多个微服务&#xff0c;前端应用需要调用多个服务的接口&#xff0c;为了解决这个问题&#xff0c;网关就产生了。网…

【LeetCode】55.跳跃游戏

题目 给定一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。 数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标。 示例 1&#xff1a; 输入&#xff1a;nums [2,3,1,1,4] 输出&#xff1a;true 解释&#xff1a;可以…

一个月学通Python(二十六):Django使用缓存

专栏介绍 结合自身经验和内部资料总结的Python教程,每天3-5章,最短1个月就能全方位的完成Python的学习并进行实战开发,学完了定能成为大佬!加油吧!卷起来! 全部文章请访问专栏:《Python全栈教程(0基础)》 文章目录 专栏介绍使用缓存Django项目接入Redis为视图提供缓…

Flask 文件上传,删除上传的文件

目录结构 app.py from flask import Flask, request, render_template, redirect, url_for import osapp Flask(__name__) BASE_DIR os.getcwd() UPLOAD_FOLDER os.path.join(BASE_DIR, testfile)app.route(/) def home():files os.listdir(UPLOAD_FOLDER)return render_t…

欧盟新规,燃油噩梦?2025年起,高速公路每60公里设立一处快充站

根据外媒The Verge报道&#xff0c;欧洲电动汽车用户将获得更多便捷的待遇&#xff0c;同时还能减少有害温室气体排放&#xff0c;这得益于欧盟理事会最新通过的法规。 根据欧盟的法规要求&#xff0c;自2025年起&#xff0c;TEN-T高速公路系统在欧洲将需要每隔60公里设立一座高…

Langchain 和 Chroma 的集成

Langchain 和 Chroma 的集成 1. Chroma2. 基本示例​3. 基本示例(包括保存到磁盘)4. 将 Chroma Client 传递到 Langchain ​5. 基本示例(使用 Docker 容器)6. 更新和删除7. 带分数的相似性搜索​ 1. Chroma Chroma 是一个人工智能原生开源矢量数据库&#xff0c;专注于开发人员…

ES6基础知识六:你是怎么理解ES6中 Promise的?使用场景?

一、介绍 Promise&#xff0c;译为承诺&#xff0c;是异步编程的一种解决方案&#xff0c;比传统的解决方案&#xff08;回调函数&#xff09;更加合理和更加强大 在以往我们如果处理多层异步操作&#xff0c;我们往往会像下面那样编写我们的代码 doSomething(function(resu…