数据结构与算法--各类排序(判断+选择+填空+程序题--附解析)

判断题

1、仅基于比较的算法能得到的最好的“最坏时间复杂度”是O(NlogN)

T

2、对N个记录进行简单选择排序,比较次数和移动次数分别为O(N2)O(N)

T

3、对N个不同的数据采用冒泡排序进行从大到小的排序,当元素基本有序时交换元素次数肯定最多。

F 当元素基本有序时,交换元素元素肯定较少。

4、要从50个键值中找出最大的3个值,选择排序比堆排序快。

T 选择排序就是在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。

5、对N个记录进行快速排序,在最坏的情况下,其时间复杂度是O(NlogN)

F 对N个记录进行快速排序,在最坏的情况下,其时间复杂度是O(n^2)

6、直接插入排序算法在最好情况下的时间复杂度为O(n)。

T

单选题

1、下列排序算法中,哪种算法可能出现:在最后一趟开始之前,所有的元素都不在其最终的位置上?(设待排元素个数N>2)

A.冒泡排序

B.插入排序

C.堆排序

D.快速排序

B

在插入排序中,如果待排序列中的最后一个元素其关键字值为最小,则在最后一趟开始之前,前n-1个排好序的元素都不在其最终位置

上,与排好序后的位置相差一个位置。

2、对于7个数进行冒泡排序,需要进行的比较次数为:

A.7

B.14

C.21

D.49

C

6+5+4+3+2+1+0=21

3、排序方法中,从未排序序列中依次取出元素与已排序序列中的元素进行比较,将其放入已排序序列的正确位置的方法称为:

A.插入排序

B.选择排序

C.快速排序

D.归并排序

A

4、对于10个数的简单选择排序,最坏情况下需要交换元素的次数为:

A.9

B.36

C.45

D.100

A

简单选择排序在最坏情况下,会经过n-1次选取最值,才能完成排序。

由于交换只发生在找到最值后,因此交换次数等于找到最值的次数,为n-1。

5、若数据元素序列{ 12, 13, 8, 11, 5, 16, 2, 9 }是采用下列排序方法之一得到的第一趟排序后的结果,则该排序算法只能是:

A.快速排序

B.选择排序

C.堆排序

D.归并排序

D

快速排序一次后,有两个值相同,有一个数存放在临时变量,因此不是快速排序

前2个元素和后2个元素均不是最小或最大的2个元素并按序排列,因此不是冒泡排序和选择排序

对该元素序列建堆,发现不符合堆排序第一趟排序后的结果,因此不是堆排序

序列中两两元素有序排列,因此是2路归并排序

6、设有1000个元素的有序序列,如果用二分插入排序再插入一个元素,则最大比较次数是:

A.1000

B.999

C.500

D.10

D

二分查找的时间复杂度为O(logN)

对log1000向上取整为10,向下取整为9。

则比较次数为10,二分次数为9。

7、对初始状态为递增序列的表按递增顺序排序,最费时间的是()算法。

A.快速排序

B.归并排序

C.插入排序

D.堆排序

A

快速排序:最好情况一趟比较可以划分两等份nlogn,最坏相对有序n^2

归并排序:最好最坏都是nlogn

插入排序:最好相对有序n,最坏n^2

堆排序:最好最坏都是nlogn

8、对序列{15,9,7,8,20,-1,4}进行排序,进行一趟后数据的排列变为{4,9,-1,8,20,7,15},则采用的是()排序法。

A.快速

B.希尔

C.冒泡

D.选择

B

希尔排序:

{15,9,7,8,20,-1,4}

第一趟

{4,9,7,8,20,-1,15}

{4,9,-1,8,20,7,15}

第二趟:

{-1,9,4,8,15,7,20}

{-1,7,4,8,15,9,20}

{-1,4,7,8,9,15,20}

9、就平均性能而言,目前最好的内排序方法是()排序法。

A.希尔

B.冒泡

C.快速

D.交换

C

书P206第二段第二行

10、对序列{15,9,7,8,20,-1,4,} 用希尔排序方法排序,经一趟后序列变为{15,-1,4,8,20,9,7}则该次采用的增量是()。

