算法与数据结构(十三) 冒泡排序、插入排序、希尔排序、选择排序(Swift3.0版)

本篇博客中的代码实现依然采用Swift3.0来实现。在前几篇博客连续的介绍了关于查找的相关内容, 大约包括线性数据结构的顺序查找、折半查找、插值查找、Fibonacci查找,还包括数结构的二叉排序树以及平衡二叉树的构建与查找,而后还聊了哈希表的构建与查找。接下来的几篇博客中咱们就集中的聊一下常见的集中排序方式,并并给出相应的时间复杂度。本篇博客咱们将会详细的介绍冒泡排序、插入排序、希尔排序以及选择排序,下篇博客将继续介绍堆排序、归并排序以及快速排序的相关内容。固然上述内容的代码实现咱们依然采用Swift面向对象语言来实现。git

本篇博客的思路与以往博客的思路一直,先分析每种排序的规则,而后给出原理示意图,最后根据示意图给出相应的代码实现。编程这东西,只要是思路清晰,给出相应的代码实现并不困难,本篇是使用Swift语言来实现的,若是你对Swift语言不熟悉,你能够选择其余你熟悉的语言来实现。虽然语言不一样,可是思路和方法都是同样的。废话少说,开始今天博客的主题。github

 

1、排序协议的定义算法

在博客的开头的,咱们先给出排序协议的定义。由于咱们本篇博客含有多种排序方式,为了使每种排序方法对外调用方式一致,咱们须要定义一个排序的相关协议。全部排序的相关类都必须遵循该协议,让此协议来定义具体的排序类对外的调用方式。编程

下方的SortType协议就是咱们定义的排序类型的协议。其中的sort()方法是遵循该协议的类必需要实现的方法。sort()函数的参数是一个含有Int类型的数组,该数组就是要排序的数组。该方法的返回值是已经被排好序的数组。具体代码以下所示。数组

  

 

 

 2、冒泡排序数据结构

接下来咱们来聊一下冒泡排序,冒泡排序就像其名字同样,仍是比较生动的。在冒泡排序过程当中会将数组分红两部分,一部分是已经有序的数列,一部分是无序的数列。无序数列中不断的将其中最小的值往有序序列中冒泡,泡冒完后,咱们的序列就建立好了。本部分,咱们将要给出冒泡排序的示意图,已经相应的代码实现。函数

 

一、冒泡排序示意图测试

下方就是第一轮冒泡的具体过程,咱们要对[62, 88, 58, 47, 62, 35, 73, 51, 99, 37, 93]序列进行冒泡排序。通过第一轮的冒泡后,该序列中最小的值35被冒到了数列的最前方。由于冒泡的过程是挨个比较已经交换的过程。元素状态咱们的泡中是93,93与前一个值37进行比较,发现37要小于93,因此将泡中的值改为37,并往前移动。紧接着37在与前面的99比较,发现泡中的值要小,此刻不更新泡中的值并往前移动一个格。以此类推,无序序列中最小的值就会被冒到序列的起始位置。spa

每轮冒泡都会从无序序列中冒出那个最小的值,因此通过n(数列有n个值)次冒泡后,咱们的数列就是有序的了。冒泡过程当中的比较与交换的具体步骤以下所示:对象

  

2.代码实现

根据上述示意图,咱们很容易给出下方的代码。下方就是冒泡排序的代码,BubbleSort这个类就是冒泡排序所对应的类,此类为了统一对外的调用方式,因此必需要遵循咱们上一部分所定义的SortType协议。

说白了,冒泡的过程就是不断比较和交换的过程,若是前一个值比后一个值要大,那么就要进行交换了

  

 

三、运行结果

下方代码就是上述BubbleSort类所运行的具体结果。排序结果中详细的打印了冒泡排序在每一轮冒泡中每一步要作的事情,具体以下所示。

  

  

 

 

3、插入排序

插入排序算是比较好理解的排序方式,插入排序也是将要排序的数列分为两部分,前半部分是已经排好序的,后半部分则是无序的。插入排序中的插入是指“取出无序数列中第一个值,插入到有序数列中相应的位置”。其实这个插入过程也是不断比较和交换的过程。

 

一、插入排序示意图

下方就是插入排序的示意图,红色部分是有序数列,而绿色部分是无序数列。每一轮插入都会取出无序数列中的第一个元素插入到有序数列中,这个插入的过程其实就是一个比较交换的过程,若是要插入的值比前面的值要小,就要交换,直到不能交换为止。下方就是插入排序的过程。具体以下所示:

  

二、代码实现

有了上述的示意图,给出相应的代码实现并不困难。代码的核心思想就是经过循序不断从无序数列中取出值,而后循环遍历有序数列寻找合适的插入点。在下方中有两个循环嵌套,外层循环负责不断从无序序列中取值,而后经过内层循环将外层循环取出的值插入到有序数列中相应的位置,具体以下代码所示:

  

 

三、运行结果

下方是运行结果的截图,该运行结果其实就是插入排序的详细过程。每一轮插入的过程就是有序序列增长,无序序列减小的过程。下方就是插入过程的详细信息。

  

 

 

