JAVA版的4种排序法

   今天的工作完成的早,有空写了排序方法:
package infon.util.ds;

import java.util.Random;

/**
 * 几种排序算法的比较和选择
 * 1. 选取排序方法需要考虑的因素:
 * (1) 待排序的元素数目n;
 * (2) 元素本身信息量的大小;
 * (3) 关键字的结构及其分布情况;
 * (4) 语言工具的条件,辅助空间的大小等。
 * 2. 小结: (1) 若n较小(n <=50),则可以采用直接插入排序或直接选择排序。由于直接插入排序所需的记录移动操作较直接选择排序多,
 *       因而当记录本身信息量较大时,用直接选择排序较好。
 * (2)若文件的初始状态已按关键字基本有序,则选用直接插入或冒泡排序为宜。
 * (3)若n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序、堆排序或归并排序。
 *         快速排序是目前基于比较的内部排序法中被认为是最好的方法。
 * (4)在基于比较排序方法中,每次比较两个关键字的大小之后,仅仅出现两种可能的转移,因此可以用一棵二叉树来描述比较判定过程,
 *         由此可以证明:当文件的n个关键字随机分布时,任何借助于"比较"的排序算法,至少需要O(nlog2n)的时间。
 * (5) 当记录本身信息量较大时,为避免耗费大量时间移动记录,可以用链表作为存储结构。
 *
 * 效率:从上往下递减
 * 排序名称        复杂度
 * 冒泡排序        O(N^2)
 * 选择排序        O(N^2)
 * 插入排序        O(N^2)
 * 归并排序       
 * 希尔排序        O(N*(logN)^2)
 * 快速排序        O(N*(logN)^2)
 *
 * @author infon
 *
 */
public class Sort {
    /**
     * 插入排序(Insertion Sort)
     *  1. 基本思想:
     * 每次将一个待排序的数据元素,插入到前面已经排好序的数列中的适当位置,使数列依然有序;直到待排序数据元素全部插入完为止。
     *  2. 排序过程:
     * 【示例】:
     * [初始关键字] [49] 38 65 97 76 13 27 49
     * J=2(38) [38 49] 65 97 76 13 27 49
     * J=3(65) [38 49 65] 97 76 13 27 49
     * J=4(97) [38 49 65 97] 76 13 27 49
     * J=5(76) [38 49 65 76 97] 13 27 49
     * J=6(13) [13 38 49 65 76 97] 27 49
     * J=7(27) [13 27 38 49 65 76 97] 49
     * J=8(49) [13 27 38 49 49 65 76 97]
     *
     * @param src
     */
    public int[] insertSort(int[] src) {
        int in,out;
        for(out=1;out<src.length;out++){
            int tmp=src[out];
            in=out;
            while(in>0&&src[in-1]>=tmp){
                src[in]=src[in-1];
                --in;
            }
            src[in]=tmp;
        }
        return src;
    }
    //----------------------------------------------------------------
    
    /**
     * 希尔排序
     */
    public int[] shellSort(int[] src) {
        int inner, outer;
        int temp;

        int h = 1; // find initial value of h
        while (h <= src.length / 3)
            h = h * 3 + 1; // (1, 4, 13, 40, 121, ...)

        while (h > 0) // decreasing h, until h=1
        {
            // h-sort the file
            for (outer = h; outer < src.length; outer++) {
                temp = src[outer];
                inner = outer;
                // one subpass (eg 0, 4, 8)
                while (inner > h - 1 && src[inner - h] >= temp) {
                    src[inner] = src[inner - h];
                    inner -= h;
                }
                src[inner] = temp;
            } // end for
            h = (h - 1) / 3; // decrease h
        } // end while(h>0)
        return src;
    } // end shellSort()
    // --------------------------------------------------------------

