高快省的排序算法

有没有既不浪费空间又能够快一点的排序算法呢?那就是“高速排序”啦!

光听这个名字是不是就认为非常高端呢。

如果我们如今对“6 1 2 7 9 3 4 5 10 8”这个10个数进行排序。

首先在这个序列中随便找一个数作为基准数(不要被这个名词吓到了,就是一个用来參照的数,待会你就知道它用来做啥的了)。为了方便,就让第一个数6作为基准数吧。接下来,须要将这个序列中所有比基准数大的数放在6的右边,比基准数小的数放在6的左边,相似以下这种排列:

3 1 2 5 4 6 9 7 10 8

在初始状态下。数字6在序列的第1位。我们的目标是将6挪到序列中间的某个位置,如果这个位置是k。如今就须要寻找这个k。而且以第k位为分界点,左边的数都小于等于6。右边的数都大于等于6。

想一想。你有办法能够做到这点吗?

排序算法显神威

方法事实上非常easy:分别从初始序列“6 1 2 7 9 3 4 5 10 8”两端開始“探測”。先从找一个小于6的数,再从找一个大于6的数,然后交换他们。这里能够用两个变量i和j。分别指向序列最左边和最右边。

我们为这两个变量起个好听的名字“哨兵i”和“哨兵j”。

刚開始的时候让哨兵i指向序列的最左边(即i=1)。指向数字6。

让哨兵j指向序列的最右边(即=10),指向数字。



首先哨兵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碰头为止。

OK,解释完成。如今基准数6已经归位。它正优点在序列的第6位。此时我们已经将原来的序列,以6为分界点拆分成了两个序列,左边的序列是“3 1 2 5 4”。右边的序列是“9 7 10 8”。接下来还须要分别处理这两个序列。由于6左边和右边的序列眼下都还是非常混乱的。

只是不要紧,我们已经掌握了方法,接下来仅仅要模拟刚才的方法分别处理6左边和右边的序列就可以。如今先来处理6左边的序列现吧。

左边的序列是“3 1 2 5 4”。

请将这个序列以3为基准数进行调整,使得3左边的数都小于等于3,3右边的数都大于等于3。

好了開始动笔吧

如果你模拟的没有错,调整完成之后的序列的顺序应该是:

2 1 3 5 4

OK。如今3已经归位。接下来须要处理3左边的序列“2 1”和右边的序列“5 4”。对序列“2 1”以2为基准数进行调整,处理完成之后的序列为“1 2”。到此2已经归位。

序列“1”仅仅有一个数,也不须要进行不论什么处理。至此我们对序列“2 1”已所有处理完成,得到序列是“1 2”。序列“5 4”的处理也仿照此方法,最后得到的序列例如以下:

1 2 3 4 5 6 9 7 10 8

对于序列“9 7 10 8”也模拟刚才的过程。直到不可拆分出新的子序列为止。终于将会得到这种序列,例如以下

1 2 3 4 5 6 7 8 9 10

到此。排序全然结束。

细心的同学可能已经发现。高速排序的每一轮处理事实上就是将这一轮的基准数归位,直到所有的数都归位为止。排序就结束了。

以下上个霸气的图来描写叙述下整个算法的处理过程。

这是为什么呢?

高速排序之所比較快。由于相比冒泡排序,每次交换是跳跃式的。每次排序的时候设置一个基准点,将小于等于基准点的数所有放到基准点的左边。将大于等于基准点的数所有放到基准点的右边。这样在每次交换的时候就不会像冒泡排序一样每次仅仅能在相邻的数之间进行交换,交换的距离就大的多了。因此总的比較和交换次数就少了。速度自然就提高了。当然在最坏的情况下,仍可能是相邻的两个数进行了交换。

因此高速排序的最差时间复杂度和冒泡排序是一样的都是O(N2),它的平均时间复杂度为O(NlogN)。事实上高速排序是基于一种叫做“二分”的思想。我们后面还会遇到“二分”思想,到时候再聊。

先上代码,例如以下

代码实现:

