`
wengge
  • 浏览: 38780 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

排序算法: 归并排序,堆排序,桶式排序,基数排序

阅读更多

六 归并排序
算法思想是每次把待排序列分成两部分,分别对这两部分递归地用归并排序,完成后把这两个子部分合并成一个
序列。
归并排序借助一个全局性临时数组来方便对子序列的归并,该算法核心在于归并。

package algorithms;

import java.lang.reflect.Array;

/**
*
@author yovn
*
*/
public class MergeSorter<E extends Comparable<E>> extends Sorter<E> {

/* (non-Javadoc)
* @see algorithms.Sorter#sort(E[], int, int)
*/
@SuppressWarnings(
"unchecked")
@Override
public void sort(E[] array, int from, int len) {
if(len<=1)return;
E[] temporary
=(E[])Array.newInstance(array[0].getClass(),len);
merge_sort(array,from,from
+len-1,temporary);

}

private final void merge_sort(E[] array, int from, int to, E[] temporary) {
if(to<=from)
{
return;
}
int middle=(from+to)/2;
merge_sort(array,from,middle,temporary);
merge_sort(array,middle
+1,to,temporary);
merge(array,from,to,middle,temporary);
}

private final void merge(E[] array, int from, int to, int middle, E[] temporary) {
int k=0,leftIndex=0,rightIndex=to-from;
System.arraycopy(array, from, temporary,
0, middle-from+1);
for(int i=0;i<to-middle;i++)
{
temporary[to
-from-i]=array[middle+i+1];
}
while(k<to-from+1)
{
if(temporary[leftIndex].compareTo(temporary[rightIndex])<0)
{
array[k
+from]=temporary[leftIndex++];

}
else
{
array[k
+from]=temporary[rightIndex--];
}
k
++;
}

}

}

七 堆排序
堆是一种完全二叉树,一般使用数组来实现。
堆主要有两种核心操作,
1)从指定节点向上调整(shiftUp)
2)从指定节点向下调整(shiftDown)
建堆,以及删除堆定节点使用shiftDwon,而在插入节点时一般结合两种操作一起使用。
堆排序借助最大值堆来实现,第i次从堆顶移除最大值放到数组的倒数第i个位置,然后shiftDown到倒数第i+1个位置,一共执行N此调整,即完成排序。
显然,堆排序也是一种选择性的排序,每次选择第i大的元素。

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->package algorithms;

/**
*
@author yovn
*
*/
public class HeapSorter<E extends Comparable<E>> extends Sorter<E> {

/* (non-Javadoc)
* @see algorithms.Sorter#sort(E[], int, int)
*/
@Override
public void sort(E[] array, int from, int len) {
build_heap(array,from,len);

for(int i=0;i<len;i++)
{
//swap max value to the (len-i)-th position
swap(array,from,from+len-1-i);
shift_down(array,from,len
-1-i,0);//always shiftDown from 0
}
}

private final void build_heap(E[] array, int from, int len) {
int pos=(len-1)/2;//we start from (len-1)/2, because branch's node +1=leaf's node, and all leaf node is already a heap
for(int i=pos;i>=0;i--)
{
shift_down(array,from,len,i);
}

}

private final void shift_down(E[] array,int from, int len, int pos)
{

E tmp
=array[from+pos];
int index=pos*2+1;//use left child
while(index<len)//until no child
{
if(index+1<len&&array[from+index].compareTo(array[from+index+1])<0)//right child is bigger
{
index
+=1;//switch to right child
}
if(tmp.compareTo(array[from+index])<0)
{
array[from
+pos]=array[from+index];
pos
=index;
index
=pos*2+1;

}
else
{
break;
}

}
array[from
+pos]=tmp;

}


}


八 桶式排序
桶式排序不再是基于比较的了,它和基数排序同属于分配类的排序,这类排序的特点是事先要知道待排序列的一些特征。
桶式排序事先要知道待排序列在一个范围内,而且这个范围应该不是很大的。
比如知道待排序列在[0,M)内,那么可以分配M个桶,第I个桶记录I的出现情况,最后根据每个桶收到的位置信息把数据输出成有序的形式。
这里我们用两个临时性数组,一个用于记录位置信息,一个用于方便输出数据成有序方式,另外我们假设数据落在0到MAX,如果所给数据不是从0开始,你可以把每个数减去最小的数。

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->package algorithms;

/**
*
@author yovn
*
*/
public class BucketSorter {



public void sort(int[] keys,int from,int len,int max)
{
int[] temp=new int[len];
int[] count=new int[max];


for(int i=0;i<len;i++)
{
count[keys[from
+i]]++;
}
//calculate position info
for(int i=1;i<max;i++)
{
count[i]
=count[i]+count[i-1];//this means how many number which is less or equals than i,thus it is also position + 1
}

System.arraycopy(keys, from, temp,
0, len);
for(int k=len-1;k>=0;k--)//from the ending to beginning can keep the stability
{
keys[
--count[temp[k]]]=temp[k];// position +1 =count
}
}
/**
*
@param args
*/
public static void main(String[] args) {

int[] a={1,4,8,3,2,9,5,0,7,6,9,10,9,13,14,15,11,12,17,16};
BucketSorter sorter
=new BucketSorter();
sorter.sort(a,
0,a.length,20);//actually is 18, but 20 will also work


for(int i=0;i<a.length;i++)
{
System.out.print(a[i]
+",");
}

}

}


九 基数排序
基数排序可以说是扩展了的桶式排序,比如当待排序列在一个很大的范围内,比如0到999999内,那么用桶式排序是很浪费空间的。而基数排序把每个排序码拆成由d个排序码,比如任何一个6位数(不满六位前面补0)拆成6个排序码,分别是个位的,十位的,百位的。。。。
排序时,分6次完成,每次按第i个排序码来排。
一般有两种方式:
1) 高位优先(MSD): 从高位到低位依次对序列排序
2)低位优先(LSD): 从低位到高位依次对序列排序
计算机一般采用低位优先法(人类一般使用高位优先),但是采用低位优先时要确保排序算法的稳定性。
基数排序借助桶式排序,每次按第N位排序时,采用桶式排序。对于如何安排每次落入同一个桶中的数据有两种安排方法:
1)顺序存储:每次使用桶式排序,放入r个桶中,,相同时增加计数。
2)链式存储:每个桶通过一个静态队列来跟踪。

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->package algorithms;

import java.util.Arrays;


/**
*
@author yovn
*
*/
public class RadixSorter {

public static boolean USE_LINK=true;

/**
*
*
@param keys
*
@param from
*
@param len
*
@param radix key's radix
*
@param d how many sub keys should one key divide to
*/
public void sort(int[] keys,int from ,int len,int radix, int d)
{
if(USE_LINK)
{
link_radix_sort(keys,from,len,radix,d);
}
else
{
array_radix_sort(keys,from,len,radix,d);
}

}


private final void array_radix_sort(int[] keys, int from, int len, int radix,
int d)
{
int[] temporary=new int[len];
int[] count=new int[radix];
int R=1;

for(int i=0;i<d;i++)
{
System.arraycopy(keys, from, temporary,
0, len);
Arrays.fill(count,
0);
for(int k=0;k<len;k++)
{
int subkey=(temporary[k]/R)%radix;
count[subkey]
++;
}
for(int j=1;j<radix;j++)
{
count[j]
=count[j]+count[j-1];
}
for(int m=len-1;m>=0;m--)
{
int subkey=(temporary[m]/R)%radix;
--count[subkey];
keys[from
+count[subkey]]=temporary[m];
}
R
*=radix;
}

}


private static class LinkQueue
{
int head=-1;
int tail=-1;
}
private final void link_radix_sort(int[] keys, int from, int len, int radix, int d) {

int[] nexts=new int[len];

LinkQueue[] queues
=new LinkQueue[radix];
for(int i=0;i<radix;i++)
{
queues[i]
=new LinkQueue();
}
for(int i=0;i<len-1;i++)
{
nexts[i]
=i+1;
}
nexts[len
-1]=-1;

int first=0;
for(int i=0;i<d;i++)
{
link_radix_sort_distribute(keys,from,len,radix,i,nexts,queues,first);
first
=link_radix_sort_collect(keys,from,len,radix,i,nexts,queues);
}
int[] tmps=new int[len];
int k=0;
while(first!=-1)
{

tmps[k
++]=keys[from+first];
first
=nexts[first];
}
System.arraycopy(tmps,
0, keys, from, len);


}
private final void link_radix_sort_distribute(int[] keys, int from, int len,
int radix, int d, int[] nexts, LinkQueue[] queues,int first) {

for(int i=0;i<radix;i++)queues[i].head=queues[i].tail=-1;
while(first!=-1)
{
int val=keys[from+first];
for(int j=0;j<d;j++)val/=radix;
val
=val%radix;
if(queues[val].head==-1)
{
queues[val].head
=first;
}
else
{
nexts[queues[val].tail]
=first;

}
queues[val].tail
=first;
first
=nexts[first];
}

}
private int link_radix_sort_collect(int[] keys, int from, int len,
int radix, int d, int[] nexts, LinkQueue[] queues) {
int first=0;
int last=0;
int fromQueue=0;
for(;(fromQueue<radix-1)&&(queues[fromQueue].head==-1);fromQueue++);
first
=queues[fromQueue].head;
last
=queues[fromQueue].tail;

while(fromQueue<radix-1&&queues[fromQueue].head!=-1)
{
fromQueue
+=1;
for(;(fromQueue<radix-1)&&(queues[fromQueue].head==-1);fromQueue++);

nexts[last]
=queues[fromQueue].head;
last
=queues[fromQueue].tail;

}
if(last!=-1)nexts[last]=-1;
return first;
}

/**
*
@param args
*/
public static void main(String[] args) {
int[] a={1,4,8,3,2,9,5,0,7,6,9,10,9,135,14,15,11,222222222,1111111111,12,17,45,16};
USE_LINK
=true;
RadixSorter sorter
=new RadixSorter();
sorter.sort(a,
0,a.length,10,10);
for(int i=0;i<a.length;i++)
{
System.out.print(a[i]
+",");
}


}

}

 

分享到:
评论

相关推荐

    Java排序算法(桶排序,基数排序等)

    Java排序算法:插入,冒泡,选择,Shell,快速排序,归并排序,堆排序,桶式排序,基数排序

    各种排序算法

    包含算法导论/数据结构中各种常用的排序算法:快速排序 冒泡排序 堆排序 选择排序 归并排序 插入排序 二分插入排序 希尔排序 计数排序 基数排序 桶式排序

    java排序算法大全

    各类java排序算法: 1.插入排序2.冒泡排序3.选择排序4.Shell排序5.快速排序6.归并排序7.堆排序8.桶式排序9.基数排序

    常见排序算法-C语言

    C语言实现常见排序算法。编译环境:VS2010。 包括: 冒泡排序 快速排序 直接插入排序 Shell排序 直接选择排序 堆排序 归并排序(递归和非递归两种) ...基数排序:顺序和静态队列两种方法 索引排序(采用简单插入排序)

    Java排序算法详细整理

    文档包含以下内容: 一 插入排序 二 冒泡排序 三 选择排序 四 Shell排序 五 快速排序 六 归并排序 七 堆排序 八 桶式排序 九 基数排序

    常用排序算法java版

    选择排序(直接选择排序,堆排序) 交换排序(冒泡排序,快速排序) 插入排序(直接插入排序,折半插入排序,Shell排序) 归并排序 桶式排序 基数排序

    java十二种排序算法实现源代码(类)

    java常用的排序算法 冒泡排序,选择排序,插入排序,稀尔排序,快速排序,归并排序,堆排序,桶式排序,基数排序,含鸡尾排序。以及二叉树和拓扑结构!

    java最常用的排序算法

    插入排序,冒泡排序,选择排序,shell排序,快速排序,归并排序,堆排序,桶式排序,基数排序,

    几十张无水印图完美搞定面试官经常问的十大经典排序算法(含C语言代码.rar

    堆排序 简介 复杂度与稳定性 什么是堆? 过程介绍 主要代码实现 归并排序 简介 复杂度与稳定性 过程介绍 图示过程 主要代码实现 快速排序 简介 复杂度与稳定性 过程介绍 图示过程 主要代码实现 ...

    所有排序方法.zip

    直接选择排序、堆排序、冒泡排序、快速排序、直接插入排序、折半插入排序、Shell排序、归并排序、桶式排序、基数排序

    所有排序的写法(Java).zip

    直接选择排序、堆排序、冒泡排序、快速排序、直接插入排序、折半插入排序、Shell排序、归并排序、桶式排序、基数排序

    九种排序算法及其测试程序(java版)

    九种排序算法及其测试程序(java版)本人耗时三天整理而成,绝对精典。记忆技巧:"冒择路(入)兮(希)快归堆+桶基" 冒泡、选择、插入、希尔、快速、归并、堆、桶式、基数。

    liveness_src.zip

    就常用的内部排序算法来说,可以分为以下几类: * 选择排序(直接选择排序,堆排序) * 交换排序(冒泡排序,快速排序) * 插入排序(直接插入排序,折半插入排序,Shell排序) * 归并排序 * 桶式排序 * 基数排序

    数据结构动画演示

    '冒泡排序.swf', '分块查找.swf', '单链表结点的删除.swf', '单链表结点的插入.swf', '图的深度优先遍历.swf', '基数排序.swf', '堆排序.swf', '头插法建单链表.swf', '寻找中序线索化二叉树指定结点的前驱.swf', '...

    突破程序员基本功的16课.part2

    12.6 桶式排序 12.7 基数排序 12.8 小结 第13课 程序开发 13.1 扎实的基本功 13.1.1 快速的输入能力 13.1.2 编程实现能力 13.1.3 快速排错 13.2 程序开发之前 13.2.1 分析软件的组件模型 13.2.2 建立软件...

Global site tag (gtag.js) - Google Analytics