PAT A1098 Insertion or Heap Sort
Sample Input 1:
10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0
Sample Output 1:
Insertion Sort
1 2 3 5 7 8 9 4 6 0
Sample Input 2:
10
3 1 2 8 7 5 9 4 6 0
6 4 5 1 0 3 2 7 8 9
Sample Output 2:
Heap Sort
5 4 3 1 0 2 6 7 8 9
word | meaning |
---|---|
ascending | adj.上升的 |
- 思路 1: 类似 A1089
- 写出模拟插入排序和堆排序1次的函数
- 先模拟插入排序,每轮和sorted[]比较,若相等输出
- 模拟完插入排序还是没有相等,说明是堆排序,再开始模拟堆排序
- code 1:
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
int n, in;
int input[maxn], sorted[maxn], imitate[maxn], heap[maxn];
//Insert:
void insertSort(int idex){
insert(1, idex, imitate[idex]);
}
void insert(int left, int right, int x){
int pos = findPos(left, right, x);
for(int i = right; i > pos; --i){
imitate[i] = imitate[i-1];
}
imitate[pos] = x;
}
int findPos(int left, int right, int x){
int mid;
while(left < right){
mid = (left + right) / 2;
if(imitate[mid] < x) left = mid + 1;
else right = mid;
}
return left;
}
//Heap:
void downAdjust(int now, int high){
int v = now, lc = 2*v;
while(lc <= high){
if(lc + 1 <= high && heap[lc] < heap[lc+1])
lc = lc+1;
if(heap[v] < heap[lc]){
swap(heap[v], heap[lc]);
v = lc;
lc = 2*v;
}
else break;
}
}
void createHeap(){
for(int i = n/2; i > 0; --i){
downAdjust(i, n);
}
}
void heapSort(int idex){
swap(heap[1], heap[idex]);
downAdjust(1, idex-1);
}
bool isEqual();
bool isEqualHeap();
void output();
void outputHeap();
int main(){
scanf("%d", &n);
for(int i = 1 ; i <= n; ++i){
scanf("%d", &input[i]);
imitate[i] = input[i];
heap[i] = input[i];
}
for(int i = 1 ; i <= n; ++i){
scanf("%d", &sorted[i]);
}
//Insert:
bool flag = false;
for(int i = 2; i <= n; ++i){
insertSort(i);
if(isEqual()){
printf("Insertion Sort\n");
insertSort(i+1);
output();
}else{
flag = true;
}
}
//Heap:
if(flag){
createHeap();
for(int i = n; i > 0; --i){
heapSort(i);
if(isEqualHeap()){
printf("Heap Sort\n");
heapSort(i-1);
outputHeap();
break;
}
}
}
return 0;
}
//判断和输出
bool isEqual(){
for(int i = 1; i <= n; ++i){
if(imitate[i] != sorted[i]) return false;
}
return true;
}
bool isEqualHeap(){
for(int i = 1; i <= n; ++i){
if(heap[i] != sorted[i]) return false;
}
return true;
}
void output(){
printf("%d", imitate[1]);
for(int i = 2; i <= n; ++i) printf(" %d", imitate[i]);
}
void outputHeap(){
printf("%d", heap[1]);
for(int i = 2; i <= n; ++i) printf(" %d", heap[i]);
}
-
思路 2:
插入排序部分可以用sort(a, a+i+1)代替 -
code 2:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
int n, in;
bool flag = false;
int input[maxn], sorted[maxn], imitate[maxn];
void downAdjust(int, int);
void createHeap();
void heapSort(int);
bool isEqual();
void output();
void isInsert();
void isHeap();
int main(){
scanf("%d", &n);
for(int i = 1 ; i <= n; ++i){
scanf("%d", &input[i]);
imitate[i] = input[i];
}
for(int i = 1 ; i <= n; ++i){
scanf("%d", &sorted[i]);
}
isInsert();
isHeap();
return 0;
}
void downAdjust(int now, int high){
int v = now, lc = 2*v;
while(lc <= high){
if(lc + 1 <= high && imitate[lc] < imitate[lc+1])
lc = lc+1;
if(imitate[v] < imitate[lc]){
swap(imitate[v], imitate[lc]);
v = lc;
lc = 2*v;
}
else break;
}
}
void createHeap(){
for(int i = n/2; i > 0; --i){
downAdjust(i, n);
}
}
void heapSort(int idex){
swap(imitate[1], imitate[idex]);
downAdjust(1, idex-1);
}
void isInsert(){
for(int i = 2; i <= n; ++i){
sort(imitate+1, imitate+i+1);
if(isEqual()){
printf("Insertion Sort\n");
sort(imitate+1, imitate+i+2);
output();
}else{
flag = true;
}
}
}
void isHeap(){
if(flag){
for(int i = 1 ; i <= n; ++i){
imitate[i] = input[i];
}
createHeap();
for(int i = n; i > 0; --i){
heapSort(i);
if(isEqual()){
printf("Heap Sort\n");
heapSort(i-1);
output();
break;
}
}
}
}
//判断和输出
bool isEqual(){
for(int i = 1; i <= n; ++i){
if(imitate[i] != sorted[i]) return false;
}
return true;
}
void output(){
printf("%d", imitate[1]);
for(int i = 2; i <= n; ++i) printf(" %d", imitate[i]);
}
- T2 code:
#include <bits/stdc++.h>
using namespace std;
//void UpAdjust(vector<int> & test, int id){ //建好堆以后,Insert才用UpAdjust()
// while(id != 1 && test[id] > test[id / 2]){
// swap(test[id], test[id / 2]);
// id /= 2;
// }
//}
void DownAdjust(vector<int> & test, int id, int right){
int i = id, j = 2 * id;
while(j <= right){
if(j + 1 <= right && test[j + 1] > test[j]) j++;
if(test[i] < test[j]){
swap(test[i], test[j]);
i = j;
j = 2 * i;
}else break;
}
}
void BuildHeap(vector<int> & test, int right){
for(int i = right / 2; i > 0; --i){
DownAdjust(test, i, right);
}
}
void Print(vector<int> & ans){
for(int i = 1; i < ans.size(); ++i){
printf("%d", ans[i]);
if(i < ans.size()-1) printf(" ");
}
}
bool IsHeap(vector<int> test, vector<int> & aim){
BuildHeap(test, test.size()-1);
for(int i = 1; i < test.size(); ++i){
int right = test.size() - i;
swap(test[1], test[right]);
DownAdjust(test, 1, right-1);
if(test == aim){
swap(aim[1], aim[right - 1]);
DownAdjust(aim, 1, right - 2);
return true;
}
}
return false; //Wrong 1: 不写return false就会出错
}
void Insert(vector<int> & test, int id){
test[0] = test[id]; //哨兵
while(test[id-1] > test[0]){
test[id] = test[id-1];
id--;
}
test[id] = test[0];
test[0] = 0; //否则 test == aim 会出错,aim[0] == 0
}
void InsertSort(vector<int> test, vector<int> & aim){
for(int i = 2; i < test.size() - 1; ++i){
Insert(test, i);
if(test == aim){
Insert(test, i + 1);
printf("Insertion Sort\n");
Print(test);
return;
}
}
}
int main(){
int n;
scanf("%d", &n);
vector<int> initial(n+1), ans(n+1);
for(int i = 1; i <= n; ++i){
scanf("%d", &initial[i]);
}
for(int i = 1; i <= n; ++i){
scanf("%d", &ans[i]);
}
if(IsHeap(initial, ans)){
printf("Heap Sort\n");
Print(ans);
}else{
InsertSort(initial, ans);
}
return 0;
}
-
思路3:用 heap的库函数 is_heap(), make_heap(), pop_heap(), push_heap(), sort_heap();
-
Algorithm中的heap函数
函数 | 函数原型 | 作用 |
---|---|---|
is_heap() | bool is_heap( RandomIt first, RandomIt last, Compare comp); | 判断区间是否为heap |
is_heap_until() | RandomIt is_heap_until( RandomIt first, RandomIt last, Compare comp ); | 找出区间中第一个不满足heap条件的位置. |
make_heap() | make_heap( RandomIt first, RandomIt last, Compare comp); | 在指定区间建堆 |
push_haep() | void push_heap( RandomIt first, RandomIt last, Compare comp ); | 把指定区间的最后一个元素插入到heap中 |
pop_heap() | void pop_heap( RandomIt first, RandomIt last, Compare comp ); | 弹出heap顶元素, 将其放置于区间末尾. |
sort_heap() | void sort_heap( RandomIt first, RandomIt last, Compare comp ); | 堆排序,make_heap后反复调用pop_heap来实现 |
【注】cmp:less<int>()
是默认的大顶堆(Max Heap), greater<>()
小顶堆
- T2 code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
bool IsHeap(vector<int> t, vector<int> & aim){
make_heap(t.begin(), t.end(), less<int>());
for( int i = 0; i < t.size() - 1; ++i){
pop_heap(t.begin(), t.end() - i, less<int>());
if(t == aim){
pop_heap(aim.begin(), aim.end() - i - 1, less<int>());
return true;
}
}
return false;
}
void Insert(vector<int> t, vector<int> & aim){
for(int i = 2; i < t.size() - 1; ++i){ //Wrong 1: 样例2: i要从2开始,因为不包括初始序列
sort(t.begin(), t.begin() + i);
if(t == aim){
sort(aim.begin(), aim.begin() + i + 1);
return;
}
}
}
void Print(vector<int> ans){
for(int i = 0; i < ans.size(); ++i){
printf("%d", ans[i]);
if(i < ans.size() - 1) printf(" ");
}
}
int main(){
int n;
scanf("%d", &n);
vector<int> initial(n), ans(n);
for(int i = 0; i < n; ++i){
scanf("%d", &initial[i]);
}
for(int i = 0; i < n; ++i){
scanf("%d", &ans[i]);
}
if(IsHeap(initial, ans)){
printf("Heap Sort\n");
Print(ans);
}else{
Insert(initial, ans);
printf("Insertion Sort\n");
Print(ans);
}
return 0;
}
-
Wrong 1: 样例2: i要从2开始,因为不包括初始序列
-
T3 code:
#include <bits/stdc++.h>
using namespace std;
void Print(const vector<int> & v)
{
for(int i = 1; i < v.size(); ++i)
{
printf("%d", v[i]);
if(i < v.size()-1) printf(" ");
}
printf("\n");
}
void Insert(vector<int> & ori, int id, int n)
{
ori[0] = ori[id];
int idex = id;
while(ori[idex-1] > ori[0])
{
ori[idex] = ori[idex-1];
idex--;
}
swap(ori[idex], ori[0]);
ori[0] = 0;
}
bool InsertSort(vector<int> ori, vector<int> & aim, int n)
{
for(int i = 2; i < n; ++i)
{
Insert(ori, i, n);
if(ori == aim)
{
Insert(aim, i + 1, n);
return true;
}
}
return false;
}
void DownAdjust(vector<int> & ori, int now, int n)
{
int v = now, lc = 2 * now;
while(lc <= n)
{
if(lc + 1 <= n && ori[lc+1] > ori[lc]) lc = lc + 1;
if(ori[lc] > ori[v])
{
swap(ori[lc], ori[v]);
v = lc;
lc = v * 2;
}else break;
}
}
void MakeHeap(vector<int> & ori, int n)
{
for(int i = n / 2; i > 0; --i)
{
DownAdjust(ori, i, n);
}
}
void HeapSort(vector<int> & ori, vector<int> aim, int n)
{
MakeHeap(ori, n);
bool flg = false;
for(int i = n; i > 0; --i)
{
if(ori == aim) flg = true;
swap(ori[i], ori[1]);
DownAdjust(ori, 1, i-1);
if(flg) break;
}
}
int main()
{
int n;
scanf("%d", &n);
vector<int> ori(n+1), aim(n+1);
for(int i = 1; i <= n; ++i)
{
scanf("%d", &ori[i]);
}
for(int i = 1; i <= n; ++i)
{
scanf("%d", &aim[i]);
}
if(InsertSort(ori, aim, n))
{
printf("Insertion Sort\n");
Print(aim);
}else
{
HeapSort(ori, aim, n);
printf("Heap Sort\n");
Print(ori);
}
return 0;
}