算法设计第七周(应用哈夫曼算法解决文件归并问题)

一、【实验目的】

(1)进一步理解贪心法的设计思想

(2)掌握哈夫曼算法的具体应用

(3)比较不同的文件归并策略,探讨最优算法。

二、【实验内容】

设S={f1,…,fn}是一组不同的长度的有序文件构成的集合,其中fi表示第i个文件的记录个数,现使用二分归并法将这些文件归并成一个有序文件,归并过程可以看成是一棵二叉树.参考教材P102例4.7,请采用两种方法进行二分归并,其中一种为哈夫曼算法。

提示:其中n个文件可用n个数组模拟,文件的内容为数组中已排好序的整数;可以用教材例4.7中定义的S集合中6个文件的长度作为数组长度进行测试。注意,要编写两个数组进行顺序归并的程序。

三、实验源代码

四、实验结果

五、实验分析与总结

实验分析:

要求完成以下两种归并

按照哈夫曼算法的思路,先取最小的两个点进行归并,得到一个父结点。再放回去再选择两个小的。

⚠️错误写法

  • 这里用的优先队列实现了插入一个元素后排序且可以有队列的特性。
  • j用于叶子结点的创建,i用于父结点的创建。
  • returnElement函数取最小的两个元素,再加起来放回去
#include <bits/stdc++.h>
using namespace std;int n = 6;
vector<int> s = {21, 10, 32, 41, 18, 70};
vector<int> a = s;
vector<int> temp(10);
priority_queue<int, vector<int>, greater<int>> pq; //升序队列模板struct treeNode{int weight;int parent;int leftchild, rightchild;
}tree[20];void returnElement(int& element1, int& element2)
{if(!pq.empty()){element1 = pq.top();pq.pop();element2 = pq.top();pq.pop();int sum = element1 + element2;pq.push(sum);}
}void CreateHuffmanTree(){ //二分归并法最优//输入for(auto e : s)pq.push(e);int j=1, element1, element2;//初始化-1for(int i=1; i<=2*n-1; i++){tree[i].parent = -1,  tree[i].leftchild = -1; tree[i].rightchild = -1;}for(int i=n; i<=2*n-1; i++){//左右孩子结点returnElement(element1, element2);tree[j].weight = element1;j++;tree[j].weight = element2;j++;//父节点tree[i].weight = element1 + element2;tree[i].leftchild = j-2;tree[i].rightchild = j-1;}}
//由于中文乱码,所以输出英文
void printTree()
{for (int i = 1; i <=2*n-1; i++){cout << setw(7) << "i:" << i ;cout << setw(7) << "node:" << tree[i].weight << "\t";cout << setw(7) << "parent:" << tree[tree[i].parent].weight << "\t";cout << setw(7) << "leftchild:" << tree[tree[i].leftchild].weight << "\t";cout << setw(7) << "rightchild:" << tree[tree[i].rightchild].weight << endl;}
}int main()
{CreateHuffmanTree();printTree();return 0;
}

行结果:

  • 叶子结点和父结点交叉存放
  • -1的值未打印出来
  • 有一些数据被覆盖掉了


对比书上的图,缺项多项

正确写法: 

【【数据结构】构造哈夫曼树手写代码】icon-default.png?t=N7T8https://www.bilibili.com/video/BV1EV4y1V7Vx/?share_source=copy_web&vd_source=7ffbd7feaeedb3d59fb21e59435a53d8 改进: 

returnElement函数弃用,改成每次在tree中寻找最小元素、和次小元素的下标。

先把叶子结点存入,以免出现交叉存放和覆盖数据

先把叶子结点存入后,直接更新父结点的值就可以了,叶子结点的parent指向父结点的下标

#include <bits/stdc++.h>
using namespace std;int n = 6;
vector<int> s = {21, 10, 32, 41, 18, 70};
vector<int> a = s;
vector<int> temp(10);
//priority_queue<int, vector<int>, greater<int>> pq; //升序队列模板struct treeNode{int weight;int parent;int leftchild, rightchild;
}tree[20];void selectMinElementIndex(int n, int& index1, int& index2)
{int min = 9e8; //打擂台,用于确定最小的那个//寻找最小的权值下标for(int i=1; i<= n; i++){if(tree[i].parent == -1 && tree[i].weight < min){min = tree[i].weight;index1 = i;}}min = 9e8;//寻找次小的权值下标for(int i=1; i<= n; i++){if(tree[i].parent == -1 && tree[i].weight < min && i != index1){min = tree[i].weight;index2 = i;}}
}void CreateHuffmanTree(){ //二分归并法最优sort(s.begin(), s.end());	int index1, index2;//初始化-1for(int i=1; i<=2*n-1; i++){tree[i].parent = -1,  tree[i].leftchild = -1; tree[i].rightchild = -1;}//放入叶子结点for(int i=1; i<=n; i++){tree[i].weight = s[i-1];}for(int i=n+1; i<=2*n-1; i++){//传入了i-1,保证在新建立的父节点和叶子结点中寻找两个最小selectMinElementIndex(i-1, index1, index2);// 左右孩子结点指向父结点tree[index1].parent = i;tree[index2].parent = i;//父结点更新值tree[i].weight = tree[index1].weight + tree[index2].weight;tree[i].leftchild = index1;tree[i].rightchild = index2;}
}
//由于中文乱码,所以输出英文
void printTree()
{for (int i = 1; i <= 2*n-1; i++){cout << setw(7) << "i:" << i << "  ";cout << setw(7) << "node:" << tree[i].weight << "\t";cout << setw(7) << "parent:" <<  (tree[i].parent != -1 ? tree[tree[i].parent].weight : -1) << "\t";cout << setw(7) << "leftchild:" <<  (tree[i].leftchild != -1 ? tree[tree[i].leftchild].weight : -1) << "\t";cout << setw(7) << "rightchild:" << (tree[i].rightchild != -1 ? tree[tree[i].rightchild].weight : -1) << endl;}
}void CreateATree(){ //另一种二分归并法int j=1;//初始化-1for(int i=1; i<=2*n-1; i++){tree[i].parent = -1,  tree[i].leftchild = -1; tree[i].rightchild = -1;}//放入叶子结点for(int i=1; i<=n; i++){tree[i].weight = s[i-1];}for(int i=n+1; i<=2*n-1; i++){// 左右孩子结点指向父结点,j直接选两个平推过去tree[j].parent = i;tree[j+1].parent = i;//父结点更新值tree[i].weight = tree[j].weight + tree[j+1].weight;tree[i].leftchild = j;tree[i].rightchild = j+1;j += 2;}
}int main()
{cout << "The another method:" << endl;CreateATree();printTree();cout << "The best method:" << endl;CreateHuffmanTree();printTree();return 0;
}

