了解七大经典排序算法,看这一篇就足够了!!!

news2025/1/21 12:20:57

✏️✏️✏️好,那么今天给大家分享一下七大经典排序算法!

清风的CSDN博客

😛😛😛希望我的文章能对你有所帮助,有不足的地方还请各位看官多多指教,大家一起学习交流!

动动你们发财的小手,点点关注点点赞!在此谢过啦!哈哈哈!😛😛😛

目录

一、排序的概念以及运用 

1.1 排序的概念

1.2 排序的运用

1.3 常见的排序算法 

二、七大经典排序算法的实现 

 2.1 插入排序

2.1.1 基本思想

 2.1.2 直接插入排序

2.1.3 插入排序实现代码 

2.1.4 直接插入排序的特性总结

2.2 希尔排序 

2.2.1 基本思想

 2.2.2 希尔排序实现代码

2.2.3 希尔排序特性总结

2.3 选择排序

2.3.1 基本思想

 2.3.2 选择排序

 2.3.3 选择排序实现代码

2.3.4 选择排序特性总结

2.4 堆排序

2.4.1 堆排序基本思想

 2.4.2 堆排序实现代码

2.4.3 堆排序特性总结

2.5 冒泡排序 

2.5.1 冒泡排序基本思想

2.5.2 冒泡排序实现代码 

2.5.3 冒泡排序特性总结

2.6 快速排序 

2.6.1 快速排序基本思想

2.6.2 快速排序实现代码 

2.6.3 快速排序非递归实现

2.6.4 快速排序特性总结

2.7 归并排序 

 2.7.1 归并排序基本思想

2.7.2 归并排序实现代码 

2.7.3 归并排序非递归实现

2.7.4 归并排序特性总结

三、排序算法复杂度及稳定性一览表


一、排序的概念以及运用 

1.1 排序的概念

排序 :所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
稳定性 :假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j] ,且 r[i] r[j] 之前,而在排序后的序列中, r[i] 仍在 r[j] 之前,则称这种排序算法是稳定的;否则称为不稳定的。

 内部排序:数据元素全部放在内存中的排序。

 外部排序 :数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据     的排序。

1.2 排序的运用

1.3 常见的排序算法 

二、七大经典排序算法的实现 

 2.1 插入排序

2.1.1 基本思想

直接插入排序是一种简单的插入排序法,其基本思想是: 把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。实际中我们玩扑克牌时,就用了插入排序的思想。

 2.1.2 直接插入排序

当插入第 i(i>=1) 个元素时,前面的 array[0],array[1],…,array[i-1] 已经排好序,此时用 array[i] 的排序码与 array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将 array[i] 插入,原来位置上的元素顺序后移。

2.1.3 插入排序实现代码 

    public static void insertSort(int[] array){
        for (int i = 1; i < array.length ; i++) {
            int tmp=array[i];
            int j = i-1;
            for (; j >=0 ; j--) {
                if(array[j]>tmp){
                    array[j+1]=array[j];
                }else{
                    break;
                }
            }
            array[j+1]=tmp;
        }
    }

2.1.4 直接插入排序的特性总结

  • 元素集合越接近有序,直接插入排序算法的时间效率越高
  • 时间复杂度:O(N^2)
  •  空间复杂度:O(1),它是一种稳定的排序算法
  • 稳定性:稳定

2.2 希尔排序 

2.2.1 基本思想

希尔排序法又称缩小增量法。希尔排序法的基本思想是: 把待排序文件中所有记录分成多个组,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。最后,所有记录在同一组内排好序。

 2.2.2 希尔排序实现代码

    public static void shellSort(int[] array){
        int gap= array.length;
        while(gap>1){
            gap/=2;
            shell(array,gap);
        }
    }
    public static void shell(int[] array,int gap){
        for (int i = gap; i <array.length ; i++) {
            int tmp=array[i];
            int j = i-gap;
            for (; j >=0 ; j-=gap) {
                if(array[j]>tmp){
                    array[j+gap]=array[j];
                }else{
                    break;
                }
            }
            array[j+gap]=tmp;
        }
    }

