高速排序——JAVA实现(图文并茂)
高快省的排序算法
有没有既不浪费空间又能够快一点的排序算法呢?那就是“高速排序”啦!
光听这个名字是不是就认为非常高端呢。
如果我们如今对“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
高速排序——JAVA实现(图文并茂)的更多相关文章
- 高速排序java语言实现
本博客不再更新,很多其它精彩内容请訪问我的独立博客 高速排序是非常重要的排序算法,可是我在学的时候发现网上没有特别好的样例所以自己动手写了一个. 自己动手丰衣足食. package sort; imp ...
- java:高速排序算法与冒泡排序算法
Java:高速排序算法与冒泡算法 首先看下,冒泡排序算法与高速排序算法的效率: 例如以下的是main方法: /** * * @Description: * @author:cuiyaon ...
- 高速排序(Java版)
package com.love.test; import java.util.Scanner; /** * @author huowolf *高速排序实现 *快排是十分优秀的排序算法. *核心:分治 ...
- 排序算法之高速排序(Java)
//高速排序 public class Quick_Sort { // 排序的主要算法 private int Partition(int[] data, int start, int end) { ...
- 高速排序及优化(Java版)
高速排序(Quicksort)是对冒泡排序的一种改进. 高速排序由C. A. R. Hoare在1962年提出. 一次高速排序具体过程: 选择数组第一个值作为枢轴值. 代码实现: package Qu ...
- 插入排序、冒泡排序、选择排序、希尔排序、高速排序、归并排序、堆排序和LST基数排序——C++实现
首先是算法实现文件Sort.h.代码例如以下: <pre name="code" class="java">/* * 实现了八个经常使用的排序算法: ...
- 希尔排序及希尔排序java代码
原文链接:http://www.orlion.ga/193/ 由上图可看到希尔排序先约定一个间隔(图中是4),然后对0.4.8这个三个位置的数据进行插入排序,然后向右移一位对位置1.5.9进行插入排序 ...
- 排序(5)---------高速排序(C语言实现)
继shell发明了shell排序过后呢,各位计算机界的大牛们又開始不爽了,为什么他能发明.我就不能发明呢.于是又有个哥们蹦出来了.哎...那么多排序,就木有一个排序是中国人发明的.顺便吐槽一下,一百年 ...
- 高速排序-c++(分别用数组和容器实现)
/********************************************************************** *版权全部 (C)2014, cheng yang. * ...
随机推荐
- eclipse软件快捷键的使用
[Ct rl+T] 搜索当前接口的实现类 1. [ALT +/] 此快捷键为用户编辑的好帮手,能为用户提供内容的辅助,不要为记不全方法和属性名称犯愁,当记不全类.方法和属性的名字时,多体验一下[ ...
- 使用sshfs来挂载远程的文件
只要安装sshfs就可以通过ssh的端口来远程挂载文件夹, 不需要其他额外的配置非常的方便. 这个软件在只有ssh权限的情况下远程范围文件是非常有用的. 1. 安装sshfs 2. 用法非常简单 ...
- SVN在vs2013中使用
http://download.csdn.net/download/show_594/9112963 内包含VisualSVN 5.0.1的官方原版安装包及破解文件VisualSVN.Core.L.d ...
- Spring MVC 核心架构图
架构图对应的DispatcherServlet核心代码如下: //前端控制器分派方法 protected void doDispatch(HttpServletRequest request, Htt ...
- codeforces 400 D Dima and Bacteria【并查集 Floyd】
题意:给出n个点,分别属于k个集合,判断每个集合里面的点的距离都为0,为0的话输出yes,并输出任意两个集合之间的最短路 这道题目有两个地方不会处理, 先是n个点,分别属于k个集合,该怎么记录下来这里 ...
- SSD-实现
一.制作voc数据集 1.数据集文件夹 新建一个文件夹,用来存放整个数据集,或者和voc2007一样的名字:VOC2007 然后像voc2007一样,在文件夹里面新建如下文件夹: 2.将训练图片放到J ...
- [USACO08DEC]拍头Patting Heads 水题
类似素数筛,暴力可过,不需要太多的优化 Code: #include<cstdio> #include<algorithm> #include<string> us ...
- 昼猫笔记 JavaScript -- 异步执行 | 定时器真的定时执行?
本篇主要内容:异步.定时器引发的思考 预计阅读时间:8分钟 了解 我们都知道在js中定时器有两种 setInterval() . setTimeout() setInterval() :按 ...
- 记intel杯比赛中各种bug与debug【其五】:朴素贝叶斯分类器的实现和针对性的优化
咱这个项目最主要的就是这个了 贝叶斯分类器用于做可以统计概率的二元分类 典型的例子就是垃圾邮件过滤 理论基础 对于贝叶斯算法,这里附上两个链接,便于理解: 朴素贝叶斯分类器的应用-阮一峰的网络日志 基 ...
- shell脚本不同运行方式的差异
说明:以下是个人的见解,不一定都正确,如有错误,欢迎指正! 一,shell脚本的运行方式,最常见的有以下几种: 1 ) . xxx.sh,注意,前面是一个点'.' 2 ) source xxx.sh ...