上机一 E ModricWang's QuickSort

ModricWang's QuickSort

时间限制:1000ms   内存限制:65536kb

通过率:64/92 (69.57%)    正确率:64/306 (20.92%)

题目描述

羊瑞大佬说:“现在的年轻人啊,写个快排都吃力。”

ModricWang觉得他说的情况是真的,决定帮大家复习一下快排的写法。

快排的一个基础操作就是划分(partition),就是将当前的数组分为前后两个部分。

一种较为经典的partition方法是,将数组中处于中间位置(注意,只和位置有关,和大小无关)的元素作为分隔元素,然后将小于等于它的元素放到左侧,大于它的元素放到右侧,然后对左右两侧分别进行递归操作。在此题中为了统一,如果数组长度为偶数,取靠后的一个作为分隔元素。

需要注意的是,快排的划分是一种原地划分,而且左右两边的长度是未知的,因此它在操作时采取以下的一种方式:

  1. 设数组为arr[n],元素从0开始存储
  2. 令i=0,j=n-1, mid=arr[n/2]
  3. 如果 i < j,转到4,否则转到7
  4. 如果arr[i] <= mid, i++ ,重复执行直到arr[i]>mid
  5. 如果arr[j] > mid, j-- ,重复执行直到arr[j]<=mid
  6. 如果i < j, 交换arr[i]和arr[j],转到4
  7. 退出

进行第一次递归时,数组被分为左右两个部分。进行第二层的递归时,数组总共被分为4个部分。现在ModricWang想让你输出第二层递归时从左往右的第二部分的元素。

输入

第一个数为数组长度n, 16n106 16≤n≤106

第二行n个整数,为待排序的元素,保证在int范围内且不重复

输出

输出一行,第二层递归时从左往右的第二部分的元素。

数据保证这一部分不为空。

输入样例

16
10 6 2 7 14 4 1 13 8 15 5 3 9 11 12 16

输出样例

7 6 8

HINT

原数据

10 6 2 7 14 4 1 13 8 15 5 3 9 11 12 16

第一次递归

3 6 2 7 5 4 1 8 / 13 15 14 10 9 11 12 16

第二次递归

3 1 2 4 5 / 7 6 8 / 9 / 15 14 10 13 11 12 16

解析:

本题在理解快排的基础下十分简单。题目采用取中间数为标志值的方法,但要注意:题中只给出了划分的方法,输出时应当按照题目的划分输出第二部分。

代码:

#include<cstdio>
#define maxn 1000007
int a[maxn];

void mov(int &a,int &b)
{
    int hold = a;
    a = b;
    b = hold;
}

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i = 0; i < n; i++)
        {
            scanf("%d",&a[i]);
        }

        int i = 0;
        int j = n-1;
        int mid = n/2;
        int key = a[mid];
        while(i < j)
        {
            while(a[i] <= key)
            {
                i++;
            }
            while(a[j] > key)
            {
                j--;
            }
            mov(a[i],a[j]);
        }

        mov(a[i],a[i-1]);

        int tem = i;

        i = 0;
        j = tem - 1;
        mid = tem/2;
        key = a[mid];
        while(i < j)
        {
            while(a[i] <= key)
            {
                i++;
            }
            while(a[j] > key)
            {
                j--;
            }
            mov(a[i],a[j]);
        }

        mov(a[i],a[i-1]);

        for(int k = i;k < tem;k++)
        {
            printf("%d ",a[k]);
        }
        puts("");
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值