返回顶部

常用的6种排序算法(冒泡,选择,插入,希尔,快排,归并)

排序算法

1 冒泡排序

  • 相邻元素两辆比较,大的往后放.第一次将数据遍历完成之后,最大值就出现在了最大的索引处.同理,即可得到一个排好序的数组.

  • 过程图解:

  • 代码实现

    • 第一次遍历代码

      def sort(alist):
          for i in range(len(alist)-1):
              if alist[i] > alist[i + 1]:
                  alist[i], alist[i + 1] = alist[i + 1], alist[i]  # 大值放后面
          return alist
      
    • 完整代码

      def sort(alist):
          for j in range(len(alist) - 1):  # 控制遍历的次数
              for i in range(len(alist) - 1 - j):  # 控制比较的次数
                  if alist[i] > alist[i + 1]:
                      alist[i], alist[i + 1] = alist[i + 1], alist[i]
          return alist
      
      alist = [2, 1, 4, 6, 3]
      print(sort(alist))
      

2 选择排序

  • 选择排序改进了冒泡排序,每次遍历只做一次交换.例如:每次遍历都找到最大值,将最大值放到最后的位置

  • 流程图解:

  • 代码实现

    • 第一次遍历

      def sort(alist):
          max = 0  # 假定索引为0的值最大
          for i in range(len(alist) - 1):
              if alist[max] < alist[i + 1]:
                  max = i + 1
          alist[max], alist[len(alist) - 1] = alist[len(alist) - 1], alist[max]
          return alist
      
    • 完整代码

      def sort(alist):
          for j in range(len(alist) - 1, 0, -1): # 控制遍历次数
              max = 0  # 假定索引为0的值最大
              for i in range(j):   # 控制比较次数
                  if alist[max] < alist[i + 1]:
                      max = i + 1
              # 将最大值放置到列表末尾的位置        
              alist[max], alist[j] = alist[j], alist[max]
          return alist
      
      alist = [2, 1, 4, 6, 3]
      print(sort(alist))
      

3 插入排序

  • 插入排序是每次去一个列表元素与列表中已经排序好的列表进行比较,然后插入,从而得到排序好的列表段,最终获取到排序好的列表,比如,待排序列表为[49,38,65,97,76,13,27,49],则比较的步骤和得到的新列表如下:(带有背景颜色的列表段是已经排序好的,红色背景标记的是执行插入并且进行过交换的元素)

  • 代码实现插入排序

    • step1

      i = 1#表示的是列表中左部分有序部分的数据个数,其次还需要让i充当列表的下标
      if alist[i] < alist[i-1]:
          alist[i],alist[i-1] = alist[i-1],alist[i]
          i += 1
      
    • step2

      i = 2
      #alist[i]乱序部分的第一个数据
      #alist[i-1]:有序部分的第二个数
      while i >= 1:
          if alist[i] < alist[i-1]:
              alist[i],alist[i-1] = alist[i-1],alist[i]
              i -= 1
          else:
              break
      
    • 完整代码

      def sort(alist):
          for i in range(1, len(alist)):
              while i > 0: # 与有序段全部数据比较
                  if alist[i] < alist[i - 1]:
                      alist[i], alist[i - 1] = alist[i - 1], alist[i]
                  i -= 1
          return alist
      
      alist = [2, 1, 4, 6, 3]
      print(sort(alist))
      

4 希尔排序

