java实现各种排序算法

最近整理了一下各种排序算法,代码如下,欢迎大家提问与转载,转载请注明出处

import java.util.Arrays;  
public class ArraySort {  
    //插入排序:直接插入排序  
    public void insertSort(int [] array) {  
        if(array.length == 0 || array.length == 1)  return;  
        for(int i = 1;i < array.length;i ++) {  
            //从后往前遍历  
            int temp = array[i];  
            int j = i - 1;  
            for(;j >= 0 && array[j] > temp;j --) {  
                array[j + 1] = array[j];    //比temp大的数整体后移  
            }  
            array[j + 1] = temp;  
        }  
    }  
      
    public void insertSort2(int [] array) {  
        if(array.length == 0 || array.length == 1)  return;  
        for(int i = 1;i < array.length;i ++) {  
            //从后往前遍历  
            int index = i;    
            for(int j = i - 1;j >= 0 && array[j] > array[index];j --) {  
                int temp = array[index];  
                array[index] = array[j];      
                array[j] = temp;  
                index = j;  //下标也要跟着走  
            }  
        }  
    }  
      
    /*插入排序:希尔排序,直接插入排序的升级版,也称为“缩小增量排序” 
     *基本原理:将待排序的数组元素分成多个子序列,使得每个子序列的元素个数相对较少, 
     *然后对各个子序列分别进行直接插入排序,待整个待排序列“基本有序”后, 
     *最后在对所有元素进行一次直接插入排序。 
     *希尔排序最好的时间复杂度和平均时间复杂度都是O(nlogn),最坏时间复杂度是O(n^2) 
     *由于记录是跳跃式的移动,希尔排序并不是一种稳定的排序算法。 
     *衡量算法是否稳定的标准:键值相同的元素排序前后相对次序不变。 
     */    
    public void shellSortSmallToBig(int[] array) {  
        if(array.length == 0 || array.length == 1)  return;  
        //每一次的增量折半,最后一次的增量为1  
        for(int increment = array.length / 2;increment >= 1;increment = increment / 2) {   
            //画图可以看出,针对分割线后面的每一个元素,不断地往前追踪比较  
            for(int i = increment;i < array.length;i ++) {     
                int temp = array[i];  
                int j = i - increment;
                for(;j >= 0 && array[j] > temp;j -= increment) {                     
                	array[j + increment] = array[j];                    
                }  
                array[j + increment] = temp;
            }  
              
            System.out.println("增量是:" + increment);  
            for(int i : array) {  
                System.out.print(i + " ");  
            }  
            System.out.println();  
        }  
    }  
      
    /*选择排序:简单选择排序 
     *基本原理:在要排序的一组数中,选出最小的一个数与第一个位置的数交换; 
     *然后在剩下的数当中再找最小的与第二个位置的数交换, 
     *如此循环到倒数第二个数和最后一个数比较为止。 
     */  
    public void simpleSelectSort(int [] array) {  
        if(array.length == 0 || array.length == 1)  return;   
        for(int i = 0;i < array.length - 1;i ++) {  
            int minIndex = i;  
            int minValue = array[i];  
            for(int j = i + 1;j < array.length;j ++) {  
                if(array[j] < minValue) {  
                    minIndex = j;     
                    minValue = array[j];  
                }  
            }  
            array[minIndex] = array[i];  
            array[i] = minValue;  
        }  
    }  
      
