堆排序的插入和删除

news2025/7/30 21:24:40

插入:

        1.  检查你的顺序表是否还有位置去插入,如果没有需要扩展

        2. 插入到已有序列的后一位置

        3. 和其父节点进行比较,是否满足大根堆/小根堆规则

        4. 不满足则需要交换数值

删除:

        1. 将最后一个元素覆盖将要删除的元素,然后将最后一个元素置空

图1-1输出说明:

        1.  建立大根堆然后排序结果

        2. 插入元素后 结果

        3. 插入元素 调整好新元素位置后 输出结果

        4. 重新排序结果

        5. 删除数据后结果

 

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

/*大根堆:根节点的值大于左右孩子的数值*/
/*
1. 建立大根堆(检查所有的非终端结点 i<=n/2的结点  下标0舍弃不用)
2. 如果根节点不满足大根堆 那么将根节点与他最大的孩子结点交换 小元素不断下坠
3. 然后交换根节点和最后一个元素  根节点是最大的 最后一个元素是最小的
*/

typedef struct {
	int* e;//存储堆数据
	int len;//堆的长度  元素个数
	int mlen;//堆的最大长度
}Heap;

void InitHeap(Heap *hp,int n) {
	(*hp).e = (int*)malloc(sizeof(int) * (n + 1)); //0号位置不使用
	(*hp).len = 0;
	(*hp).mlen = n;
}

//将数据填入数组中
void AddData(Heap hp, int d[], int n) {
	for (int i = 1; i <= n; i++) {
		hp.e[i] = d[i - 1];
	}
}
//将以k为根结点的树调整为大根堆
void HeapAdjust(Heap hp, int k, int n) {
	hp.e[0] = hp.e[k];   //临时存储该根节点的数据
	//沿着数值较大的子节点向下筛选
	for (int i = 2 * k; i <= n; i *= 2) {//左孩子结点
		if (i < n && hp.e[i] < hp.e[i + 1])
			i++;//右孩子大
		if (hp.e[0] > hp.e[i])  break;
		else {
			hp.e[k] = hp.e[i];
			k = i;
		}
	}
	hp.e[k] = hp.e[0];
}
void HeapAdjustLittle(Heap hp, int k, int n) {
	hp.e[0] = hp.e[k];   //临时存储该根节点的数据
	//沿着数值较大的子节点向下筛选
	for (int i = 2 * k; i <= n; i *= 2) {//左孩子结点
		if (i < n && hp.e[i] > hp.e[i + 1])
			i++;//右孩子小
		if (hp.e[0] < hp.e[i])  break;
		else {
			hp.e[k] = hp.e[i];
			k = i;
		}
	}
	hp.e[k] = hp.e[0];
}
//建立大根堆
void BuildBigRootHeap(Heap hp, int n) {
	for (int i = n / 2; i >= 1; i--) {
		HeapAdjust(hp, i, n);
	}

}
void Print(Heap hp, int n) {
	for (int i = 1; i <= n; i++) {
		printf("%d   ", hp.e[i]);
	}
	printf("\n");
}

//堆排序:每一趟将堆顶元素加入到有序子序列与待排序序列的最后一个元素交换
//交换以后,len长度数值-1  然后在将待排序树调整为大根堆  小元素下坠的过程 然后每一趟选出一个最大的数值
void HeapSort(Heap hp, int n) {
	for (int i = n; i >= 1; i--) {
		int tmp = hp.e[i];
		hp.e[i] = hp.e[1];
		hp.e[1] = tmp;//交换最后一个元素和堆顶元素

		HeapAdjust(hp, 1, i - 1);
	}
}
//插入元素

