排序算法 下

1.快速排序

快速排序是Hoare在1962年提出的一种二叉树结构的交换排序的方法,采用了递归的思想

思想:任取待排序的元素序列中的某元素作为基准值,按照原来的顺序将序列分为两个子序列,

左子序列中的所有元素均小于基准直,右子树的所有序列中的元素均大于基准直,然后左右子序列重复该过程,直到所有元素都排在相应的位置上。

先写出大致的框架,与二叉树的前序遍历非常之像,写递归框架可以照着二叉树前序遍历写出来,

后续只要分析如何按照基准直对区间中的数据划分即可

java 复制代码
public static void  QuickSort(int[] array,int start,int end){
        //递归结束的条件
        if(start >= end){
            return;
        }

        //如果子区间的数据越来越少了,直接采用 范围插入排序 更快
        if(end-start+1 < 10){
            insertSort(array,start,end);
            return;
        }

        //三数取中原因:
        //如果这个序列是接近有序的,1 2 3 4 5 6 7 8 9 11 10
        //基准值一般选取最左侧的数据 1,那么每次递归1的左侧没有子序列,只有右侧
        //所以会大大提高时间复杂度,
        //那么就取最左,最有,最中三个数据的中位数,
        //将中位数与第一个数交换,这样返回的基准直就不是1了,而是与1交换的数
        int index = midTreeNum(array,start,end);
        swap(array,start,index);

        //寻找基准直位置的下标
        //该方法有很多种,等下面我们一一介绍
        int par = paririon(array,start,end);

        //按照基准直,将其左右两个子区间进行排序
        QuickSort(array,start,par-1);
        QuickSort(array,par+1,end);
    }
    //挖坑法
    private static int paririon(int[]array,int left,int right){
        int temp = array[left];
        while (left < right){
            while (left < right && array[right]<=temp){
                right--;
            }
            array[left] = array[right];
            while (left < right && array[left] > temp){
                left++;
            }
            array[right] =array[left];
        }
        array[left] = temp;
        return left;
    }

    //找到中间值的下标
    private static int midTreeNum(int[]array,int left,int right){
        //中间位置下标
        int mid = left+(right-left)/2;

        if(array[left]<array[right]){
            if(array[mid]<array[left]){
                return left;
            }else  if(array[mid]>array[right]){
                return right;
            }else {
                return mid;
            }
        }else {
            if(array[mid]>array[left]){
                return left;
            }else if(array[mid]<array[right]){
                return right;
            }else {
                return mid;
            }
        }
    }
    private static void insertSort(int[]array,int left,int right){
        for(int i=left+1;i<=right;i++){
            int temp = array[i];
            int j = i-1;
            for(;j>=0;j--){
                if(array[j] > temp){
                    array[j+1] = array[j];
                }else {
                    break;
                }
            }
            array[j+1] = temp;
        }
    }

paririon 方法使用用来找到基准直的,通过找到的基准直将序列化分为两个子区间,再通过递归不断排序,缩小子区间,直到子区间就一个数字。

复制代码
int index = midTreeNum(array,start,end);

这条语句什么意思? 就是取到三个数的中位数

复制代码
三数取中原因:
如果这个序列是接近有序的,1 2 3 4 5 6 7 8 9 11 10
基准值一般选取最左侧的数据 1,那么每次递归1的左侧没有子序列,只有右侧
所以会大大提高时间复杂度,
那么就取最左,最有,最中三个数据的中位数,
将中位数与第一个数交换,这样返回的基准直就不是1了,而是与1交换的数

上面查找基准值的paririon方法是挖坑法

下面例举Hoare法查找基准值

java 复制代码
//Hoare法
    private static int paririon2(int[]array,int left,int right){
        int i = left;
        int temp = array[left];
        
        while (left < right){
            while (left < right && array[right] >= temp){
                right--;
            }
            while (left < right && array[left]<=temp){
                left++;
            }
            swap(array,left,right);
        }
        swap(array,left,i);
        return left;
    }

