本章介绍两种高级排序,希尔排序和快速排序,这两种排序比之前讲到的简单排序都要快很多;希尔排序大约需要O(N*(logN)2)的时间,快速排序的时间复杂度为(N*logN),这两种算法和我们在讲递归的时候讲到的归并排序不同,不需要大量的辅助存储空间,快速排序是所有通用排序算法中最快的排序算法。

希尔排序:

  希尔排序是基于插入排序的,希尔排序在插入排序的基础之上通过加大插入排序元素之间的间隔,并在这些间隔元素之间进行插入排序,使数据实现大跨度的移动,从而使排序更有效率,我们习惯将排序时数据项之间的间隔称为增量,用h来表示,下图表示了十个数据项,以增量为4进行第一趟排序后的结果

  通过上面的一趟排序之后我们可以看到元素离他们的最终有序序列位置都很近了,希尔排序就是通过创建这种交错有序的数据项集合,从而提高排序的效率,当上面完成了4增量的排序之后,就可以进行普通的插入排序,这样就比普通的插入排序的效率要高很多。

  上面对于有十个数据项的数组初始增量我们设置为4,对于数据项更大的数组我们的初始增量也应该设置得更大,这里我们使用Knuth提出的间隔序列,序列的通项表达式为h=3*h+1,假设我们数据项的个数为100,那么通过Knuth间隔序列1,4,13,40,121,364,1093这里1093大于了我们的数据项1000,所以我们取初始的增量为364然后通过Knuth间隔序列依次减小我们的增量值,最终达到我们想要的一个个排序的效果,接下来我们给出希尔排序的java代码

public class ArrayShell {

    public long[] theArray;
private int nElems; public ArrayShell(int size) {
this.theArray = new long[size];
this.nElems = 0;
} public void insert(long value) {
theArray[nElems++] = value;
} public void shellSort() {
//首先找到初始增量
int h = 1;
int outer, inner;
while (h <= nElems/3) {
h = 3 * h + 1;
}
while (h > 0) {
//以下就是普通的插入排序,只是步长换为h即可
for (outer = h; outer < nElems; outer++) {
long temp = theArray[outer];
//增量为h,所以我们首个比较的元素从h开始,h和第一个索引为0的元素比较大小、h+1和索引为1比较是否交换。然后以此类推
inner = outer;
while (inner > h - 1 && temp < theArray[inner - h]) { //需要进行数据交换的元素的满足条件
theArray[inner] = theArray[inner - h];
inner -= h;
}
theArray[inner] = temp;
}
//从最大增量一直递减到1做插入排序
h = (h - 1) / 3;
}
}
}

希尔排序中间隔序列互质很重要,他能是每一趟排序更有可能保持前一趟已排序好的效果。

快速排序

  快速排序是基于划分算法之上的一种排序算法,首先我们介绍一下划分算法的基本原理

  • 划分

  划分的基本原理就是把数据分为两组,使关键值大于特定值的数据在一组,使关键值小于特定值的数据在另一组,比如我们日常生活中将家距离办公点15km以内和以外的雇员分为两组。划分算法中我们将两个标记分别指向数组的两头,左边的标记leftPtr ,向右移动,右边的标记 rightPtr,向左移动,当leftPtr遇到比枢纽小的数据项时,继续向右移动,当遇到比枢纽大的数据项时就停下来,同样当rightPtr遇到比枢纽大的数值的时候继续向左移动,遇到比枢纽小的就停下来,然后需要交换这两个数据项。交换之后继续移动指针,重复上面的步骤,知道两个标记的值相等的时候则划分算法完成。

  接下来我们看划分算法的java代码