    /**
     * 选择排序
     * 1. 基本思想:
     * 每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。
     * 2.排序过程: 【示例】:
     *  初始关键字   [49 38 65 97 76 13 27 49]
     *  第一趟排序后 13 [38 65 97 76 49 2749]
     *  第二趟排序后 13 27 [65 97 76 49 38 49]
     *  第三趟排序后 13 27 38 [97 76 49 65 49]
     *  第四趟排序后 13 27 38 49 [49 97 65 76]
     *  第五趟排序后 13 27 38 49 49 [97 97 76]
     *  第六趟排序后 13 27 38 49 49 76 [76 97]
     *  第七趟排序后 13 27 38 49 49 76 76 [ 97]
     *  最后排序结果 13 27 38 49 49 76 76 97
     *
     * @param src
     * @return
     */
    public int[] selectSort(int src[]) {
        for(int i=0;i<src.length;i++){
            int index=i;
            for(int j=i+1;j<src.length;j++){
                if(src[index]>src[j]){
                    index=j;
                }//~end if
            }//~end for2
            if(i!=index){
                int tmp;
                tmp=src[i];
                src[i]=src[index];
                src[index]=tmp;
            }//~end if
        }//~end for1
        return src;
    }
    //-----------------------------------------------------------------------------------

    /**
     *
     * 冒泡排序(BubbleSort)
     * 1. 基本思想:
     *   两两比较待排序数据元素的大小,发现两个数据元素的次序相反时即进行交换,直到没有反序的数据元素为止。
     * 2. 排序过程:
     *   设想被排序的数组R[1..N]垂直竖立,将每个数据元素看作有重量的气泡,根据轻气泡不能在重气泡之下的原则,
     * 从下往上扫描数组R,凡扫描到违反本原则的轻气泡,就使其向上"漂浮",如此反复进行,直至最后任何两个气泡都是轻者在上,重者在下为止。
     * 【示例】:
     *  49 13 13 13 13 13 13 13
     *  38 49 27 27 27 27 27 27
     *  65 38 49 38 38 38 38 38
     *  97 65 38 49 49 49 49 49
     *  76 97 65 49 49 49 49 49
     *  13 76 97 65 65 65 65 65
     *  27 27 76 97 76 76 76 76
     *  49 49 49 76 97 97 97 97
     *
     * @param src
     * @return
     */
    public int[] bubbleSort(int[] src){
        for(int i=0;i<src.length;i++){
            boolean isChange=false; //
            for(int j=src.length-1;j>i;j--){
                if(src[j]<src[j-1]){
                    int tmp=src[j];
                    src[j]=src[j-1];
                    src[j-1]=tmp;
                    isChange=true;
                }//~end if
            }//~end for2
            if(!isChange)return src;  //本趟排序未发生交换,提前终止算法
        }//~end for1
        return src;
    }//~end bubbleSort()
    
    //------------------------------------------------------------------------------------
    
    /**
     * 快速排序(Quick Sort)
     * 1. 基本思想: 在当前无序区R[1..H]中任取一个数据元素作为比较的"基准"(不妨记为X),
     * 用此基准将当前无序区划分为左右两个较小的无序区:R[1..I-1]和R[I+1..H],且左边的无序子区中数据元素均小于等于基准元素,
     * 右边的无序子区中数据元素均大于等于基准元素,而基准X则位于最终排序的位置上,即R[1..I-1]
     * ≤X.Key≤R[I+1..H](1≤I≤H),当R[1..I-1]和R[I+1..H]均非空时,分别对它们进行上述的划分过程,
     * 直至所有无序子区中的数据元素均已排序为止。
     * 2. 排序过程:
     * 【示例】:
     * 初始关键字   [49 38 65 97 76 13 27 49]
     * 第一次交换后 [27 38 65 97 76 13 49 49]
     * 第二次交换后 [27 38 49 97 76 13 65 49]
     * J向左扫描,位置不变,第三次交换后 [27 38 13 97 76 49 65 49]
     * I向右扫描,位置不变,第四次交换后 [27 38 13 49 76 97 65 49]
     * J向左扫描 [27 38 13 49 76 97 65 49]
     *(一次划分过程)
     * 初始关键字 [49 38 65 97 76 13 27 49]
     * 一趟排序之后 [27 38 13] 49 [76 97 65 49]
     * 二趟排序之后 [13] 27 [38] 49 [49 65]76 [97]
     * 三趟排序之后 13 27 38 49 49 [65]76 97
     * 最后的排序结果 13 27 38 49 49 65 76 97
     *
     * 改进后的算法枢轴不再是第一个或者是最后一个,而是取第一个、最后一个及中间一个的中间值
     * 如果要排序的基数少于10的话,我们就用插入排序,效果会更理想一些
     *
     * @param src
     * @return
     */
    public int[] quickSort(int[] src) {
        recQuickSort(src,0, src.length - 1);
        return src;
    }

