1098 Insertion or Heap Sort

判断是否是插入排序的部分与 1035 插入与归并一样。

本题主要考察 堆排序的原理和实现。

首先,把所有双亲结点进行向下调整, 建立大顶堆;

然后,把堆顶元素 与 待排序区的最后一个元素 交换并对堆顶元素向下调整, 如此重复 n-1 次,待排序区逐渐变小,有序区逐渐变大。

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 
 5 const int maxn = 200;
 6 int n;
 7 int origin[maxn],temp[maxn];
 8 
 9 //向下调整
10 void downAjust(int low,int high) { //low为待调整的双亲结点,high是最后一个叶子结点
11     int i = low,j = i*2;
12     while( j <= high) {
13         //右孩子存在,且大于左孩子
14         if(j + 1 <= high && origin[j+1] > origin[j])
15             j = j +1;
16         //根结点小于孩子结点
17         if(origin[i] < origin[j]) {
18             swap(origin[i],origin[j]);
19             i = j;
20             j = i*2;
21         } else break;
22     }
23 }
24 
25 //建立大顶堆
26 void create() {
27     //从倒数第一个双亲结点 到 根结点进行 向下调整
28     for(int i = n/2; i>=1; --i)
29         downAjust(i,n);
30 }
31 
32 int main() {
33     cin>>n;
34     for(int i = 1; i <= n; ++i)
35         cin>>origin[i];
36     for(int i = 1; i <= n; ++i)
37         cin>>temp[i];
38     int i,j;
39     for(i = 1; i+1 <= n && temp[i] <= temp[i+1]; ++i);
40     for(j = i+1; j <= n && temp[j] == origin[j]; ++j);
41     if(j > n) {
42         printf("Insertion Sort\n");
43         sort(temp+1,temp+i+2);
44         for(i = 1 ; i <= n; ++i) {
45             if(i > 1) printf(" ");
46             printf("%d",temp[i]);
47         }
48     } else {
49         printf("Heap Sort\n");
50         create(); //建立大顶堆
51         for(i = n; i > 1; --i) { //堆排序
52             swap(origin[1],origin[i]);//堆顶元素覆盖最后一个元素
53             downAjust(1,i-1);
54             for(j = 1; j <= n && origin[j] == temp[j]; ++j);//中间序列比较
55             if( j > n) break;
56         }
57         --i;
58         swap(origin[1],origin[i]);
59         downAjust(1,i-1);
60         for(i = 1 ; i <= n; ++i) {
61             if(i > 1) printf(" ");
62             printf("%d",origin[i]);
63         }
64     }
65     return 0;
66 }

 重新分析题目:

如果是堆排序,可以不用建立大顶堆,而是先找到待排序区的最后一个元素,把堆顶元素与其交换并对堆顶元素向下调整,即可得到题目所要求的下一趟排序序列。

AC代码如下:

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 
 5 const int maxn = 200;
 6 int n;
 7 int origin[maxn],temp[maxn];
 8 
 9 //向下调整
10 void downAjust(int t[],int low,int high) { //low为待调整的双亲结点,high是最后一个叶子结点
11     int i = low,j = i*2;
12     while( j <= high) {
13         //右孩子存在,且大于左孩子
14         if(j + 1 <= high && t[j+1] > t[j])
15             j = j +1;
16         //根结点小于孩子结点
17         if(t[i] < t[j]) {
18             swap(t[i],t[j]);
19             i = j;
20             j = i*2;
21         } else break;
22     }
23 }
24 
25 int main() {
26     cin>>n;
27     for(int i = 1; i <= n; ++i)
28         cin>>origin[i];
29     for(int i = 1; i <= n; ++i)
30         cin>>temp[i];
31     int i,j;
32     for(i = 1; i+1 <= n && temp[i] <= temp[i+1]; ++i);
33     for(j = i+1; j <= n && temp[j] == origin[j]; ++j);
34     if(j > n) {
35         printf("Insertion Sort\n");
36         sort(temp+1,temp+i+2);
37     } else {
38         printf("Heap Sort\n");
39         for( i = n ; i-1 >= 2 && temp[1] <= temp[i]; --i);//找到第一个小于堆顶元素的元素
40         swap(temp[1],temp[i]); //堆顶元素与待排序区的最后一个元素交换
41         downAjust(temp,1,i-1); //向下调整
42     }
43     for(i = 1 ; i <= n; ++i) {
44         if(i > 1) printf(" ");
45         printf("%d",temp[i]);
46     }
47     return 0;
48 }

 

posted @ 2020-03-05 12:43  tangq123  阅读(148)  评论(0编辑  收藏  举报