关于快速排序算法(一个90%的人都不懂其原理、99.9%的人都不能正常写出来的算法.)

一、奇怪的现象


  研究快速排序很久了,发现一个古怪的实情:这算法描述起来很简单,写一个正确的出来实在不容易.写一个优秀的快速排序算法更是难上加难.

也难怪该算法提出来过了很久才有人写出一个正确的算法,过了很久才优秀的版本出来.

二、原理描述


  1. 从数列中挑出一个元素,称为 "基准"(pivot),

  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。

  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序.

三、最容易让人理解的版本

一个List形式的数组,找到其中的第一个做基准,遍历剩下的数据,然后创建两个左右List,大的放右边,小的放左边.然后对左右List各自进行如上操作.......

详情见代码

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

?using 
System;

using 
System.Collections.Generic;

using 
System.Text;

namespace
test

{

    class
Program

    {

        static
void Main(string[]args)

        {

            List<int> array=new
List<int>();

            array.AddRange(new
int[]{3,2,9,5,8,6,23,23,222,12,21});

            var
t1=DateTime.Now.Ticks;

            sort(array);

            var
t2=DateTime.Now.Ticks;

            Console.WriteLine(t2-t1);

            

            Console.ReadLine();

        }

        static
int Count=0;

        public
static void sort(List<int> array)

        {

            var
guid=Count++;

            Console.WriteLine();

            Console.Write("目标字符串:("+guid+")");

            Show(array);

            

            if
(array.Count<=1) {

                return;

            }

            if
(array.Count==2) {

                if
(array[0]>array[1]) {

                    var
temp=array[0];

                    array[0]=array[1];

                    array[1]=temp;

                    Console.Write("双值交换:");

                    Show(array);

                }

            }

            else{

                var
xData=array[0];

                var
leftList=new
List<int>();

                var
rightList=new
List<int>();

                for
(int
i = 1; i < array.Count; i++) {

                    var
t=array[i];

                    if
(t<=xData) {

                        leftList.Add(t);

                    }else{

                        rightList.Add(t);

                    }

                }

                

                Console.WriteLine("中间值:"+xData);

                

                Console.Write("左边的字符串("+guid+"):");

                Show(leftList);

                

                Console.Write("右边的字符串("+guid+"):");

                Show(rightList);

                

                sort(leftList);

                Console.Write("左边的字符串(排序后)("+guid+"):");

                Show(leftList);

                

                sort(rightList);

                Console.Write("右边的字符串(排序后)("+guid+"):");

                Show(rightList);

                

                array.Clear();

                array.AddRange(leftList);

                array.Add(xData);

                array.AddRange(rightList);

                Console.Write("排好的("+guid+"):");

                Show(array);

                

                Console.WriteLine();

                leftList.Clear();

                rightList.Clear();

            }

        }

        public
static void Show(List<int>array){

            foreach
(var
a in
array) {

                Console.Write(a+",");

            }

            

            Console.WriteLine();

        }

    }

}

四、正确但不优化的版本