class ArrayPar {
public Long[] theArray;
private int nElems;
public ArrayPar(int max) {
theArray = new Long[max];
this.nElems = 0;
}
public void insert(Long value) {
theArray[nElems] = value;
nElems++;
}
public int partitionIt(int leftPtr, int rightPtr, long pivot) {
while (true) {
//当leftPtr遇到比枢纽小的数据项时,继续向右移动(即 leftPtr++),当遇到比枢纽大的数据项时就停下来
while (leftPtr < rightPtr && theArray[leftPtr] <= pivot) //防止索引越界加上leftPtr<rightPtr的判断
leftPtr++;
//当rightPtr遇到比枢纽大的数据项时,继续向左移动(即 rightPtr--),当遇到比枢纽大的数据项时就停下来
while (rightPtr > leftPtr && theArray[rightPtr] >= pivot)
rightPtr--;
//当leftPtr标记大于等于right标记的时候结束外层循环,否则交换两个标记的数据项
if (leftPtr >= rightPtr)
break;
else
swap(leftPtr, rightPtr);
}
return leftPtr;
}
/**交换数据方法*/
public void swap(int dex1, int dex2) {
long temp = theArray[dex1];
theArray[dex1] = theArray[dex2];
theArray[dex2] = temp;
}
}
  • 快速排序

  快速排序的执行时间为O(N*logN)级,快速排序是基于划分算法之上的,利用递归的思想的一种排序算法,这里我们选择数组的最右边的元素作为枢纽,在划分算法完成之后,需要在之前的算法的基础上加一步,将枢纽项和右数组的起始项进行位置交换,交换后的枢纽值的顺序就是最终的顺序,然后在利用递归将划分后的左右数组进行上述步骤。首先我们来看看快速排序的java代码

class ArrayPar {
public Long[] theArray;
private int nElems; public ArrayPar(int max) {
theArray = new Long[max];
this.nElems = 0;
} public void insert(Long value) {
theArray[nElems] = value;
nElems++;
} public int partitionIt(int leftPtr, int rightPtr, long pivot) {
int right = rightPtr;
while (true) {
//当leftPtr遇到比枢纽小的数据项时,继续向右移动(即 leftPtr++),当遇到比枢纽大的数据项时就停下来
while (leftPtr < rightPtr && theArray[leftPtr] <= pivot) //防止索引越界加上leftPtr<rightPtr的判断
leftPtr++;
//当rightPtr遇到比枢纽大的数据项时,继续向左移动(即 rightPtr--),当遇到比枢纽大的数据项时就停下来
while (rightPtr > leftPtr && theArray[rightPtr] >= pivot)
rightPtr--;
//当leftPtr标记大于等于right标记的时候结束外层循环,否则交换两个标记的数据项
if (leftPtr >= rightPtr)
break;
else
swap(leftPtr, rightPtr);
}
swap(leftPtr,right); //最后将当前枢纽数值放入对应的排序位置
return leftPtr;
} /**
* 交换数据方法
*/
public void swap(int dex1, int dex2) {
long temp = theArray[dex1];
theArray[dex1] = theArray[dex2];
theArray[dex2] = temp;
}
/***快速排序的方法*/
public void recQuickSort(int left, int right) {
if (right - left <= 0) //这里是递归的基值条件,当只有一个数据项的时候结束递归
return;
else {
long pivot = theArray[right]; //选择最右边的数据作为划分的枢纽数据
int partition = partitionIt(left, right, pivot); //调用划分的算法
//然后将划分好的两部分利用递归的思想进行再次划分排序
recQuickSort(left, partition - 1);
recQuickSort(partition + 1, right);
}
}
}

下图显示了快速排序的过程

上面就是希尔排序算法和快速排序算法的所有内容