2.2.3 希尔排序特性总结

  • 希尔排序是对直接插入排序的优化。
  •  gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。整体而言,可以达到优化的效果。
  •  希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的希尔排序的时间复杂度都不固定。
  • 稳定性:不稳定

《数据结构(C语言版)--- 严蔚敏  

 《数据结构-用面向对象方法与C++描述》--- 殷人昆

2.3 选择排序

2.3.1 基本思想

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。

 2.3.2 选择排序

  • 在元素集合array[i]--array[n-1]中选择关键码最大()的数据元素
  • 若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换
  • 在剩余的array[i]--array[n-2]array[i+1]--array[n-1])集合中,重复上述步骤,直到集合剩余1个元素

 2.3.3 选择排序实现代码

    public void selectSort(int[] array){
        for (int i = 0; i < array.length; i++) {
            int smallest=i;
            int j = i+1;
            for (; j < array.length; j++) {
                if(array[j]<array[smallest]){
                    smallest=j;
                }
            }
            swap(array,i,smallest);
        }
    }
    public static void swap(int[] array,int i,int j){
        int tmp=array[i];
        array[i]=array[j];
        array[j]=tmp;
    }

2.3.4 选择排序特性总结

  • 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
  • 时间复杂度:O(N^2)
  • 空间复杂度:O(1)
  •  稳定性:不稳定

2.4 堆排序

2.4.1 堆排序基本思想

堆排序 (Heapsort) 是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。

 2.4.2 堆排序实现代码

   public static void heapSort(int[] array){
        crearMaxheap(array);
        int end=array.length-1;
        while(end>0){
            swap(array,0,end);
            siftDown(array,0,end);
            end--;
        }
    }
    private static void crearMaxheap(int[] array){

        for (int parent = (array.length-1-1)/2; parent >=0 ; parent--) {
            siftDown(array,parent,array.length);
        }
    }
    private static void siftDown(int[] array,int parent,int len){
        int child=2*parent+1;
        while(child<len){
            if(child+1<len && array[child+1]>array[child]){
                child=child+1;
            }
            //孩子最大值以及找到
            if(array[child]>array[parent]){
                swap(array,child,parent);
                parent=child;
                child=2*parent+1;
            }else{
                break;
            }
        }
    }

2.4.3 堆排序特性总结

  • 堆排序使用堆来选数,效率就高了很多。
  • 时间复杂度:O(N*logN)
  • 空间复杂度:O(1)
  • 稳定性:不稳定

2.5 冒泡排序 

2.5.1 冒泡排序基本思想

就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特
点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。

2.5.2 冒泡排序实现代码 

    public static void bubbleSort(int[] array){
        for (int i = 0; i < array.length-1; i++) {
            boolean flg=false;
            for (int j = 0; j < array.length-1-i; j++) {
                if(array[j]>array[j+1]){
                    swap(array,j,j+1);
                    flg=true;
                }
            }
            if(flg==false){
                break;
            }
        }
    }

2.5.3 冒泡排序特性总结

  • 冒泡排序是一种非常容易理解的排序
  • 时间复杂度:O(N^2)
  • 空间复杂度:O(1)
  • 稳定性:稳定

2.6 快速排序 

2.6.1 快速排序基本思想

任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

2.6.2 快速排序实现代码 

    public static void quickSort(int[] array){
        int start=0;
        int end= array.length-1;
        quick(array,start,end);
    }
    private static void quick(int[] array,int start,int end){
        if(start>=end){
            return;
        }
        int pivot=paratition(array,start,end);
        quick(array,start,pivot-1);
        quick(array,pivot+1,end);

    }
    //选轴值
    private static int paratitionHoare(int[] array,int left,int right){
        int i=left;
        int tmp=array[left];
        while (left<right){
            while (left<right && array[right]>=tmp){
                right--;
            }
            while (left<right && array[left]<=tmp){
                left++;
            }
            swap(array,left,right);
        }
        swap(array,i,left);
        return left;
    }
    //选基准的两种方法

    //挖坑法
    private static int paratition(int[] array,int left,int right){
        int tmp=array[left];
        while(left<right){
            while (left<right && array[right]>=tmp){
                right--;
            }
            array[left]=array[right];
            while (left<right && array[left]<=tmp){
                left++;
            }
            array[right]=array[left];
        }
        //相遇之后,把tmp放到坑里
        array[left]=tmp;
        return left;
    }

