排序,java代码实现(下)

承接上篇文章,本文章主要为后续的三种排序:

  • 冒泡排序
  • 快速排序
  • 归并排序

冒泡排序
冒泡排序的原理是:
通过遍历无序区间,比较相邻的数,将较大的放在后面,通过多段交换,使其达成一种无序区在前,有序区在后的形态,直至完全有序为止。

时间复杂度:
最好O(n) 平均O(n^2) 最坏O(n^2)
空间复杂度:O(1)
稳定性:稳定

代码实现:

private static void swap(int[] array, int i, int j) {//交换部分
        int t = array[i];
        array[i]= array[j];
        array[j]= array[i];
    }



    public static void bubbleSort(int[] array){//冒泡部分
        for (int i = 0;i<array.length-1;i++){
            for (int j=0;j<array.length-i-1;j++){
                if (array[j]>array[j+1]){
                    swap(array,j,j+1);
                }
            }
        }
    }

快速排序
快速排序属于分治排序,我们可以采用递归的思想,将一个无序的大数组,分割成若干个小数组,再对小数组进行排序,以达到整体有序的目的。

步骤:
1.在整个待排序区间中确认一个基准值
2.遍历整个待排序区间,将所有数据和基准值进行比较,最终实现:
比基准值小的在基准值的左边
比基准值大的在基准值的右边
3.用同样的方法去处理左右两个小的待排序区间,直到小的待排序区间内没有数据(size0)或者已经有序了(size1)为止

代码实现:

public static void quickSort(int[] array){//快速排序
        quickSortInteral(array,0,array.length-1);
    }

    private static void quickSortInteral(int[] array, int left, int right) {
        if (left>=right){
            return;
        }

        int pivotindex = partition(array,left,right);

        quickSortInteral(array,left,pivotindex-1);
        quickSortInteral(array,pivotindex+1,right);
    }

代码中的 partition 即为具体的处理方法,在此主要有这四种方法:
1.Hover 左右靠近,不满足条件则交换
2.挖坑 左右靠近,不满足条件则埋坑
3.前后下标 从左到右,满足条件则交换
4.会把和基准值相等的情况单独处理

代码如下:

private static int partition(int[] array, int left, int right) {
        int pivot = array[right];
        int less = left;
        int great = right;

        while (less<great){
            while (less <great&&array[less]<=pivot){
                less++;
            }
            while (less <great&&array[great]>=pivot){
                great--;
            }
            swap(array,less,great);
        }
        swap(array,right,less);
        return less;
    }
    private static int partition2(int[] array, int left, int right){
        int pivot = array[right];
        int less = left;
        int great = right;
        while (less<great){
            while (less <great&&array[less]<=pivot){
                less++;
            }
            array[great]=array[less];
            while (less <great&&array[great]>=pivot){
                great--;
            }
            array[less]=array[great];
        }
       array[less]=pivot;
        return less;

    }

    public static int partition3(int[] array,int left,int right){
        int blue = left;
        int pivot = array[right];

        for (int i = left;i<right;i++){
            if(array[i]<pivot){
                swap(array,blue,i);
                blue++;
            }
        }
        swap(array,blue,right);
        return blue;
    }

也可以用非递归的方式实现快速排序:
如何使用非递归实现快速排序?
使用栈记录,待排序区间的左右边界

public static void quickSortNoR(int[] array){
        Stack<Integer> stack = new Stack<>();
        stack.push(array.length-1);
        stack.push(0);

        while (!stack.isEmpty()){
            int left =stack.pop();
            int right = stack.pop();

            int pivot = partition(array,left,right);
            stack.push(right);
            stack.push(pivot+1);

        }
    }

快速排序时间复杂度:
最好/平均 O(n*log(n))
最坏:O(n^2)

空间复杂度:O(N)

归并排序(合并排序)
合并两个有序数组的过程:
平均切分待排序区间,如果待排序区间的左右两个小区间有序了,则按照合并有序数组的方式使其最终有序。
这种方法是最常见的一种外部排序。

如果数据量大到内存中存放不下,就可以使用归并排序来处理

注:外部排序:不是所有的操作都需要借助内存的排序

代码如下:

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

    private static void internal(int[] array, int low, int high) {
        if (low+1>=high){
            return;
        }
        int mid = (low + high)/2;
        internal(array,low,mid);
        internal(array,mid,high);
        merge(array,low,mid,high);
    }

    private static void merge(int[] array, int low, int mid, int high) {
        int length = high - low;
        int[] extra = new int[length];
        int iLeft= low;
        int iRight = mid;
        int iE = 0;

        while(iLeft<mid&&iRight<high){
            if (array[iLeft]<=array[iRight]){
                extra[iE++]=array[iLeft++];
            }else {
                extra[iE++]=array[iRight++];
            }
            
        }
		while (iLeft<mid){
                extra[iE++]=array[iLeft++];
        }

        while (iRight<high){
                extra[iE++]=array[iRight++];
        }
        for (int i = 0;i < length;i++){
                array[low+i] = extra[i];
        }
    }

时间复杂度 O(n*log(n)) 数据不敏感
空间福再度O(n)
稳定性:稳定
优化点:
减少搬移次数

总结

七大基于比较的排序
时间复杂度:
1.O(n^2) 插排/选择/冒泡
2.O(n*log(n))堆排/快排/归并
3.O(n^1.2)

空间复杂度
O(1)插排/选择/冒泡/希尔/堆排
O(log(n))快排
O(n) 归并

稳定性:
稳定: 插排/冒泡/归并
数据不敏感:选择/堆排/归并
最好O(n) 插排/冒泡

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值