排序算法

Posted ghh520

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序算法相关的知识,希望对你有一定的参考价值。

排序算法

冒泡排序

思想:冒泡排序(Bubble Sort)是一种简单直观的排序算法。它的工作原理是:它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

实例:

def bubbleSort(alist):
    # 找最大值的方式是通过对列表中的元素进行两两比较,值大的元素逐步向后移动
    # 序列中有n个元素,两两比较的话,需要比较n-1次
    n = len(alist)
    for j in range(n - 1): # 外层循环次数递增,内层循环次数递减
        for i in range(n - 1 - j): # 循环n-1-j次,控制两两比较的次数
            if alist[i] > alist[i + 1]: # 如果前面的元素大于后面的元素,交换两个元素的位置
                alist[i], alist[i + 1] = alist[i + 1], alist[i]
            else: # 如果后面的元素大于前面的元素,则不作任何操作
                pass

    return alist

alist = [2, 6, 0, 9, 4]
print(bubbleSort(alist))

选择排序

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

实例:

# 将乱序序列中的元素两两比较,找出最大值,然后直接将最大值放置到序列最后的位置,将最大值直接和最后一个元素交换位置
def selectionSort(alist):
    n = len(alist)
    for j in range(n - 1):
        max_index = 0 # 最大值元素的下标,一开始假设下标为0的元素为最大值
        for i in range(n - 1 - j):
            if alist[max_index] < alist[i + 1]:
                max_index = i + 1
        # 循环结束后max_index就一定是最大值的下标
        alist[n - 1 - j], alist[max_index] = alist[max_index], alist[n - 1 - j]
    return alist

alist = [3, 9, 8, 2, 0]
print(selectionSort(alist))

插入排序

思想:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫码,找到相应位置并插入

实例:

# 思路:
# 需要将原始序列分成两部分:有序部分,无序部分
# 将无序部分中的元素逐一插入到有序部分中
# 注意:初始情况下,有序部分为乱序序列的第一个元素,无序部分为乱序序列的n-1个元素
# 乱序序列:[3,8,5,7,6]
# [3,,,,8,5,7,6]:3就是初始的有序部分,8,5,7,6就是初始的无序部分
# [3,8,,,,5,7,6]
# [3,5,8,,,,7,6]
# [3,5,7,8,,,,6]
# [3,5,6,7,8,,,]
# 定义一个变量i,i表示的是有序部分元素的个数&无序部分第一个元素下标。
def insertionSort(alist):
    for i in range(1, len(alist)):
        while i > 0:
            if alist[i - 1] > alist[i]:
                alist[i - 1], alist[i] = alist[i], alist[i - 1]
                i -= 1
            else:
                break
    return alist

alist = [3, 8, 5, 7, 6]
print(insertionSort(alist))

希尔排序

思想:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,在对全体记录进行依次直接插入排序。希尔排序也成递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。

实例:

def shellSort(alist):
    grep = len(alist) // 2  # 初始增量
    while grep >= 1:
        for i in range(grep, len(alist)):
            while i > 0:
                if alist[i - grep] > alist[i]:
                    alist[i - grep], alist[i] = alist[i], alist[i - grep]
                    i -= grep
                else:
                    break
        grep //= 2 # 缩减增量
    return alist

alist = [1, 3, 7, 9, 8, 4, 2]
print(shellSort(alist))

快速排序

思想:

  • 将列表中第一个元素设定为基准数字,赋值给mid变量,然后将整个列表中比基准小的数值放在基准的左侧,比基准到的数字放在基准右侧。然后将基准数字左右两侧的序列在根据此方法进行排放。
  • 定义两个指针,low指向最左侧,high指向最右侧
  • 然后对最右侧指针进行向左移动,移动法则是,如果指针指向的数值比基准小,则将指针指向的数字移动到基准数字原始的位置,否则继续移动指针。
  • 如果最右侧指针指向的数值移动到基准位置时,开始移动最左侧指针,将其向右移动,如果该指针指向的数值大于基准则将该数值移动到最右侧指针指向的位置,然后停止移动。
  • 如果左右侧指针重复则,将基准放入左右指针重复的位置,则基准左侧为比其小的数值,右侧为比其大的数值。

实例:

# 核心操作:将基数mid放置到序列中间,使得基数左侧都是比它小的,右侧是比它大的
def quickSort(alist, left, right):
    low = left  # 第一个元素的下标
    high = right # 最后一个元素的下标
    if low > high: # 结束递归的条件
        return
    mid = alist[low] # 基数,初始值为序列的第一个元素
    while low < high:
        # 先偏移high
        while low < high:
            if mid < alist[high]:  # 向左偏移high
                high -= 1
            else:# 将high指向的数值放置到左侧的空位
                alist[low] = alist[high]
                break

        # 向右偏移low
        while low < high:
            if mid >= alist[low]: # 向右偏移low
                low += 1
            else:# 将low指向的数值放置到右侧的空位
                alist[high] = alist[low]
                break

    if low == high:
        alist[low] = mid

    # 上述为核心操作,需要将核心操作递归左右到左右子序列中
    quickSort(alist, left, low - 1)# 将quickSort作用到左侧序列中
    quickSort(alist, high + 1, right)# 将quickSort作用到右侧序列中
    return alist

alist = [0, 9, 4, 7, 2, 3, 1]
print(quickSort(alist, 0, len(alist) - 1))

以上是关于排序算法的主要内容,如果未能解决你的问题,请参考以下文章

算法排序之堆排序

快速排序-递归实现

从搜索文档中查找最小片段的算法?

在第6731次释放指针后双重免费或损坏

TimSort算法分析

以下代码片段的算法复杂度