2.6.3 快速排序非递归实现

    private static void quickNor(int[] array,int start,int end){
        if(start>=end){
            return;
        }
        Stack<Integer> stack=new Stack<>();
        int pivot=paratitionHoare(array,start,end);
        if(pivot-1>start){
            //说明左边有2个以上的元素
            stack.push(start);
            stack.push(pivot-1);
        }
        if(pivot+1<end){
            //说明右边有2个以上的元素
            stack.push(pivot+1);
            stack.push(end);
        }

        while (!stack.isEmpty()){
            end=stack.pop();
            start=stack.pop();
            pivot=paratitionHoare(array,start,end);
            if(pivot-1>start){
                //说明左边有2个以上的元素
                stack.push(start);
                stack.push(pivot-1);
            }
            if(pivot+1<end){
                //说明右边有2个以上的元素
                stack.push(pivot+1);
                stack.push(end);
            }
        }

2.6.4 快速排序特性总结

  • 快速排序整体的综合性能和使用场景都是比较好的,所以才敢叫快速排序
  • 时间复杂度:O(N*logN)
  • 空间复杂度:O(logN)
  • 稳定性:不稳定

2.7 归并排序 

 2.7.1 归并排序基本思想

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

 

2.7.2 归并排序实现代码 

public static void mergeSort(int[] array){
        mergeSortFun(array,0,array.length-1);
    }
    private static void mergeSortFun(int[] array,int start,int end){
        if(start>=end){
            return;
        }
        int mid=(start+end)/2;
        mergeSortFun(array,start,mid);
        mergeSortFun(array,mid+1,end);
        //开始合并
        merge(array,start,mid,end);
    }
    private static void merge(int[] array,int left,int mid,int right){
 
        int s1=left;
        int e1=mid;
        int s2=mid+1;
        int e2=right;
        int k=0;

        int[] tmpArr=new int[right-left+1];
        while (s1<=e1 && s2<=e2){
            if(array[s1]<=array[s2]){
                tmpArr[k++]=array[s1++];
            }else {
                tmpArr[k++]=array[s2++];
            }
        }
        while (s1<=e1){
            tmpArr[k++]=array[s1++];
        }
        while (s2<=e2){
            tmpArr[k++]=array[s2++];
        }
        for (int i = 0; i < tmpArr.length; i++) {
            array[i+left]=tmpArr[i];
        }
    }

2.7.3 归并排序非递归实现

    public static void mergeSortNor(int[] array){
        int gap=1;
        while (gap<array.length){
            for (int i = 0; i < array.length; i+=gap*2) {
                int left=i;
                int mid=left+gap-1;
                int right=mid+gap;
                //mid和right可能会越界
                if(mid>=array.length){
                    mid=array.length-1;
                }
                if(right>=array.length){
                    right=array.length-1;
                }
                merge(array,left,mid,right);
            }
            gap*=2;
        }
    }

2.7.4 归并排序特性总结

  • 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
  • 时间复杂度:O(N*logN)
  • 空间复杂度:O(N)
  • 稳定性:稳定

三、排序算法复杂度及稳定性一览表

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

✨希望各位看官读完文章后,能够有所提升。

🎉好啦,今天的分享就到这里!!

创作不易,还希望各位大佬支持一下!

👍点赞,你的认可是我创作的动力!

收藏,你的青睐是我努力的方向!

✏️评论:你的意见是我进步的财富!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1215056.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录算法训练营第五十五天 | LeetCode 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结

代码随想录算法训练营第五十五天 | LeetCode 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结 文章链接&#xff1a;两个字符串的删除操作、编辑距离、编辑距离总结 视频链接&#xff1a;两个字符串的删除操作、编辑距离 1. LeetCode 583. 两个字符串的删除操作 1.1 思…

算法通关村第九关-白银挑战二分查找与高频搜索树

大家好我是苏麟,今天看看二分查找相关的题目 . 大纲 二分查找拓展问题山脉数组的峰顶索引 中序与搜索树二叉搜索树中的搜索验证二叉搜索树 二分查找拓展问题 山脉数组的峰顶索引 描述 : 符合下列属性的数组 arr 称为 山脉数组 &#xff1a; arr.length > 3存在 i&#…

【halcon】外观检测总结之灰度操作

1 灰度操作之 滞后延时 *滞后阈值 hysteresis_threshold (ImageInvert, RegionHysteresis, 190, 220, 3)这句话的意思就是&#xff0c;逐个判断这个图片区域里像素的灰度值&#xff0c;如果这个值小于190就不考虑了pass掉&#xff0c;如果大于220就直接入选。值在190和220之间…

企业商标信息查询API的优势和应用实例分析

前言 企业商标是企业在市场中的重要标识和竞争力的体现&#xff0c;而商标信息查询API则成为了企业品牌管理的重要工具。那么&#xff0c;这篇文章将详细阐述企业商标信息查询API的优势和应用实例分析。 企业商标信息API的优势 企业商标信息查询API的优势在于它可以快速、准…

通过Python脚本支持OC代码重构实践(三):数据项使用模块接入数据通路的适配

作者 | 刘俊启 导读 在软件开发中&#xff0c;经常会遇到一些代码问题&#xff0c;例如逻辑结构复杂、依赖关系混乱、代码冗余、不易读懂的命名等。这些问题可能导致代码的可维护性下降&#xff0c;增加维护成本&#xff0c;同时也会影响到开发效率。这时通常通过重构的方式对已…

还在为忘记BIOS密码担心?至少有五种方法可以重置或删除BIOS密码

忘记密码是一个我们都非常熟悉的问题。虽然在大多数情况下,只需单击“忘记密码”选项,然后按照几个简单的步骤即可恢复访问权限,但情况并非总是如此。忘记BIOS密码(通常为避免进入BIOS设置或避免个人计算机启动而设置的密码)意味着你将无法完全启动系统。 幸运的是,就像…

非对口专业测试人,婉拒猎头、放弃6份高薪offer,你敢信?

从非对口的国贸专业&#xff0c;步入测试之路&#xff1b;从红色旅游小城湘潭&#xff0c;迈入国际化都市上海。“明确方向-及时实践-谨慎选择-踏实扎根-计划未来”。她的每一步&#xff0c;都走得格外坚定有力......话不多说&#xff0c;让我们一起来看看这位小姐姐的成长故事…

揭秘2023年最热门的跨境电商源码趋势,你不能错过的关键信息

随着全球市场的不断扩大和国际贸易的加速&#xff0c;跨境电商源码正成为越来越多企业的首选。在本文中&#xff0c;我们将揭秘2023年跨境电商源码的最新趋势&#xff0c;为您带来关键信息&#xff0c;帮助您抓住机遇&#xff0c;实现商业成功。 2023年跨境电商源码趋势解析 …

JavaWeb-CSS

一、什么是CSS CSS&#xff08;Cascading Style Sheets&#xff0c;层叠样式表&#xff09;能够对网页中元素的位置排版进行精确的控制&#xff0c;拥有对网页对象和模型样式的编辑能力&#xff0c;简单来说就是页面美化。 CSS样式代码中的注释需要使用/**/。 二、CSS的引入方…

未来服务器操作系统的趋势与展望

摘要&#xff1a; 随着云计算、大数据和人工智能不断的发展&#xff0c;服务器操作系统也需要随之进行新一轮的升级。本文通过分析当前服务器操作系统的现状&#xff0c;探讨了未来服务器操作系统的趋势和展望&#xff0c;并针对一些关键问题提出了解决方案。 一、引言 服务器…

最全100种副业汇总,如果你没一份稳定的副业,那么要仔细看看了

为什么一定要有一份副业&#xff1f;三种人一定要有一份自己的副业&#xff0c;宝妈、大学生、死工资的上班族。因为有了一份优质的副业&#xff0c;您将不用依靠老公生活&#xff0c;您将不用向父母伸手要钱&#xff0c;您将不用时时刻刻看领导的颜色。 今天为大家总结了各类副…

折爱心教程(简单版本)

文章目录 1.折出双三角形2.向中心折叠3.形成正方形4.对折正反面相同5.向中心折6.外侧角向中心折7.顶部三角形向下折叠注意参考资料 我怎么也没有想到&#xff0c;身为混迹职场多年的老油子&#xff0c;竟然还能遇到折纸这种硬性task。 可是给的教程步骤省略太多了&#xff0c;看…

自动驾驶大模型,是怎么学习「世界知识」的?

近期&#xff0c;科技产业大佬不约而同地发出一个非常强烈的信号&#xff1a;自动驾驶走向完全的成熟&#xff0c;必须要被AI大模型重构。 中国工程院院士、清华大学教授、清华智能产业研究院&#xff08;AIR&#xff09;院长张亚勤认为&#xff0c;「自动驾驶是高度复杂的、最…

《QT从基础到进阶·二十九》QT,opencv源码调试

有时候我们在使用VS调试程序的bug&#xff0c;但发现程序崩溃的地方并不在我们写的程序中&#xff0c;我们通过调用堆栈发现程序崩溃的地方出现在QT或者opencv等源码中&#xff0c;那么我们怎么能把断点打到这些开源库中&#xff0c;下面提供一种办法&#xff1a; 解决方案–右…

老哥们平日是怎么排查线上问题的?

1、做好监控告警 如果线上出现了问题&#xff0c;我们更多的是希望由监控告警发现我们出了线上问题&#xff0c;而不是等到业务侧反馈。所以&#xff0c;我们需要对核心接口做好监控告警的功能。 2、定位报警层面 如果是业务代码层面的监控报警&#xff0c;那我们应该是可以…

2023 年 数维杯(C题)国际大学生数学建模挑战赛 |数学建模完整代码+建模过程全解全析

问题重述 信息技术和人工智能的迅速发展&#xff0c;特别关注大型语言模型&#xff08;Large Language Models&#xff0c;LLMs&#xff09;在全球范围内的广泛应用&#xff0c;以ChatGPT为代表。这些模型在机器人导航、语音识别、图像识别、自然语言处理和智能推荐等领域表现…

Dread Hunger恐惧饥荒服务器宣布关服

Dread Hunger恐惧饥荒服务器宣布关服 大家好我是艾西&#xff0c;如果不是被逼无奈 谁不喜欢在自己的舒适圈待着呢.从2022年年初到2023年下半年有太多的记忆了从最开始的当狼激动开心到后面慢慢的变成了一种恐惧&#xff0c;从最开始的变态花活变成了只要赢就行逐渐麻木了 作为…

Ubuntu 安装VMware Tools选项显示灰色,如何安装VMware Tools

只要你的网络没问题&#xff0c;你直接执行这几个命令&#xff0c;重启ubuntu虚拟机即可、 sudo dpkg --configure -a sudo apt-get autoremove open-vm-tools sudo apt-get install open-vm-tools sudo apt-get install open-vm-tools-desktop

苹果电脑录屏快捷键,让你成为录屏达人

“苹果电脑录屏好麻烦呀&#xff0c;操作步骤很繁琐&#xff0c;有人知道苹果电脑怎么快速录屏呀&#xff0c;要是有快捷键就更好了&#xff0c;大家知道苹果电脑有录屏快捷键吗&#xff1f;谢谢啦&#xff01;” 苹果电脑以其直观的用户界面和卓越的性能而闻名&#xff0c;而…

MES选型注意事项

1、明确需求和边界 企业首先要明确需要MES哪些模块及要实现的目标&#xff0c;如实现质量透明化、设备状态管理、IPQC检验管理等。MES通常要与其他系统集成&#xff0c;如与ERP集成&#xff0c;要事先明确哪些在ERP中做&#xff0c;哪些在MES中做&#xff0c;哪些需要同步。 车…