using System;
namespace Sort
{
class Program
{
static void Main(string[] args)
{
string result = string.Empty;
int[] unsort = { 2, 0, 3, 7, 5,6 };
//快速排序
QuickSort(unsort, 0, unsort.Length - 1);
Console.ReadLine();
}

/// <summary>
/// 调用快速排序算法
/// </summary>
/// <param name="unsort">待排序的整形数组</param>
/// <param name="left">左边起始点</param>
/// <param name="right">右边结束点</param>
public static void QuickSort(int[] unsort, int left, int right)
{
if (left < right)
{
//获取一次排序的中间索引位置
int midPosition = GetSplitNum(unsort, left, right);

//递归实现
QuickSort(unsort, left, midPosition - 1);
QuickSort(unsort, midPosition + 1, right);
}
}

static int ORDER_INDEX=1;
/// <summary>
/// 获取一次排序的中间索引位置
/// </summary>
/// <param name="unsort">待排序的整形数组</param>
/// <param name="left">左边起始点</param>
/// <param name="right">右边结束点</param>
public static int GetSplitNum(int[] unsort, int left, int right)
{
int splitNum = unsort[left];
while (left < right)
{
/**
* 从右端开始比较
* (1)假如从右端过来的数比分隔数要大,则不用处理
* (2)假如从右端过来的数比分隔数要小,则需要挪到分隔线左边
* */
while (left < right && splitNum <= unsort[right])
{
right--;
}
unsort[left] = unsort[right];
GetPrint(unsort);
/**
* 从从端开始比较
* (1)假如从左端过来的数比分隔数要小,则不用处理
* (2)假如从左端过来的数比分隔数要大,则需要挪到分隔线右边
* */
while (left < right && splitNum >= unsort[left])
{
left++;
}
unsort[right] = unsort[left];
GetPrint(unsort);
}
//一趟比较之后,分隔数的位置就可以确认起来
unsort[left] = splitNum;
Console.WriteLine(string.Format("第{0}轮排序完毕",(ORDER_INDEX++)));
GetPrint(unsort);
return left;
}

/// <summary>
/// 打印输出结果
/// </summary>
/// <param name="unsort">数据</param>
public static string GetPrint(int[] unsort)
{
string result = string.Empty;
foreach (int n in unsort)
{
if (!string.IsNullOrEmpty(result))
{
result += string.Format("->{0}", n);
}
else
{
result = string.Format("{0}", n);
}
}
Console.WriteLine(result);
return result;
}
public static string GetPrint(int[] unsort,int replaceIndex)
{
string result = string.Empty;
foreach (int n in unsort)
{
if (!string.IsNullOrEmpty(result))
{
result += string.Format("->{0}", n);
}
else
{
result = string.Format("{0}", n);
}
}
Console.WriteLine(result+" ==>"+replaceIndex);
return result;
}
}
}

关于快速排序算法(一个90%的人都不懂其原理、99.9%的人都不能正常写出来的算法.),布布扣,bubuko.com

时间: 2024-08-05 19:12:54

关于快速排序算法(一个90%的人都不懂其原理、99.9%的人都不能正常写出来的算法.)的相关文章

聪明人都在远离手机虚假繁荣的“人脉”关系

文丨杨奇函 听过这样一个段子:市政协会议散会,几个身价超十亿的老板去打牌,某超市连锁企业的老板同为身家过亿的政协委员,和他们一起开过几次会,也提出去一起玩.煤老板们面面相觑,最后还是首富张嘴说话了:“我们哥几个一起玩,是因为我们都有产业,你一个开小卖店的跟着我们凑什么热闹?”然后在凛冽的秋风中,超市企业老板悻悻地回家了. 我又想起来另一个故事.某哥经常炫耀他跟某女神关系多熟,讲述他们共事的点点滴滴,还把对方设置为特别好友,描述很是亲密.我们都感叹“哇噻,好牛的感觉”.只是我们从来没有见过此女神和

hadoop下实现kmeans算法——一个mapreduce的实现方法

写mapreduce程序实现kmeans算法,我们的思路可能是这样的 1. 用一个全局变量存放上一次迭代后的质心 2. map里,计算每个质心与样本之间的距离,得到与样本距离最短的质心,以这个质心作为key,样本作为value,输出 3. reduce里,输入的key是质心,value是其他的样本,这时重新计算聚类中心,将聚类中心put到一个全部变量t中. 4. 在main里比较前一次的质心和本次的质心是否发生变化,如果变化,则继续迭代,否则退出. 本文的思路基本上是按照上面的步骤来做的,只不过

一个项目的从创意到发布上线,需要多少人最合适?

有时候我在工作中嘲笑我们的项目牵扯了太多人.这个项目大约需要三个月,包括我和另一个程序员还有 20 – 30 个其他人可以算进来.由数不清的副总(VP)经过大约 6 个月的评审之后,所有的需求都定妥了,但变更还是不断出现. 最重要的是,它跟另一个团队的项目没什么区别(但是代码却不能重用),而那个项目已经快要发布了. 为什么要这么多人?为什么大公司要用大团队做出不那么大的东西,这真是个谜.我得出的结论是,你给一个项目投入的人越多,你就需要越多的人来管理这些人,再加上管理这些管理者的人,等等等等.“

