排序总结(下)

一.堆排序
(1)思想
基本原理也是选择排序,只是不在使用遍历的方式查找无序区间的最大的数,而是通过堆来选择无序区间的最大的数。
注意: 排升序要建大堆;排降序要建小堆。
(2)实现

public static void heapsort(int[] array){  //堆排序 升序为例
        creatHeap(array);  //建大堆
        for(int i = 0; i < array.length; i++){
            swap(array, 0, array.length - 1 - i);    //将此时堆中最大值与堆最后值交换,把最大值放到排序数组中。也就是队尾逐渐向前。
            shiftDown(array,array.length - i - 1, 0);  //堆中元素就是总数 - 当前排序数组好总数
        }
    }
    public static void creatHeap(int[] array){  //建堆
        for(int cur = (array.length - 1 - 1) / 2; cur >= 0; cur-- ){
            shiftDown(array,array.length,cur);
        }
    }
    public static void shiftDown(int[] array,int size, int index){ //向下调整
        int parent = index;
        int child = 2 * parent + 1;
        while(child < size){
            if(child + 1 < size && child + 1 > child){
                child = child + 1;
            }
            if(array[parent] < array[child]){
                swap(array, parent, child);
            }

            parent = child;
            child = 2 * parent + 1;
        }
    }
    public static void swap(int[] array, int left, int right){
        int tem = array[left];
        array[left] = array[right];
        array[right] = tem;
    }

(3)性能分析
时间复杂度 空间复杂度
O(n * log(n)) O(1)
数据不敏感 数据不敏感
稳定性:不稳定

二.冒泡排序
(1)思想
在无序区间,通过相邻数的比较,将最大的数冒泡到无序区间的最后,持续这个过程,直到数组整体有序
(2)实现

public static void bubbleSort(int[] array){  //冒泡排序  升序
        for(int bound = 0; bound < array.length; bound++){
            //(bound,arr.length) 未排序
            // [0,bound) 已排序组合
            for(int cur = array.length - 1; cur > bound; cur--){  //从最后一个元素交换最小值到最前面,直到排序好数组前。
                if(array[cur] < array[cur - 1]){
                    swap(array, cur, cur - 1);
                }
            }
        }
    }

(3)性能分析
时间复杂度 空间复杂度
最好 平均 最坏
O(n) O(n^2) O(n^2) O(1)
数据有序 数据逆序
稳定性:稳定

(3)快速排序
(1)思想

  1. 从待排序区间选择一个数,作为基准值(pivot);
  2. Partition: 遍历整个待排序区间,将比基准值小的(可以包含相等的)放到基准值的左边,将比基准值大的(可以包含相等的)放到基准值的右边;
  3. 采用分治思想,对左右两个小区间按照同样的方式处理,直到小区间的长度 == 1,代表已经有序,或者小区间的长度 == 0,代表没有数据。

(2)实现
递归实现

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

    public static  void quickSortInternal(int[] array, int left, int right){
            if(left >= right){
               return;
           }
            // 最简单的选择基准值的方式,选择 array[right] 作为基准值
            // pivotIndex 代表基准值最终停留的下标
            int pivotIndex = partition(array, left, right);
            // [left, pivotIndex - 1] 都是小于等于基准值的
            // [pivotIndex + 1, right] 都是大于等于基准值的
            quickSortInternal(array, left, pivotIndex - 1);
            quickSortInternal(array, pivotIndex + 1, right);
        }
    public static int partition(int[] array, int left, int right){  
        int baseIndex = right;
        int baseValue = array[baseIndex];
        while(left < baseIndex){  //从左往后看是否有比基准值大的,有就跳出
            while(left < baseIndex && array[left] <= baseValue){
                left++;
            }
            while(left < baseIndex && baseValue <= array[baseIndex]){ //从右往前看是否有比基准值小的,有就跳出
                baseIndex--;
            }
            swap(array, left, baseIndex);  //交换
        }
        swap(array, right, left); //交换基准值
        return left;
    }

非递归实现
其实和递归差不多,就是把他的左右界限,放到栈中,执行玩partition函数就分成俩半,需要快速排序的数组,继续放到栈中,直到栈空。

  public static void quickSortByLoop(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();
            if(left <= right){
                continue;
            }
            int pivotIndex = partition(array,left,right);

            //左半部分进栈
            stack.push(pivotIndex - 1);
            stack.push(left);

            //右半部分进栈
            stack.push(right);
            stack.push(pivotIndex + 1);
        }

    }

(3)优化
你有没有想到牵涉到递归,会有空间不够用的问题,所以就得做出优化。
下面是一些简单的优化
(1) 在待排序区间选择一个基准值
选择基准值选最前面,最后面可能是最大值,那他就一直只能分为1个数组,另一个就是最大值。

  1. 选择左边或者右边
  2. 随机选取
  3. 几数取中法
    (2)做 partition,使得小的数在左,大的数在右
    (3) 待排序区间小于一个阈值时(例如 48),使用直接插入排序
    分治处理左右两个小区间,直到小区间数目小于一个阈值,使用插入排序。
    (4)性能分析
    时间复杂度 空间复杂度
    最好 平均 最坏 最好 平均 最坏
    O(n * log(n)) O(n * log(n)) O(n^2) O(log(n)) O(log(n)) O(n)

稳定性:不稳定

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

(2)实现

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

    public static void mergeSortHelper(int[] array, int left, int right){
        if(left >= right || right - left == 1){
            return;
        }
        int mid = (left + right) / 2;  //取中间值
        mergeSortHelper(array, left, mid); //递归左边,
        mergeSortHelper(array, mid, right); //递归右边
        mergr(array, left, mid, right); //将递归后的数祖归并。
    }

    public static void mergr(int[] array, int left, int mid, int right){
        int length = right - left;  //得到数组的长度
        int[] output = new int[length];
        int outputIndex = 0;
        int i = left;
        int j = mid;
        while(i < mid && j < right){  //排序数组
            if (array[i] <= array[j]) {
                // i 对应的元素比 j 小
                // 就把 i 对应的元素插入到 output 末尾
                output[outputIndex++] = array[i++];
            } else {
                output[outputIndex++] = array[j++];
            }
        }

        while(i < mid){
            output[outputIndex++] = array[i++];
        }
        while(j < right){
            output[outputIndex++] = array[j++];
        }

        for(int k = 0; k < length; k++){
            array[left + k] = output[k];
        }
    }

(3)性能分析
时间复杂度 空间复杂度
O(n * log(n)) O(n)
数据不敏感 数据不敏感
稳定性:稳定

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值