python基本排序算法

  • 2019 年 10 月 5 日
  • 筆記

一、冒泡排序

  这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。

  冒泡排序算法的原理如下:

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
#!/usr/bin/env python  # -*- coding: utf-8 -*-    li = [99, 0, -1, 46, -87, 7, 17, 20]    le = len(li)  # 长度8    for i in range(le):  # [0,7] 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。      for j in range(le - i - 1):  # 针对所有的元素重复以上的步骤,除了最后一个。          if li[j + 1] > li[j]:  # 比较相邻的元素。如果第一个比第二个大,就交换他们两个。              li[j], li[j + 1] = li[j + 1], li[j]              # 这里不要break,    print(li)

二、选择排序

  选择排序是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。

#!/usr/bin/env python  # -*- coding: utf-8 -*-    li = [99, 0, -1, 46, -87, 7, 17, 20]    le = len(li)  # 长度8    for i in range(le):  # [0,7]      max_val = i  # 记录最大值的角标,我们先假设i为最大值      for j in range(i + 1, le):  # 再去循环我们假设的最大值和其它值去逐个比较          if li[j] > li[max_val]:  # 当有值比我们假设的最大值大时,我们记录角标              max_val = j      li[i], li[max_val] = li[max_val], li[i]  # 这样我们循环i次以后,我们就可以得到集合内的最大值,然后我们放在第i个位置,  print(li)

为什么我们回收选择排序是不稳定的排序呢?简单地说就是所有相等的数经过某种排序方法后,仍能保持它们在排序之前的相对次序,我们就 说这种排序方法是稳定的。反之,就是非稳定的。例如我们要排序[1,1,1,1,1,1,1],实则我们排序之后,每一个1的顺序是不会变化的,还是按照原来的颜色放置就是稳定排序。也就是说排序以后还是这样的[1,1,1,1,1,1,1]

三、插入排序

插入排序是一种简单直观且稳定的排序算法。如果有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到一种新的排序方法——插入排序法,插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素)。在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中。

  插入排序的基本思想是:每步将一个待排序的记录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。

#!/usr/bin/env python  # -*- coding: utf-8 -*-  li = [9, 0, -1, 46, -87, 7, 17, 20]    le = len(li)  # 长度8    k = 0  # 记录交换次数  for i in range(1, le):      val = li[i]  # 先记下每次大循环走到的第几个元素的值      j = i      while j > 0 and li[j - 1] < val:  # 循环次数j大于0  and  前一位数大于后一位数          li[j] = li[j - 1]  # 将后一位数放到前面,根据值的大小排序          j -= 1  # 把前面的数放到后面          k += 1      li[j] = val  # 已经找到了左边排序好的列表里不小于val的元素的位置,把val放在这里  print(li)  print(k)

四、快速排序

  快速排序是对冒泡排序的一种改进。

  通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

#!/usr/bin/env python  # -*- coding: utf-8 -*-  """  1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;  2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];  3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;  4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;  5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,  直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。  """  li = [9, 0, -1, 46, -87, 7, 17, 20]    le = len(li)      def QuickSort(li, start, end):      # 判断end结束是否小于start开始,如果为false,直接返回      if start < end:          i, j = start, end          # 设置基准数          base = li[i]          while i < j:              # 如果列表后边的数,比基准数大或相等,则前移一位直到有比基准数小的数出现              while (i < j) and (li[j] >= base):                  j = j - 1              # 如找到,则把第j个元素赋值给第个元素i,此时表中i,j个元素相等              li[i] = li[j]              # 同样的方式比较前半区              while (i < j) and (li[i] <= base):                  i = i + 1              li[j] = li[i]          # 做完第一轮比较之后,列表被分成了两个半区,并且i=j,需要将这个数设置回base          li[i] = base          # 递归前后半区          QuickSort(li, start, i - 1)          QuickSort(li, j + 1, end)      return li      sortli = QuickSort(li, 0, le - 1)  print(sortli)

五、归并排序

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

#!/usr/bin/env python  # -*- coding: utf-8 -*-      def merge(a, b):      c = []      h = j = 0      while j < len(a) and h < len(b):          if a[j] < b[h]:              c.append(a[j])              j += 1          else:              c.append(b[h])              h += 1        if j == len(a):          for i in b[h:]:              c.append(i)      else:          for i in a[j:]:              c.append(i)        return c      def merge_sort(lists):      if len(lists) <= 1:          return lists      middle = int(len(lists) / 2)      left = merge_sort(lists[:middle])      right = merge_sort(lists[middle:])      return merge(left, right)      if __name__ == '__main__':      li = [9, 0, -1, 46, -87, 7, 17, 20, 2]      print(merge_sort(li))