排序算法大全:冒泡/选择/插入/希尔/快速排序法(python示例)

排序算法1: 冒泡排序法(python示例)

冒泡排序法又称为交换排序法,是从观察水中气泡变化构思而成。原理是从第一个元素开始,比较相邻元素的大小,若大小顺序有误,则对调后再进行下一个元素的比较。如此经过第一次扫描后就可以确保最后一个元素位于正确的顺序;经过第二次扫描可以确保倒数第二个元素位于正确的顺序。由此可知,N个元素经过(N-1)次扫描,就可以完成所有元素的排序。

下面使用55、23、87、62、16数列来演示排序过程,这样大家可以清楚地知道冒泡排序法的具体流程。从小到大排序,原始顺序如图:
在这里插入图片描述

  1. 第一次扫描,会先拿第一个元素55和第二个元素23进行比较,如果第二个元素小于第一个元素,则进行互换。接着拿55和87进行比较,就这样往右方向一直比较并交换。第一次比较完后,即可确定最大值在数组的最后面。下图是第一次扫描互换的一次过程,颜色填充为蓝色的数字是在此次扫描过程中向右交换前进的数字。
    在这里插入图片描述
    第一次扫描排序后的结果为:23、55、62、16、87。
  2. 第二次扫描,也是从头比较,但因为最后一个元素在第一次扫描就已确定是数组中的最大值(下图填充为绿色的数字),故只需比较3次即可把剩余数组元素的最大值排到剩余数组的最后面,即倒数第二个位置。
    在这里插入图片描述
  3. 第三次扫描完,完成三个值的排序,如下图所示。
    在这里插入图片描述
  4. 第四次扫描完,即可完成所有的排序,如下图所示。
    在这里插入图片描述
    由此可知,5个元素的冒泡排序法必须执行4(5-1)次扫描,第一次扫描需比较4(5-1)次,共比较了4+3+2+1=10次。

下面设计一个python程序,并使用冒泡排序法来对数列进行从小到大的排序。
读入原始数列:

data = [55, 23, 87, 62, 16]  #原始数据
data_len = len(data)  #原始数据长度
print('原始数据为:')
for i in range(data_len):
    print('%d' %data[i], end=' ')

使用冒泡排序法排序:

for i in range(data_len-1, 0, -1):  #扫描次数,共4次,(4,3,2,1)
    for j in range(i):
        if data[j] > data[j+1]:  #比较,交换
            data[j], data[j+1] = data[j+1], data[j]  #比较相邻两数,如果第一数较大则交换
    print('第%d次排序后的结果是:'%(data_len-i), end=' ')  #把各次扫描后的结果打印出来
    for j in range(data_len):
        print('%d' %data[j], end=' ')
    print()

排序过程为:
在这里插入图片描述
排序后的结果为:

print('排序后的结果为:')
for j in range(data_len):
    print('%d' %data[j], end=' ')

在这里插入图片描述

排序算法2: 选择排序法(python示例)

选择排序法(Selecting Sort)也算是枚举法的应用,就是反复从未排序的数列中取出最小的元素,加入到另一个数列中,最后的结果即为已排序的数列。从小到大排序的操作是一开始在所有的数据中挑选一个最小项放在第一个位置,再从第二项开始挑选剩下元素的最小项放在第2个位置,以此反复,直到完成排序为止。由此可知,N个元素经过(N-1)次扫描,就可以完成所有元素的排序。

下面使用55、23、87、62、16数列从小到大的排序过程来说明选择排序法的演算流程。原始数据如图:
在这里插入图片描述

  1. 首先找到此数列中最小值后,与数列中的第一个元素交换,如下图所示。
    在这里插入图片描述
  2. 从第二个值开始找,找到剩余数列中(不含第一个填充为绿色的数字)的最小值,再和第二个值交换,如下图所示。本次扫描,第二个数字恰巧是剩余数字中的最小值,因此位置不变。
    在这里插入图片描述
  3. 从第三个值开始找,找到此数列中(不含第一、二个的最小值),再和第三个值交换,如下图。
    在这里插入图片描述
  4. 从第四个值开始找,找到剩余数列的最小值,再和第四个值交换,排序完成,如下图。
    在这里插入图片描述
    由此可知,5个元素的选择排序法必须执行4(5-1)次扫描。