//1. 扩展空间
/*void ExpandSpase(Heap *hp,int n) {
	int* p = hp->e;
	hp->e = (int*)realloc(hp->e,sizeof(int)*(hp->mlen + n));
	hp->mlen += n;
	free(p);
}*/
void ExpandSpase(Heap* hp, int n) {
	hp->e = (int*)realloc(hp->e, sizeof(int) * (hp->mlen + n + 1));
	hp->mlen += n; // 更新最大长度
}
void swap(int *a,int *b) {
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
/*
注意点:
1. 此时堆已经是有序的了,所以已经由无序大根堆变为了有序小根堆
2. 所以在判断是否交换数据的时候,判断条件是 孩子节点是否大于父亲结点 如果是 那么不交换  否则交换

*/
void InsertElement(Heap *hp,int value) {
	if (hp->len == hp->mlen)
		ExpandSpase(hp,1);//扩展一个空间
	hp->len += 1;
	hp->e[hp->len] = value;

	printf("插入元素但未调整:\n");
	Print(*hp, hp->len);

	hp->e[0] = hp->e[hp->len]; //使用数组下标为0的暂时存储新元素 new element 然后开始和父亲结点进行对比/交换
	int k = hp->len;//暂时存储孩子结点
	for (int i = k / 2; i >= 1;i/=2) {
		if (hp->e[i] < hp->e[k]) break;//孩子结点是否大于父亲  是就不交换 仍然满足小根堆
		swap(&hp->e[k],&hp->e[i]);
		k = i;//需要检查的结点(new point)向上移动
	}
	printf("调整后:\n");
	Print(*hp, hp->len);
	printf("重新排序:\n");
}
//删除:删除就是将最后一个元素覆盖要删除的点,然后数组长度-1  如果删除最后一个结点,那么直接-1即可
//然后采用元素下坠的办法进行调整(大元素下坠)
void DeleteElement(Heap *hp,int i) {//i表示删除第几个元素
	hp->e[i] = hp->e[hp->len];
	hp->len--;
	HeapAdjustLittle(*hp,i,hp->len);
	printf("删除后:\n");
	Print(*hp,hp->len);
}
int main() {
	int data[] = { 53,17,78,9,45,65,87,32 };//数据元素
	int n = 8;
	Heap hp;
	InitHeap(&hp,n);
	AddData(hp,data,n);
	hp.len = n;
	BuildBigRootHeap(hp,n);
	HeapSort(hp,n);
	Print(hp, n);

	//插入元素
	InsertElement(&hp,1);
	//重新排序  每次重新排序都要基于大根堆
	BuildBigRootHeap(hp,hp.len);
	HeapSort(hp,hp.len);
	Print(hp,hp.len);
	//删除1元素
	DeleteElement(&hp,1);
	free(hp.e);
	return 0;
}

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

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

相关文章

第八季完美童模全球十佳人气超模【许馨予】荣耀加冕 见证星芒风采!

7月20-23日&#xff0c;2024第八季完美童模全球总决赛在青岛圆满落幕&#xff0c;在盛大的颁奖典礼上&#xff0c; 全球观众网友通过现场参与和网络直播的方式&#xff0c;见证了一位人气榜样的诞生&#xff01;在众多优秀的小超模中&#xff0c;性格开朗的10岁女孩许馨予从本次…

二叉树 - 二叉树的层序遍历

二叉树的层序遍历 102. 二叉树的层序遍历 /*** Definition for a binary tree node.* function TreeNode(val, left, right) {* this.val (valundefined ? 0 : val)* this.left (leftundefined ? null : left)* this.right (rightundefined ? null : right)…

揭秘!华为手表如何成为运动达人的秘密武器

巴黎奥运会已经告一段落&#xff0c;但大家的运动热情仍旧高涨。我发现&#xff0c;身边喜欢健身的小伙伴都需要更智能的设备去精准的记录运动轨迹、心率、配速等数据&#xff0c;想要成为一个运动健身达人&#xff0c;拥有一款适合自己的运动穿戴设备&#xff0c;会让你的健身…

数据结构----双向链表

一丶双向链表 1.特点 逻辑结构&#xff1a;线性结构 存储结构&#xff1a;链式存储 操作&#xff1a;增删改查 2.函数的操作 创空 双链表从中间插入 双向链表尾插 删除中间节点 删除尾节点 #include <stdio.h> #include <stdlib.h> typedef int datatype; /…

全自动商用油炸锅介绍:

全自动商用油炸锅‌是一种专门为商业用途设计的厨房设备&#xff0c;旨在高效、节能、卫生地完成大量食品的油炸加工。这种设备通常采用油水混合技术&#xff0c;能够自动过滤残渣&#xff0c;延长换油周期&#xff0c;从而大大降低用油成本。全自动商用油炸锅适合中、小型油炸…

来聊一聊JVM

为什么需要JVM&#xff0c;不要JVM可以吗&#xff1f; 1.JVM可以帮助我们屏蔽底层的操作系统 一次编译&#xff0c;到处运行 2.JVM可以运行Class文件 我们的编译器到底干了什么事&#xff1f; 仅仅是将我们的 .java 文件转换成了 .class 文件&#xff0c;实际上就是文件格式…

C的温故而知新:结构和其他数据形式(C Primer Plus第十四章)

第十四章&#xff1a;结构和其他数据形式 在我们使用语言进行程序编程设计的时候&#xff0c;经常会出现很多复杂的数据&#xff0c;&#xff0c;每到这种时候&#xff0c;就需要创建很多的变量去存储各种各类的数据。还有一种情况&#xff0c;不同类型的数据是相互关联的&…

通过 MATLAB 的 cylinder 函数生成圆柱体的表面坐标,生成表示一个具有非标准形状的圆柱体(在本例中是杯子)

MATLAB的机器人系统工具箱&#xff08;RST&#xff09;的官方例程Plan a Reaching Trajectory with Multiple Kinematic Constraints规划具有多个运动学约束的到达轨迹 % 创建用于视觉化杯子的点 [X,Y,Z] cylinder(cupRadius*linspace(0,1,50).^0.125); % 调整 Z 坐标的比例…

element-plus form 表单嵌套表格树单行校验问题

需要实现这样的效果&#xff0c;单行校验表格树 公共方法可以直接用 const findPosi (tree, targetId, path "") > {for (let i 0; i < tree.length; i) {const node tree[i];if (node.id targetId) {return path i;}if (node.sub_parameters &&a…

网站服务包含哪些

网站服务是指一系列通过互联网提供的服务&#xff0c;涵盖了多个方面&#xff0c;从基本的网站建设到更高级的在线业务解决方案。以下是网站服务可能包含的一些主要方面&#xff1a; 网站设计与开发&#xff1a; 网站设计&#xff1a; 包括整体网站结构、用户界面设计、图形设…

一、插件开发入门【Qt环境-mingw6.5.3-qmake版】-封装dll调用

1.先创建一个名为mainProject的主项目,并进行简单的ui布局 2.使用C Library库创建动态库项目作为主项目的子插件 2.1 Qt模块选择为Widgets 2.2 环境配置和主项目要一致 3.给插件添加qt界面设计类 4.给subPlugin插件添加一个名为PluginInterface.h的头文件 #ifndef PLUGININTERF…

软件设计师全套备考系列文章8 -- 查找、排序

软考-- 软件设计师&#xff08;8&#xff09;-- 查找、排序 文章目录 软考-- 软件设计师&#xff08;8&#xff09;-- 查找、排序前言一、查找二、排序三、排序的评价指标&#xff08;重点&#xff09; 前言 考试时间&#xff1a;每年5月、11月&#xff0c;软件设计师每年都会…

湖南 | 产能利用率高达80%的龙头砼企如何进行站内外高效配合

走进标杆企业 走进标杆企业&#xff0c;感受名企力量&#xff0c;探寻学习优秀企业领先之道。本期要跟砼行们推介的标杆企业是湖南省新宁县鑫旺混凝土有限公司。 鑫旺混凝土有限公司成立于2012年&#xff0c;建有三条混凝土生产线&#xff0c;自有水泥、砂石骨料、房地产等一…

vue3 中 defineProps 和 defineEmits

在 Vue 3 中&#xff0c;defineProps 和 defineEmits 是组合式 API 的核心功能&#xff0c;用于处理父子组件之间的传值和事件通信。 1. defineProps defineProps 用于定义并接收父组件传递过来的数据&#xff08;props&#xff09;。它是在子组件中使用的&#xff0c;接收的…

100000在银行存个3年利息居然12000

python存款利息问题 设计一个函数来计算存款利息。存款利息由存款金额和存款时间决定。 如果存款金额小于或等于5000元&#xff0c;则年利率为2%;5000元到10000元之间&#xff0c;则年利率为3%;大于10000元&#xff0c;则年利率为4%。返回本金和利息 def getMoney(amount,yea…

44.开发商购买土地

44.开发商购买土地 &#xff08;用到了前缀和的知识&#xff09; 题目链接 //卡码网题号44.开发商购买土地 #include<iostream> #include<vector> #include<climits> using namespace std;int main() {int n, m;int sum0;cin >> n >> m;vector…

stable-diffusion-webui容器构建教程

一、介绍 Stable Diffusion WebUI 是一个提供了易于使用的 AI 绘画工具&#xff0c;它允许用户通过一个更友好、可视化的网页界面来与 Stable Diffusion 模型互动&#xff0c;可以实现文生图、图生图等。 二、特点 易于使用的界面 &#xff1a;用户可以通过网页界面进行操作…

【数据同步】SeaTunnel初体验,5000字深入浅出带你用上Oracle-CDC

Apache SeaTunnel 是啥&#xff1f;下一代高性能、分布式、海量数据集成框架。支持上百个数据源、传输速度快、准确率高&#xff0c;丰富易扩展的连接器和插件化的连接器设计&#xff0c;能够更轻松的运行复杂的集成。是一个分布式、高性能的数据集成平台&#xff0c;用于数据迁…

USB Type-C如何取9V、12V、15V、20V电压-PD快充协议芯片ECP5701

相信大家在生活中也发现了&#xff0c;现在越来越多的设备都改用这种type-C接口的母座进行取电了。 因为欧盟决议 &#xff1a;自2024年起部分消费电子产品必须提供单一的USB-C充电接口。 那么这种type-C接口相比之前的Micro-B接口有着一个很大的优势就是可以有更高的电压&…

部署同步工具syncthing

1、下载包arm包&#xff08;根据自己的环境下载包&#xff09; #进到指定目录 cd /usr/local/ #可以根据自己的环境下载不同版本的包 wget https://github.com/syncthing/syncthing/releases/download/v1.27.10/syncthing-linux-arm64-v1.27.10.tar.gz2、进行部署 #将其解压 …