七大排序算法

七大排序应用场景

数据量规模较小,考虑插入或选择。当元素分布有序时插入将大大减少比较和移动记录的次数,如果不要求稳定性,可以使用选择,效率略高于插入;
数据量规模中等,使用希尔排序;
数据量规模较大,考虑堆排序(元素分布接近正序或逆序)、快速排序(元素分布随机)和归并排序(稳定性);
一般来说不使用冒泡。

性能总结

来源于其他博主

交换排序:1、冒泡排序;2、快速排序
选择排序:3、选择排序;4、堆排序
插入排序:5、直接插入排序;6、希尔排序
归并排序:7、归并排序

1、冒泡排序

双指针
时间复杂度:O(N^2)
空间复杂度:O(1)
稳定性:稳定

    //冒泡排序:时间复杂度O(n^2);空间复杂度O(1);稳定
    public static void bubbleSort(int[] array){
        for(int i=0;i<array.length-1;i++){//趟数
            boolean sort = true;
            for(int j=0;j<array.length-i-1;j++){
                if(array[j] > array[j+1]){//交换,大值往后走
                    int tmp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = tmp;
                    sort = false;//在交换证明无序
                }
            }
            if(sort == true)//如果已经有序的话,直接返回
                return;
        }
    }

2、快速排序

时间复杂度:最好O(NlgN),最坏O(N^2)
空间复杂度:O(lgN)
稳定性:不稳定

    //快速排序:时间复杂度最好O(NlogN),最坏O(N^2);空间复杂度O(logN);不稳定
    public static void quickSort(int[] array,int low,int high){
        int start = low;
        int end = high;
        int key = array[start];//基准
        while(start < end){
            while(end>start && array[end]>=key){//从右边找小于基准key的值
                end--;
            }
            if(array[end] < key){//小于基准的值放基准key左边
                int tmp = array[end];
                array[end] = array[start];
                array[start] = tmp;
            }
            while(end>start && array[start]<key){//从左边找大于基准的值
                start++;
            }
            if(array[start] > key){//大于放右边
                int tmp = array[start];
                array[start] = array[end];
                array[end] = tmp;
            }
        }
        if(start > low){//证明start往右边走了,low和start之间还存在无序,继续排序
            quickSort(array,low,start-1);
        }
        if(high > end){//证明end往左走了,end和high之间无序,继续排序
            quickSort(array,end+1,high);
        }
    }

3、选择排序

时间复杂度:O(N^2)
空间复杂度:O(1)
稳定性:不稳定

    //选择排序:时间复杂度O(n^2);空间复杂度:O(1);不稳定
    public static void selectSort(int[] array){
        int index = 0;
        for(int i=0;i<array.length;i++){//趟数
            int tmpMin = array[i];//每趟默认当前位置值在剩下的所有值中最小
            for(int j=i;j<array.length;j++){//在剩下位置中找到最小值
                if(array[j]<=tmpMin){
                    tmpMin = array[j];
                    index = j;
                }
            }
            array[index] = array[i];//交换最小值和i位置的值
            array[i] = tmpMin;
        }
    }

4、堆排序

时间复杂度:O(N*lgN)
空间复杂度:O(1)
稳定性:不稳定
堆排序步骤分三步
1、对初始数组构造大根堆;
2、将堆顶元素交换到最后;
3、对剩余数组构造大根堆

    public static void heapSort(int[] arr) {
        //构造大根堆
        heapInsert(arr);
        int size = arr.length;
        while (size > 1) {
            //固定最大值
            swap(arr, 0, size - 1);
            size--;
            //构造大根堆
            heapify(arr, 0, size);

        }

    }

    //构造大根堆(通过新插入的数上升)
    public static void heapInsert(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            //当前插入的索引
            int currentIndex = i;
            //父结点索引
            int fatherIndex = (currentIndex - 1) / 2;
            //如果当前插入的值大于其父结点的值,则交换值,并且将索引指向父结点
            //然后继续和上面的父结点值比较,直到不大于父结点,则退出循环
            while (arr[currentIndex] > arr[fatherIndex]) {
                //交换当前结点与父结点的值
                swap(arr, currentIndex, fatherIndex);
                //将当前索引指向父索引
                currentIndex = fatherIndex;
                //重新计算当前索引的父索引
                fatherIndex = (currentIndex - 1) / 2;
            }
        }
    }
    //将剩余的数构造成大根堆(通过顶端的数下降)
    public static void heapify(int[] arr, int index, int size) {//index-父节点的索引,size-剩余数组大小
        int left = 2 * index + 1;
        int right = 2 * index + 2;
        while (left < size) {
            int largestIndex;
            //判断孩子中较大的值的索引(要确保右孩子在size范围之内)
            if (arr[left] < arr[right] && right < size) {
                largestIndex = right;
            } else {
                largestIndex = left;
            }
            //比较父结点的值与孩子中较大的值,并确定最大值的索引
            if (arr[index] > arr[largestIndex]) {
                largestIndex = index;
            }
            //如果父结点索引是最大值的索引,那已经是大根堆了,则退出循环
            if (index == largestIndex) {
                break;
            }
            //父结点不是最大值,与孩子中较大的值交换
            swap(arr, largestIndex, index);
            //将索引指向孩子中较大的值的索引
            index = largestIndex;
            //重新计算交换之后的孩子的索引
            left = 2 * index + 1;
            right = 2 * index + 2;
        }

    }
    //交换数组中两个元素的值
    public static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

