JAVA算法之高级排序

本章介绍两种高级排序,希尔排序和快速排序,这两种排序比之前讲到的简单排序都要快很多;希尔排序大约需要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

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

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);

}

}

}

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

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

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

推荐阅读更多精彩内容

  • 数据结构 Java中的数组有差不多一样的语法。只是java中处理8种基本类型,数组也是作为对象处理的,所以创建对...
    赵宇_阿特奇阅读 702评论 0 0
  • 【程序1】 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔...
    开心的锣鼓阅读 3,307评论 0 9
  • 已经用了很久了,效果还是挺明显的,痘痘都淡化了,现在感觉皮肤变好多了,痘印很明显的在变淡,有些小的痘印已经消失了。
    大大手掌阅读 424评论 0 0
  • “完治着急的四处寻找,想起莉香一直想到自己的故乡爱媛县,便匆匆赶回去,最后在学校的柱子上,发现自己从前刻的名字旁...
    45度向阳阅读 1,033评论 0 3
  • 我现在怀了孕,根本没有办法照顾潼曦。再说我婆婆那里也不好交代。 孩子又不是我一个人的,难道要我一个人拉扯吗? 林大...
    漫花灿烂时阅读 362评论 0 0