希尔排序:特殊的插入排序,或者说插入排序就是增量为1的希尔排序

  • 希尔排序(shell sort )是插入排序的一种.也称缩小增量排序,先将整个待排元素序列分割成若干个子序列(由相隔某个“增量(gap)”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率比直接插入排序有较大提高。

  • 代码实现希尔排序

    • 增量为1的希尔排序

      gap = 1
      for i in range(1,len(alist)):
              #alist[i]乱序部分的第一个数据
              #alist[i-1]:有序部分的第二个数
              while i >= 1:
                  if alist[i] < alist[i-1]:
                      alist[i],alist[i-1] = alist[i-1],alist[i]
                      i -= 1
                  else:
                      break
          print(alist)
      
    • step 1

      # 增量为gap的希尔排序
      def sort(alist):
          gap = len(alist) // 2
          #将增量设置成gap
          for i range(gap,len(alist)):
              while i > 0 :
                  if alist[i] < alist[i-gap]:
                      alist[i],alist[i-gap] = alist[i-gap],alist[i]
                      i -= gap
                  else:
                      break 
      
    • 完整代码

      #继续缩小增量
      def sort(alist):
          gap = len(alist) // 2
          while gap >= 1:
              #将增量设置成gap
              for i in range(gap,len(alist)):
                  while i > 0 :
                      if alist[i] < alist[i-gap]:
                          alist[i],alist[i-gap] = alist[i-gap],alist[i]
                          i -= gap
                      else:
                          break
              gap //= 2
          return alist
      

5 快速排序

  • 快速排序

    • 设定一个基数,就是原始列表中第0个元素的数据值,并且技术需要存储在一个mid的变量中
    • 定义两个指针,low指向最左侧,high指向最右侧
    • 开始移动最右侧指针,移动规则是:当右侧指针对应的数值比基数小,则停止移动右指针,并且将右侧指针对应的数值移动到基准数字原始的位置,然后偏移左侧指针.
    • 移动最左侧指针,移动规则是: 当左侧指针对应的数值比基数大,则停止移动左指针,并且将左侧指针对应的数值移动到右侧指针的位置,然后偏移右侧指针
    • 当左右侧指针重复相遇后,将基数赋值到low或者high指向的位置(指针位置)
    • 然后将初步处理的列表以指针指向的位置分为两个列表
    • 重复上述操作,递归完成排序

  • 代码实现快速排序:

    • 第一次排序

      def sort(alist):
          low = 0
          high = len(alist)-1
          #基准:最左侧的数值
          mid = alist[low]
          #low和high的关系只能是小于,当等于的时候就要填充mid了
          while low < high:
              while low < high:
                  if alist[high] > mid:
                      high -= 1
                  else:
                      alist[low] = alist[high]
                      break
              while low < high:
                  if alist[low] < mid:
                      low += 1
                  else:
                      alist[high] = alist[low]
                      break
              #当low和high重复的时候,将mid填充
              if low == high:
                  alist[low] = mid #or alist[high] = mid  
                  break
          return alist
      
    • 完整代码

      def sort(alist,start,end):
          low = start
          high = end
          if low > high: # 递归结束条件
              return
         	mid = alist[low]
          while low < high:
              while low < high:
                  if alist[high] > mid:#将high向左偏移
                      high -= 1
                  else:
                      alist[low] = alist[high]
                      break
      
              while low < high:
                  if alist[low] < mid:#向右移动low
                      low += 1
                  else:
                      alist[high] = alist[low]
                      break
                  
          if low == high:
              alist[low] = mid#alist[high] = mid
              
          #将sort的操作作用到基数左侧部分
          sort(alist,start,low-1)
          #将sort的操作作用的基数右侧部分
          sort(alist,high+1,end)
          return alist    
      

6.归并排序

  - 归并排序采用分而治之的原理:

    - 将一个序列从中间位置分成两个序列;

    - 在将这两个子序列按照第一步继续二分下去;

    - 直到所有子序列的长度都为1,也就是不可以再二分截止。这时候再两两合并成一个有序序列即可。

      - 如何合并?

        下图中的倒数第三行表示为第一次合并后的数据。其中一组数据为 4 8 , 5 7。该两组数据合并方式为:每一小组数据中指定一个指针,指针指向每小组数据的第一个元素,通过指针的偏移指定数据进行有序排列。排列情况如下:

      1. p1指向4,p2指向5,p1和p2指向的元素4和5进行比较,较小的数据归并到一个新的列表中。经过比较p1指向的4会被添加到新的列表中,则p1向后偏移一位,指向了8,p2不变。

      2.p1和p2指向的元素8,5继续比较,则p2指向的5较小,添加到新列表中,p2向后偏移一位,指向了7。

      3.p1和p2指向的元素8,7继续比较,7添加到新列表中,p2偏移指向NULL,比较结束。

      4.最后剩下的指针指向的数据(包含该指针指向数据后面所有的数据)直接添加到新列表中即可。

posted @ 2019-10-06 10:05  高薪程序员  阅读(922)  评论(0编辑  收藏  举报