A.2

B.1

C.4

D.3

C

11、下列排序算法中,()算法可能会出现下面情况:在最后一趟开始之前,所有元素都不在其最终的位置上。

A.快速排序

B.堆排序

C.冒泡排序

D.插入排序

D

在插入排序中,如果待排序列中的最后一个元素其关键字值为最小,则在最后一趟开始之前,前n-1个排好序的元素都不在其最终位置

上,与排好序后的位置相差一个位置。

12、数据序列{ 3, 1, 4, 11, 9, 16, 7, 28 }只能是下列哪种排序算法的两趟排序结果?

A.冒泡排序

B.快速排序

C.插入排序

D.堆排序

B

冒泡排序和选择排序:不符合,两边都不是最大最小,排除。

插入排序:数组开头并未有序,排除。

所以是快速排序。

13、若数据元素序列{ 11,12,13,7,8,9,23,4,5 }是采用下列排序方法之一得到的第二趟排序后的结果,则该排序算法只能是:

A.冒泡排序

B.选择排序

C.插入排序

D.归并排序

C

前2个元素和后2个元素均不是最小或最大的2个元素并按序排列,因此不是冒泡排序和选择排序

第一趟排序结束后不存在若干个有序子序列,因此不是归并排序

14、对于快速排序,当待排记录有序时,每回划分均以第一个元素作为枢轴,如下说法正确的是:

A.适用于顺序存储结构,算法时间复杂度是O(N)

B.适用于链式存储结构,算法时间复杂度是O(N)

C.适用于顺序存储结构,算法时间复杂度是O(N^2)

D.适用于链式存储结构,算法时间复杂度是O(N^2)

C

快速排序适用于数组(顺序存储结构)排序。

快速排序的最坏(序列有序)时间复杂度为O(n^2)。

15、在对N个元素进行排序时,基于比较的算法中,其“最坏时间复杂度”中最好的是:

A.O(logN)

B.O(N)

C.O(NlogN)

D.O(N^2)

C

基于比较操作的排序算法有插入排序,冒泡排序,快速排序,归并排序。

其中归并排序的最坏时间复杂度最小,为O(nlogn)

16、在基于比较的排序算法中,哪种算法的最坏情况下的时间复杂度不高于O(NlogN)

A.冒泡排序

B.归并排序

C.希尔排序

D.快速排序

B

冒泡排序的最坏时间复杂度为O(n^2)

归并排序的最坏时间复杂度为O(nlogn)

希尔排序的最坏时间复杂度为O(nlog2n)

快速排序的最坏时间复杂度为O(n^2)

程序填空题

1、冒泡排序

本题要求用冒泡排序将一组整数按增序排序。冒泡排序每次从头到尾扫描待排序列,检查相邻两数的顺序,如果顺序不对就交换。请补全下列冒泡排序的代码。

typedef struct node *nodeptr;
struct node{
   int value;
   nodeptr next;
   /* 一些其他的项,在此忽略 */
};
​
nodeptr BubbleSort (nodeptr h)
{/* h 是带空头结点的链表的头指针 */
   nodeptr p, q;
   int flag_swap;
​
   if (!h->next)  return h;
   do{
      flag_swap = 0;
      p = h;
      while (p->next->next){
         if ( p->next->value>p->next->next->value ){//p->next->value>p->next->next->value
            flag_swap++;
            q = p->next;
            p->next=q->next;//p->next=q->next
            q->next=p->next->next;//q->next=p->next->next
            p->next->next=q;//p->next->next=q
         }
         else p = p->next;
      }
   } while (flag_swap > 0);
   return h;
}

2、希尔排序的分步结果

本题要求给出希尔排序对给定初始序列{9, 8, 7, 6, 5, 4, 3, 2, 1}利用增量序列{1, 3, 7}进行排序的分步结果。将每步结果填在下列空中。注

意:相邻数字间必须有一个空格,开头结尾不得有多余空格。