    /*选择排序:堆排序,时间复杂度O(nlogn),不稳定 
     *若要递增则建立大顶堆(根节点的值大于剩余所有节点的值),若要递减则建立小顶堆(根节点的值小于剩余所有节点的值)。 
     *基本原理:1.将数组构造成初始堆,从最后一个节点开始调整,得到初始堆。 
     *2.堆排序处理,交换堆顶的元素和最后一个元素,此时最后一个位置作为有序区; 
     *然后进行其他无序区的堆调整,重新得到大顶堆后,交换堆顶和倒数第二个元素的位置…… 
     */  
    public void heapSort(int [] array) {  
        if(array.length == 0 || array.length == 1)  return;   
          
        //新建一个大顶堆  
        for(int i = array.length / 2;i >= 0;i --) {  
            adjustHeap(i, array.length, array); //新建大顶堆的时候根节点是数组中间节点及前半部分  
            System.out.println("初始化大顶堆:" + Arrays.toString(array));  
        }  
          
        //调整堆:交换堆顶和堆尾,然后除去堆尾重新调整大顶堆  
        for(int i = array.length - 1;i >= 0;i --) {  
            int temp = array[i];  
            array[i] = array[0];  
            array[0] = temp;  
            adjustHeap(0, i, array);    //只需调整堆顶节点即可  
            System.out.println("调整大顶堆:" + Arrays.toString(array));  
        }  
    }  
      
    public void adjustHeap(int parent, int length, int [] array) {  //根节点的位置以及欲调节的最大长度  
        int parentValue = array[parent];  
        int leftChild = 2 * parent + 1; //画图可得出此关系    
          
        while(leftChild < length) {  
            //右孩子存在且右孩子的值比左孩子的值大,则取右孩子  
            if(leftChild + 1 < length && array[leftChild + 1] > array[leftChild]) {     
                leftChild ++;  
            }  
              
            if(parentValue > array[leftChild]) {  
                break;  
            }  
              
            array[parent] = array[leftChild];  
            parent = leftChild;  
            leftChild = parent * 2 + 1;  
        }  
        array[parent] = parentValue;    //往右找完了,将最开始的parentValue赋给最后一个父节点  
          
    }  
      
    /*交换排序:冒泡排序,平均时间复杂度O(n^2),稳定 
     *基本思想:在要排序的一组数中,对当前还未排好序的范围内的全部数 
     *自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。 
     */  
    public void bubblingSort(int [] array) {  
        if(array.length == 0 || array.length == 1)  return;   
        for(int i = 0;i < array.length - 1;i ++) {  
            for(int j = 0;j < array.length - 1 - i;j ++) {  
                if(array[j] > array[j + 1]) {    //小的排前面,大的一直往后冒  
                    int temp = array[j];  
                    array[j] = array[j + 1];  
                    array[j + 1] = temp;  
                }  
            }  
        }  
    }  
      
    /*交换排序:快速排序,平均时间复杂度O(nlogn),不稳定 
     *基本思想:基于分治的思想,是冒泡排序的改进型。 
     *首先在数组中选择一个基准点(该基准点的选取可能影响快速排序的效率,后面讲解选取的方法), 
     *然后分别从数组的两端扫描数组,设两个指示标志(lo指向起始位置,hi指向末尾), 
     *首先从后半部分开始,如果发现有元素比该基准点的值小,就交换lo和hi位置的值, 
     *然后从前半部分开始扫秒,发现有元素大于基准点的值,就交换lo和hi位置的值, 
     *如此往复循环,直到lo>=hi,然后把基准点的值放到hi这个位置。一次排序就完成了。 
     *以后采用递归的方式分别对前半部分和后半部分排序,当前半部分和后半部分均有序时该数组就自然有序了。 
     */  
    public int getMiddle(int [] array, int pHead, int pTail) {        
        //int base = array[pHead];  //固定切分的基准  
        int base = getBase2(array, pHead, pTail);  
        while(pHead < pTail) {  
            while(pHead < pTail && array[pTail] > base){  
                pTail --;  
            }  
              
            if(pHead >= pTail) {  
                break;  
            }  
            else {  
                int temp = array[pTail];  
                array[pTail] = array[pHead];  
                array[pHead] = temp;  
                pHead ++;  
            }  
              
            while(pHead < pTail && array[pHead] < base){  
                pHead ++;  
            }  
              
            if(pHead >= pTail) {  
                break;  
            }  
            else {  
                int temp = array[pHead];  
                array[pHead] = array[pTail];  
                array[pTail] = temp;  
                pTail --;  
            }  
        }     
          
        System.out.println(Arrays.toString(array) + " " + "pHead:" + pHead + " pTail:" + pTail);  
        return pHead;         
    }  
      
