常见排序算法

排序的稳定性:两个相等的数字在排序后相对位置不发生变化,这种算法就是稳定的。

排序算法时间,复杂度空间复杂度以及稳定性
排序方法最好平均最坏空间复杂度稳定性
冒泡排序O(n)O(n^2)O(n^2)O(1)稳定
插入排序O(n)O(n^2)O(n^2)O(1)稳定
选择排序O(n^2)O(n^2)O(n^2)O(1)不稳定
希尔排序O(n)O(n^1.3)O(n^2)O(1)不稳定
堆排序O(n*log(n))O(n*log(n))O(n*log(n))O(1)不稳定
快速排序O(n*log(n))O(n*log(n))O(n^2)O(log(n))~O(n)不稳定
归并排序O(n*log(n))O(n*log(n))O(n*log(n))O(1)稳定

1.直接插入排序:认为第一个数已经有序,从第二个数开始,从后往前遍历已经有序的数组,直到找到比第二个数字小的数字,将第二个数字排在比它小的数字后;这时认为前两个数字已经有序,继续从第三个数字开始,重复前面的步骤;一直重复,直到排序完成。

static int[] insertionSort (int[] arr) {
        if (arr.length==0) return arr;
        int cur = 0;
        for (int i=0; i<arr.length; i++) {
            cur = arr[i+1];
            int preIndex = i;
            while (preIndex>=0&&cur<arr[preIndex]) {
                arr[preIndex+1] = arr[preIndex];
                preIndex--;
            }
            arr[preIndex+1] = cur;
        }
        return arr;
    }

2.希尔排序:又称为缩小增量法,是插入排序的改良版。先把所有数进行分组,再对每一组进行插入排序;然后重复分组,排序,直到最终有序。

public static void shellSort(int[] arr) {
        int gap = arr.length;
        while (gap>1) {
            insertSortGap(arr,gap);
            gap = (gap/3)+1;
        }
        insertSortGap(arr,1);
    }
    private static void insertSortGap(int[] arr, int gap) {
        for (int i = 0; i < arr.length; i++) {
            int v = arr[i];
            int j = i - gap;
            for ( ; j >= 0 && arr[j] > v; j -= gap) {
                arr[j+gap] = arr[j];
            }
            arr[j+gap] = v;
        }
    }

3.选择排序:在数组中找出最小的数排在最前面;已经排序好的最小数字除外,重复操作,直到排序完成。

 static int[] selectionSort (int[] arr) {
        if (arr.length==0) return arr;
        int min = 0, index = 0;
        for (int i=0; i<arr.length; i++) {
            min = arr[i];
            index = i;
            for (int j=i; j<arr.length; j++) {
                if (min>arr[j]) {
                    min = arr[j];
                    index = j;
                }
            }
            int tmp = arr[i];
            arr[i] = min;
            arr[index] = tmp;
        }
        return arr;
    }

4.堆排序:堆排序是基于堆这种数据结构产生的一种排序算法。堆有小根堆和大根堆两种,大根堆的根节点的值大于左右子节点的值,小根堆的根节点的值小于左右子节点的值。如下图所示,

 以大根堆为例,堆排序的操作步骤是,堆顶元素是最大的元素,将堆顶元素放到队尾,然后将其余元素重新构造成为大根堆,然后重复前面的步骤,最终就得到了降序排列的一组元素。

5.冒泡排序:比较相邻两个数大小,让较小的数在前面;对每一对数字进行比较,这样最大的数就在最后了;重复上面操作,但是最后一个数不动;一直重复,直到排序完成。

static int[] bubbleSort (int[] arr) {
        if (arr.length==0) return arr;
        for (int i=0; i<arr.length; i++) {
            for (int j=0; j<arr.length-1-i; j++) {
                if (arr[j]>arr[j+1]) {
                    int tmp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = tmp;
                }
            }
        }
        return arr;
    }

6.快速排序:选一个数作为基准,遍历数组,将比基准小的数放到基准左边,比基准大的数放到基准右边;采用分治思想,对基准左右两个区间进行选基准,遍历数组操作,直到区间长度为1,表示已经有序,或者区间长度为0,代表没有数据了。

public class QuickSort {
    public void quickSort(int[] a,int l,int r){
        if (l<r){
            int temp=a[l];
            while (l<r){
                while (l<r && a[r]>temp){
                    r--;
                }
                if (l<r){
                    a[l++]=a[r];
                }
                while (l<r && a[l]<=temp){
                    l++;
                }
                if (l<r){
                    a[r--]=a[l];
                }
            }
            a[l]=temp;
            quickSort(a,l,temp-1);
            quickSort(a,temp+1,r);
        }
    }
}

7.归并排序:归并排序是建立在归并操作上的一种有效的排序算法,采用分治思想。将已有序的子序列合并,得到完全有序的序列;即先让每个子序列有序,再让子序列段间有序。若将两个有序表合并成一个有序表,称为二路合并。

public static void mergeSort(int[] array) {
    mergeSortInternal(array, 0, array.length);
}
private static void mergeSortInternal (int[] array, int low, int high) {
    if (low-1 >= high) {
        return;
    }
    int mid = (low+high) / 2;
    mergeSortInternal(array, low, mid);
    mergeSortInternal(array, mid, high);
    
    merge(array, low, mid, high);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值