一、判断题
1、
答案:F
解析:堆排序的空间复杂度是O(1),所以需要的额外空间就是O(1)
2、
答案:T
3、
答案:F
4、
答案:F
解析:基本有序一般指的是基本都是升序,不是完全。所有基本有序次数不一定最多,完全有序次数才最多。
二、单选题
1、
答案:C
解析:如果左右指针都会停止移动,也就意味着停下来就交换,这种情况对应的时间复杂度为O(nlogn)
2、
答案:D
解析:左右指针不停止移动的话,也就是假设第一个数为基准数,那么从左边开始移动指针的时候,最终将一直移动到第一个元素,选择的枢轴在序列的某一端,这种情况对应的时间复杂度为最差为O(n方)
每次都划分得很均匀,那么就是最优时间复杂度
3、
答案:D
解析:一个指针会移动,另一个指针根本没来得及动,会造成选择的主元在序列的某一端,这种情况对应的时间复杂度为最差为O(n方)
4、
答案:A
5、
答案:C
解析: 需要比较的次数为:N(N-1)/2
6、
答案:D
解析:
建堆的话,默认是建立大顶堆
7、
答案:C
解析:递归次数与初始数据的排列次序有关,与每次划分后得到的分区处理顺序无关
8、
答案:C
9、
答案:D
解析:以最左边位置的数据为基准,也就是46为基准
- 46(左)、79、56、38、40、84(右)
- 右指针移动,找到第一个比基准数小的,放到左边的位置 40(左)、79、56、38、40(右)、84
- 左指针移动,找到第一个比基准数大的,放到右边的位置 40、79(左)、56、38、79(右)、84
- 右指针移动,找到第一个比基准数小的,放到左边的位置 40、38(左)、56、38(右)、79、84
- 左指针移动,找到第一个比基准数大的,放到右边的位置 40、38、56(左)、56(右)、79、84
- 第一次移动的最终次序是 40、38、46(左)、56(右)、79、84
注意:开始移动的时候,不能除去第一个数据,应当加上基准数据
不动的值反而改变了
10、
答案:B
解析:49、38、65、97、76、13、27、50
49、13、27、50、76、38、65、97
注意:步长为4的意思是,从下个数开始数其,长度为4,而不是从这个数开始数起,长度为4
11、
答案:D
解析:挨个试一试就可以了
12、
答案:A
解析:对于交换次数而言,当最好的时候,交换为0次,最差的时候,也就初始排序,交换次数为n-1次,复杂度为O(n)。
13、
答案:A
解析:简单选择排序它最大的特点是交换移动数据次数相当少,这样也就节约了相应的时间,无论最好最坏的情况,其比较次数都是一样多。第 i 次排序需要进行n-i 次关键字的比较,此时需要比较n-1+n-2+...+1=n(n-1)/2次,时间复杂度为O(n^2)。对于交换次数而言,当最好的时候,交换为0次,最差的时候,也就初始排序,交换次数为n-1次,复杂度为O(n)
14、
答案:C
15、
答案:A
三、编程题
1、寻找大富翁 (25 分)
胡润研究院的调查显示,截至2017年底,中国个人资产超过1亿元的高净值人群达15万人。假设给出N个人的个人资产值,请快速找出资产排前M位的大富翁。
输入格式:
输入首先给出两个正整数N(≤106)和M(≤10),其中N为总人数,M为需要找出的大富翁数;接下来一行给出N个人的个人资产值,以百万元为单位,为不超过长整型范围的整数。数字间以空格分隔。
输出格式:
在一行内按非递增顺序输出资产排前M位的大富翁的个人资产值。数字间以空格分隔,但结尾不得有多余空格。
输入样例:
8 3
8 12 7 3 20 9 5 18
输出样例:
20 18 12
答案:
#include <bits/stdc++.h>
using namespace std;
//按照从小到大排序
void HeapAdjust(long A[],int parent,int length)
{
int temp=A[parent];//temp保存当前父节点
int child=2*parent+1;//先获得左孩子
while(child<length) // 如果有右孩子结点
{
if(child+1<length&&A[child]>A[child+1])//右孩子结点的值小于左孩子结点,则选取右孩子结点
{
child+=1;
}
if(temp<A[child])
{
break;// 如果父结点的值已经小于孩子结点的值,则直接结束
}
A[parent]=A[child];
// 选取孩子结点的左孩子结点,继续向下筛选
parent=child;
child=2*child+1;
}
A[parent]=temp;
}
void heapSort(long A[],int N)
{
for(int i=N/2; i>=0; i--)
{
HeapAdjust(A,i,N);
}
for(int i=N-1; i>=0; i--) // 进行n-1次循环,完成排序
{
int temp=A[i];// 最后一个元素和第一元素进行交换
A[i]=A[0];
A[0]=temp;
// 筛选R[0]结点,得到i-1个结点的堆
HeapAdjust(A,0,i);
}
}
int main()
{
int N,M;
long a[1000000];
scanf("%d%d",&N,&M);
for(int i=0; i<N; i++)
{
scanf("%ld",&a[i]);
}
heapSort(a,N);
if(N<M)
{
for(int i=0; i<N; i++)
{
if(i==0)
printf("%ld",a[i]);
else
printf(" %ld",a[i]);
}
}
else
{
for(int i=0; i<M; i++)
{
if(i==0)
printf("%ld",a[i]);
else
printf(" %ld",a[i]);
}
}
return 0;
}
2、冒泡法排序 (20 分)
将N个整数按从小到大排序的冒泡排序法是这样工作的:从头到尾比较相邻两个元素,如果前面的元素大于其紧随的后面元素,则交换它们。通过一遍扫描,则最后一个元素必定是最大的元素。然后用同样的方法对前N−1个元素进行第二遍扫描。依此类推,最后只需处理两个元素,就完成了对N个数的排序。
本题要求对任意给定的K(<N),输出扫描完第K遍后的中间结果数列。
输入格式:
输入在第1行中给出N和K(1≤K<N≤100),在第2行中给出N个待排序的整数,数字间以空格分隔。
输出格式:
在一行中输出冒泡排序法扫描完第K遍后的中间结果数列,数字间以空格分隔,但末尾不得有多余空格。
输入样例:
6 2
2 3 5 1 6 4
输出样例:
2 1 3 4 5 6
答案:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,m;
scanf("%d%d",&n,&m);
int A[100000];
for(int i=0; i<n; ++i)
scanf("%d",&A[i]);
int s=0;
for(int j=1; j<n; j++)
{
for(int k=0; k<n-j; k++)
{
if(A[k]>A[k+1])
{
int l=A[k];
A[k]=A[k+1];
A[k+1]=l;
}
}
s+=1;
if(s==m)
{
for(int i=0; i<n; i++)
{
if(i==0)
printf("%d",A[i]);
else
printf(" %d",A[i]);
}
}
}
return 0;
}