排序算法学习

顶部膜拜大神:https://www.cnblogs.com/onepixel/articles/7674659.html,https://blog.csdn.net/qq_38963493/article/details/80204118

突然发现得先理解,再记住,能够达到提到算法的名字,就能手敲,写出来的地步;

排序算法的使用场景

冒泡排序 *  时间复杂度O(n^2),空间复杂度O(1),稳定 * 适用场合:数据量量不大,对稳定性有要求,且数据基本有序的情况下

插入排序* 时间复杂度O(n^2),空间复杂度O(1),稳定   * 适用场合:数据量不大,对算法的稳定性有要求,且数据局部或者整体有序的情况,小规模如10个数平均时间最快,可以在快排中调用

选择排序 * 时间复杂度O(n^2),空间复杂度O(1),不稳定 * 适用场合:当数据量不大,且对稳定性没有要求的时候

快速排序

* 时间复杂度O(n log n),空间复杂度O(n log n),不稳定,选好枢纽元是使坏情况发生的关键
* 截断范围选10比较合适,进入截断范围改用小规模高效率算法对小片段排序
* 适用场合:数值范围较大,相同值的概率较小,数据量大且不考虑稳定性的情况,数值远大于数据量时威力更大

希尔排序
* 使用简单的希尔增量序列,复杂的增量序列中Sedgewick 增量序列最坏时间复杂度达到O(n^1.3)
* 时间复杂度取决于增量序列,空间复杂度O(1),不稳定!!!
* 适用场合:数据量较大,不要求稳定性

1.冒泡排序

自己理解:数组中循环比较前一个元素和后一个元素的大小,如果前一个大于后一个元素就进行交换,比较到最后,数组中的最后一个值就是最大的那个了,然后继续比较剩下的元素,直到比较完成

//冒泡排序
public static void maoSort(int[] arr) {
        int len = arr.length;
        for (int i = 0; i < len - 1; i++) {
            for (int j = 0; j < len - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }

2.选择排序

个人理解:先以数组第一个值为基准值,比较数组其他元素,找到最小的元素,并与当前基准值交换,然后以数组第二个元素为基准值,比较数组其他元素,找到最小的元素,并与当前基准值交换,以此类推。排序完成

//选择排序
    public static void selectSort(int[] arr) {
        int min,temp;
        for (int i = 0; i < arr.length-1; i++) {
            min = i;
            for (int j = i+1; j < arr.length; j++) {
                if (arr[j]<arr[min]){
                    min=j;
                }
            }
            temp = arr[i];
            arr[i]=arr[min];
            arr[min]=temp;
            
        }
    }

3.插入排序

个人理解:

第一轮:把数组第一个元素当作已排序队列,拿第二个元素比较第一个元素,大于就把该元素插入到第一个元素后面

第二轮:前两个元素作为已排序队列,拿第三个元素从后往前比已排序队列,大于第i-1个元素并小第i个元素,把元素插入到i位置

以此类推

当元素小于已排序列表的第一个元素时,pre为-1,插入到已排序数组首位

public static void insertSort(int[] a){
        int len = a.length;
        int pre,current;
        for (int i = 1; i <len ; i++) {
            pre = i-1;
            current = a[i];
            while (pre>=0&&a[pre]>current){
                a[pre+1] = a[pre];
                pre--;
            }
            a[pre+1] = current;
        }
    }

4.希尔排序

基于插入排序的排序算法

 public static void shellSort(int[] arr){
        int length = arr.length;
        int temp;
        for (int step = length / 2; step >= 1; step /= 2) {
            for (int i = step; i < length; i++) {
                temp = arr[i];
                int j = i - step;
                while (j >= 0 && arr[j] > temp) {
                    arr[j + step] = arr[j];
                    j -= step;
                }
                arr[j + step] = temp;
            }
        }
    }

5.归并排序

 public static void guiSort(int[] arr,int[] result, int start, int end){
        if (start >= end)
            return;
        int len = end - start, mid = (len >> 1) + start;
        int start1 = start, end1 = mid;
        int start2 = mid + 1, end2 = end;
        guiSort(arr, result, start1, end1);
        guiSort(arr, result, start2, end2);
        int k = start;
        while (start1 <= end1 && start2 <= end2)
            result[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];
        while (start1 <= end1)
            result[k++] = arr[start1++];
        while (start2 <= end2)
            result[k++] = arr[start2++];
        for (k = start; k <= end; k++)
            arr[k] = result[k];
    }

 

6.快速排序

 public static int[] quickSort(int arr[],int start,int end) {
        int pivot = arr[start];
        int i = start;
        int j = end;
        while (i<j) {
            while ((i<j)&&(arr[j]>pivot)) {
                j--;
            }
            while ((i<j)&&(arr[i]<pivot)) {
                i++;
            }
            if ((arr[i]==arr[j])&&(i<j)) {
                i++;
            } else {
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
        if (i-1>start) arr=quickSort(arr,start,i-1);
        if (j+1<end) arr=quickSort(arr,j+1,end);
        return (arr);
    }

 

7.堆排序

public static int[] heapSort(int[] array) {
        //这里元素的索引是从0开始的,所以最后一个非叶子结点array.length/2 - 1
        for (int i = array.length / 2 - 1; i >= 0; i--) {
            adjustHeap(array, i, array.length);  //调整堆
        }

        // 上述逻辑,建堆结束
        // 下面,开始排序逻辑
        for (int j = array.length - 1; j > 0; j--) {
            // 元素交换,作用是去掉大顶堆
            // 把大顶堆的根元素,放到数组的最后;换句话说,就是每一次的堆调整之后,都会有一个元素到达自己的最终位置
            swap(array, 0, j);
            // 元素交换之后,毫无疑问,最后一个元素无需再考虑排序问题了。
            // 接下来我们需要排序的,就是已经去掉了部分元素的堆了,这也是为什么此方法放在循环里的原因
            // 而这里,实质上是自上而下,自左向右进行调整的
            adjustHeap(array, 0, j);
        }
        return array;
    }

    /**
     * 整个堆排序最关键的地方
     * @param array 待组堆
     * @param i 起始结点
     * @param length 堆的长度
     */
    public static void adjustHeap(int[] array, int i, int length) {
        // 先把当前元素取出来,因为当前元素可能要一直移动
        int temp = array[i];
        for (int k = 2 * i + 1; k < length; k = 2 * k + 1) {  //2*i+1为左子树i的左子树(因为i是从0开始的),2*k+1为k的左子树
            // 让k先指向子节点中最大的节点
            if (k + 1 < length && array[k] < array[k + 1]) {  //如果有右子树,并且右子树大于左子树
                k++;
            }
            //如果发现结点(左右子结点)大于根结点,则进行值的交换
            if (array[k] > temp) {
                swap(array, i, k);
                // 如果子节点更换了,那么,以子节点为根的子树会受到影响,所以,循环对子节点所在的树继续进行判断
                i  =  k;
            } else {  //不用交换,直接终止循环
                break;
            }
        }
    }

    /**
     * 交换元素
     * @param arr
     * @param a 元素的下标
     * @param b 元素的下标
     */
    public static void swap(int[] arr, int a, int b) {
        int temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }

根据大神的动图,我能明白意思,但还是记不住...实现不了

posted @ 2021-05-25 11:39  张碧晨  阅读(106)  评论(0)    收藏  举报