【运行结果】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/842211.shtml

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

相关文章

基于springboot+vue的仓库管理系统

免费获取方式↓↓↓ 项目介绍029&#xff1a; http://localhost:8081/ eclipse mysql jdk1.8 密码admin root 用户员&#xff08;id 账号 密码 年龄 角色 电话&#xff09; 仓库表&#xff08;id 名称 备注&#xff09; 分类表&#xff08;id 名称 备注&#xff09; 记录表(id…

基于翔云C#语言的身份证实名认证接口开发示例

现如今&#xff0c;安全与便捷成为了互联网服务的两大关键词。为了进一步提升用户体验并加强网络安全管理&#xff0c;国内多家主流App近日宣布完成一项重要功能升级——集成身份证实名认证系接口。这一举措标志着用户在进行App注册时&#xff0c;将享受到更加高效、安全的身份…

深度学习论文: YOLOv10: Real-Time End-to-End Object Detection

深度学习论文: YOLOv10: Real-Time End-to-End Object Detection YOLOv10: Real-Time End-to-End Object Detection PDF: https://arxiv.org/pdf/2405.14458 PyTorch代码: https://github.com/shanglianlm0525/CvPytorch PyTorch代码: https://github.com/shanglianlm0525/PyTo…

104-1389-006马达单价1041389006可议价

104-1389-006 产品 M 马达 系列 02 2000 系列 排量 149 244.3 CM3/R [14.91 IN3/R] 安装类型 AH 标准&#xff0c;4 螺栓&#xff1b;先导直径为 82.6 [3.25] 13.59 直径为 [0.535] 直径为 106.4 [4.19] 的孔螺栓圆周 输出轴 16 直径为 32.00 [1…

用一个装饰器代替 try except

用一个装饰器代替 try except 要写很多封装的时候&#xff0c;大量的使用 try except 很麻烦&#xff0c;直接使用python装饰器解决 import functoolsdef handle_exceptions(func):functools.wraps(func)def wrapper(*args, **kwargs):try:return func(*args, **kwargs)excep…

地铁判官:啥时候B端系统界面,也出个“判官”,讲好不准打脸。

小编所在的城市——山东青岛&#xff0c;出了个地铁判官&#xff0c;我看了视频&#xff0c;哈哈哈&#xff0c;俗世的判断标准就是那么简单直接&#xff0c;而放到B端系统那就难说啦。 如何判断B端系统的优劣&#xff0c;各位看官&#xff0c;各抒己见吧。 判断B端系统界面的…

智慧校园建设规划方案

在信息化浪潮的推动下&#xff0c;智慧校园的建设已成为教育现代化的必然趋势。以创新科技赋能教育&#xff0c;打造智慧校园&#xff0c;旨在提升教学品质&#xff0c;优化管理流程&#xff0c;增强学生体验。构建智慧校园需要具有前瞻性的规划方案&#xff0c;它将以教育为核…

PL5358A 单芯锂离子/聚合物电池保护IC芯片