原始序列9 8 7 6 5 4 3 2 1
增量7排序后2 1 7 6 5 4 3 9 8
增量3排序后2 1 4 3 5 7 6 9 8
增量1排序后1 2 3 4 5 6 7 8 9
2 1 7 6 5 4 3 9 8

2 1 4 3 5 7 6 9 8

3、归并排序(递归法)

归并排序(递归法)。

#include <iostream>
#define MAXSIZE 1000
using namespace std;
​
typedef struct
{
 int key;
 char *otherinfo;
}ElemType;
                    
typedef struct
{
 ElemType *r;
 int  length;
}SqList;
                                                                        
void Create_Sq(SqList &L)
{
 int i,n;
 cin>>n;    //输入的值不大于 MAXSIZE
 for(i=1;i<=n;i++)
 {
  cin>>L.r[i].key;
  L.length++;
 }
}
void show(SqList L)
{
 int i;
 for(i=1;i<=L.length;i++)
  if(i==1) 
   cout<<L.r[i].key;
  else
   cout<<" "<<L.r[i].key;
}
​
void Merge(ElemType R[],ElemType T[],int low,int mid,int high)
{ 
 int i,j,k;
 i=low; j=mid+1;k=low; 
 while(i<=mid&&j<=high)
 {                     
   if(R[i].key<=R[j].key) T[k++]=R[i++]; 
   else T[k++]=R[j++]; 
 } 
 while(i<=mid)
   T[k++]=R[i++];                 
 while(j<=high)
   T[k++]=R[j++];                       
} 
​
void MSort(ElemType R[],ElemType T[],int low,int high)
{ 
  int mid;
  ElemType *S=new ElemType[MAXSIZE];
  if(low==high) 
    T[low]=R[low];//T[low]=R[low]
  else
  { 
    mid=(low+high)/2;
    MSort(R,S,low,mid);//MSort(R,S,low,mid)
    MSort(R,S,mid+1,high);//MSort(R,S,mid+1,high)
    Merge(S,T,low,mid,high);//Merge(S,T,low,mid,high)
  } 
} 
 
void MergeSort(SqList &L)
{ 
   MSort(L.r,L.r,1,L.length); 
} 
​
int main()
{
  SqList R;
  R.r=new ElemType[MAXSIZE+1];
  R.length=0;
  Create_Sq(R);
  MergeSort(R);
  show(R);
  return 0;
}

输入样例:

第一行输入一个数n,接下来输入n个数。

7
24 53 45 45 12 24 90

输出样例:

输出排序结果。

12 24 24 45 45 53 90

编程题

1、快速排序

本题要求实现快速排序的一趟划分函数,待排序列的长度1<=n<=1000。

函数接口定义:

int Partition ( SqList L, int low,  int high );

其中L是待排序表,使排序后的数据从小到大排列。 ###类型定义:

typedef  int  KeyType;
typedef  struct 
{                      
  KeyType *elem; /*elem[0]一般作哨兵或缓冲区*/                       
  int Length;      
}SqList;

裁判测试程序样例:

#include<stdio.h>
#include<stdlib.h>
typedef  int  KeyType;
typedef  struct 
{                      
  KeyType *elem; /*elem[0]一般作哨兵或缓冲区*/                     
  int Length;      
}SqList;
void  CreatSqList(SqList *L);/*待排序列建立,由裁判实现,细节不表*/ 
int Partition ( SqList  L,int low,  int  high );
void Qsort ( SqList  L,int low,  int  high );
int main()
{
  SqList L;
  int i;
  CreatSqList(&L);
  Qsort(L,1,L.Length);
  for(i=1;i<=L.Length;i++)
      printf("%d ",L.elem[i]);
  return 0;
}
void Qsort ( SqList  L,int low,  int  high ) 
{ 
    int  pivotloc;
    if(low<high)
    {  
        pivotloc = Partition(L, low, high ) ;
        Qsort (L, low, pivotloc-1) ; 
        Qsort (L, pivotloc+1, high );
     }
}
/*你的代码将被嵌在这里 */

输入样例:

第一行整数表示参与排序的关键字个数。第二行是关键字值 例如:

10
5 2 4 1 8 9 10 12 3 6

输出样例:

