排序算法系列(2)——快速排序

前几天被一哥们儿实力嘲讽,问我快速排序怎么实现,我只是记得自己学过,但是忘记了具体怎么实现,原理是什么ORZ,然后LL就努力去百度学习,汲取,大致将一些自己的感受:

注意!文档只是以我的想法来进行阐述,只是尽量以我能理解的方式来解释算法原理,只是为了将来上了年纪,或者忘记了这个原理的时候来学习一下。

废话不多说,套用之前那哥们讲话,冒泡是最简单的排序方法
那么接下来
讲一下快速排序

情景拟定:

一个数组array,需要将其从由小到大的顺序排列
array = { 4 , 5 , 2 , 22 , 11 , 32 , 2 , 5 }
快速排序原理是这样子的:

分治的原理:

首先选定一个元素a,然后将这个数组中比这个元素小的元素们放到该元素的左边,将数组中比这个元素大的元素放到该元素的右边。 至此a元素的位置已经排好了,剩下的就是由a将数组划成两半进行排序

每一半排序方式同上。
这样子最后肯定能排好序
明显能够看出这是**递归**的思想

然后问题来了,首先怎么具体的将a放到他应该的位置?
是这样子的
/(比较方便,确保了只是将除了该a之外的其余数字只比较一遍)→往下看就能理解我这句话了/

首先我们需要给这个数组定义一个首、尾index,比如 i=0,j=array.length-1=7;
假定我们需要排的元素 a=array[0]=4
那么首先我们从array[j]处向前遍历比较
array[7]=5>4 正常 j--
array[6]=2<4 应该在4左边,所以将array[0]=2
此时 j = 6 ;
array现在是这样子的 array = {2 , 5 , 2 , 22 , 11 , 32 , 空 ,5}

那么现在array[6] (也就是array[j]) 空出来了

我们这时候应该看一下i往后了
array[0] < a 正常 i++
array[1] = 5 > a 不对哦 比4大应该在右边
所以将5放到刚才上面缺的地方
array[j] = 5
那么现在是array = {2,空,2,22,11,32,5,5}
i = 1
现在array[1] 也就是array[i] 空了

接下来接着从j的位置向前
array[6] = 5 < 4 okay j--
array[5] = 32 >4 okay j--
array[4] = 11 > 4 okay j--
array[3] = 22 > 4 okay j--
array[2] = 2 < 4 换换换
array[i] = array[1] = 2
那么现在 j 为2了,
array = {2,2,空,22,11,32,5,5}

再从i开始
i=1
array[i] = 2 < 4 okay i++
此时 i=2=j 交头了说明over了
那么将刚才最开始的a 放到array[i] or array[j]位置上就好了 (反正 i 和 j 相等了)
array = {2,2,4,22,11,32,5,5}

那么接下来需要对array的两个子串
array1={2,2}
array2={22,11,32,5,5}
然后对子串进行像刚才那样的顺序排序

package quickSort;
import java.util.Arrays;
/**
 * 递归实现快速排序
 * @author mengf
 *
 */
public class Qsort {
    
    public static int[] quickSort(int[] array,int start , int end){
        int i = start;
        int j = end;
        int a = array[i];
        
        //好的情况
        while (i!=j&&i<j) {
            
            while (j!=i) {
                if (array[j]<a) {
                    array[i]=array[j];
                    i++;
                    break;
                }else{
                    j--;
                }
            }
            
            while (j!=i) {
                if (array[i]>a) {
                    array[j]=array[i];
                    j--;
                    break;
                }else{
                    i++;
                }
            }
        }
        
        //然后最后i=j
        array[i]=a;
        //分成两半
        if (i>start) {
            quickSort(array, start, i-1);
        }
        if (i<end) {
            quickSort(array, i+1, end);
        }
        return array;
    }
    
    public static void main(String[] args) {
        int[] array = {12,10,22,5,6,8,11,7,3,4,5,33,32,23,34,32,43,34};
        quickSort(array, 0, array.length-1);
        System.out.println(Arrays.toString(array));
    }
}

所以不难看出如果要实现递归实现是很好理解的
注:如果有大神看到这里肯定会觉得我上面写的有些问题
我承认我顺着思路写完之后其实有地方需要改进的
!就是需要替换的时候,比如j往前跟4对比,遇到需要替换的时候,将array[i]替换之后,可以将i++
因为替换到i位置上肯定已经满足这个数字<4 所以将i++之后
从i这边开始的时候就不需要重新再将刚替换的位置的数字和a再比较了。

下面开始看一下递归的java代码实现:

然后后来百度了一下百科是这样写的,原理是一样的

package quickSort;
import java.util.Arrays;
public class QuickSort {
    
    
    /**
     * 无边界检查 
     * 完全专注于算法
     * @param arrays
     * @param start
     * @param end
     * @return
     */
    public int[] quickSort(int[] arrays,int low,int high){
        int start = low;
        int end = high;
        //只有一个元素的时候是排好序的了
        if (start==end) {
            return arrays;
        }
        
        //算法开始
        int temp = arrays[start];
        
        while (start<end) {
            
            while (start<end && arrays[end]>=temp) {
                end--;
            }
            arrays[start]=arrays[end];
            while (start<end && arrays[start]<=temp) {
                start++;
            }
            arrays[end]=arrays[start];
        }
        
        //start = end
        arrays[start]=temp;
        //迭代两边排序
        if (start>low) {
            quickSort(arrays, 0, start-1);
        }
        if (end<high) {
            quickSort(arrays,start+1,arrays.length-1);
        }
        
        return arrays;
    }
    public static void main(String[] args) {
        QuickSort quickSort = new QuickSort();
        int[] arrays = {1,11,35,2,3,5,323,213,22,3,1,2,3,4,5,3};
        quickSort.quickSort(arrays, 0, arrays.length-1);
        System.out.println(Arrays.toString(arrays));
    }
}

臭美一下,我觉得这个大概就是我之前没有在换位置之后将对应的位置的 i++或者 j-- 这样感觉会多一次判断,虽然对算法复杂度没有影响。
再就是如果加上了的话这个写法比我写的好多了,判断写在while里面
而我的是while中又有if,感觉效率没有这个高。

算法复杂度: O(n*logn)

但是写到这里,我有问题了
递归对伐,大家都知道浪费空间的做法,但是递归对于程序的理解有着极大的帮助,而且我记得数据结构老师说过,所有的递归都能改为循环的,这就是对于这个问题的下一步探讨了,我先学习下,等搞懂了再搞一篇优化后的快速排序。

现在说说我觉得这样的<u>局限</u>在哪里:

如果排序对象较大,数目较多,内存可能不够,虽然很少有出现这种情况,但是如果能够改成循环,而放弃递归
无疑是对能力的提升,像我这种懒人还是觉得递归好,起码理解起来简单,至于循环,最近看情况找找资料学学,要是没有下一篇了的话,可能LL已经忘记这件事情了,大家可以先用着递归,毕竟现在普通项目中也不太可能遇到占用很大内存来递归的情况。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,719评论 0 33
  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    蚁前阅读 5,159评论 0 52
  • 概述:排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    每天刷两次牙阅读 3,726评论 0 15
  • 某次二面时,面试官问起Js排序问题,吾绞尽脑汁回答了几种,深感算法有很大的问题,所以总计一下! 排序算法说明 (1...
    流浪的先知阅读 1,186评论 0 4
  • 每日推荐: 每日一歌――许巍《我们》 每日一影――彭浩翔《人间小团圆》 每日一诗――王翰《凉州词》 葡萄美酒夜...
    萨拉芯雪阅读 171评论 0 0