必威体育Betway必威体育官网
当前位置:首页 > IT技术

快速选择排序

时间:2019-08-23 20:13:16来源:IT技术作者:seo实验室小编阅读:59次「手机版」
 

排序

快速选择排序是一个在平均情况下的时间复杂度为O(nlogn),最坏的时间复杂度为O(n^{2}) ,且是一个不稳定的排序方法,但一般情况下它的排序速度很快,只有当数据基本有序的时候速度是最慢的。

排序的过程:

  1. 一般选择待排序表中的第一个记录作为基准数,然后初始化两个指针 low 和 high ,分别指向表的上界和下界

  2. 从表的最右侧开始依次向左搜索,找到第一个关键字小于基准数的记录,将其移到 low 处并high--。
  3. 接着从表的最左侧位置开始依次向右边搜索,找到第一个大于基准数的记录,将其移到 high 的位置后 low++.
  4. 重复操作2和3,直至 low 和 high 相等,此时 low 和 high 的位置即为基准数在此序列中的最终位置。

由上面的过程我们可以写出以下的代码

void quick_sort(int low, int high)
{
	if(low < high)
	{
		//swap(s[low], s[(low + high) / 2]); 有些快速选择排序是将中间的值作为基准数作为排序,这样当数据基本有序的时候可以降低运行时间
		int i = low, j = high, x = s[low];
		while(i < j)
		{
			while(i < j && s[j] >= x) //从右往左找第一个小于x的数
				j--;
			if(i < j)      //跟左边的l位置上进行交换
				s[i++] = s[j];
			while(i < j && s[i] < x) //从左往右找第一个大于或等于x的数
				i++;
			if(i < j)   //同理
				s[j--] = s[i];
		}
		s[i] = x; //注意最后排序好后要将基准数填进去
		quick_sort(a, low, i - 1); //递归排序左边的区间
		quick_sort(a, i + 1, high); //递归排序右边的区间
	}	
}

但此时的快排的代码还不够快。。。如果你去做洛谷的P1177就会发现还是会TLE。。。。。

搜了一下题解发现还有另一种写法的快排。。所以下面就来分享一波。。。

这一种方法是从左右两个方向同时进行的快排。。下面就用个例子来解释一下。

从初始序列“6  1  2 7  9  3  4  5 10  8”两端开始“探测”。先从右往左找一个小于6的数,再从左往右找一个大于6的数,然后交换他们。这里可以用两个变量i和j,分别指向序列最左边和最右边。我们为这两个变量起个好听的名字“哨兵i”和“哨兵j”。刚开始的时候让哨兵i指向序列的最左边(即i=1),指向数字6。让哨兵j指向序列的最右边(即j=10),指向数字8。

首先哨兵j开始出动。因为此处设置的基准数是最左边的数,所以需要让哨兵j先出动。哨兵j一步一步地向左挪动(即j--),直到找到一个小于6的数停下来。接下来哨兵i再一步一步向右挪动(即i++),直到找到一个数大于6的数停下来。最后哨兵j停在了数字5面前,哨兵i停在了数字7面前。

现在交换哨兵i和哨兵j所指向的元素的值。交换之后的序列如下:

6  1  2  5  9 3  4  7  10  8

到此,第一次交换结束。接下来开始哨兵j继续向左挪动(再友情提醒,每次必须是哨兵j先出发)。他发现了4(比基准数6要小,满足要求)之后停了下来。哨兵i也继续向右挪动的,他发现了9(比基准数6要大,满足要求)之后停了下来。此时再次进行交换,交换之后的序列如下:

6  1  2 5  4  3  9  7 10  8

第二次交换结束,“探测”继续。哨兵j继续向左挪动,他发现了3(比基准数6要小,满足要求)之后又停了下来。哨兵i继续向右移动,糟啦。此时哨兵i和哨兵j相遇了,哨兵i和哨兵j都走到3面前。说明此时“探测”结束。我们将基准数6和3进行交换。交换之后的序列如下:

3  1 2  5  4  6  9 7  10  8

到此第一轮“探测”真正结束。此时以基准数6为分界点,6左边的数都小于等于6,6右边的数都大于等于6。回顾一下刚才的过程,其实哨兵j的使命就是要找小于基准数的数,而哨兵i的使命就是要找大于基准数的数,直到i和j碰头为止。

代码实现如下:

(注意://此处的m的值的设置是为了使快排更快。前面图的基数设置是为了方便大家理解)

void quick_sort(int l, int r)
{
    int i = l, j = r, m = a[(l+r)/2];
    while(i <= j)
    {
        while(a[j] > m)
            j--;
        while(a[i] < m)
            i++;
        if(i <= j)
        {
            swap(a[i], a[j]);
            i++;
            j--;
        }
    }
    //至此,i > j,  l 到 j 部分为小于基准数, i 到 r 部分为大于基准数
    if(l < j)  
        quick_sort(l, j);
    if(i < r)
        quick_sort(i, r);
}

顺便附上洛谷P1177的AC代码:

#include <iOStream>
#include <algorithm>
using namespace std;
int a[100005];
void quick_sort(int l, int r)
{
    int i = l, j = r, m = a[(l+r)/2];
    while(i <= j)
    {
        while(a[j] > m)
            j--;
        while(a[i] < m)
            i++;
        if(i <= j)
        {
            swap(a[i], a[j]);
            i++;
            j--;
        }
    }
    if(l < j)
        quick_sort(l, j);
    if(i < r)
        quick_sort(i, r);
}
int main()
{
    int n;
    while(cin >> n)
    {
        for(int i = 0; i < n; i++)
            cin >> a[i];
        quick_sort(0, n - 1);
        for(int i = 0; i < n; i++)
        {
            cout << a[i];
            if(i != n - 1)
                cout << " ";
        }
        cout << endl;
    }
    return 0;
}

参考链接:https://yq.aliyun.com/ziliao/353024      https://blog.csdn.net/morewindows/article/details/6684558

相关阅读

新站怎样才能快速收录?老站如何有效提高权重?

据我所知,现在互联网上的草根站长,大多数都是靠搜索引擎吃饭,所以站长们就不断利用各种手段来讨好搜索蜘蛛,乞求有朝一日能一柱擎天飙

学习方法论------《方法比技能重要》,《如何比别人快速

第01课:高效学习方程式,你的学习到底是哪里出了问题一、学习不好的原因高效学习的方程式,最终的学习效果=时间*精力*注意力*目标*策

索尼掌机PSV正式停产 手游快速发展令其淘汰出市场

A5创业网(公众号:iadmin5)3月3日报道,索尼正式结束便携式游戏机PlayStation Vita的生产,剩余的的两个型号现在该设备的官方产品页面上

直通车优化技巧之如何快速整体提升?

直通车思维并不是指直通车操作,而是怎么去更好的选择,我在哪个时期要花多少钱,哪个时期要选择广泛还是人群,多高的投产要提高流量。不

csdn快速的转载别人博客里的文章,不需要复制,简单一点

  对于喜欢逛CSDN的人来说,看别人的博客确实能够对自己有不小的提

分享到:

栏目导航

推荐阅读

热门阅读