生活中走得远的,都是自愈能力很强的人

就像冯仑说过:伟大,都是熬出来的.生活中走得远的,都是自愈能力很强的人. 1918年12月23日深夜,巴黎的某个街角,两辆马车轰然相撞,其中一辆车主随着车身一起翻覆,被压在沉重的钢铁支架下,口袋里滑落一串珍珠项链,刺眼地闪耀在血色中. 这个男人叫亚瑟·卡伯,是当时著名的贵族和工业家,几乎100年后,即便贵族的徽印被时光涤荡,他还有另一个知名的身份:可可·香奈儿的恋人和支持者. 他资助一名不文的香奈儿开办自己的帽子店,从他制作精良的男士服装中汲取灵感运用到女性衣饰,他请巴黎最炙手可热的歌剧演员带上

我们都需要时间,成为更好的人(转载)

我们都需要时间,成为更好的人 文/许中波 一个三卷本<平凡的世界>,从人物的童年走到壮年.暮年.悲欢离合着主角的故事,唏嘘感叹着读者的心情.如果从田润叶初和孙少安出场的情节起,任谁也无法料想到这个妙龄女子会接受以后残疾的丈夫并安之余生.每一本小说自始至终的读者既是观众,又是书中某个人物的灵魂再现--悸动着对方的悸动,苦难着对方的苦难.我们伴随人物前行的脚步,感受了甜蜜爱情的美好,祭奠了勇敢生命的早逝,体会了成长过程的辛酸.但故事终有一个结局,也许我们也一直在期待结局,不过当结局来临的一刻,在我

Java练习 份证号码组成规则是前4位是代表省份和地区 编写一个程序,通过身份证号码判断某人是否是武汉人以及其性别。

package com.swift; public class ID_Where_Male_Test { public static void main(String[] args) { /* * 中华人民共和国公民身份证号码组成规则是前4位是代表省份和地区(例如4201代表湖北省武汉市), * 第17位代表性别(奇数代表男性).编写一个程序,通过身份证号码判断某人是否是武汉人以及其性别. */ String str="420103199801010312"; if(str.subst

一个序列,除了一个数出现两次,其他数都出现一次,找出来重复的这个数-位运算应用(异或运算)

一个序列,除了一个数出现两次,其他数都出现一次,找出来重复的这个数-位运算应用 面试的题目 贴一下代码: 1 //位运算应用 2 #include<bits/stdc++.h> 3 using namespace std; 4 typedef long long ll; 5 const int maxn=1e5+10; 6 7 int n; 8 int a[maxn]; 9 10 void found(){ 11 int xors=0; 12 for(int i=0;i<n;i++){

【如何快速的开发一个完整的iOS直播app】(原理篇)

一.个人见解(直播难与易) 直播难:个人认为要想把直播从零开始做出来,绝对是牛逼中的牛逼,大牛中的大牛,因为直播中运用到的技术难点非常之多,视频/音频处理,图形处理,视频/音频压缩,CDN分发,即时通讯等技术,每一个技术都够你学几年的. 直播易:已经有各个领域的大牛,封装好了许多牛逼的框架,我们只需要用别人写好的框架,就能快速的搭建一个直播app,也就是传说中的站在大牛肩膀上编程. 二.了解直播 热门直播产品 映客,斗鱼,熊猫,虎牙,花椒等等 直播效果图 直播效果.jpeg 1.一个完整直播ap

算法改变世界——《算法之美——隐匿在数据结构背后的原理(C++版)》

所谓算法,就是隐匿在数据结构后背后的原理,在开发中好的算法可以降低时间复杂度提升可复用性.<算法之美--隐匿在数据结构背后的原理(C++版)>一书围绕算法与数据结构这个话题,用汉诺塔问题和八皇后问题等22个经典算法问题循序渐进.深入浅出地介绍了现代计算机技术中常用的45个经典算法.读后让人醍醐灌顶,茅塞顿开,并感觉相见恨晚. 这本书的第六章<递归--老和尚讲故事>写的很好,首先介绍了递归的概念,然后用汉诺塔问题,传染病问题和八皇后问题分别阐述并实践了递归的两种思想--分治和回溯.