(2016)第七届蓝桥杯省赛(软件类) C/C++ 大学A组 题解(第四题)

时间:2022-09-10 08:53:19

第三题 

题目

    快速排序
    排序排序在各种场合经常被用到。
    快速排序是十分常用的高效率的算法。

    其思想是:先选一个“标尺”,
    用它把整个队列过一遍筛子,
   以保证:其左边的元素都不大于它,其右边的元素都不小于它。

   这样,排序问题就被分割为两个子区间。
   再分别对子区间排序就可以了。
   下面的代码是一种实现,请分析并填写划线部分缺少的代码。

#include <stdio.h>

void swap(int a[], int i, int j)
{
	int t = a[i];
	a[i] = a[j];
	a[j] = t;
}

int partition(int a[], int p, int r)
{
    int i = p;
    int j = r + 1;
    int x = a[p];
    while(1){
        while(i<r && a[++i]<x);
        while(a[--j]>x);
        if(i>=j) break;
        swap(a,i,j);
    }
	______________________;
    return j;
}

void quicksort(int a[], int p, int r)
{
    if(p<r){
        int q = partition(a,p,r);
        quicksort(a,p,q-1);
        quicksort(a,q+1,r);
    }
}
    
int main()
{
	int i;
	int a[] = {5,13,6,24,2,8,19,27,6,12,1,17};
	int N = 12;
	
	quicksort(a, 0, N-1);
	
	for(i=0; i<N; i++) printf("%d ", a[i]);
	printf("\n");
	
	return 0;
}

思路分析

     基于分划交换的快速排序的基本思想是:
1.先从数列中取出一个数作为基准数。
2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
3.再对左右区间重复第二步,直到各区间只有一个数。
掌握好第这三步后利用分治递归的方法即可解决左右区间的排序问题
     对于填空前后,加入以下几行代码输出中间的排序结果和分划位置p,对照可知:位置p和位置j需要调换位置。
void quicksort(int a[], int p, int r)
{
    if(p<r){
        int q = partition(a,p,r);
        for(int i=0; i<12; i++) 
        
		 printf("%d ", a[i]); //输出中间测试的每一轮排序结果 
         printf("\n"); 
         printf("%d\n",q);//输出中间测试的每一轮分划位置 
         
        quicksort(a,p,q-1);
        quicksort(a,q+1,r);
    }
}
(2016)第七届蓝桥杯省赛(软件类) C/C++ 大学A组 题解(第四题)(2016)第七届蓝桥杯省赛(软件类) C/C++ 大学A组 题解(第四题)

填空

swap(a,p,j);

代码

#include <iostream>
#include <stdio.h>

void swap(int a[], int i, int j)
{
	int t = a[i];
	a[i] = a[j];
	a[j] = t;
}

int partition(int a[], int p, int r)//p是左区间数,r是右区间数 
{
    int i = p;//选择p作为基准值的下标 
    int j = r + 1;//右边数扩1位 
    int x = a[p];//x为基准值 
    while(1){
        while(i<r && a[++i]<x);// 从左向右找第一个大于等于x的数
        while(a[--j]>x);// 从右向左找第一个小于x的数 
        if(i>=j) break;
        swap(a,i,j);
    }
	swap(a,p,j);//将每次分划后,将左区间的基准值与最后过分小于x的值进行交换(最后j停留的值) 
    return j;
}

void quicksort(int a[], int p, int r)
{
    if(p<r){
        int q = partition(a,p,r);
        quicksort(a,p,q-1);
        quicksort(a,q+1,r);
    }
}
int main(int argc, char** argv) {
	int i;
	int a[] = {5,13,6,24,2,8,19,27,6,12,1,17};
	int N = 12;
	
	quicksort(a, 0, N-1);
	
	for(i=0; i<N; i++) printf("%d ", a[i]);
	printf("\n");
	
	return 0;
}
    

另一种实现代码,基本思想是相同的:

void quick_sort(int s[], int l, int r)  
{  
    if (l < r)  
    {  
        //Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1  
        int i = l, j = r, x = s[l];  
        while (i < j)  
        {  
            while(i < j && s[j] >= x) // 从右向左找第一个小于x的数  
                j--;    
            if(i < j)   
                s[i++] = s[j];  

            while(i < j && s[i] < x) // 从左向右找第一个大于等于x的数  
                i++;    
            if(i < j)   
                s[j--] = s[i];  
        }  
        s[i] = x;  
        quick_sort(s, l, i - 1); // 递归调用   
        quick_sort(s, i + 1, r);  
    }  
}