生产备案号怎么查询网站深圳十大工业设计公司
web/
2025/10/8 1:42:22/
文章来源:
生产备案号怎么查询网站,深圳十大工业设计公司,东莞软件网站推广,软件开发包括什么内容模拟堆也是对堆的一次深入理解和一些其它操作#xff0c;可以了解一下。 文章目录 前言 一、模拟堆 二、算法思路 1.结点上移 2.结点下移 3.插入一个数 4.输出当前集合的最小值 5.删除当前集合的最小值#xff08;数据保证此时的最小值唯一#xff09; 6.删除第k个插入的数 … 模拟堆也是对堆的一次深入理解和一些其它操作可以了解一下。 文章目录 前言 一、模拟堆 二、算法思路 1.结点上移 2.结点下移 3.插入一个数 4.输出当前集合的最小值 5.删除当前集合的最小值数据保证此时的最小值唯一 6.删除第k个插入的数 7.修改第k个插入的数修改为x 三、代码如下 1.代码如下 2.读入数据 3.代码运行结果 总结 前言
模拟堆也是对堆的一次深入理解和一些其它操作可以了解一下。 提示以下是本篇文章正文内容下面案例可供参考
一、模拟堆
维护一个集合初始时集合为空支持如下几种操作
I x插入一个数 xPM输出当前集合中的最小值DM删除当前集合中的最小值数据保证此时的最小值唯一D k删除第 k 个插入的数C k x修改第 k 个插入的数将其变为 x
现在要进行 N 次操作对于所有第 22 个操作输出当前集合的最小值。
输入格式
第一行包含整数 N。
接下来 N 行每行包含一个操作指令操作指令为 I xPMDMD k 或 C k x 中的一种。
输出格式
对于每个输出指令 PM输出一个结果表示当前集合中的最小值。
每个结果占一行。
数据范围
1≤N≤100000 −1000000000≤x≤1000000000 数据保证合法。
二、算法思路
我们还是通过一维整型数组heap来存储堆的值数组下标来表示是哪一个结点size表示堆中结点的个数或者堆中最后一个元素的下标。这道题中我们还是以小根堆为例子。堆在数组中存储任一结点的下标为x那么它的左孩子在数组中存储的下标为2x右孩子在数组中存储的下标为2x 1。注数组存储结点下标从1开始
1.结点上移
当我们插入一个新结点这个结点值比它的父结点值小或者修改某一个结点结点值比它的父节点小这两种情况我们才会让结点上移来维护小根堆的性质。 //结点上移只需要跟父结点比较即可public static void up(int x){while ( x / 2 1 heap[x / 2] heap[x]){int temp heap[x / 2];heap[x / 2] heap[x];heap[x] temp;x / 2;}}
我们需要判断当前下标有没有父结点即 x / 2是否满足大于等于1并且当父结点的值比子结点的值大的时候我们就需要将父结点和子结点进行交换然后再判断父结点是否小于它的父节点重复上述过程。具体详情可以看https://blog.csdn.net/m0_63267251/article/details/139388919这篇博客。
2.结点下移
当我们结点值修改后比它的左孩子或者右孩子值大然后我们从中找到值最小的那个索引然后让父结点跟最小的结点进行交换交换后我们再判断当前结点的值是否比它的左孩子或者右孩子值大重复上述操作我们要保证父节点的值要小于它的左孩子和右孩子的值。 具体详情可以看https://blog.csdn.net/m0_63267251/article/details/139388919这篇博客。 //传入结点下标public static void down(int x){int temp x;//两个if语句来找出3个结点中最小的结点的下标if(2 * x size heap[2* x] heap[temp]){temp 2 * x;}if (2 * x 1 size heap[2*x 1] heap[temp]){temp 2 * x 1;}//说明此时结点不是最小值进行交换再递归处理看是否还需要交换if(temp ! x){int t heap[temp];heap[temp] heap[x];heap[x] t;down(temp);}}
3.插入一个数
插入一个数我们直接在数组的末尾添加元素即可而size既可以表示堆中元素的个数也可以表示堆中元素在数组中存储的最后一个结点的下标。故我们添加元素为heap[size] x;size; if (cmd.equals(I)){x Integer.parseInt(s[1]);heap[size] x;} 4.输出当前集合的最小值
因为我们搭建的是小根堆故我们堆中的根结点的值就是堆中元素的最小值即heap[1];
5.删除当前集合的最小值数据保证此时的最小值唯一
我们删除当前集合的最小值数组的第一个元素是很难被删除的我们还是删除数组的最后一个元素将根节点赋值为数组的最后一个元素即heap[1] heap[size];size--;然后此时有可能小根堆的性质被破坏所以我们只需要将根节点结点下移操作就可以即down(1)此时我们就完成了删除当前集合最小值的情况。 6.删除第k个插入的数
这个操作麻烦的是删除第k个插入的数而不是删除第k个结点。因此我们需要一个一维整型数组khp来存储第k个插入的数在堆中的下标即khp[k]我们还需要一个一维整型数组hp来存储我们堆中的点是第几个插入的点例如kph[j] k表示第j个插入的点是堆中第k个结点ph[k] j表示堆中的第k个结点时我们第k个插入的点这两个数组的值对应的是相反的。那么我们就需要更新一下我们的down操作和up操作。 public static void down(int x){int temp x;if(2 * x size heap[2 * x] heap[temp]){temp 2 * x;}if(2 * x 1 size heap[2 * x 1] heap[temp]){temp 2 * x 1;}if(temp ! x){hp_swap(temp,x);down(temp);}}//结点上移只需要跟父结点比较即可public static void up(int x){while ( x / 2 1 heap[x / 2] heap[x]){hp_swap(x,x/2);x / 2;}}//因为hp数组可以对应为堆中的元素下标在khp数中的关系所以我们先交换khp后交换hp或者先交换hp再交换khp也可以public static void hp_swap(int a,int b){int t khp[hp[a]];khp[hp[a]] khp[hp[b]];khp[hp[b]] t;t hp[a];hp[a] hp[b];hp[b] t;t heap[a];heap[a] heap[b];heap[b] t;} 对应的插入一个数、输出当前集合和最小值和删除集合最小值操作更新。 if (cmd.equals(I)){x Integer.parseInt(s[1]);size;m;heap[size] x;khp[m] size;hp[size] m;up(size);} else if (cmd.equals(PM)) {pw.println(heap[1]);} else if (cmd.equals(DM)) {hp_swap(1,size);size--;down(1);} else if (cmd.equals(D)) {k Integer.parseInt(s[1]);//找到第k歌数在堆中的位置k khp[k];hp_swap(k,size);size--;//两个操作最多执行一个up(k);down(k);} 7.修改第k个插入的数修改为x
我们将插入第k个数在堆中的坐标找到即khp[k]然后将堆中的值修改为x即heap[khp[k]] x。然后再维护一下小根堆性质down(kph[k])、up(khp[k])即可。 if (cmd.equals(C)) {k Integer.parseInt(s[1]);x Integer.parseInt(s[2]);k khp[k];heap[k] x;down(k);up(k);}
三、代码如下
1.代码如下 import java.util.*;
import java.io.*;
public class 模拟堆 {static PrintWriter pw new PrintWriter(new OutputStreamWriter(System.out));static BufferedReader br new BufferedReader(new InputStreamReader(System.in));static StreamTokenizer st new StreamTokenizer(br);static int N 100010;//堆中的数据static int[] heap new int[N];static int size 0;//第k个插入数在堆中的下标static int[] khp new int[N];//堆中的哪一个点是我们第几个插入的点static int[] hp new int[N];public static void main(String[] args) throws Exception{Scanner sc new Scanner(br);int n nextInt();//表示第几个插入的数int m 0;while (n-- 0){String[] s nextLine().split( );String cmd s[0];int x;int k;if (cmd.equals(I)){x Integer.parseInt(s[1]);size;m;heap[size] x;khp[m] size;hp[size] m;up(size);} else if (cmd.equals(PM)) {pw.println(heap[1]);} else if (cmd.equals(DM)) {hp_swap(1,size);size--;down(1);} else if (cmd.equals(D)) {k Integer.parseInt(s[1]);//找到第k歌数在堆中的位置k khp[k];hp_swap(k,size);size--;//两个操作最多执行一个up(k);down(k);} else if (cmd.equals(C)) {k Integer.parseInt(s[1]);x Integer.parseInt(s[2]);k khp[k];heap[k] x;down(k);up(k);}}pw.flush();}public static void down(int x){int temp x;if(2 * x size heap[2 * x] heap[temp]){temp 2 * x;}if(2 * x 1 size heap[2 * x 1] heap[temp]){temp 2 * x 1;}if(temp ! x){hp_swap(temp,x);down(temp);}}//结点上移只需要跟父结点比较即可public static void up(int x){while ( x / 2 1 heap[x / 2] heap[x]){hp_swap(x,x/2);x / 2;}}//因为hp数组可以对应为堆中的元素下标在khp数中的关系所以我们要先交换khp后交换hp或者先交换hp再交换khp也可以public static void hp_swap(int a,int b){int t khp[hp[a]];khp[hp[a]] khp[hp[b]];khp[hp[b]] t;t hp[a];hp[a] hp[b];hp[b] t;t heap[a];heap[a] heap[b];heap[b] t;}public static int nextInt()throws Exception{st.nextToken();return (int)st.nval;}public static String nextLine()throws Exception{return br.readLine();}
}2.读入数据
8
I -10
PM
I -10
D 1
C 2 8
I 6
PM
DM
3.代码运行结果
-10
6 总结
上述解释了一下模拟堆中的一些基本操作知道题中各个数组的意思比较长和难以理解可以多看看梳理一下。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/88810.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!