一般说明 PL5358A系列产品是锂离子/聚合物电池保护的高集成解决方案。PL5358A包含先进 的功率MOSFET&#xff0c;高精度电压检测电路和延迟电路。5358A被放入一个超小的SOT23-5封装&#xff0c;只有一个外部元件&#xff0c;使其成为理想的解决方案&#xff0c;在有限的…

vue2+elementui 表格中操作列不定个数按钮的折叠展开

vue2elementui 实现表格中操作列不定个数按钮的折叠展开&#xff0c;可以根据自己的需求自行修改样式和展示等。基本代码如下&#xff1a; <template><div class"table-action-col-box" :ref"_bf${rowId}"><div :ref"_bf${rowId}_but…

开源博客项目Blog .NET Core源码学习(28:App.Hosting项目结构分析-16)

本文学习并分析App.Hosting项目中后台管理页面的用户管理页面。   用户管理页面用于显示、检索、新建、编辑、删除用户数据&#xff0c;其附带一新建及编辑页面&#xff0c;以支撑新建和编辑用户数据&#xff0c;同时还附带重置密码页面&#xff0c;以重置用户密码。整个页面…

SUPRA:无须额外训练,将Transformer变为高效RNN,推理速度倍增

Transformers 已经确立了自己作为首要模型架构的地位&#xff0c;特别是因为它们在各种任务中的出色表现。但是Transformers 的内存密集型性质和随着词元数量的指数扩展推理成本带来了重大挑战。为了解决这些问题&#xff0c;论文“Linearizing Large Language Models”引入了一…

android-mvp模式

mvvm可以理解成使用databing的mvp模式&#xff0c;modleview 通过接口让view和Presenter层解耦 从图中就可以看出&#xff0c;最明显的差别就是view层和model层不再相互可知&#xff0c;完全的解耦&#xff0c;取而代之的presenter层充当了桥梁的作用&#xff0c;用于操作view…

set怎么实现有序

在Java集合框架中&#xff0c;Set接口的实现类主要有三种常见的变体&#xff1a;无序的HashSet、保持插入顺序的LinkedHashSet和按自然顺序或自定义比较器排序的TreeSet。要实现有序的Set&#xff0c;可以使用LinkedHashSet或TreeSet。 有序的Set实现类 LinkedHashSet&#xf…

0基础认识C语言(代码实操)

首先呢大家要知道C语言的常见格式如下 #include <stdio.h> int main() {return 0; } 可能看起来会有点懵&#xff0c;但是不着急&#xff0c;咱们一句一句讲 #include <stdio.h> 这是一个头文件&#xff0c;是标准输入输出&#xff0c;怎么理解呢&#xff0c;你…

芯片设计 | 什么是 NVMe?

文章目录 什么是 NVMe&#xff1f;什么是固态硬盘&#xff1f;为什么 NVMe 很重要&#xff1f;NVMe、SAS 和 SATA 之间的区别只有SSD运行在NVMe上PCIe和NVMe有关系&#xff0c;但它们不是同一个东西NVMe-oF连接SSD到网络NVMe 的工作原理是什么&#xff1f;NVMe SSD 外形尺寸M.2…

零售品牌做好差旅报销管理,真的能省钱

一年一度的“618”如期而至,甚至启动更早了。 各大厂商宣布取消延用了十多年的预售机制,主打“现货开卖”,充分回归“消费者价值”。 零售品牌给消费者省钱,更要给自己省钱。而这前提是充分了解“钱花在哪了”、“怎么花更合理”: ● 商业化BD、促销、营销等市场活动频繁,差…

手动验证 Azure AD 并设置登录状态

几个核心要点 1. client_id&#xff0c;client_secret&#xff0c;username&#xff0c;password 是必须要的 2. 通过 https://login.microsoftonline.com/...... 提交参数&#xff0c;成功就可以拿到 token 3. 自定义一个 CustomAuthenticationStateProvider 类继承自抽象类…

如何知道huggingface/modelscope的大模型的模型层名字

下载模型后&#xff0c;有个文件叫model.safetensors.index.json&#xff0c;里面有。 你下载的大模型位置在用户名/.cache/huggingface/hub/大模型名差不多这个路径。 或者直接print(parameters.name)&#xff0c;但是这样打出来特别多&#xff0c;很难看。差不多这样写&am…

LeetCode hot100-52-G

994. 腐烂的橘子 在给定的 m x n 网格 grid 中&#xff0c;每个单元格可以有以下三个值之一&#xff1a;值 0 代表空单元格&#xff1b;值 1 代表新鲜橘子&#xff1b;值 2 代表腐烂的橘子。每分钟&#xff0c;腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。返回 直到单…

软件项目管理过程中的会议管理

项目会议类型 软件项目管理中的会议通常包括评审会议、项目例会、技术研讨会、项目启动会、项目回顾会、风险管理会议等多种类型&#xff0c;每种类型的会议都有其特定的目的和参与者。 1. 评审会议&#xff08;Review Meetings&#xff09;&#xff1a; & 需求评审&…