十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)

算法分类

十种常见排序算法可以分为两大类:

1.非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序。

2.线性时间非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此称为线性时间非比较类排序。 

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》

 

算法复杂度:

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》

图片名词解释:

n: 数据规模

k:“桶”的个数

In-place: 占用常数内存,不占用额外内存

Out-place: 占用额外内存

稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。

不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。

时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。

空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。 

1、冒泡排序

       冒泡排序的基本思想是,对相邻的元素进行两两比较,顺序相反则进行交换,这样,每一趟会将最小或最大的元素“浮”到顶端,最终达到完全有序。JAVA实现冒泡排序代码及详解

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》 冒泡排序过程

2、插入排序

    插入排序基本思想是每一步将一个待排序的记录,插入到前面已经排好序的有序序列中去,直到插完所有元素为止。

(Java实现插入排序代码及详解)

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》 插入排序过程

 

3、选择排序

       选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。(Java实现选择排序代码及详解

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》 选择排序过程

4、快速排序

基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。(Java实现快速排序代码及详解

                    

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》 快速排序过程

5、希尔排序

       希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。(Java实现希尔排序代码及详解)

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》 希尔排序过程

6、堆排序

      堆排序是利用这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。(Java实现堆排序代码及详解

  堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。如下图:

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》

同时,我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》

该数组从逻辑上讲就是一个堆结构,我们用简单的公式来描述一下堆的定义就是:

大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]  

小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]  

堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了

步骤一 构造初始堆。将给定无序序列构造成一个大顶堆(一般升序采用大顶堆,降序采用小顶堆)。

  a.假设给定无序序列结构如下

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》

2.此时我们从最后一个非叶子结点开始(叶结点自然不用调整,第一个非叶子结点 arr.length/2-1=5/2-1=1,也就是下面的6结点),从左至右,从下至上进行调整。

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》

4.找到第二个非叶节点4,由于[4,9,8]中9元素最大,4和9交换。

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》

这时,交换导致了子根[4,5,6]结构混乱,继续调整,[4,5,6]中6最大,交换4和6。

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》

此时,我们就将一个无需序列构造成了一个大顶堆。

步骤二 将堆顶元素与末尾元素进行交换,使末尾元素最大。然后继续调整堆,再将堆顶元素与末尾元素交换,得到第二大元素。如此反复进行交换、重建、交换。

a.将堆顶元素9和末尾元素4进行交换

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》

b.重新调整结构,使其继续满足堆定义

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》

c.再将堆顶元素8与末尾元素5进行交换,得到第二大元素8.

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》

后续过程,继续进行调整,交换,如此反复进行,最终使得整个序列有序

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》

再简单总结下堆排序的基本思路:

  a.将无需序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;

  b.将堆顶元素与末尾元素交换,将最大元素”沉”到数组末端;

  c.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。

7、归并排序

归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案”修补”在一起,即分而治之)。(Java实现归并排序代码及详解

分而治之

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》

   可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现)。阶段可以理解为就是递归拆分子序列的过程,递归深度为log2n。

合并相邻有序子序列

  再来看看治阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤。

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》

《十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)》

 

    原文作者:常用算法
    原文地址: https://blog.csdn.net/qq_34801169/article/details/81459448
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