排序

1.概念

1.1 排序
排序,就是让一串记录,按照其中某个或者某些关键字的大小,递增或递减的排列起来的操作。平时上下文中,如果提到排序,通常升序排列。

1.2 稳定性
两个相等的数据,如果排序后,排序算法能保证其相对位置不会发生变化,则我们就称该算法是稳定的排序算法。

2.基于比较的常用排序算法
常用排序算法:插入排序(直接插入排序、希尔排序),选择排序(选择排序、堆排序),交换排序(冒泡排序、快速排序),归并排序

3.插入排序

3.1直接插入排序
原理:将整个区间分为有序区间和无序区间,每次选择无序区间的第一个元素,在有序区间的合适位置插入

3.2 插入排序的代码实现

//插入排序
    public static void insertSort(int[] arr) {
        int bound = 1;
        for (; bound < arr.length; bound++) {
            int v = arr[bound];
            int cur = bound - 1;
            for (; cur >= 0; cur--) {
                if (arr[cur] > v) {
                    arr[cur + 1] = arr[cur];
                }else{
                    break;
                }
            }
            arr[cur + 1] = v;
        }
    }

3.3性能分析

时间复杂度为:最好为O(n)、平均为O(n2)、最坏为O(n2)

空间复杂度;O(1)

稳定性:稳定

4.希尔排序
4.1希尔排序原理
希尔排序法的基本思想是:先选定一个整数,把带排序文件中所有记录分成个gap组,所有距离为gap的记录分在同一个组内,并对每一组的记录进行排序。然后,取gap=gap/2,重复上述分组和排序工作。当gap=1时,所有记录在同一组内排好序。
1、希尔排序是对直接插入排序的优化
2、当gap>1时都是预排序,目的是让数组更接近于有序。当gap==1时,数组已经接近有序了。
希尔排序图示4.2希尔排序的代码实现

public static void shellSort(int[] arr) {
        int gap = arr.length / 2;
        while (gap >= 1) {
            _shellSort(arr, gap);
            gap = gap / 2;

        }
    }

    public static void _shellSort(int[] arr, int gap) {
        int bound = gap;
        for (; bound < arr.length; bound++) {
            int v = arr[bound];
            int cur=bound-gap;
            for (; cur >= 0; cur--) {
                if (arr[cur] > v) {
                    arr[cur + gap] = arr[cur];
                }
                else {
                    break;
                }
            }
            arr[cur + gap] = v;
        }
    }

4.3性能分析
时间复杂度
最好:O(n),平均时间复杂度:O(n^1.3),空间复杂度:O(1)

稳定性;不稳定

5.选择排序
5.1 选择排序原理
每一次从无序区间选出最大(或最小)的一个元素,存放在无序区间的最后(或者最前),直到全部待排序的数据排完。

