王道C语言笔记NOTE-中级阶段Note8-排序算法真题实战

发布时间 2023-04-06 15:39:56作者: Alkaid*

一、2016年43题

1、问题描述

2、答案解析

(1)、算法的基本设计思想

由题意知,将最小的n/2个元素放进A1中,剩余元素放在A2中,分组结果即可满足题目要求。

仿照快速排序的思想,基于枢轴把n个整数划分成两个子集,根据划分后枢轴所处的位置i分别处理:

①、若i=n/2,则分组完成,算法结束;

②、若i<n/2,则枢轴及之前的所有元素均属于A1,继续对i之后的元素划分;

③、若i>n/2,则枢轴及之后的所有元素均属于A2,继续对i之前的元素划分。

基于设计思想实现的算法,不需要对全部元素进行全排序,平均时间复杂度是O(n),空间复杂度是O(1)。

3、代码实战

①、代码

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 int SetPartition(int *A,int n)
 4 {
 5     int pivot,low=0,low0=0,high=n-1,high0=n-1,flag=1,k=n/2,i;
 6     int s1=0,s2=0;
 7     while(flag)
 8     {
 9         pivot=A[low];//选择枢轴
10         while(low<high)
11         {
12             while(low<high&&pivot<=A[high])
13             {
14                 --high;
15             }
16             if(low!=high)
17             {
18                 A[low]=A[high];
19             }
20             while(low<high&&pivot>=A[low])
21             {
22                 ++low;
23             }
24             if(low!=high)
25             {
26                 A[high]=A[low];
27             }
28         }
29         A[low]=pivot;
30         if(low=k-1)
31         {
32             flag=0;
33         }
34         else//继续划分
35         {
36             if(low<k-1)
37             {
38                 low0=++low;
39                 high=high0;
40             }
41             else
42             {
43                 low=low0;
44                 high0=--high;
45             }
46         }
47     }
48     for(i=0;i<k;i++)
49     {
50         s1=s1+A[i];
51     }
52     for(i=k;i<n;i++)
53     {
54         s2=s2+A[i];
55     }
56     return s2-s1;
57 }
58 
59 //主函数
60 int main()
61 {
62     int A[10]={4,1,12,18,7,13,18,16,2,15};
63     int difference;
64     difference=SetPartition(A,10);
65     printf("%d\n",difference);
66     return 0;
67 }

②、结果

二、2022年42题

1、问题描述

2、答案解析

思路一:最小值(插入排序思想)

1)、算法思想

1 定义含10个元素的数组A,初始时元素值均为该数组类型所能表示的最大数MAX
2 for M中的每个元素s
3     if(s<A[9]) 丢弃A[9]并将s按照升序插入到A中;(插入排序算法)
4 当数据全部扫描完毕,数组A[0]-A[9]保存的即是最小的10个数。

2)、复杂度分析

①、时间复杂度:O(n),每次要插入时都是需要对小数组A进行遍历的;
②、空间复杂度:O(1),中间过程额外需要常数个变量。

思路二:堆(堆排序思想)

1)、算法思想

 

1 定义含10个元素的大根堆H,元素值均为该堆元素类型能表示的最大数MAX
2 for M中的每个元素s
3     if(s<H的堆顶元素) 删除堆顶元素并将s插入到H中;
4 当数据全部扫描完毕,堆H中保存的即是最小的10个元素。 

 

2)、复杂度分析

算法平均情况下的时间复杂度是O(n),空间复杂度是O(1)。

进一步分析:

先用A[0:9]原地建立大根堆(注意这里不能使用小根堆),遍历A[10:n],每个元素A[i]逐一和堆顶元素A[0]进行比较,如果A[i]大于等于堆顶元素A[0],不进行任何操作,如果该元素小于栈顶元素A[0],那么就删除堆顶元素,将该元素放入栈顶,即令A[0]=A[i],然后将A[0:9]重新调整为大根堆。

最后堆A[0:9]中留存的元素即为最小的10个数。

思路三:快速排序

通过快速排序,分割思想,第一次知道n/2位置,再次partition得到n/4,最终缩小为10个,就拿到了最小的10个元素,遍历的平均次数是n+n/2+n/4+…+1,次数是2n,因此时间复杂度是O(n),由于不进行快排,只是记录剩余部分、起始和结束,因此空间复杂度是O(1)。

3、代码实战

①、代码

 

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<time.h>
 4 //顺序表的数据结构定义
 5 typedef struct{
 6     int *elem;
 7     int len;
 8 }SSTable;
 9 
10 //初始化顺序表
11 void ST_Init(SSTable &ST,int n)
12 {
13     ST.len=n;
14     ST.elem=(int*)malloc(sizeof(int)*ST.len);
15     int i;
16     srand(time(NULL));
17     for(i=0;i<ST.len;i++)//进行随机数生成
18     {
19         ST.elem[i]=rand();
20     }
21 }
22 
23 //打印元素
24 void ST_Print(SSTable ST)
25 {
26     int i=0;
27     for(i=0;i<10;i++)
28     {
29         printf("%3d",ST.elem[i]);
30     }
31     printf("\n");
32 }
33 
34 //交换两个元素
35 void swap(int &a,int &b)
36 {
37     int tmp;
38     tmp=a;
39     a=b;
40     b=tmp;
41 }
42 
43 //调整子树
44 void AdjustDown(int *A,int k,int len)
45 {
46     int dad=k;
47     int son=2*dad+1;
48     while(son<=len)
49     {
50         if(A[son]<A[son+1]&&son+1<=len)
51         {
52             son++;
53         }
54         if(A[son]>A[dad])
55         {
56             swap(A[son],A[dad]);
57             dad=son;
58             son=2*dad+1;
59         }
60         else
61         {
62             break;
63         }
64     }
65 }
66 
67 //堆排序
68 void Heap_Sort(int *A,int len)
69 {
70     int i;
71     //先对前10个元素建立大根堆
72     for(i=len/2;i>=0;i--)
73     {
74         AdjustDown(A,i,len);
75     }
76     //比较剩余A[10]到A[99999]元素,小于堆顶元素,就放入A[0],继续调整10个元素为大根堆
77     for(i=0;i<100000;i++)
78     {
79         if(A[i]<A[0])
80         {
81             A[0]=A[i];
82             AdjustDown(A,0,9);//继续调整为大根堆
83         }
84     }
85 }
86 //主函数
87 int main()
88 {
89     SSTable ST;
90     ST_Init(ST,100000);
91     Heap_Sort(ST.elem,9);
92     ST_Print(ST);
93     return 0;
94 }

 

②、结果