4、希尔排序

由于这个排序是一个叫希尔的人发明的,因此就叫希尔排序了。其实希尔排序是插入排序的升级版, 希尔排序根据其排序的特色又叫作缩小增量排序。希尔排序的大致步骤就是先将无序序列按照必定的步长(增量)分为几组,分别将这几组中的数据经过插入排序的方式将其进行排序。而后缩小步长(增量)分组,而后将组内的数据再次进行排序。知道增量为1位置。通过上述这些步骤,咱们的序列就是有序的了。其实上述的插入排序就是增量为1的希尔排序,下方会给出相应的示意图以及代码实现。

 

1.希尔排序示意图

下方就是希尔排序的详细步骤,接下来咱们将会对每一步进行详细的解说。以下所示:

  • (1)、首先按照增量进行分组,由于咱们要排序的数列有11个,增量初始值是 step = 11 / 2 = 5。也就是按照增量为5的步长对数组进行分组。在下方第一步中就是按照增量为5的方式进行分组的。咱们将为一组的元素使用直线进行相连,分完组后,咱们就将组内中的元素进行插入排序。
  • (2)、将上一步使用的 增量进行缩小,也就是本步骤的 step = 5 / 2 = 2。 本部分,就要按照2的增量将上一步排序后的数组进行分组,而后再次将每一个组内的数据进行插入排序。
  • (3)、 再次缩小增量,此刻 step = 2 / 2 = 1, 当增量为1时,其实就是咱们上一部分的插入排序。将整个数组进行插入排序,而后咱们的数组就是有序的了。

具体示意图以下所示:

  

 

二、希尔排序的代码实现

根据上述的步骤,而后再结合着插入排序的代码,给出希尔排序相应的代码并不困难。就是将插入排序的步长从1修改为咱们每次生成的步长便可,每次增量排序完毕后,咱们要对增量按照相应的规则进行缩小便可。下方就是希尔排序的代码实现。

在下方代码中,最外层循环负责增量的生成和缩减,里边的双重循环就是咱们以前咱们插入排序的代码,不步长要使用咱们希尔排序生成的step,具体代码以下所示:

  

 

三、运行结果

下方就是Shell排序的运行结果,从下方结果中咱们不难看出增量是逐渐减少的。下方的输出结果结合着本部分第一部分的示意图看更为直观一些。

  

 

 5、选择排序

接下来来聊聊选择排序,选择排序也是比较好理解的。在选择排序过程当中,数组仍然被分做有序和无序两部分。而选择排序中的“选择”是指不断从无序序列中选择最小的值放入到有序序列的最后的位置,换句话说就是从现有的无序序列中找出那个最小的值,而后与无序序列的第一个值进行交换,而后缩小无序序列的范围便可。由于有序序列的最后一个值与无序序列的第一个值紧挨着,交换后,这个无序序列中的第一个值就成了有序序列的最后一个值。重复这个选择的过程,咱们的数组就会变得有序。下方将会给出详细的示意图以及相应的代码实现。

 

1.选择排序示意图 

下方就是简单选择排序的部分步骤,只须要重复下方的步骤就能够经过选择排序将咱们的数组变成有序的序列。下方是对下方步骤的详细介绍:

  • 初识状态下,咱们整个数组就是无序的,从整个数组中咱们找到了最小的元素35,其下标为5。而后将35与无序序列第一个元素62进行交换。交换后,有序序列中就有了一个值:35,而无序序列中就少了一个值:35。无序序列中的第一个值也就是变成了88。
  • 再次从无序序列中选择那个最小的值。因而乎咱们又找到了37,而后让37与88进行交换。有序序列就成了 {35,37}
  • 再次从无序序列中选择最小的那个值,通过查找咱们找到了47,而后将47与58进行交换。此刻有序序列就成了 {35, 37, 47}
  • 重复的从无序序列中选择最小的值进行交换......

  

 

2.选择排序具体代码实现

有了上述选择的示意图,根据思路敲代码。下方就是选择排序的具体代码实现。代码实现起来仍是比较简单的,就是经过一个循环,不断的从无序序列中选出那个最小的值与无序序列中的第一个值进行交换便可。下方第一个框中就是从无序序列中查找最小的那个值的代码,第二个框就是交换的过程。以下所示:

  

 

三、运行结果

与上几个排序同样,咱们输出的运行结果就是选择排序的详细的过程。下方就是选择排序的详细过程,以下所示:

  

 

6、测试用例

在博客要结尾的部分,咱们仍然会给出本篇博客所使用的测试用例。下方就是本篇博客所使用的测试用例。上述的运行结果就是下方咱们测试用例的输出结果。虽然输出的结果不一样,可是咱们用的都是一个测试函数,只是传入的排序对象不一样。这也就是咱们在程序的第一部分为何要给出相应的协议定义的缘由。测试用例以下所示:

  

 

本篇博客所涉及的全部代码都会在github上进行分享,下方是分享地址。后面会继续更新其余排序算法。

github代码分享地址: https://github.com/lizelu/DataStruct-Swift/tree/master/AllKindsOfSort 

相关文章
相关标签/搜索