By Jalan
这题出的就是一坨狗屎,就是同样是堆排序,实现也是多样的,这里也没有明确的给出堆排每一步的限制,难道就让人自己摸索?
最恶心的是我用stl自带的heap去一步步排,居然构成的堆和结果的堆是细部不一致的,我想问问pta的人,你们的heap牛还是stl的heap牛啊?
知识工具需求
数学
数据结构和算法
- 插入排序
- 堆排序
语言
- stl heap
题干
插入排序是每次迭代输入一个元素,找到他在目标排序中的位置,将他插入,直到没有输入为止
堆排序是把输入区分成排序好和没排序好的两个分段,每次迭代把未排序段最大的数字加入排序段.
给一个整型序列,给一个序列是某种排序的几次迭代结果,找出排序方式
输入条件
第一行N<=100是整型数量
N个整型,初始序列.
N个整型,现在序列
假设目标排序是升序
输出条件
第一行打印是"Insertion Sort" or “Heap Sort”
第二行打印再执行一次这种排序方法的迭代的排序
保证得到的方法唯一,末尾不能有空格
例子
例1
输入
10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0
输出
Insertion Sort
1 2 3 5 7 8 9 4 6 0
例2
输入
10
3 1 2 8 7 5 9 4 6 0
6 4 5 1 0 3 2 7 8 9
//
3 1 2 8 7 5 4 6 0 9
3 1 2 7 5 4 6 0 8 9
3 1 2 5 4 6 0 7 8 9
输出
Heap Sort
5 4 3 1 0 2 6 7 8 9
题解
第一次
思路
- 输入这个数组
- 测试是哪种排序
- 针对排序写出一次迭代
- 输出迭代结果
预期时间复杂度
n
编写用时
没写出来
代码
代码来自https://blog.csdn.net/qq_45472866/article/details/106108806
我当时没写出来,参考了这个哥们的,写的比我好多了
CPP
#include<bits/stdc++.h>
using namespace std;
const int N = 105;
int n, a[N], temp[N];
void downadj(int low, int high) {
int i = low, j = i * 2;
while (j <= high) {
if (j + 1 <= high && temp[j + 1] > temp[j]) j++;
if (temp[j] > temp[i]) {
swap(temp[j], temp[i]);
i = j;
j = i * 2;
}
else break;
}
}
void insertsort(int i) { //插排,将数组temp中的第i个元素插到它应该在的位置
printf("Insertion Sort\n");
if (i == n + 1) return; //如果temp已经是a排好序的(这句可有可无,本题并没有这样的测试点)
int t = temp[i], j; //插排典型代码,不解释
for (j = i - 1; j >= 1 && temp[j] > t; j--)
temp[j + 1] = temp[j];
temp[j + 1] = t;
}
void heapsort() { //堆排序
printf("Heap Sort\n");
int i = n;
while (i && temp[i] > temp[1])
i--; //从后往前找到第一个小于temp[1]的元素,那个元素即为根节点应该去的位置
swap(temp[i--], temp[1]);
downadj(1, i); //向下调整法的堆排序
}
void read() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= n; i++)
scanf("%d", &temp[i]);
}
int main() {
read(); //读入数据
int i = 1, j;
while (i < n && temp[i] <= temp[i + 1]) i++; //从头开始遍历temp数组,找到不是升序的分界点。 注意这里的temp[i] <= temp[i + 1]的等号(测试点4的坑)
for (j = i + 1; j <= n && a[j] == temp[j]; j++) //从分界点开始遍历temp,判断temp和a是否完全吻合
;
if (j == n + 1) insertsort(i + 1); //j == n + 1说明完全吻合,执行一次插排
else heapsort(); //否则执行一次堆排
for (int i = 1; i <= n; i++) //输出处理过一次的temp数组
printf("%d%s", temp[i], i < n ? " " : "\n");
return 0;
}
自己写的,2点不过,但是没啥问题.
#include <algorithm>
#include <stdio.h>
#include <vector>
using namespace std;
int main(int argc, char const *argv[])
{
int N;
scanf("%d", &N);
vector<int> ori(N), test(N);
for (int i = 0; i < N; i++)
{
scanf("%d", &ori[i]);
}
for (int i = 0; i < N; i++)
{
scanf("%d", &test[i]);
}
//插排特征是前部有序,堆排特征是后部一致.
int isHeapSort = false;
vector<int> ordered(test);
sort(ordered.begin(), ordered.end());
vector<int> h(test);
make_heap(h.begin(), h.end());
for (int i = N; i > 0; i--)
{
pop_heap(h.begin(), h.begin() + i);
if (h == test)
{
isHeapSort = true;
pop_heap(h.begin(), h.begin() + i - 1);
break;
}
}
if (isHeapSort)
{
printf("Heap Sort\n");
for (int i = 0; i < N; i++)
{
printf("%d", h[i]);
if (i != N - 1)
{
printf(" ");
}
}
}
else
{
int orderdIndex = 0;//指向最后一个排好的元素
for (int i = 1; i < N; i++)
{
if (test[i-1] < test[i])
{
orderdIndex = i;
}
else
{
break;
}
}
vector<int> I(test);
int insertIndex=0;
int insert=I[orderdIndex+1];
for (int i = 0; i <=orderdIndex; i++)
{
if (insert<I[i])
{
insertIndex=i;
break;
}
}
//排序部分移动
for (int i = orderdIndex+1;i>=insertIndex+1 ;i--)
{
I[i] = I[i - 1];
}
I[insertIndex]=insert;
printf("Insertion Sort\n");
for (int i = 0; i < N; i++)
{
printf("%d", I[i]);
if (i != N - 1)
{
printf(" ");
}
}
}
return 0;
}
运行用时
结尾
看在我写了这么多注释的份上可以给我点个赞嘛,求求惹=]砰砰砰,给我加点写下去的油呀@.@
也欢迎关注我的CSDN账号呀,接下来两个月我应该会按这个格式更新所有的PTA甲级题目
**开心code每一天**