高快省的排序算法

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

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

如果我们如今对“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. Web端本地存储

    1.需求背景:当用户在页面上添加一行一行的数据时,突然发现网络断掉了,页面上编辑的数据没法保存进数据库,所以需要一个本地端的临时保存功能,以便在网络通畅后重新加载出来! 2.解决方案: 结合网上搜刮, ...

  2. bzoj2438: [中山市选2011]杀人游戏(强联通+特判)

    2438: [中山市选2011]杀人游戏 题目:传送门 简要题意: 给出n个点,m条有向边,进行最少的访问并且可以便利(n-1)个点,求这个方案成功的概率 题解: 一道非常好的题目! 题目要知道最大的 ...

  3. Windows PE 工具

    通过大白菜.老毛桃等装机软件,然后制作 U 盘启动工具, 1. 什么是 windows pe 工具 PE(Preinstall Environment),Win pe 全称 Windows Prein ...

  4. Objects are mutable

    We can change the state of an object by making an assignment to one of its attributes. For example, ...

  5. java 通过httpclient调用https 的webapi

    java如何通过httpclient 调用采用https方式的webapi?如何验证证书.示例:https://devdata.osisoft.com/p...需要通过httpclient调用该接口, ...

  6. springMVC学习笔记_转载(一)-----springMVC原理

    阅读目录 一.什么是springmvc 二.mvc在b/s系统下的应用 三.SpringMVC框架介绍 回到顶部 一.什么是springmvc springMVC是spring框架的一个模块,spri ...

  7. Linux防火墙iptables介绍

    介绍网络防火墙是通过一个或多个允许或拒绝的规则来过滤网络流量的网络设备或软件.网络防火墙还可以执行更复杂的任务,例如网络地址转换,带宽调整,提供加密隧道以及更多与网络流量相关的任务.而我们的任务就是需 ...

  8. python的模块导入机制

    在python中用import或者from...import来导入相应的模块. 模块(Module)其实就是一些函数和类的集合文件,它能实现一些相应的功能,当我们需要使用这些功能的时候,直接把相应的模 ...

  9. apache(XAMPP)禁止IP访问的httpd-vhosts.conf设置

    httpd-vhosts.conf <virtualhost *:80> ServerName 123.123.123.123   ServerAlias 123.123.123.123  ...

  10. NOIP2017 Day-1 模板荟萃

    #include<bits/stdc++.h> #define MAXN 100005 using namespace std; int read(){ ;char c=getchar() ...