java排序算法

Posted Java第一傻

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java排序算法相关的知识,希望对你有一定的参考价值。

Java排序算法


排序算法

对一序列对象根据某个关键字进行排序


一、冒泡排序(Bubble Sort)

1.原理

1.比较相邻的元素,如果第一个比第二个大,就交换他们两个;

2.对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数;

3.针对除了最后一个之外的所有的元素重复以上的步骤;

4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

2.代码实现

public static long[] bubblesort(long[] array) 
        if(array.length==0)
            return array;
        for (int i = 0; i <array.length; i++) 
            for (int j = 0; j <array.length-1-i ; j++) 
                if (array[j]>array[j])
                    long temp= array[j];
                    array[j]=array[j];
                    array[j]=temp;
                
            
        
        return array;
    

二、快速排序(Quick Sort)

1.原理

1.在数组中选一个基准数pivot(我选取了数字的最后一个数字作为基准数);

2.通过“遍历的方式”,比较给定元素和区间内其他元素的大小关系,形成<=pivot,pivot,>=pivot三个区间;

3.对于基准数左、右两边的数组,不断重复以上两个过程,直到每个子集只有一个元素,即为全部有序。

2.代码实现

public static void quickSort(long[] array) 
        quickSortRange(array, 0, array.length - 1);
    
    // 为了代码书写方便,我们选择使用左闭右闭的区间表示形式
    // 其中,from,to 下标的元素都算在区间的元素中
    // 左闭右闭的情况下,区间内的元素个数 = to - from + 1;
    private static void quickSortRange(long[] array, int from, int to) 
        if (to - from + 1 <= 1) 
            // 区间中元素个数 <= 1 个
            return;
        
        // 挑选中区间最右边的元素 array[to]
        int pi = partitionMethodA(array, from, to);
        quickSortRange(array, from, pi - 1);    
        // 针对小于等于 pivot 的区间做处理
        quickSortRange(array, pi + 1, to);   
        // 针对大于等于 pivot 的区间做处理
    

    private static int partitionMethodA(long[] array, int from, int to) 
        // 1. 先把 pivot 找出来
        long pivot = array[to];
        // 2. 通过定义 left 和 right 两个下标,将区间划分出来
        int left = from;
        int right = to;
        // [from, left)   都是 <= pivot 的
        // [left, right)  都是未参与比较的
        // [right, to]    都是 >= pivot 的
        while (left < right) 
            // 随着 left 在循环过程中一直在 left++,请问 left < right 的条件不一定能保证,所以,我们时刻进行 left < right 条件的保证
            while (left < right && array[left] <= pivot) 
                left++;
            
            while (left < right && array[right] >= pivot) 
                right--;
            
            // 循环停止时,说明 array[right] < pivot
            // 两边都卡住时,交换 [left] 和 [right] 位置的元素
            long t = array[left];
            array[left] = array[right];
            array[right] = t;
        
        long t = array[to];
        array[to] = array[left];
        array[left] = t;
        // 返回 pivot 最终所在下标
        return left;
    

三、选择排序(Selection Sort)

1.原理

1.遍历所有数据,先在数据中找出最大或最小的元素,放到序列的起始;
2.再从余下的数据中继续寻找最大或最小的元素,依次放到序列中;
3.直到所有数据有序。

2.代码实现

public static long[] selectionsort(long[] array)
        if (array.length == 0)
            return array;
        for (int i = 0; i < array.length; i++) 
            int minIndex = i;
            for (int j = i+1; j < array.length; j++) 
                if (array[j] < array[minIndex]) 
                //找到最小的数
                    minIndex = j; 
                    //将最小数的索引保存
            
            long temp = array[minIndex];
            array[minIndex] = array[i];
            array[i] = temp;
        
        return array;
    

四、插入排序(Insertion Sort)

1.原理

将前i个(初始为1)数据假定为有序序列,依次遍历数据,将当前数据插入到前述有序序列的适当位置,形成前i+1个有序序列,依次遍历完所有数据,直至序列中所有数据有序。

2.代码实现

// [from, to] 是左闭右闭的
    private static void insertSortRange(long[] array, int from, int to) 
        int size = to - from;
        for (int i = 0; i < size; i++) 
            // 有序区间 [from, from + i]
            // 无序区间 [from + i + 1, to]
            // 选中的无序区间的第一个元素 array[from + i + 1]
            long key = array[from + i + 1];
            int j;
            for (j = from + i; j >= from && array[j] > key; j--) 
                array[j + 1] = array[j];
            
            array[j + 1] = key;
        
    

五、希尔排序(Shell Sort)

1.原理

先将整个数据序列分割成若干子序列分别进行直接插入排序,待整个序列中的记录基本有序时,再对全部数据进行依次直接插入排序,直至所有数据有序。

2.实现代码