5.2 选择排序代码实现

 public static void selectSort(int[] arr) {
        int bound = 0;
        for (; bound < arr.length; bound++) {
            for (int cur = bound + 1; cur < arr.length; cur++) {
                if (arr[cur] < arr[bound]) {
                    swap(arr, cur, bound);
                }
            }
        }
    }

    public static void swap(int[] arr, int x, int y) {
        int tem = arr[x];
        arr[x] = arr[y];
        arr[y] = tem;

5.3 性能分析
时间复杂度:O(n^2)
空间复杂度:O(1)
稳定性:不稳定

6.堆排序

6.1 堆排序原理
基本原理也是选择排序,只是不再使用遍历的方式查找无序区间的最大的数,而是通过堆来选择无序区间的最大数。
排升序建大堆,排降序建小堆。

6.2 堆排序代码实现

public static void heapSort(int[] arr) {
        createHeap(arr);
        int heapSize = arr.length;
        for (int i = 0; i < arr.length; i++) {
            swap(arr, 0, heapSize);
            heapSize--;
            shiftDown(arr, heapSize, 0);
        }
    }

    public static void createHeap(int[] arr) {
        for (int i = (arr.length - 1 - 1) / 2; i >= 0; i--) {
            shiftDown(arr, arr.length, i);
        }
    }

    public static void shiftDown(int[] arr, int size, int index) {
        int parent = index;
        int child = 2 * parent + 1;
        while (child < size) {
            if (child + 1 < size && arr[child + 1] > arr[child]) {
                child = child + 1;
            }
            if (arr[parent] < arr[child]) {
                swap(arr, parent, child);
            }
            else {
                break;
            }
            parent=child;
            child = 2 * parent + 1;
        }
    }
    public static void swap(int[] arr, int x, int y) {
        int tem = arr[x];
        arr[x] = arr[y];
        arr[y] = tem;

6.3性能分析
时间复杂度:O(n*log(n))
空间复杂度:O(1)

稳定性:不稳定

7.冒泡排序
7.1冒泡排序原理
在无序区间,通过相邻数的比较,将最大的数冒泡到无序区间的最后,持续整个过程,直到数组整体有序。

7.2冒泡排序代码实现

public static void bubbleSort(int[] arr) {
        for (int bound = 0; bound < arr.length; bound++) {
            for (int cur = arr.length - 1; cur >= bound; cur--) {
                if (arr[cur - 1] > arr[cur]) {
                    swap(arr, cur - 1, cur);
                }
            }
        }
    }
    public static void swap(int[] arr, int x, int y) {
        int tem = arr[x];
        arr[x] = arr[y];
        arr[y] = tem;

7.3性能分析
最好时间复杂度:O(n),平均时间复杂度O(n2),最坏时间复杂度:O(n2).
空间复杂度:O(1)

稳定性:稳定

8.快速排序
8.1快速排序原理
1、从带排序区间选择一个数,作为基准值(pivot);
2、Partition:遍历整个待排序区间,将比基准值小的(可以包含相等的)放到基准值的左边,将播基准值大的放到基准值的右边;
8.2 快速排序代码实现

public static void quickSort(int[] arr) {
        _quickSort(arr, 0, arr.length - 1);
    }

    public static void _quickSort(int[] arr, int left, int right) {
        if (left >= right) {
            return;
        }
        int index = partition(arr, left, right);
        _quickSort(arr, left, index - 1);
        _quickSort(arr, index + 1, right);
    }
    public static int partition(int[] arr,int left,int right) {
        int v = arr[right];
        int l = left;
        int r = right;
        while (l < r) {
            while (l < r && arr[l] <= v) {
                l++;
            }
            while (l < r && arr[r] >= v) {
                r--;
            }
            swap(arr, l, r);
        }
        swap(arr, l, right);
        return l;
    }

8.3性能分析
时间复杂度
最好时间复杂度:O(nlog(n))
平均时间复杂度:O(n
log(n)
最坏时间复杂度:O(n^2)

空间复杂度
最好空间复杂度:O(nlog(n))
平均空间复杂度:O(n
log(n))
最坏时间复杂度:O(n)

9.归并排序

9.1归并排序原理
归并排序(MERGE-SORT)是建立在归并操作上的一种有效排序算法,该算法是采用分治法的一个非常典型应用。将已有序的子序合并,得到完全有序的序列;即先使每个子序有序,再使子序列断间有序。若将两个有序表合成一个有序表,称为二路归并。

9.2归并排序代码实现

    public static void mergeSort(int[] arr) {
        _mergeSort(arr, 0, arr.length);
    }

    // 辅助递归的方法
    public static void _mergeSort(int[] arr, int left, int right) {
        if (right - left <= 1) {
            // 判定当前区间是不是只有一个元素或者没有元素
            // 此时不需要进行排序
            return;
        }
        int mid = (left + right) / 2;
        // 先让 [left, mid) 区间变成有序
        _mergeSort(arr, left, mid);
        // 再让 [mid, right) 区间变成有序
        _mergeSort(arr, mid, right);
        // 合并两个有序区间
        merge(arr, left, mid, right);
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值