scau 8642 快速排序

Description

用函数实现快速排序,并输出每次分区后排序的结果

输入格式

第一行:键盘输入待排序关键的个数n
第二行:输入n个待排序关键字,用空格分隔数据

输出格式

每行输出每趟排序的结果,数据之间用一个空格分隔

输入样例

10
5 4 8 0 9 3 2 6 7 1

输出样例

1 4 2 0 3 5 9 6 7 8
0 1 2 4 3 5 9 6 7 8
0 1 2 4 3 5 9 6 7 8
0 1 2 3 4 5 9 6 7 8
0 1 2 3 4 5 8 6 7 9
0 1 2 3 4 5 7 6 8 9
0 1 2 3 4 5 6 7 8 9

好久都没有更新啦!五一玩过头了TUT

排序这一章的前面几个算法,像直接插入排序、折半插入排序都是比较简单的,这里我对快速排序做个小小的笔记。

首先,我们要了解快速排序的步骤。

书上其实介绍的蛮清楚的,不过全是文字,所以看起来会有点枯燥且难懂。下面我用样例来进行解释。(PS:快排也是有很多方法哒!我下面所介绍的这个方法和书上有点点不太一样,因为上课没听懂,所以在网上找了点小小资源,不过弄明白了一种方法,另一种方法也是很好理解的。我先介绍我的方法,再介绍书上的方法

以题目所给输入样例为例。

步骤:

(1)以第一个数“5”为基准点,设置头尾指针,分别指向第一个数和最后一个数。

(2)从右往左,找出第一个小于基准点“5”的数,也就是“1”,找的同时要移动尾指针j哦,即j--

(3)再从左往右,找出第一个大于基准点“5”的数,也就是“8”,同理,找的时候要移动头指针,即i++

(4)现在的指针i和j如上图所示,交换指针i和j所指的数,如下图所示

 

(5)重复步骤(2)~(4),直至指针i和j相遇

 

当指针i和j相遇时,交换基准点“5”和指针i和j共同指向的数“3”

如上图所示,这就是第一次调用快排函数的结果。你会发现,此时的“5”已经归位,“5”左边的数均小于5,右边的数均大于5。

然后以“5”为中心,将这段数列分成左右两段,“3 4 1 0 2”和“9 6 7 8”,再调用快排函数对左右两个子段进行处理,即重复步骤(1)~(5)【左段以3为基准点,右段以9为基准点】

递归结束时,排序就完成了。

代码如下

#include <iostream>

using namespace std;

int n,a[100005];

void print()
{
    std::ios::sync_with_stdio(false);
    for(int k=1;k<=n;k++)
        cout << a[k] << ' ';
    cout << endl;
}

void kuaipai(int a[],int i,int j)//a[]为要排序的数组,i指向第一个数,j指向最后一个数
{
    if(i>=j)//结束条件写前面
        return;
    int temp=a[i];//基准数
    int m,n;
    m=i,n=j;
    while(m!=n)
    {
        while(a[n]>=temp && m<n)//从右往左找第一个小于等于基准数的数
            n--;//没找到就n--(相当于尾指针向前移)
        while(a[m]<=temp && m<n)//从左向右找第一个大于等于基准数的数
            m++;//没找到就m++(相当于头指针向后移)
        if(n>m)//如果头尾指针没有相遇,则交换两个数
        {
            int t=a[m];
            a[m]=a[n];
            a[n]=t;
        }
    }
    a[i]=a[m];//当头尾指针相遇时,把头尾指针指向的那个数和基准数交换
    a[m]=temp;
    print();
    kuaipai(a,i,m-1);//归位的基准点的左半段
    kuaipai(a,m+1,j);//归位的基准点的右半段
}

int main()
{
    std::ios::sync_with_stdio(false);
    cin >> n;
    int k;
    for(k=1;k<=n;k++)
    {
        cin >> a[k];
    }
    kuaipai(a,1,n);
    return 0;
}

输入输出结果如下

 

 下面来介绍书上的方法。

 还是以这个为例

步骤:

(1)把第一个数作为基准点暂存在a[0]中,设置头尾指针i和j,分别指向第一个数和最后一个数。

(2)从右往左,找出第一个小于基准点“5”的数,没找到就j--,找到之后将j所指向的这个第一个小于“5”的数和基准点“5”交换

(3)从左往右,找出第一个大于基准点“5”的数,没找到就i++,找到之后将i所指向的这个第一个大于“5”的数和基准点“5”交换

{PS:注意我上面标成粉红色的字,这就是和上面第一种方法的区别所在。第一种是把指针i和j所指向的数进行交换,而这里是把指针i和j分别和基准点交换}

(4)重复步骤(2)~(3),直至指针i和j相遇

好了,上面就是第一次调用快排函数所得到的结果,此时指针i和j相遇,“5”已归位,以“5”为中心,原来的数列被分成两个子段“1 4 2 0 3”和“9 6 7 8”

和前面介绍的第一种方法得到的结果不太一样,但是规律是相似的哦——“5”归位,“5”左边的数均小于5,右边的数均大于5。

(5)重复步骤(1)~(4),调用函数对左右两个子段进行处理。

         例如左子段“1 4 2 0 3”,以“1”为基准点,最后得到“0 1 2 4 3”,“1”已归位,以“1”为中心,“0 1 2 4 3”又被分成了两个子段“0”和“2 4 3”,再进行递归调用……

直到所有递归结束,排序结束

代码如下

(1)这个提交可以过

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <algorithm>

using namespace std;

int n,a[100005];

int kuaipai(int a[],int i,int j)
{
    a[0]=a[i];//用a[0]暂存基准点
    while(i<j)
    {
        while(i<j && a[j]>=a[0])
            j--;
        a[i]=a[j];
        while(i<j && a[i]<=a[0])
            i++;
        a[j]=a[i];
    }
    a[i]=a[0];//基准点记录到位
    return i;
}

void Qsort(int a[],int i,int j)
{
    if(i<j)
    {
        int k;
        k=kuaipai(a,i,j);//返回中心
        for(int p=1;p<=n;p++)
            cout<<a[p]<<' ';
        cout << endl;
        Qsort(a,i,k-1);
        Qsort(a,k+1,j);
    }
}

int main()
{
    cin >> n;
    for(int k=1;k<=n;k++)
        cin >> a[k];
    Qsort(a,1,n);
    return 0;
}

运行结果如图 

 (2)下面这个也能得出正确答案,但是不知道为什么多了几行重复的。有没有兄弟可以帮我找找问题TUT

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <algorithm>

using namespace std;

int n,a[100005];

void print()
{
    std::ios::sync_with_stdio(false);
    for(int k=1;k<=n;k++)
        cout << a[k] << ' ';
    cout << endl;
}

void kuaipai(int a[],int i,int j)
{
    if(i>j)
        return;
    int m,n;
    m=i,n=j;//用于记录,最后递归需要用到

    a[0]=a[i];//用a[0]暂存基准点
    while(i<j)
    {
        while(i<j && a[j]>=a[0])
            j--;
        a[i]=a[j];
        while(i<j && a[i]<=a[0])
            i++;
        a[j]=a[i];
    }
    a[i]=a[0];//基准点记录到位
    print();
    kuaipai(a,m,i-1);
    kuaipai(a,i+1,n);
}

int main()
{
    cin >> n;
    for(int k=1;k<=n;k++)
        cin >> a[k];
    kuaipai(a,1,n);
    return 0;
}

运行结果如图

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值