堆排序的插入和删除

2024-08-21 16:44
文章标签 删除 插入 堆排序

本文主要是介绍堆排序的插入和删除,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

插入:

        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.chinasem.cn/article/1093712

相关文章

电脑桌面文件删除了怎么找回来?别急,快速恢复攻略在此

在日常使用电脑的过程中,我们经常会遇到这样的情况:一不小心,桌面上的某个重要文件被删除了。这时,大多数人可能会感到惊慌失措,不知所措。 其实,不必过于担心,因为有很多方法可以帮助我们找回被删除的桌面文件。下面,就让我们一起来了解一下这些恢复桌面文件的方法吧。 一、使用撤销操作 如果我们刚刚删除了桌面上的文件,并且还没有进行其他操作,那么可以尝试使用撤销操作来恢复文件。在键盘上同时按下“C

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

顺序表之创建,判满,插入,输出

文章目录 🍊自我介绍🍊创建一个空的顺序表,为结构体在堆区分配空间🍊插入数据🍊输出数据🍊判断顺序表是否满了,满了返回值1,否则返回0🍊main函数 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以:点赞+关注+评论+收藏(一键四连)哦~ 🍊自我介绍   Hello,大家好,我是小珑也要变强(也是小珑),我是易编程·终身成长社群的一名“创始团队·嘉宾”

学习记录:js算法(二十八):删除排序链表中的重复元素、删除排序链表中的重复元素II

文章目录 删除排序链表中的重复元素我的思路解法一:循环解法二:递归 网上思路 删除排序链表中的重复元素 II我的思路网上思路 总结 删除排序链表中的重复元素 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 图一 图二 示例 1:(图一)输入:head = [1,1,2]输出:[1,2]示例 2:(图

如何恢复回收站中已删除/清空的文件

回收站清空后如何恢复已删除的文件?是否可以恢复永久删除的文件?或者最糟糕的是,如果文件直接被删除怎么办?本文将向您展示清空回收站后恢复已删除数据的最佳方法。 回收站清空后如何恢复已删除的文件? “回收站清空后我还能恢复已删除的文件吗?” 答案是肯定的,但是在这种情况下您将需要一个  回收站恢复工具 来从回收站中检索文件: 错误/永久删除回收站或任何数字存储设备中的文件 直接删除的文件/

matplotlib绘图中插入图片

在使用matplotlib下的pyplot绘图时,有时处于各种原因,需要采用类似贴图的方式,插入外部的图片,例如添加自己的logo,或者其他的图形水印等。 一开始,查找到的资料都是使用imshow,但是这会有带来几个问题,一个是图形的原点发生了变化,另外一个问题就是图形比例也产生了变化,当然最大的问题是图形占据了整个绘图区域,完全喧宾夺主了,与我们设想的只在绘图区域中占据很小的一块不相符。 经

Linux 删除 当前下的 mysql-8.0.31 空文件夹

在Linux中,如果你想要删除当前目录下的名为mysql-8.0.31的空文件夹(即该文件夹内没有任何文件或子文件夹),你可以使用rmdir命令。但是,如果mysql-8.0.31文件夹并非完全为空(即它包含文件或子文件夹),rmdir命令会失败。 如果你的目标是删除mysql-8.0.31文件夹及其内部的所有内容(无论是否为空),你应该使用rm命令结合-r(或-R,它们是等价的)选项来递归地删

如何删除不小心上传到git远程仓库中的.idea .iml文件

如果在开始的时候不配置,gitignore文件或者文件配置不正确,初始化上传的时候就会有一些不必要的信息上传上去 如果已经存在了一些文件在git远程仓库中,如。idea,.iml文件等。 首先在项目中定义一个  .gitignore文件,简单的实例如下也可以用idea中的gitignore插件 .DS_Storeclasses/*.settings/target/.classpath

Win8下如何快速查找和删除电脑中的病毒

Win8系统如何查找和删除病毒?检查你的电脑是否存在病毒的一种快速方法是使用 Windows Defender. 此恶意软件防护随 Windows 提供,可帮助识别和删除病毒、间谍软件和其他恶意软件。   注意:如果你使用的是 Windows RT,则 Windows Defender 会始终启用,并且不能关闭。   如果你使用的是 Windows 8,则可以根据自己的喜好运行由其他

【数据结构与算法 | 灵神题单 | 删除链表篇】力扣3217, 82, 237

总结,删除链表节点问题使用到列表,哈希表,递归比较容易超时,我觉得使用计数排序比较稳,处理起来也不是很难。 1. 力扣3217:从链表中移除在数组中的节点 1.1 题目: 给你一个整数数组 nums 和一个链表的头节点 head。从链表中移除所有存在于 nums 中的节点后,返回修改后的链表的头节点。 示例 1: 输入: nums = [1,2,3], head = [1,2,3,