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

一、【实验目的】

(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;
	//初始化-1
	for(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;
	//初始化-1
	for(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;
	//初始化-1
	for(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;
}

【运行结果】

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【测评】OrangePi AIPro环境配置与基础应用

1.介绍 官网&#xff1a;http://www.orangepi.cn/ 社区&#xff1a;http://forum.orangepi.cn/ 昇腾社区&#xff1a;https://www.hiascend.com/ OrangePi AIPro 是一款基于昇腾AI技术的开发板&#xff0c;它采用华为昇腾910E AI芯片&#xff0c;集成4核64位CPU和AI处理器&am…

CRMEB多门店的门店后台首页路由

如何在输入 http://localhost:8080/、http://localhost:8080/store/、http://localhost:8080/custom-store/ 这三个中任意一个链接都能正确跳转到 http://localhost:8080/store/home/index 。要实这个要求&#xff0c;有两种方式&#xff1a; 重定向const router new VueRout…

恒创科技:Linux 服务器和 Windows 服务器哪个更好?

选择正确的服务器系统至关重要&#xff0c;目前广泛使用的选项是 Windows 服务器 和 Linux 服务器&#xff0c;它们各有优缺点。本文将比较 Linux 与 Windows 服务器&#xff0c;让我们来看看它们的主要区别&#xff0c;然后再决定哪种操作系统适合使用。 主要区别&#xff1a;…

几种流行的并行方法了解

几种流行的并行方法&#xff1a; 数据并行&#xff08;data parallel&#xff09;模型并行&#xff08;model parallel&#xff09; tensor并行pipeline并行sequence并行Zero Redundancy Data Parallelism&#xff08;ZeRO&#xff09; Data parallelism (DP) 经典的数据并行…

基本Java语法和语义 (Reading 2)

&#xff08;1&#xff09;Java和C在变量类型命名和使用 基本数据类型 对象类型与引用类型 特殊类型 关键字和修饰符 &#xff08;2&#xff09;快照图&#xff1a; IDE调试工具: 许多IDE&#xff08;如Eclipse、IntelliJ IDEA&#xff09;提供了调试功能&#xff0c;可以…

智慧水坝:科技变革的里程碑

在曾经的水利工程领域&#xff0c;水坝只是为了水资源的调配和控制&#xff0c;提供一定的安全储备。然而&#xff0c;随着现代科技的不断发展&#xff0c;传统的水坝已经不再是单一的水源控制工程&#xff0c;而是变成了一个充满智慧与创新的生态系统。智慧水坝的概念已经超越…

远大阀门集团携创新产品亮相南京,展现石化行业新风采

2024年5月22日&#xff0c;备受瞩目的第八届中国石油和化工行业采购大会在江苏省南京市盛大开幕。作为石化行业物资采购领域极具影响力的年度盛会&#xff0c;本次大会吸引了众多国内外能源化工企业、化工新材料企业、工程公司以及相关领域的供应商参加。远大阀门集团作为特邀优…

Python筑基之旅专栏(导航)

目录 一、Python筑基之旅专栏博文清单及链接 二、推荐阅读 一、Python筑基之旅专栏博文清单及链接 01、溯源及发展 02、变量和数据类型 03、搭建Python开发环境及库 04、两个重要函数/列表/元组 05、字符串(一) 06、字符串(二) 07、字符串(三) 08、字典 09、集合 10…

看汽车冲压件的工厂,如何做PFMEA分析?

为了确保冲压件的质量稳定&#xff0c;提高生产效率&#xff0c;PFMEA&#xff08;过程潜在失效模式及影响分析&#xff09;分析成为了汽车冲压件工厂不可或缺的重要工具。本文将带您走进汽车冲压件工厂&#xff0c;一探PFMEA分析的奥秘与实践。 PFMEA分析&#xff0c;作为一种…

I.MX6ULL的蜂鸣器实验

系列文章目录 I.MX6ULL的蜂鸣器实验 I.MX6ULL的蜂鸣器实验 系列文章目录一、前言二、有源蜂鸣器简介三、硬件原理分析四、程序编写五、编译下载验证5.1编写 Makefile 和链接脚本5.2编译下载 一、前言 在 I.MX6U-ALPHA 开发板上有一个有源蜂鸣器&#xff0c;通过 IO 输出高低电…

git中忽略文件的配置

git中忽略文件的配置 一、在项目根目录下创建.gitignore文件二、配置规则如果在配置之前已经提交过文件了&#xff0c;要删除提交过的&#xff0c;如何修改&#xff0c;参考下面的 一、在项目根目录下创建.gitignore文件 .DS_Store node_modules/ /dist# local env files .env…

设计模式基础——设计原则介绍

1.概述 ​ 对于面向对象软件系统的设计而言&#xff0c;如何同时提高一个软件系统的可维护性、可复用性、可拓展性是面向对象设计需要解决的核心问题之一。面向对象设计原则应运而生&#xff0c;这些原则你会在设计模式中找到它们的影子&#xff0c;也是设计模式的基础。往往判…

电脑由于ntdll.dlI丢失导致exe崩溃有什么解决办法?解决ntdll.dll丢失问题

相信有一些用户正在面临一个叫做“ntdll.dll丢失”的问题&#xff0c;这种情况多半发生在试图运行某个程序时&#xff0c;系统会提示一条错误消息&#xff1a;“程序无法启动&#xff0c;因为计算机中丢失了ntdll.dll”。那么&#xff0c;为何ntdll.dll文件会丢失&#xff0c;又…

全能集成开发平台Team·IDE

三甲医院的床位太难等了。反正也是小手术&#xff0c;老苏周五在附近找了家二甲医院&#xff0c;幸运的是&#xff0c;门诊迅速为我开具了入院证。周六早晨就接受了手术&#xff0c;周日挂了一天水&#xff0c;周一下午就出院了。准备在家先休息两天。 2~4 周之后把支架取出来…

Pytorch深度学习实践笔记9(b站刘二大人)

&#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;pytorch深度学习 &#x1f380;CSDN主页 发狂的小花 &#x1f304;人生秘诀&#xff1a;学习的本质就是极致重复! 《PyTorch深度学习实践》完结合集_哔哩哔哩_bilibi…

YOLOv10:全面的效率-准确性驱动模型设计

YOLOv10&#xff1a;全面的效率-准确性驱动模型设计 提出背景精细拆分解法双重标签分配一致的匹配度量以效率为导向的模型设计 YOLO v10 总结1. 双重标签分配策略2. 一致匹配度量策略 论文&#xff1a;https://arxiv.org/pdf/2405.14458 代码&#xff1a;https://github.com/T…

【源码】java + uniapp交易所源代码/带搭建教程java交易所/完整源代码

java uniapp交易所源代码/带搭建教程java交易所/完整源代码 带简洁教程&#xff0c;未测 java uniapp交易所源代码/带搭建教程java交易所/完整源代码 - 吾爱资源网

数据结构第二篇【关于java线性表(顺序表)的基本操作】

【关于java线性表&#xff08;顺序表&#xff09;的基本操作】 线性表是什么&#xff1f;&#x1f435;&#x1f412;&#x1f98d;顺序表的定义&#x1f9a7;&#x1f436;&#x1f435;创建顺序表新增元素,默认在数组最后新增在 pos 位置新增元素判定是否包含某个元素查找某个…

HTTP 与 HTTPS 对比

HTTP&#xff1a;HTTPS&#xff1a;超文本传输协议 超文本传输安全协议加入SSL/TLS协议&#xff0c;依靠证书来验证服务器的身份需要到CA申请证书&#xff0c;需要一定费用TCP 协议 80 端口 TCP 协议 443 端口更耗费服务器资源

zabbix自定义监控项

文章目录 1、配置conf文件(zabbix_agent2)linuxwindows 2、配置监控项3、配置触发器4、查看监控数据 示例自定义程序 hash_tool&#xff1a;输出指定目录的哈希值 调用指令&#xff1a; hash_tool --path [指定目录] 1、配置conf文件(zabbix_agent2) linux vim /etc/zabbix/z…