JAVA算法之高级排序的更多相关文章

  1. 数据结构与算法之--高级排序:shell排序和快速排序

    高级排序比简单排序要快的多,简单排序的时间复杂度是O(N^2),希尔(shell)排序大约是O(N*(logN)^2),而快速排序是O(N*logN). 说明:下面以int数组的从小到大排序为例. 希 ...

  2. JAVA算法之简单排序

    冒泡排序: 在概念上是排序算法中最简单的,但是运行起来非常慢,冒泡排序遵循以下几个规则(假如我们现在要给一队打乱的足球队员排序): 比较两个队员 如果左边的队员比右边的高,则交换位置 向右移动一位,比 ...

  3. 数据结构和算法 – 11.高级排序算法(上)

      对现实中的排序问题,算法有七把利剑可以助你马道成功. 首先排序分为四种:       交换排序: 包括冒泡排序,快速排序.       选择排序: 包括直接选择排序,堆排序.       插入排序 ...

  4. [Java算法] -- 1. 常用排序之冒泡排序和选择排序

    使用Java语言实现冒泡排序和选择排序 推荐一个数据结构可视化的网站:http://zh.visualgo.net/zh (暂时访问不了) 对排序不太熟悉的朋友,建议去上面的网站学习一下,你将会发现一 ...

  5. 数据结构和算法 – 11.高级排序算法(下)

    三.选择类排序 3.1.简单选择排序 http://www.cnblogs.com/tangge/p/5338734.html#XuanZe 3.2 堆排序 要知道堆排序,首先要了解一下二叉树的模型. ...

  6. Java算法简介及排序剖析

    本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 从小白晋升,一路走来:从helloworld,到JFrame,再到Android:从城外小子,到内城 ...

  7. JAVA算法系列 冒泡排序

    java算法系列之排序 手写冒泡 冒泡算是最基础的一个排序算法,简单的可以理解为,每一趟都拿i与i+1进行比较,两个for循环,时间复杂度为 O(n^2),同时本例与选择排序进行了比较,选择排序又叫直 ...

  8. JAVA算法系列 快速排序

    java算法系列之排序 手写快排 首先说一下什么是快排,比冒泡效率要高,快排的基本思路是首先找到一个基准元素,比如数组中最左边的那个位置,作为基准元素key,之后在最左边和最右边设立两个哨兵,i 和 ...

  9. Java数据结构和算法(九)——高级排序

    春晚好看吗?不存在的!!! 在Java数据结构和算法(三)——冒泡.选择.插入排序算法中我们介绍了三种简单的排序算法,它们的时间复杂度大O表示法都是O(N2),如果数据量少,我们还能忍受,但是数据量大 ...

随机推荐

  1. mysql创建新用户并且授权远程访问

    1 修改root用户的密码 linux安装了mysql后,默认情况下,如果是root用户,不需要密码就可以登陆. mysql -u root -p 然后回车就可以登陆了,如果是普通用户,不能登陆. 2 ...

  2. ros机器人导航设置原点,目标点

    之前利用movebase导航定位都是通过rviz用鼠标指来指去,实验时非常方便,但实际应用总不能也人工指来指去吧,这怎么体现智能呢 启动导航后,用以前使用的rviz设设置目标点来获取map坐标系下的位 ...

  3. http11.Http11OutputBuffer.SocketOutputBuffer.doWrite

    这是一个错误. 我在spring框架中,创建了一个基类SuperBaseController, 并且使用了@ModelAttribute用来给HttpServletRequest和HttpServle ...

  4. vue中使用axios与axios的请求响应拦截

    VUE中使用Axios axios的安装 npm install axios vue-axios axios在vue的配置与使用 在main.js中引入axios和vue-axios import a ...

  5. CF 848E(动态规划+分治NTT)

    传送门: http://codeforces.com/problemset/problem/848/E 题解: 假设0-n一定有一条边,我们得到了一个方案,那么显然是可以旋转得到其他方案的. 记最大的 ...

  6. 在Panel上绘图的实现

    近期制作了FDS的一个建模工具,由于知识有限,做出的效果是2D的.昨天上课的时候看老师画一个长方体,突然想到,为什么不给普通的2D图形加画上几条直线,就能实现2D图形的3D视觉效果呢?于是回来马上做了 ...

  7. 2019年12月12日英语学习-Will I Or Won't I ?

    这节英语课上的内容没记住多少东西,觉得这个主题太枯燥了,不过整堂课和外教沟通交流还是不错的,因为这节课就我一个学生.给我了充分的机会去张嘴交流互动. 也没记住什么东西,不知道写什么.只记住将要决定做某 ...

  8. NX二次开发-UFUN工程图更新视图UF_DRAW_update_one_view

    NX9+VS2012 #include <uf.h> #include <uf_draw.h> #include <uf_obj.h> #include <u ...

  9. AtCoder ARC061E Snuke's Subway Trip 最短路

    目录 Catalog Solution: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 Catalog Problem:传送门  Portal  原题目描述在最下面.  \(n(1 ...

  10. ionic:temple

    ylbtech-ionic:temple 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部     6.返回顶部   作者:ylbtech出处:http://ylb ...