public class QuickSort {
public static void quickSort(int[] arr,int low,int high){
int i,j,temp,t;
if(low>high){
return;
}
i=low;
j=high;
//temp就是基准位
temp = arr[low]; while (i<j) {
//先看右边,依次往左递减
while (temp<=arr[j]&&i<j) {
j--;
}
//再看左边,依次往右递增
while (temp>=arr[i]&&i<j) {
i++;
}
//如果满足条件则交换
if (i<j) {
t = arr[j];
arr[j] = arr[i];
arr[i] = t;
} }
//最后将基准为与i和j相等位置的数字交换
arr[low] = arr[i];
arr[i] = temp;
//递归调用左半数组
quickSort(arr, low, j-1);
//递归调用右半数组
quickSort(arr, j+1, high);
} public static void main(String[] args){
int[] arr = {10,7,2,4,7,62,3,4,2,1,8,9,19};
quickSort(arr, 0, arr.length-1);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
输出为
1
2
2
3
4
4
7
7
8
9
10
19
62

原文地址:http://developer.51cto.com/art/201403/430986.htm

高速排序——JAVA实现(图文并茂)的更多相关文章

  1. 高速排序java语言实现

    本博客不再更新,很多其它精彩内容请訪问我的独立博客 高速排序是非常重要的排序算法,可是我在学的时候发现网上没有特别好的样例所以自己动手写了一个. 自己动手丰衣足食. package sort; imp ...

  2. java:高速排序算法与冒泡排序算法

     Java:高速排序算法与冒泡算法 首先看下,冒泡排序算法与高速排序算法的效率: 例如以下的是main方法: /**   *  * @Description:  * @author:cuiyaon ...

  3. 高速排序(Java版)

    package com.love.test; import java.util.Scanner; /** * @author huowolf *高速排序实现 *快排是十分优秀的排序算法. *核心:分治 ...

  4. 排序算法之高速排序(Java)

    //高速排序 public class Quick_Sort { // 排序的主要算法 private int Partition(int[] data, int start, int end) { ...

  5. 高速排序及优化(Java版)

    高速排序(Quicksort)是对冒泡排序的一种改进. 高速排序由C. A. R. Hoare在1962年提出. 一次高速排序具体过程: 选择数组第一个值作为枢轴值. 代码实现: package Qu ...

  6. 插入排序、冒泡排序、选择排序、希尔排序、高速排序、归并排序、堆排序和LST基数排序——C++实现

    首先是算法实现文件Sort.h.代码例如以下: <pre name="code" class="java">/* * 实现了八个经常使用的排序算法: ...

  7. 希尔排序及希尔排序java代码

    原文链接:http://www.orlion.ga/193/ 由上图可看到希尔排序先约定一个间隔(图中是4),然后对0.4.8这个三个位置的数据进行插入排序,然后向右移一位对位置1.5.9进行插入排序 ...

  8. 排序(5)---------高速排序(C语言实现)

    继shell发明了shell排序过后呢,各位计算机界的大牛们又開始不爽了,为什么他能发明.我就不能发明呢.于是又有个哥们蹦出来了.哎...那么多排序,就木有一个排序是中国人发明的.顺便吐槽一下,一百年 ...

  9. 高速排序-c++(分别用数组和容器实现)

    /********************************************************************** *版权全部 (C)2014, cheng yang. * ...

随机推荐

  1. html5播放m3u8视频,web端看直播

    https://github.com/jiqing9006/hLive <!DOCTYPE html> <html> <head> <meta charset ...

  2. 13.MongoDB 连接命令格式

    转自:https://www.linuxidc.com/Linux/2016-03/129456.htm 使用用户 admin 使用密码 123456 连接到本地的 MongoDB 服务上.输出结果如 ...

  3. hdu1978 How many ways

    How many ways Problem Description 这是一个简单的生存游戏,你控制一个机器人从一个棋盘的起始点(1,1)走到棋盘的终点(n,m).游戏的规则描述如下: 机器人一开始在棋 ...

  4. POJ 3190 priority_queue 贪心

    思路: 贪心?就算是吧 先把所有的开始时间排个序 如果当前的能匹配上已有的牛栏,就找开始时间最早的那个. 否则新加一个牛栏 整个过程用priority_queue实现就OK了.. //By Siriu ...

  5. Metasploit渗透测试实验报告

    Metasploit渗透测试实验报告

  6. HBase的体系结构

  7. kotlin官方文档-1.0入门

    什么是Kotlin?   图片发自简书App Kotlin是JetBrains开发的基于JVM的语言,JetBrains想必大家应该很熟悉了,他们创造了很多强大的IDE,android studio谷 ...

  8. 使用ShareSDK分享-图片的链接

    微信中使用ShareSDK分享,需要申请微信开放平台账号,并且以微信中的声明的应用签名打包程序. private void showShare(String url, String title, St ...

  9. bzoj 3408 热浪 最短路

    一道最短路的模板题,就当练习一下SPFA和dijkstra了 SPFA #include<bits/stdc++.h> using namespace std; struct edge{ ...

  10. Lenovo k860i 移植Android 4.4 cm11进度记录【下篇--实时更新中】

    2014.8.24 k860i的cm11的移植在中断了近两三个月之后又开始继续了,进度记录的日志上一篇已经没什么写的了,就完结掉它吧,重新开一篇日志做下篇好了.最近的战况是,在scue同学的努力之下, ...