public static long[] shellsort(long[] array,int gap)
        for (int i = 0; i < array.length-gap; i++) 
            //[0,i+gap)为有序区间,[i+gap,n)为无序区间
            long k=array[i+gap];
            //无序区间的第一个
            int j;
            for (j = i; j >0&&k<array[j] ; j=j-gap) 
                array[j+gap]=array[j];
            
            array[j+gap]=k;
        
        return array;
    

六、堆排序(Heap Sort)

1.原理

堆排序利用堆这种近似完全二叉树的数据结构进行排序。堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。以最大堆为例,堆中的最大值总是位于根节点。首先将待排序的n个数据构造为大根堆,将顶端数据与末尾数据进行交换并将堆的尺寸减一,然后剩余n-1个数据再次构造为大根堆,再次交换,再次缩减,直至所有数据有序。

2.实现代码

public static void heapSort(long[] array) 
        // 建立大堆
        createBigHeap(array);
        for (int i = 0; i < array.length - 1; i++) 
            //交换之前的无序区间 [0, n - i)
            swap(array, 0, array.length - i - 1);
            // 交换之后的无序区间 [0, n - i - 1),元素个数 n - i - 1 个
            // 对堆的 [0] 进行向下调整,堆里的元素个数就是无序区间的元素个数
            shiftDown(array, array.length - i - 1, 0);
        
    
    private static void shiftDown(long[] array, int size, int index) 
        while (2 * index + 1 < size) 
            int maxIdx = 2 * index + 1;
            int right = maxIdx + 1;
            if (right < size && array[right] > array[maxIdx]) 
                maxIdx = right;
            
            if (array[index] >= array[maxIdx]) 
                return;
            
            swap(array, index, maxIdx);
            index = maxIdx;
        
    
    private static void createBigHeap(long[] array) 
        // 从最后一个元素的双亲开始
        for (int i = (array.length - 2) / 2; i >= 0; i--) 
            shiftDown(array, array.length, i);
        
    
    private static void swap(long[] array, int i, int j) 
        long t = array[i];
        array[i] = array[j];
        array[j] = t;
    

七、归并排序(Merge Sort)

1.原理

归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序

2.实现代码

public static void mergeSort(long[] array) 
        mergeSortRange(array, 0, array.length);
    
    //这里的 [from, to) 是左闭右开来表示区间的
    private static void mergeSortRange(long[] array, int from, int to) 
        int size = to - from;
        if (size <= 1) 
            return;
        
        int mid = from + (size / 2);    
        //优先对左 [from, mid) 和右 [mid, to) 两个小区间先进行排序(使用同样的方式处理:分治思想)
        mergeSortRange(array, from, mid);
        mergeSortRange(array, mid, to);        
        //有了两个分别各自有序的小区间 [from, mid) 和 [mid, to)
        //通过一定的方式,将 [from, mid) [mid, to) 合并到 [from, to) 都是有序的
        //两个有序数组区间合并到一个有序数组区间(需要结果放回原地去)
        merge(array, from, mid, to);
    
    private static void merge(long[] array, int from, int mid, int to) 
        // 先计算出来额外空间需要多个,计算两个区间加起来多少个元素
        int size = to - from;
        // 申请一个额外的数组作为临时保存的地方
        long[] other = new long[size];
        int left = from;    // 左边小区间的下标
        int right = mid;    // 右边小区间的下标
        int dest = 0;       // 临时空间的下标
        // 只要左右两个小区间还有元素要参与比较
        while (left < mid && right < to) 
            if (array[left] <= array[right]) 
                other[dest++] = array[left++];
             else 
                other[dest++] = array[right++];
            
        
        // 其中一个区间的元素取完了,另一个区间里一定还有元素,再把剩余的元素,统统放入 other
        while (left < mid) 
            other[dest++] = array[left++];
        
        while (right < to) 
            other[dest++] = array[right++];
        
        // 把 other 中的有序元素,复制回 array 中,要注意下标的问题
        for (int i = 0; i < size; i++) 
            array[from + i] = other[i];   
        
    

八、桶排序(Bucket Sort)

桶排序属于计数排序的升级强化版,同时利用了分治的思想,将待排数据划分到一定数量的有序的桶里,然后再对每个桶中的数据进行排序(桶排序的稳定性取决于桶内排序算法是否稳定),最后再将各个桶里的数据有序的合并到一起。最理想的情况下,输入数据可以被均匀的分配在每一个桶中,时间复杂度可以降到O(n);最坏的情况为所有数据在同一个桶中进行排序,且使用了复杂度较高的排序算法,此时时间复杂度会变为O(n²)。为了使桶排序更加高效,需要做到以下两点:①在额外空间充足的情况下,尽量增加桶的数量。②使用的映射函数能够将输入的 N 个数据均匀的分配到 K 个桶中。


以上是关于java排序算法的主要内容,如果未能解决你的问题,请参考以下文章

八大排序算法Java实现(下)-快排归排基数排序

算法练习5---快速排序Java版

快速排序——JAVA实现(图文并茂)

Unity中的快速排序算法&&二分查找

用JAVA实现快速排序

java之快速排序