5、直接插入排序

时间复杂度:最坏情况下O(N^2),最好情况下O(N),(只用i动,j不用走)
空间复杂度:O(1)
稳定性:稳定
直接插入排序步骤分三步
1、循环选择无序区间的第一个值作为要插入的值
2、将要插入的值往前比较,直到前一个数比插入的值小
3、插入

    //直接插入排序
    public static int[] insertsort(int[] arr){
        for(int i=1;i<arr.length;i++){
            int insertVal = arr[i];//保存要插入的值
            int index = i-1;//准备往前比较
            while(index>=0&&arr[index]>=insertVal){//当插入的值比被插入的值小
                arr[index+1] = arr[index];//则将arr[index]向后移动
                index--;//index向前移动
            }
            //找到插入的值的位置,插入
            arr[index+1] = insertVal;
        }
        return arr;
    }

6、希尔排序(插入排序的一种)

时间复杂度:O(NlgN)~O(N^2)
空间复杂度:O(1)
稳定性:不稳定
希尔排序是对直接插入排序的优化,和gap的取值有关

    //希尔排序
    public void shellSort(int[] array){
        int gap = 3;
        while(gap>0){
            for(int i=gap;i<array.length;i++){
                int insertVal = array[i];
                int index = i-gap;
                while(index>=0 && array[index]>insertVal){
                    array[index+gap] = array[index];
                    index -= gap;
                }
                array[index+gap] = insertVal;
            }
            gap--;
        }
    }

7、归并排序

时间复杂度:O(NlgN)
空间复杂度:O(N)
稳定性:稳定

    //归并排序
    public  static int[] mergesort(int[] data){
        sort(data,0,data.length-1);
        return data;
    }

    public static void sort(int[] data,int left,int right){
        if(left >= right){
            return;
        }
        int center = (left+right)/2;
        sort(data,left,center);//递归左边数组
        sort(data,center+1,right);//递归右边数组
        merge(data,left,center,right);
    }
    public static void merge(int[] data,int left,int center,int right){
        int[] tmpArr = new int[data.length];//临时数组
        int mid = center+1;//右边数组的第一个索引
        int third = left;//临时数组的索引
        int tmp = left;//左边数组的第一个索引
        while(left <= center&&mid <= right){//比较左右数组元素的大小,小的放入临时数组
            if(data[left]<=data[mid]){
                tmpArr[third++] = data[left++];
            }else{
                tmpArr[third++] = data[mid++];
            }
        }
        //将剩下的一个数组的剩余部分放入临时数组
        while(mid<=right){
            tmpArr[third++] = data[mid++];
        }
        while(left<=center){
            tmpArr[third++] = data[left++];
        }
        //拷贝回原数组
        while(tmp <= right){
            data[tmp] = tmpArr[tmp++];
        }
    }
  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1 冒泡排序: def bubble_sort(nums): for i in range(len(nums)-1): for j in range(len(nums)-i-1): if nums[j] > nums[j+1]: nums[j], nums[j+1] = nums[j+1], nums[j] return nums2. 选择排序: def selection_sort(nums): for i in range(len(nums)-1): min_idx = i for j in range(i+1, len(nums)): if nums[j] < nums[min_idx]: min_idx = j nums[i], nums[min_idx] = nums[min_idx], nums[i] return nums3. 插入排序: def insertion_sort(nums): for i in range(1, len(nums)): cur_val = nums[i] j = i - 1 while j >= 0 and nums[j] > cur_val: nums[j+1] = nums[j] j -= 1 nums[j+1] = cur_val return nums4. 希尔排序: def shell_sort(nums): gap = len(nums) // 2 while gap > 0: for i in range(gap, len(nums)): cur_val = nums[i] j = i while j >= gap and nums[j-gap] > cur_val: nums[j] = nums[j-gap] j -= gap nums[j] = cur_val gap //= 2 return nums5. 归并排序: def merge_sort(nums): if len(nums) <= 1: return nums mid = len(nums) // 2 left_list = merge_sort(nums[:mid]) right_list = merge_sort(nums[mid:]) return merge(left_list, right_list)def merge(left_list, right_list): res = [] while left_list and right_list: if left_list[0] < right_list[0]: res.append(left_list.pop(0)) else: res.append(right_list.pop(0)) res += left_list res += right_list return res6. 快速排序: def quick_sort(nums): if len(nums) <= 1: return nums pivot = nums[0] left_list = [x for x in nums[1:] if x < pivot] right_list = [x for x in nums[1:] if x >= pivot] return quick_sort(left_list) + [pivot] + quick_sort(right_list)7. 堆排序: def heap_sort(nums): n = len(nums) for i in range(n, -1, -1): heapify(nums, n, i) for i in range(n-1, 0, -1): nums[i], nums[0] = nums[0], nums[i] heapify(nums, i, 0) return numsdef heapify(nums, n, i): largest = i l = 2 * i + 1 r = 2 * i + 2 if l < n and nums[i] < nums[l]: largest = l if r < n and nums[largest] < nums[r]: largest = r if largest != i: nums[i], nums[largest] = nums[largest], nums[i] heapify(nums, n, largest)答:以上就是七大排序算法的Python代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值