    private void recQuickSort(int[] src,int left, int right) {
        int size = right-left+1;
          if(size < 10)                   // insertion sort if small
              insertSort(src);        
        else {
            int pivot = medianOf3(src,left, right);
            int index = partition(src,left, right, pivot);
           
            recQuickSort(src,left, index - 1);
            recQuickSort(src,index + 1, right);
        }
    }

    private int partition(int []src,int left, int right, int pivot) {
        int leftPtr = left - 1; // left (after ++)
        int rightPtr = right; // right-1 (after --)
        while (true) { // find bigger item
            while (src[++leftPtr] < pivot)
                ; // (nop)
            // find smaller item
            while (rightPtr > 0 && src[--rightPtr] > pivot)
                ; // (nop)

            if (leftPtr >= rightPtr) // if pointers cross,
                break; // partition done
            else
                // not crossed, so
                swap(src,leftPtr, rightPtr); // swap elements
        } // end while(true)
        swap(src,leftPtr, right); // restore pivot
        return leftPtr;
    }// ~end method partition

    public void swap(int []src,int dex1, int dex2) // swap two elements
    {
        int temp = src[dex1]; // A into temp
        src[dex1] = src[dex2]; // B into A
        src[dex2] = temp; // temp into B
    } // end swap()
    
    public int medianOf3(int[]src,int left, int right)
    {
    int center = (left+right)/2;
                                     // order left & center
    if( src[left] > src[center] )
       swap(src,left, center);
                                     // order left & right
    if( src[left] > src[right] )
       swap(src,left, right);
                                     // order center & right
    if( src[center] > src[right] )
       swap(src,center, right);

    swap(src,center, right-1);           // put pivot on right
    return src[right-1];        // return median value
    }  // end medianOf3()
//--------------------------------------------------------------
    // ****************************** end quickSort
    
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int[] src = new int[] { 49, 38, 65, 97, 76, 13, 27, 49 };
        int[] result=new int[src.length];
       
        Sort sort = new Sort();
       
        result=sort.insertSort(src.clone()); 
        System.out.print("insertSort: ");
        print(result);
       
        result = sort.selectSort(src.clone());
        System.out.print("selectSort: ");
        print(result);
       
        result = sort.quickSort(src.clone());
        System.out.print("quickSort: ");
        print(result);
       
        result = sort.bubbleSort(src.clone());
        System.out.print("bubbleSort: ");
        print(result);
       
        result = sort.shellSort(src.clone());
        System.out.print("shellSort: ");
        print(result);
        //测试排序所需要的时间
        test(10000);
    }
    
    public static void print(int []src){
        for (int i = 0; i < src.length; i++) {
            if(i==src.length-1){
                System.out.println(src[i]);
            }else{
                System.out.print(src[i] + ",");
            }
            if(i%10==0&&i!=0)System.out.println();
        }
    }
    
    /**
     *
     * @param num
     *        num为测试数据的数量
     */
    public static void test(int num){
        long start=System.currentTimeMillis();
        Sort sort = new Sort();
        int[] src = new int[num];
        Random rand=new Random();
        for(int i=0;i<src.length;i++){
            src[i]=Math.abs(rand.nextInt()%10000);
        }
       
        int[] result;
       
        start = System.currentTimeMillis();
        result=sort.insertSort(src.clone());
        System.out.println("insertSort: " + (System.currentTimeMillis() - start));
       
        start = System.currentTimeMillis();
        result = sort.selectSort(src.clone());
        System.out.println("selectSort: " + (System.currentTimeMillis() - start));
       
        start = System.currentTimeMillis();
        result = sort.bubbleSort(src.clone());
        System.out.println("bubbleSort: " + (System.currentTimeMillis() - start));
       
        start = System.currentTimeMillis();
        result = sort.shellSort(src.clone());
        System.out.println("shellSort: " + (System.currentTimeMillis() - start));
       
        start = System.currentTimeMillis();
        result = sort.quickSort(src.clone());
        System.out.println("quickSort: " + (System.currentTimeMillis() - start));
    }//~end test
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值