输出由小到大的有序序列,每一个关键字之间由空格隔开,最后一个关键字后有一个空格。

1 2 3 4 5 6 8 9 10 12 

//书P208
int Partition(SqList L,int low,int high)
{
    int flag=L.elem[low];//选定低位为轴值
    L.elem[0]=L.elem[low];//将轴值存放在临时变量中
    while(low!=high){//开始分割,low、high不断向中间移动,直到相遇
        while(L.elem[high]>=flag&&low<high)//当前元素大于轴值且指针未相遇
            high--;//high指针向左移动一步
        L.elem[low]=L.elem[high];//将逆置元素放到左边的位置
        while(L.elem[low]<=flag&&low<high)//当前元素小于轴值且指针未相遇
            low++;//low指针向右移动一步
        L.elem[high]=L.elem[low];//将逆置元素放到右边的位置
    }
    L.elem[low]=L.elem[0];//把轴值回填到分界位置上
    return low;//返回分界位置
}

2、堆排序

本题要求实现堆排序中的筛选函数,待排序列的长度1<=n<=1000。

函数接口定义:

void HeapAdjust( HeapType  H, int s, int m);

其中L是待排序表,使排序后的数据从小到大排列。 ###类型定义:

typedef  int  KeyType;
typedef  struct {                      
  KeyType *elem; /*elem[0]一般作哨兵或缓冲区*/                       
  int Length;      
}SqList;
typedef SqList HeapType; 

裁判测试程序样例:

#include<stdio.h>
#include<stdlib.h>
typedef  int  KeyType;
typedef  struct {                      
  KeyType *elem; /*elem[0]一般作哨兵或缓冲区*/                       
  int Length;      
}SqList;
typedef SqList HeapType; 
void  CreatSqListHeapType *L);/*待排序列建立,由裁判实现,细节不表*/ 
void HeapAdjust( HeapType  H, int s, int m);
void HeapSort( HeapType  H);
int main()
{
  HeapType L;
  int i;
  CreatSqList(&L);
  HeapSort(L);
  for(i=1;i<=L.Length;i++)
   {        
     printf("%d ",L.elem[i]);
   }
  return 0;
}
void HeapSort( HeapType  H)
{ /*堆顺序表H进行堆排序*/
  int i; KeyType rc;
  /*建立初始堆*/
  for( i=H.Length/2;i>0; i--)
   {
      HeapAdjust(H, i, H.Length);
   }
  for(i=H.Length;i>1;i--)
   {
      rc=H.elem[1];
      H.elem[1]=H.elem[i]; 
      H.elem[i]=rc;
      HeapAdjust(H, 1, i-1); 
   }
 }
/*你的代码将被嵌在这里 */

输入样例:

第一行整数表示参与排序的关键字个数。第二行是关键字值 例如:

10
5 2 4 1 8 9 10 12 3 6

输出样例:

输出由小到大的有序序列,每一个关键字之间由空格隔开,最后一个关键字后有一个空格。

1 2 3 4 5 6 8 9 10 12 

//书P123,P125(最小堆)
//本题要求为最大堆
void HeapAdjust(HeapType H,int s,int m)//该函数在HeapSort函数中循环进行
{//s为父节点,i=2*s为左子节点,i+1=2*s+1为右子结点
    KeyType temp=H.elem[s];//保存父结点
    for(int i=2*s;i<=m;i*=2){//过筛
        if(H.elem[i]<H.elem[i+1]&&i<m)//若有右子结点且key值大于左子结点
            i++;//指向右子结点
        if(temp>=H.elem[i])//如果父结点比左(右)子结点的key值大,退出循环
            break;
        H.elem[s]=H.elem[i];
        s=i;//将key值大的结点变为父结点
    }
    H.elem[s]=temp;
    //将父结点与key值大的结点交换位置
    //temp=H.elem[s]
    //H.elem[s]=H.elem[i]
    //H.elem[s]=temp;
} 

3、冒泡法排序

