抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

总时间限制: 1000ms 内存限制: 65536kB
描述
给定初始整数顺串,以及大小固定并且初始元素已知的二叉最小堆(为完全二叉树或类似完全二叉树,且父元素键值总小于等于任何一个子结点的键值),要求利用堆实现置换选择排序,并输出第一个顺串。例如给定初始顺串 29,14,35,13, 以及堆(记为 16 19 31 25 21 56 40), 置换选择排序得到的第一个顺串为 16 19 21 25。

在这里插入图片描述

输入

第一行包含两个整数,m 为初始顺串的数的个数,n 为二叉最小堆的大小
第二行包含 m 个整数,即初始顺串
第三行包含 n 个整数,即已经建好的堆的元素(有序,按照从堆顶到堆底,从左到右的顺序)

输出

输出包含一行,即第一个顺串。

样例输入

1
2
3
4 7
29 14 35 13
16 19 31 25 21 56 40

样例输出

1
16 19 21 25

思路

  1. 我们知道这是一个小根堆,堆顶元素是最小的,我们可以将堆顶元素取出,将其放入 res 数组中,然后将堆顶元素删除,注意,在这一步当中是不用关注初始化顺串的元素的。
  2. 然后将初始的顺串中的下一个元素放入堆中,然后调整堆,使其满足堆的性质。
    1. 如果初始的顺串被选中的元素比 res 数组中的最后一个元素大,那么就将这个元素放入堆中,然后调整堆;否则将这个元素先放入堆,然后与堆的最后一个元素交换,堆的大小减一,最后调整堆。
  3. 然后将堆顶元素取出,放入 res 数组中,然后将堆顶元素删除。
  4. 重复上述步骤 2、3,直到堆为空或者初始顺串中的元素全部被替换。

看完原理,我们可以将代码分为两个部分,一个是调整堆的代码,一个是置换选择排序的代码。

代码解析

先说调整堆的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void reflushHeap(int n) {
int i = 1;
while(2*i <= n || 2*i+1 <= n) {
if(2*i <= n && 2*i+1 <= n) {
if(ar[2*i] < ar[2*i+1]) {
if(ar[i] > ar[2*i]) {
swap(ar[i], ar[2*i]);
i = 2*i;
}
} else {
if(ar[i] > ar[2*i+1]) {
swap(ar[i], ar[2*i+1]);
i = 2*i+1;
}
}
} else if(2*i <= n && 2*i+1 > n) {
if(ar[i] > ar[2*i]) {
swap(ar[i], ar[2*i]);
i = 2*i;
}
} else break;
}
}

然后是置换选择排序的代码:
这代码在排除输入部分之后是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
while(t--) {
if(n <= 0) break;
res.push_back(ar[1]);
if(res.back() > in[j]) {
ar[1] = in[j];
swap(ar[1], ar[n]);
--n;
reflushHeap(n);
} else {
ar[1] = in[j];
reflushHeap(n);
}
++j;
}

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <bits/stdc++.h>
#pragma GCC optimize(3,"Ofast","inline")
using namespace std;

int ar[1024], in[1024];

void reflushHeap(int n) {
int i = 1;
while(2*i <= n || 2*i+1 <= n) {
if(2*i <= n && 2*i+1 <= n) {
if(ar[2*i] < ar[2*i+1]) {
if(ar[i] > ar[2*i]) {
swap(ar[i], ar[2*i]);
i = 2*i;
}
} else {
if(ar[i] > ar[2*i+1]) {
swap(ar[i], ar[2*i+1]);
i = 2*i+1;
}
}
} else if(2*i <= n && 2*i+1 > n) {
if(ar[i] > ar[2*i]) {
swap(ar[i], ar[2*i]);
i = 2*i;
}
} else break;
}
}

int main() {
vector<int> res;
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int m, n, t, j = 1;
cin >> m >> n;
res.reserve(m);
for(int i = 1; i <= m; ++i) {
cin >> in[i];
}
for(int i = 1; i <= n; ++i) {
cin >> ar[i];
}
t = m;
while(t--) {
if(n <= 0) break;
res.push_back(ar[1]);
if(res.back() > in[j]) {
ar[1] = in[j];
swap(ar[1], ar[n]);
--n;
reflushHeap(n);
} else {
ar[1] = in[j];
reflushHeap(n);
}
++j;
}
for(auto i: res) {
cout << i << " ";
}
}