美文网首页
冒泡、插入、归并、快速和堆排序

冒泡、插入、归并、快速和堆排序

作者: PENG先森_晓宇 | 来源:发表于2024-02-03 20:28 被阅读0次
package com.sftech.sds.common.center.manager;


import java.util.*;

class Study {

    /**
     * 冒泡:时间复杂度o(n^2),空间复杂度o(1),原地算法,且是稳定的算法
     *
     * @param nums
     * @return
     */
    public int[] sort(int[] nums) {

        for (int i = 0; i < nums.length; i++) {
            boolean flag = false;
            for (int j = 0; j < nums.length - i - 1; j++) {
                if (nums[j] > nums[j + 1]) {
                    int temp = nums[j];
                    nums[j] = nums[j + 1];
                    nums[j + 1] = temp;
                    flag = true;
                }
            }
            if (!flag) {
                break;
            }
        }
        return nums;
    }

    /**
     * 插入:时间复杂度o(n^2),空间复杂度o(1),原地且稳定的算法
     *
     * @param nums
     * @return
     */
    public int[] insertSort(int[] nums) {
        for (int i = 1; i < nums.length; i++) {
            int temp = nums[i];
            int j = i - 1;
            for (; j >= 0; j--) {
                if (temp < nums[j]) {
                    nums[j + 1] = nums[j];
                } else {
                    break;
                }
            }

            nums[j + 1] = temp;
        }
        return nums;
    }

    /**
     * 归并:时间复杂度o(n log n),空间复杂度为o(n),不是原地算法,是稳定的算法
     *
     * @param nums
     * @return
     */
    public int[] guiBingSort(int[] nums) {
        guiSort(0, nums.length - 1, nums);
        return nums;
    }

    public void guiSort(int start, int end, int[] nums) {
        if (start == end) {
            return;
        }
        int middle = (start + end) / 2;
        guiSort(start, middle, nums);
        guiSort(middle + 1, end, nums);

        mergeSort(start, middle, end, nums);
    }

    public void mergeSort(int start, int middle, int end, int[] nums) {
        int[] c = new int[end - start + 1];
        int i = start;
        int j = middle + 1;
        int x = 0;
        while (i <= middle && j <= end) {
            if (nums[i] < nums[j]) {
                c[x++] = nums[i++];
            } else {
                c[x++] = nums[j++];
            }
        }
        while (i <= middle) {
            c[x++] = nums[i++];
        }
        while (j <= end) {
            c[x++] = nums[j++];
        }
        for (int w = 0; w < c.length; w++) {
            nums[start + w] = c[w];
        }
    }

    /**
     * 快速排序:时间复杂度o(n log n),空间复杂度o(1),属于原地算法,但不是稳定算法:因为最后一个pivot需要和对应的i下表互换,如果pivot和i下标是相同值时互换则体现出不稳定了
     *
     * @param nums
     * @return
     */
    public int[] quickSort(int[] nums) {
        quick(0, nums.length - 1, nums);
        return nums;
    }

    public void quick(int start, int end, int[] nums) {
        if (start >= end) {
            return;
        }
        int pivot = getPivot(start, end, nums);
        quick(start, pivot - 1, nums);
        quick(pivot + 1, end, nums);
    }

    public int getPivot(int start, int end, int[] nums) {
        int pivot = nums[end];
        int i = start, j = start;
        while (j <= end - 1) {
            if (nums[j] < pivot) {
                int temp = nums[j];
                nums[j] = nums[i];
                nums[i] = temp;
                i++;
            }
            j++;
        }
        nums[end] = nums[i];
        nums[i] = pivot;
        return i;
    }


    /**
     * 堆排序:时间复杂度o(log n),空间复杂度o(1),原地算法,不是稳定算法:因为在排序的过程,存在将堆的最后一个节点跟堆顶节点互换的操作,所以就有可能改变值相同数据的原始相对顺序。
     * @param nums
     * @return
     */
    public int[] deapSort(int[] nums) {

        for (int i = (nums.length - 2) / 2; i >= 0; i--) {
            createDeap(i,nums,nums.length);
        }
        for(int i=nums.length-1;i>=0;i--){
            int temp = nums[0];
            nums[0] = nums[i];
            nums[i] = temp;
            createDeap(0,nums,i);
        }

        return  nums;
    }

    /**
     * 构建大顶堆:为什么是生序排序,确实构造一个大顶堆呢?因为是拿最大值放到元素中nums的最后一个元素,即在元素上直接操作,着就是为什么堆排序的空间复杂度为o(1)
     * @param i
     * @param nums
     */
    public void createDeap(int i, int[] nums,int length) {
        while (true) {
            int j = i;
            int left = i * 2 + 1;
            int right = i * 2 + 2;
            if (left < length && nums[j] < nums[left]) {
                j = left;
            }
            if (right < length && nums[j] < nums[right]) {
                j = right;
            }
            if (i != j) {
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j] = temp;
                i = j;
            } else {
                break;
            }
        }
    }


    public static void main(String[] args) {
        Study study = new Study();
        study.deapSort(new int[]{20, 7, 6, 10, 15, 8, 3, 21, 22, 2,12,13});
    }

}

相关文章

  • Datawhale | 编程第6期 Test 3

    排序 1.实现归并排序、快速排序、插入排序、冒泡排序、选择排序、堆排序(选做) 归并排序 快速排序 插入排序 冒泡...

  • 常用算法 2018-08-31

    冒泡排序 堆排序 归并排序 快速排序 插入排序 选择排序

  • 桶排序与力扣(LeetCode) -164 最大间距

    在我的博客冒泡排序、插入排序、快速排序、堆排序、归并排序总结中介绍了几种经典的排序方法,其中快速排序、堆排序和归并...

  • 常见排序算法代码集锦

    冒泡排序 快速排序 归并排序 堆排序 选择排序 插入排序 希尔排序

  • 排序算法总结

    冒泡排序 选择排序 插入排序 归并排序 希尔排序 快速排序 堆排序

  • 常用排序算法总结

    冒泡排序 选择排序 直接插入排序 归并排序 快速排序 堆排序

  • 面试准备--排序

    堆排序 快速排序(simple) 快速排序(regular) 归并排序 Shell排序 插入排序 选择排序 冒泡排序

  • 排序

    冒泡排序: 冒泡排序 选择排序: 插入排序: 希尔排序: 归并排序: 快速排序: 堆排序: 计数排序: 桶排序: ...

  • 【专题】算法

    一、排序 冒泡、选择、插入、快速、归并、堆排序https://www.cnblogs.com/eniac12/p/...

  • 前端基础整理 | 算法基础

    排序算法 冒泡排序 选择排序 插入排序 希尔排序 归并排序 堆排序 快速排序

网友评论

      本文标题:冒泡、插入、归并、快速和堆排序

      本文链接:https://www.haomeiwen.com/subject/nrbxadtx.html