用JAVA实现的9种排序算法(二)

来源:互联网 发布:java面试常用设计模式 编辑:程序博客网 时间:2024/05/16 18:19
  1. 5.Shell排序   
  2. package com.javasort.shellsorter;   
  3.   
  4. /**  
  5.  * Shell排序可以理解为插入排序的变种,它充分利用了插入排序的两个特点:  
  6.  1)当数据规模小的时候非常高效  
  7.  2)当给定数据已经有序时的时间代价为O(N)  
  8.  所以,Shell排序每次把数据分成若个小块,来使用插入排序,而且之后在这若个小块排好序的情况下把它们合成大一点的小块,继续使用插入排序,不停的合并小块,知道最后成一个块,并使用插入排序。  
  9.  
  10.  这里每次分成若干小块是通过“增量” 来控制的,开始时增量交大,接近N/2,从而使得分割出来接近N/2个小块,逐渐的减小“增量“最终到减小到1。  
  11.  
  12.  一直较好的增量序列是2^k-1,2^(k-1)-1,.....7,3,1,这样可使Shell排序时间复杂度达到O(N^1.5)  
  13.  所以我在实现Shell排序的时候采用该增量序列  
  14.  
  15.  */  
  16. import com.javasort.Sorter;   
  17.   
  18. /**  
  19.  *   
  20.  * @author Daniel Cheng  
  21.  *   
  22.  * @param <E>  
  23.  */  
  24. public class ShellSorter<E extends Comparable<E>> extends Sorter<E> {   
  25.   
  26.     @Override  
  27.     public void sort(E[] array, int from, int len) {   
  28.         //1.calculate(计算) first delta value   
  29.         int value=1;   
  30.         while((value+1)*2<len){   
  31.             value=(value+1)*2-1;   
  32.         }   
  33.         //2.小块是通过“增量” 来控制的,开始时增量较大,接近N/2,从而使得分割出来接近N/2个小块,逐渐的减小“增量“最终到减小到1。   
  34.         for(int delta=value;delta>=1;delta=(delta+1)/2-1){   
  35.             for(int i=0;i<delta;i++){   
  36.                 modify_insert_sort(array,from+i,len-i,delta);   
  37.             }   
  38.                
  39.         }   
  40.     }   
  41.   
  42.     private final void modify_insert_sort(E[] array, int from, int len, int delta) {   
  43.         if(len<=1)    
  44.             return;   
  45.         E tmp=null;   
  46.         for(int i=from+delta;i<from+len;i+=delta){   
  47.             tmp=array[i];   
  48.             int j=i;   
  49.             for(;j>from;j-=delta){   
  50.                 if(tmp.compareTo(array[j-delta])<0){   
  51.                     array[j]=array[j-delta];   
  52.                 }   
  53.                 else break;   
  54.             }   
  55.             array[j]=tmp;   
  56.         }   
  57.            
  58.     }   
  59.   
  60. }   
  61.   
  62. package com.javasort.shellsorter;   
  63.   
  64. import com.javasort.Sorter;   
  65.   
  66. public class ShellSorterTest {   
  67.   
  68.     public static void main(String[] args) {   
  69.         Comparable[] array={5,1,13,2,17,9,7,4,0};   
  70.         Sorter shellSorter=new ShellSorter();   
  71.         shellSorter.sort(array);   
  72.         shellSorter.printResult(array);   
  73.     }   
  74.   
  75. }   
  76.   
  77. 6.堆排序   
  78. package com.javasort.heapsorter;   
  79. /**  
  80.  * 堆排序:堆是一种完全二叉树,一般使用数组来实现。  
  81.  * 堆主要有两种核心操作,  
  82.  * 1)从指定节点向上调整(shiftUp)  
  83.  * 2)从指定节点向下调整(shiftDown)  
  84.  * 建堆,以及删除堆定节点使用shiftDwon,而在插入节点时一般结合两种操作一起使用。  
  85.  * 堆排序借助最大值堆来实现,第i次从堆顶移除最大值放到数组的倒数第i个位置,  
  86.  * 然后shiftDown到倒数第i+1个位置,一共执行N次调整,即完成排序。  
  87.  * 显然,堆排序也是一种选择性的排序,每次选择第i大的元素。  
  88.  
  89.  */  
  90. import com.javasort.Sorter;   
  91.   
  92. /**  
  93.  *   
  94.  * @author Daniel Cheng  
  95.  *  
  96.  */  
  97. public class HeapSorter<E extends Comparable<E>> extends Sorter<E> {   
  98.   
  99.     @Override  
  100.     public void sort(E[] array, int from, int len) {   
  101.         build_heap(array,from,len);   
  102.         for(int i=0;i<len;i++){   
  103.             //第i次从堆顶移除最大值放到数组的倒数第i个位置,   
  104.             swap(array, from, from+len-1-i);   
  105.             //一直shiftDown(从0开始)到倒数第i+1个位置,一共执行N次调整   
  106.             shift_down(array, from, len-1-i, 0);   
  107.         }   
  108.     }   
  109.   
  110.     private final void build_heap(E[] array, int from, int len) {   
  111.         //我们从(len- 1)/ 2开始,因为分支节点+1=叶子节点,而所有的叶子节点已经是一个堆   
  112.         int pos=(len-1)/2;   
  113.         for(int i=pos;i>=0;i--){   
  114.             shift_down(array,from,len,i);   
  115.         }   
  116.   
  117.     }   
  118.   
  119.     private final void shift_down(E[] array, int from, int len, int pos) {   
  120.         E tmp=array[from+pos];   
  121.         int index=pos*2+1;//用左孩子结点   
  122.         while(index<len)//直到没有孩子结点   
  123.         {   
  124.             if(index+1<len&&array[from+index].compareTo(array[from+index+1])<0)//右孩子结点是较大的   
  125.             {   
  126.                 index+=1;//切换到右孩子结点   
  127.             }   
  128.             if(tmp.compareTo(array[from+index])<0){   
  129.                 array[from+pos]=array[from+index];   
  130.                 pos=index;   
  131.                 index=pos*2+1;   
  132.                    
  133.             }   
  134.             else{   
  135.                 break;   
  136.             }   
  137.         }   
  138.         array[from+pos]=tmp;   
  139.     }   
  140.   
  141. }   
  142.   
  143. /**  
  144.  *   
  145.  */  
  146. package com.javasort.heapsorter;   
  147.   
  148. import com.javasort.Sorter;   
  149.   
  150. /**  
  151.  * @author Daniel Cheng  
  152.  *  
  153.  */  
  154. public class HeapSorterTest {   
  155.   
  156.     public static void main(String[] args) {   
  157.         Comparable[] array = { 51132179740 };   
  158.         Sorter heapSorter=new HeapSorter();   
  159.         heapSorter.sort(array);   
  160.         heapSorter.printResult(array);   
  161.     }   
  162.   
  163. }   
  164.   
  165. 7.桶式排序   
  166. /**  
  167.  * 桶式排序:  
  168.  * 桶式排序不再是基于比较的了,它和基数排序同属于分配类的排序,  
  169.  * 这类排序的特点是事先要知道待排 序列的一些特征。  
  170.  * 桶式排序事先要知道待排 序列在一个范围内,而且这个范围应该不是很大的。  
  171.  * 比如知道待排序列在[0,M)内,那么可以分配M个桶,第I个桶记录I的出现情况,  
  172.  * 最后根据每个桶收到的位置信息把数据输出成有序的形式。  
  173.  * 这里我们用两个临时性数组,一个用于记录位置信息,一个用于方便输出数据成有序方式,  
  174.  * 另外我们假设数据落在0到MAX,如果所给数据不是从0开始,你可以把每个数减去最小的数。  
  175.  
  176.  *   
  177.  */  
  178. package com.javasort.bucketsorter;   
  179.   
  180. /**  
  181.  * @author Daniel Cheng  
  182.  *  
  183.  */  
  184. public class BucketSorter {   
  185.      public void sort(int[] keys,int from,int len,int max)   
  186.         {   
  187.             int[] temp=new int[len];   
  188.             int[] count=new int[max];   
  189.                
  190.                
  191.             for(int i=0;i<len;i++)   
  192.             {   
  193.                 count[keys[from+i]]++;   
  194.             }   
  195.             //calculate position info   
  196.             for(int i=1;i<max;i++)   
  197.             {   
  198.                 count[i]=count[i]+count[i-1];//这意味着有多少数目小于或等于i,因此它也是position+ 1   
  199.             }   
  200.                
  201.             System.arraycopy(keys, from, temp, 0, len);   
  202.             for(int k=len-1;k>=0;k--)//从最末到开头保持稳定性   
  203.             {   
  204.                 keys[--count[temp[k]]]=temp[k];// position +1 =count   
  205.             }   
  206.         }   
  207.         /**  
  208.          * @param args  
  209.          */  
  210.         public static void main(String[] args) {   
  211.   
  212.             int[] a={1,4,8,3,2,9,5,0,7,6,9,10,9,13,14,15,11,12,17,16};   
  213.             BucketSorter bucketSorter=new BucketSorter();   
  214.             bucketSorter.sort(a,0,a.length,20);//actually is 18, but 20 will also work   
  215.                
  216.                
  217.             for(int i=0;i<a.length;i++)   
  218.             {   
  219.                 System.out.print(a[i]+",");   
  220.             }   
  221.   
  222.         }   
  223.   
  224.   
  225. }   
  226.   
  227. 8.基数排序   
  228. /**  
  229.  * 基数排序:基数排序可以说是扩展了的桶式排序,  
  230.  * 比如当待排序列在一个很大的范围内,比如0到999999内,那么用桶式排序是很浪费空间的。  
  231.  * 而基数排序把每个排序码拆成由d个排序码,比如任何一个6位数(不满六位前面补0)拆成6个排序码,  
  232.  * 分别是个位的,十位的,百位的。。。。  
  233.  * 排序时,分6次完成,每次按第i个排序码来排。  
  234.  * 一般有两种方式:  
  235.  * 1) 高位优先(MSD): 从高位到低位依次对序列排序  
  236.  * 2)  低位优先(LSD): 从低位到高位依次对序列排序  
  237.  * 计算机一般采用低位优先法(人类一般使用高位优先),但是采用低位优先时要确保排序算法的稳定性。  
  238.  * 基数排序借助桶式排序,每次按第N位排序时,采用桶式排序。  
  239.  * 对于如何安排每次落入同一个桶中的数据有两种安排方法:  
  240.  * 1)顺序存储:每次使用桶式排序,放入r个桶中,相同时增加计数。  
  241.  * 2)链式存储:每个桶通过一个静态队列来跟踪。  
  242.  
  243.  */  
  244. package com.javasort.radixsorter;   
  245.   
  246. import java.util.Arrays;   
  247.   
  248. /**  
  249.  * @author Daniel Cheng  
  250.  *  
  251.  */  
  252. public class RadixSorter {   
  253. public static boolean USE_LINK=true;   
  254.        
  255.     /**  
  256.      *   
  257.      * @param keys  
  258.      * @param from  
  259.      * @param len  
  260.      * @param radix  key's radix  
  261.      * @param d      how many sub keys should one key divide to  
  262.      */  
  263.     public void sort(int[] keys,int from ,int len,int radix, int d)   
  264.     {   
  265.         if(USE_LINK)   
  266.         {   
  267.             link_radix_sort(keys,from,len,radix,d);   
  268.         }   
  269.         else  
  270.         {   
  271.             array_radix_sort(keys,from,len,radix,d);   
  272.         }   
  273.            
  274.     }   
  275.        
  276.        
  277.     private final void array_radix_sort(int[] keys, int from, int len, int radix,   
  278.             int d)    
  279.     {   
  280.         int[] temporary=new int[len];   
  281.         int[] count=new int[radix];   
  282.         int R=1;   
  283.            
  284.         for(int i=0;i<d;i++)   
  285.         {   
  286.             System.arraycopy(keys, from, temporary, 0, len);   
  287.             Arrays.fill(count, 0);   
  288.             for(int k=0;k<len;k++)   
  289.             {   
  290.                 int subkey=(temporary[k]/R)%radix;   
  291.                 count[subkey]++;   
  292.             }   
  293.             for(int j=1;j<radix;j++)   
  294.             {   
  295.                 count[j]=count[j]+count[j-1];   
  296.             }   
  297.             for(int m=len-1;m>=0;m--)   
  298.             {   
  299.                 int subkey=(temporary[m]/R)%radix;   
  300.                 --count[subkey];   
  301.                 keys[from+count[subkey]]=temporary[m];   
  302.             }   
  303.             R*=radix;   
  304.         }   
  305.               
  306.     }   
  307.   
  308.   
  309.     private static class LinkQueue   
  310.     {   
  311.         int head=-1;   
  312.         int tail=-1;   
  313.     }   
  314.     private final void link_radix_sort(int[] keys, int from, int len, int radix, int d) {   
  315.            
  316.         int[] nexts=new int[len];   
  317.            
  318.         LinkQueue[] queues=new LinkQueue[radix];   
  319.         for(int i=0;i<radix;i++)   
  320.         {   
  321.             queues[i]=new LinkQueue();   
  322.         }   
  323.         for(int i=0;i<len-1;i++)   
  324.         {   
  325.             nexts[i]=i+1;   
  326.         }   
  327.         nexts[len-1]=-1;   
  328.            
  329.         int first=0;   
  330.         for(int i=0;i<d;i++)   
  331.         {   
  332.             link_radix_sort_distribute(keys,from,len,radix,i,nexts,queues,first);   
  333.             first=link_radix_sort_collect(keys,from,len,radix,i,nexts,queues);   
  334.         }   
  335.         int[] tmps=new int[len];   
  336.         int k=0;   
  337.         while(first!=-1)   
  338.         {   
  339.            
  340.             tmps[k++]=keys[from+first];   
  341.             first=nexts[first];   
  342.         }   
  343.         System.arraycopy(tmps, 0, keys, from, len);   
  344.            
  345.            
  346.     }   
  347.     private final void link_radix_sort_distribute(int[] keys, int from, int len,   
  348.             int radix, int d, int[] nexts, LinkQueue[] queues,int first) {   
  349.            
  350.         for(int i=0;i<radix;i++)queues[i].head=queues[i].tail=-1;   
  351.         while(first!=-1)   
  352.         {   
  353.             int val=keys[from+first];   
  354.             for(int j=0;j<d;j++)val/=radix;   
  355.             val=val%radix;   
  356.             if(queues[val].head==-1)   
  357.             {   
  358.                 queues[val].head=first;   
  359.             }   
  360.             else    
  361.             {   
  362.                 nexts[queues[val].tail]=first;   
  363.                    
  364.             }   
  365.             queues[val].tail=first;   
  366.             first=nexts[first];   
  367.         }   
  368.            
  369.     }   
  370.     private int link_radix_sort_collect(int[] keys, int from, int len,   
  371.             int radix, int d, int[] nexts, LinkQueue[] queues) {   
  372.         int first=0;   
  373.         int last=0;   
  374.         int fromQueue=0;   
  375.         for(;(fromQueue<radix-1)&&(queues[fromQueue].head==-1);fromQueue++);   
  376.         first=queues[fromQueue].head;   
  377.         last=queues[fromQueue].tail;   
  378.            
  379.         while(fromQueue<radix-1&&queues[fromQueue].head!=-1)   
  380.         {   
  381.             fromQueue+=1;   
  382.             for(;(fromQueue<radix-1)&&(queues[fromQueue].head==-1);fromQueue++);   
  383.                
  384.             nexts[last]=queues[fromQueue].head;   
  385.             last=queues[fromQueue].tail;   
  386.                
  387.         }   
  388.         if(last!=-1)nexts[last]=-1;   
  389.         return first;   
  390.     }   
  391.        
  392.     public static void main(String[] args) {   
  393.         int[] a={1,4,8,3,2,9,5,0,7,6,9,10,9,135,14,15,11,33,999999999,222222222,1111111111,12,17,45,16};   
  394.         USE_LINK=true;   
  395.         RadixSorter sorter=new RadixSorter();   
  396.         sorter.sort(a,0,a.length,10,10);   
  397.         for(int i=0;i<a.length;i++)   
  398.         {   
  399.             System.out.print(a[i]+",");   
  400.         }   
  401.   
  402.   
  403.     }   
  404.   
  405.   
  406. }   
  407.   
  408.   
  409. 9.归并排序   
  410. package com.javasort.mergesorter;   
  411.   
  412. /**  
  413.  * 归并排序:思想是每次把待排的序列分成两部分,分别对这两部分递归地用归并排序,  
  414.  * 完成后把这两个子部分合并成一个序列。归并排序借助一个全局性临时数组来方便  
  415.  * 对子序列的归并,该算法核心在于归并。  
  416.  */  
  417. import java.lang.reflect.Array;   
  418.   
  419. import com.javasort.Sorter;   
  420. /**  
  421.  *   
  422.  * @author Daniel Cheng  
  423.  *  
  424.  * @param <E>  
  425.  */  
  426. public class MergeSorter<E extends Comparable<E>> extends Sorter<E> {   
  427.   
  428.     @SuppressWarnings("unchecked")   
  429.     @Override  
  430.     public void sort(E[] array, int from, int len) {   
  431.         if (len <= 1)   
  432.             return;   
  433.         E[] temporary = (E[]) Array.newInstance(array[0].getClass(), len);   
  434.         merge_sort(array, from, from + len - 1, temporary);   
  435.     }   
  436.   
  437.     private final void merge_sort(E[] array, int from, int to, E[] temporary) {   
  438.         if (to <= from) {   
  439.             return;   
  440.         }   
  441.         int middle = (from + to) / 2;   
  442.         merge_sort(array, from, middle, temporary);   
  443.         merge_sort(array, middle + 1, to, temporary);   
  444.         merge(array, from, to, middle, temporary);   
  445.     }   
  446.   
  447.     private final void merge(E[] array, int from, int to, int middle,   
  448.             E[] temporary) {   
  449.         int k = 0, leftIndex = 0, rightIndex = to - from;   
  450.         System.arraycopy(array, from, temporary, 0, middle - from + 1);   
  451.         for (int i = 0; i < to - middle; i++) {   
  452.             temporary[to - from - i] = array[middle + i + 1];   
  453.         }   
  454.         while (k < to - from + 1) {   
  455.             if (temporary[leftIndex].compareTo(temporary[rightIndex]) < 0) {   
  456.                 array[k + from] = temporary[leftIndex++];   
  457.             } else {   
  458.                 array[k + from] = temporary[rightIndex--];   
  459.             }   
  460.             k++;   
  461.         }   
  462.     }   
  463.   
  464. }   
  465.   
  466.   
  467. /**  
  468.  *   
  469.  */  
  470. package com.javasort.mergesorter;   
  471.   
  472. import com.javasort.Sorter;   
  473.   
  474. /**  
  475.  * @author Daniel Cheng  
  476.  *   
  477.  */  
  478. public class MergeSorterTest {   
  479.     public static void main(String[] args) {   
  480.         Comparable[] array = { 51132179740 };   
  481.         Sorter mergeSorter = new MergeSorter();   
  482.         mergeSorter.sort(array);   
  483.         mergeSorter.printResult(array);   
  484.     }   
  485.   
  486. }  
原创粉丝点击