    //随机切分法获取基准元素:任意找一个元素与头交换  
    public int getBase(int [] array, int pHead, int pTail) {      
        //Math.random()范围是0-1  
        int randomIndex =  (int)(Math.random() * (pTail - pHead) + pHead);    
        int temp = array[randomIndex];  
        array[randomIndex] = array[pHead];  
        array[pHead] = temp;  
        return array[pHead];  
    }  
      
    //三数取中法获取基准元素:头、中、尾先进行简单排序,再取头,可节省比较次数  
    public int getBase2(int [] array, int pHead, int pTail) {     
        int pMiddle = (pTail - pHead) / 2 + pHead;  
        if(array[pMiddle] > array[pTail]) {  
            int temp = array[pMiddle];  
            array[pMiddle] = array[pTail];  
            array[pTail] = temp;  
        }  
          
        if(array[pHead] > array[pTail]) {  
            int temp = array[pTail];  
            array[pTail] = array[pHead];  
            array[pHead] = temp;  
        }  
          
        if(array[pHead] > array[pMiddle]) {  
            int temp = array[pHead];  
            array[pHead] = array[pMiddle];  
            array[pMiddle] = temp;  
        }  
          
        return array[pHead];          
    }  
      
    public void fastSort(int [] array, int pHead, int pTail) {  
        if(array.length == 0 || array.length == 1)  return;   
          
        if(pHead < pTail) {  
            int pMiddle = getMiddle(array, pHead, pTail);  
            fastSort(array, pHead, pMiddle - 1);  
            fastSort(array, pMiddle + 1, pTail);  
        }  
    }  
      
    /*归并排序:平均时间复杂度O(nlogn),稳定 
     *基本思想:将两个(或两个以上)有序表合并成一个新的有序表, 
     *即把待排序序列分为若干个子序列,每个子序列是有序的。 
     *然后再把有序子序列合并为整体有序序列。 
     */  
    public void mergeSort(int [] array, int pHead, int pTail) {  
        if(array.length == 0 || array.length == 1)  return;   
          
        if(pHead < pTail) {  
            int pMiddle = pHead + (pTail - pHead) / 2;  
            mergeSort(array, pHead, pMiddle);  
            mergeSort(array, pMiddle + 1, pTail);  
            mergeArray(array, pHead, pMiddle, pTail);  
        }  
    }  
      
    public void mergeArray(int[] array, int pHead, int pMiddle, int pTail) {  
        int [] tempArray =  new int[pTail - pHead + 1];  
        int i = pHead;  //前半段索引  
        int j = pMiddle + 1;    //后半段索引  
        int k = 0;  //辅助数组索引  
          
        while(i <= pMiddle && j <= pTail) {  
            if(array[i] < array[j]) {  
                tempArray[k ++] = array[i ++];  
            }  
            else {  
                tempArray[k ++] = array[j ++];  
            }  
        }  
          
        //经过上面循环,两个子数组里还会剩下一个最大的数,不确定是哪一个子数组  
        while(i <= pMiddle) {  
            tempArray[k ++] = array[i ++];  
        }  
          
        while(j <= pTail) {  
            tempArray[k ++] = array[j ++];  
        }  
          
        System.out.println(Arrays.toString(tempArray));  
          
        k = 0;  
        for(int t = pHead;t <= pTail;t ++) { //将辅助数组里的数据复制到原数组指定的位置  
            array[t] = tempArray[k ++];  
        }  
    }  
      
    public static void main(String[] args) {  
        ArraySort t = new ArraySort();  
        int [] array = {57, 68, 59, 52, 72, 28, 96, 33, 24, 19};          
        t.mergeSort(array, 0, array.length - 1);  
//      System.out.println(t.getBaseIndex(array, 0, array.length - 1));  
//      t.mergeSort(array, 0, array.length - 1);  
        for(int i : array) {  
            System.out.print(i + " ");  
        }  
    }  
}    




  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值