快速排序总结:

1.整体综合性能与使用场景都是比较好的,才敢较快排

2.时间复杂度:O(N*logN);

3.空间复杂度:O(logN);

4.稳定性:不稳定


2.归并排序

建立在归并操作上的有效排序算法,该算法采用分治法的一个典型的应用。将已有的子序列合并,得到完全有序的序列。

使每个子序列有序,再使每个子序列之间有序。

归并排序:

更多是解决磁盘中的外排序问题。

时间复杂度:O(N*logN)

空间复杂度:O(N)

稳定性:稳定

代码实现

java 复制代码
//归并排序
    public static void mergeSort(int[]array){
        megeFun(array,0,array.length-1);
    }
    public static void megeFun(int[]array,int left,int right){
        if(left >=right){
            return;
        }
        //分解
        int mid = left+(right-left)/2;
        megeFun(array,left,mid);
        megeFun(array,mid+1,right);
        //合并
        merge(array,left,mid,right);
    }
    public static void merge(int[]array,int left,int mid,int right){
        int[] temp = new int[right-left+1];
        int sl = left;
        int el = mid;
        int sr = mid+1;
        int er = right;
        int k = 0;
        while (sl<=el && sr<=er){
            if(array[sl] <= array[sr]){
                temp[k++] = array[sl++];
            }else{
                temp[k++] = array[sr++];
            }
        }
        while (sl<=el){
            temp[k++] = array[sl++];
        }
        while (sr<=er){
            temp[k++] = array[sr++];
        }

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

3.计数排序

又叫做鸽巢原理,是对哈希直接定址法的变形应用

1.统计相同元素的出现的次数

2.根据统计结果将序列收回到原来的序列中

时间复杂度:O(max(N,范围))

空间复杂度:O(范围)

稳定性:稳定

代码:

java 复制代码
public static void countSort(int[]array){
        //遍历数组找到最大最小值
        int mindex= array[0];
        int maxdex = array[0];

        for (int i = 0; i < array.length; i++) {
            if(maxdex<array[i]){
                maxdex = array[i];
            }
            if(mindex>array[i]){
                mindex = array[i];
            }
        }
        //已经找到最大与最小值了,定义数组
        int[]count = new int[maxdex-mindex+1];
        for (int i = 0; i < array.length; i++) {
            int val = array[i]-mindex;
            count[val]++;
        }
        //count数组以数据为下标,出现的次数为值
        int index = 0;//array的下标
        for (int i = 0; i < count.length ; i++) {
            while (count[i]>0){
                array[index] = i+mindex;
                index++;
                count[i]--;
            }
        }
    }
相关推荐
幸运超级加倍~6 分钟前
软件设计师-上午题-16 算法(4-5分)
笔记·算法
yannan2019031314 分钟前
【算法】(Python)动态规划
python·算法·动态规划
埃菲尔铁塔_CV算法15 分钟前
人工智能图像算法:开启视觉新时代的钥匙
人工智能·算法
EasyCVR16 分钟前
EHOME视频平台EasyCVR视频融合平台使用OBS进行RTMP推流,WebRTC播放出现抖动、卡顿如何解决?
人工智能·算法·ffmpeg·音视频·webrtc·监控视频接入
linsa_pursuer17 分钟前
快乐数算法
算法·leetcode·职场和发展
小芒果_0118 分钟前
P11229 [CSP-J 2024] 小木棍
c++·算法·信息学奥赛
qq_4340859020 分钟前
Day 52 || 739. 每日温度 、 496.下一个更大元素 I 、503.下一个更大元素II
算法
Beau_Will20 分钟前
ZISUOJ 2024算法基础公选课练习一(2)
算法
XuanRanDev23 分钟前
【每日一题】LeetCode - 三数之和
数据结构·算法·leetcode·1024程序员节
gkdpjj24 分钟前
C++优选算法十 哈希表
c++·算法·散列表