下面设计一个python程序,并使用选择排序法对数列进行从小到大的排序
读入原始数列:

data = [55, 23, 87, 62, 16]  #原始数据
data_len = len(data)  #原始数据长度
print('原始数据为:')
for i in range(data_len):
    print('%d' %data[i], end=' ')

使用选择排序法排序:

def select(data):
    for i in range(data_len-1):
        for j in range(i+1, data_len):
            if data[i] > data[j]:  #比较第i和第j个元素
                data[i], data[j] = data[j], data[i]

排序后的结果为:

select(data)
print('排序后的结果为:')
for j in range(data_len):
    print('%d' %data[j], end=' ')

在这里插入图片描述

排序算法3: 插入排序法(python示例)

插入排序法(Insert Sort)是将数组中的元素,逐一与已排序好的数据进行比较,前两个元素先排好,再将第三个元素插入适当的位置,所以这三个元素仍然是已排好序的,接着将第四个元素加入,重复此步骤,直到排序完成为止。可以看作是在一串有序的记录R1、R2…Ri中,插入新的记录R,使得i+1个记录排序妥当。

下面我们仍然使用55、23、87、62、16数列从小到大的排序过程来说明插入排序法的演算流程。如下图所示,在步骤一种,以23为基准与55比较后,放到55的前面。步骤二则拿87与其他两个元素(23、55)比较。步骤三62在比较完前三个数后插入到87的前面……,步骤四将最后一个元素比较完成后即完成排序。由此可知,N个元素经过(N-1)个步骤,即可完成所有元素的排序。
在这里插入图片描述
下面设计一个python程序,并使用插入排序法进行从小到大的排序。
读入原始数据:

data = [55, 23, 87, 62, 16]  #原始数据
data_len = len(data)  #原始数据长度
print('原始数据为:')
for i in range(data_len):
    print('%d' %data[i], end=' ')

使用插入排序法排序:

def insert(data):
    for i in range(1, data_len):
        tmp = data[i]  #tmp用来暂存数据
        NO = i - 1
        while NO >= 0 and tmp < data[NO]:
            data[NO+1] = data[NO]  #就把所有比tmp大的元素往后推一个位置,此步骤是由后往前比较后并插入
            NO -= 1
        data[NO+1] = tmp  #插入的位置

排序后的结果为:

insert(data)
print('排序后的结果为:')
for j in range(data_len):
    print('%d' %data[j], end=' ')

在这里插入图片描述

排序算法4: 希尔排序法(python示例)

当原始记录的键值大部分已排好序的情况下,插入排序法会非常有效率,因为它不需要执行太多的数据搬移操作。“希尔排序法”是D.L.Shell在1959年7月所发明的一种排序法,可以减少插入排序法中数据搬移的次数,以加速排序的进行。排序的原则是将数据区分成特定间隔的几个小区块,以插入排序法排完区块内的数据后,再逐渐减少间隔的距离。

下面我们用63、92、27、36、45、71、58、7数列从小到大的排序过程来说明希尔排序法的演算流程。原始数据如下图所示。
在这里插入图片描述

  1. 第一次排序过程,将所有数据分成Y:(8 div 2)份,即Y=4,Y成为划分数。注意,划分数不一定是2,质数最好。为了算法方便,所以我们习惯选2。因而一开始的间隔设置为4,如下图所示,同颜色的数字为一个区块。
    在这里插入图片描述
    如此一来可得到4个区块,分别是(63,45)(92, 71)(27, 58)(36,7),再分别用插入排序法排序成为(45,63)(71,92)(27,58)(7,36),在整个队列中数据的排序如下图所示。
    在这里插入图片描述
  2. 第二次排序,将间隔缩小为(8/2)/2(即间隔为2),如下图所示,同颜色的数字为一个区块。
    在这里插入图片描述
    (45,27,63,58)(71,7,92,36)再分别用插入排序法,得到如下图所示的结果。
    在这里插入图片描述
  3. 第三次排序,再以((8/2)/2)/2的间距进行插入排序,也就是每一个元素进行排序,于是得到最后的结果,如下图所示。
    在这里插入图片描述
    下面设计一个python程序,并使用希尔排序法来对数列进行从小到大的排序。
    读入原始数列:
data = [63,92,27,36,45,71,58,7]  #原始数据
data_len = len(data)  #原始数据长度
def showdata(data):
    for i in range(data_len):
        print('%d' %data[i], end=' ')
print('原始数组是: ')
showdata(data)

使用希尔排序法排序:

def shell(data):
    k = 1  # 第k次排序过程
    size = len(data)
    jmp = size // 2  #向下取整,例如1//2等于0;jmp为设置间距的位移量
    while jmp != 0:
        for i in range(jmp, size):  #i为扫描次数
            tmp = data[i]  #tmp用来暂存数据
            j = i - jmp  #以j来定位比较的元素
            while tmp < data[j] and j >= 0:  #插入排序法
                data[j+jmp] = data[j]
                j = j-jmp
            data[jmp+j] = tmp
        print('第%d次排序过程:'%k, end=' ')
        k += 1
        showdata(data)
        print()
        print('--------------------------------------')
        jmp = jmp//2  #控制循环次数
shell(data)

排序过程和结果为:
在这里插入图片描述

排序算法5: 合并排序法(python示例)

合并排序法(Merge Sort)的工作原理是针对已排序好的两个或两个以上的数列(或数据文件),通过合并的方式,将其组合成一个大的且已排好序的数列(或数据文件)。

下面我们使用38、16、41、72、52、98、63、25数列从小到大的排序过程来说明合并排序法的基本演算流程,如下图所示。
在这里插入图片描述
上面展示的合并排序法例子是一种最简单的合并排序,又称为2路(2-way)合并排序。
步骤如下:

  1. 将N个长度为1的数列合并成N/2个已排序妥当且长度为2的数列。
  2. 将N/2个长度为2的数列合并成N/4个长度为4的数列。
  3. 将数列不断地合并,直到合并成一组长度为N的数列为止。

下面设计一个python程序,并使用合并排序法来排序。
读入数据:

data = [38,16,41,72,52,98,63,25]  #原始数据

合并两个有序数列:

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 = len(lists)//2
    left = merge_sort(lists[:middle])
    right = merge_sort(lists[middle:])
    return merge(left, right)

输出最终结果:

print (merge_sort(data))

最终结果是 [16, 25, 38, 41, 52, 63, 72, 98]。

排序算法6: 快速排序法(python示例)

快速排序(Quick Sort)是由C.A.Hoare所提出来的。快速排序法又称分割交换排序法,是目前公认最佳的排序法,也是使用“分而治之”(Divide and Conquer)的方式,先在数据中找到一个虚拟的中间值,并按此中间值将所有打算排序的数据分为两部分。其中,小于中间值的数据放在左边,大于中间值的数据放在右边,再以同样的方式分别处理左、右两边的数据,直到排序完为止。
快速排序的步骤:
(1) 选择基准值。
(2) 将数组分成两个子数组:小于基准值的元素和大于基准值的元素。
(3) 对这两个子数组进行快速排序。
算法简单描述:选择数组第一位元素位基准值,创建两个新数组,分别存放小于基准值和大于基准值的元素。然后这两个新数组递归进行上述操作,直到数组为空。然后将左右数组和基准值进行拼接。

下面设计一个python程序,并使用快速排序法来排序。
快速排序代码:

def quicksort(array):
  if len(array) < 2:
    # 基线条件:为空或只包含一个元素的数组是“有序”的
    return array
  else:
    pivot = array[0]
    # 由所有小于基准值的元素组成的子数组
    less = [i for i in array[1:] if i <= pivot]
    # 由所有大于基准值的元素组成的子数组
    greater = [i for i in array[1:] if i > pivot]

    return quicksort(less) + [pivot] + quicksort(greater)

输出排序结果:

data = [35,10,42,3,79,12,62,18,51,23]  #原始数据
quicksort(data)

输出结果为 [3, 10, 12, 18, 23, 35, 42, 51, 62, 79]。

快速排序法图解过程可参考:
https://blog.csdn.net/qq_40941722/article/details/94396010

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值