N个整数按从小到大排序的冒泡排序法是这样工作的:从头到尾比较相邻两个元素,如果前面的元素大于其紧随的后面元素,则交换它们。通过一遍扫描,则最后一个元素必定是最大的元素。然后用同样的方法对前N−1个元素进行第二遍扫描。依此类推,最后只需处理两个元素,就完成了对N个数的排序。

本题要求对任意给定的K(<N),输出扫描完第K遍后的中间结果数列。

输入格式:

输入在第1行中给出NK(1≤K<N≤100),在第2行中给出N个待排序的整数,数字间以空格分隔。

输出格式:

在一行中输出冒泡排序法扫描完第K遍后的中间结果数列,数字间以空格分隔,但末尾不得有多余空格。

输入样例:

6 2
2 3 5 1 6 4

输出样例:

2 1 3 4 5 6

#include<iostream>
using namespace std;
int main(void)
{
    int a[10086],N,K,item;
    cin>>N>>K;
    for(int i=0;i<N;++i)
        cin>>a[i];
    for(int i=0;i<K;++i){
        for(int j=0;j<N-1;++j){
            if(a[j]>a[j+1]){
                item=a[j];
                a[j]=a[j+1];
                a[j+1]=item;
            }
        }
    }
    for(int i=0;i<N-1;++i)
        cout<<a[i]<<" ";
    cout<<a[N-1];
    return 0;
}

4、快速排序

给定包含n个元素的整型数组a[1],a[2],...,a[n],利用快速排序算法对其进行递增排序,请输出排序过程,即每次Partition之后的数组。每次选择所处理的子数组的第一个元素作为基准元素。

输入格式:

输入为两行,第一行为一个整数n(1<n≤1000),表示数组长度。第二行为n个空格间隔的整数,表示待排序的数组。

输出格式:

输出为若干行,每行依次输出Partition后的数组,每个元素后一个空格。

输入样例:

5
4 5 3 2 1

输出样例:

2 1 3 4 5 
1 2 3 4 5 
1 2 3 4 5 

#include<iostream>
using namespace std;
int n;
void print(int *arr)//输出
{
    for(int i=0;i<n;++i)
       cout<<arr[i]<<" ";
    cout<<endl;
}
void swap(int &a,int &b)//交换位置
{
    int temp=a;
    a=b;
    b=temp;
}
void quicksort(int *arr,int left,int right)//快速排序
{
    if(left>=right)
        return;//递归出口
    int l=left;//left为数组首位下标:0
    int r=right;//right为数组末尾下标:n-1
    int key=arr[left];//设定轴值为数组第一个元素
    while(l<r){//或l!=r
        while(l<r&&arr[r]>key)//arr[r]>key
            r--;
        while(l<r&&arr[l]<=key)//arr[l]<=key
            l++;
        swap(arr[r],arr[l]);
    }
    //设定新轴值,此时左边数都小,右边数都大
    swap(arr[l],arr[left]);//arr[l]也可换成arr[r],因为此时l=r
    print(arr);//输出每次快速排序后的数组
    quicksort(arr,left,l-1);//对轴值左侧进行快速排序
    quicksort(arr,l+1,right);//对轴值右侧进行快速排序
}
int main(void)
{
    cin>>n;
    int arr[n]; 
    for(int i=0;i<n;++i)
        cin>>arr[i];
    quicksort(arr,0,n-1);
    for(int i=0;i<n;++i)
        cout<<arr[i]<<" ";
    return 0;
}

5、寻找大富翁

胡润研究院的调查显示,截至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<iostream>
using namespace std;
#define MAXN 1000000
int num[MAXN];
int main(void)
{
    int n,m,count=0;
    cin>>n>>m;
    for(int i=0;i<n;++i)
        cin>>num[i];
    for(int i=0;i<n;++i){//选择排序
        int max=i;//设定最大值下标为i
        for(int j=i+1;j<n;++j)
            if(num[j]>num[max])
                max=j;//修改最大值下标为j
        int temp=num[i];//将最大值放到数组前
        num[i]=num[max];
        num[max]=temp;
        count++;
        if(count==1)
            cout<<num[i];
        else
            cout<<" "<<num[i];
        if(count==m)
            break;
    }
    return 0;
}

  • 3
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值