Python基础排序算法之冒泡排序

#要点
冒泡排序实现原理
冒泡排序的代码实现及优化
冒泡排序的性能分析

冒泡排序实现原理

  冒泡排序是一种相对而言比较简单,也是比较基础的排序算法。
  其算法的实现原理如下:
(1)比较相邻的元素,如果第一个比第二个大,就交换他们两个的位置;
(2)对每一对相邻元素做同样的功能,从开始第一对到结尾的最后一对。注意,经过比较,最后一个数就是这个列表中最大的数值;
(3)因为最后的元素最大,所以除最后一个元素,对其他元素做以上重复操作;
(4)如此一来,越来越少的元素会重复上面的步骤,知道没有任何一对数字需要比较。
  具体实现过程如图所示:
在这里插入图片描述

冒泡排序的代码实现及优化

最基本的算法实现:

collection = [3, 4, 2, 1, 5, 6, 7, 8]
# 冒泡排序之基础算法,无优化算法
def bubble_sort(collection):
    """
	内层循环实现每一对的比较	
    """
    compare_count=0
    for i in range(len(collection)-1):
        print(collection) 
        for j in range(len(collection)-1-i):
            compare_count+=1
            if collection[j] > collection[j+1]:
				collection[j],collection[j+1] = collection[j+1],collection[j]
    print(f"总循环次数{compare_count}")
    return collection
# 测试代码
print(bubble_sort(collection))

执行结果如下:

[3, 4, 2, 1, 5, 6, 7, 8]
[3, 2, 1, 4, 5, 6, 7, 8]
[2, 1, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
总循环次数28

  从执行结果上看,对于已经排序的数据,可以加以判断退出循环,如下如进行优化:

collection = [3, 4, 2, 1, 5, 6, 7, 8]
def bubble_sort2(collection):
    """
    如果没有元素交换,说明数据在排序过程中已经有序,直接退出循环
    """
    compare_count=0
    # length = len(collection)
    for i in range(len(collection)-1):
        swapped = False
        print(collection)
        for j in range(len(collection)-1-i):
            compare_count+=1
            if collection[j] > collection[j+1]:
                swapped = True
                tmp = collection[j]
                collection[j] = collection[j+1]
                collection[j+1] = tmp
        if not swapped: break  # 如果已经排序,就停止迭代,是指在执行循环时,没有进入if语句判断中,可跳出循环;
    print(f"总循环次数{compare_count}")
    return collection
print(bubble_sort2(collection))

执行结果如下:

[3, 4, 2, 1, 5, 6, 7, 8]
[3, 2, 1, 4, 5, 6, 7, 8]
[2, 1, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
总循环次数22

  根据数据判断,可分为无序数据和有序数据部分,因此,在进行循环时,可仅仅对无序部分进行比较和冒泡,如果就可大大减少次数,可加快速度。
  因此,目前关键问题在于,如何去发现有序与无序的边界?
经过得出的结论发现:
(1)第一次冒泡的过程中,第一个元素 4 被移动到下标为【3】的位置(python 列表索引从 0 开始),位置 【3】就是有序部分的开始位置。
(2)第二次冒泡的过程中,第一个元素 3 被移动到下标为【2】的位置(python 列表索引从 0 开始),位置 【2】就是有序部分的开始位置。
  可以推断出,一次冒泡的过程中,最后一个被交换的元素下标即为无序和有序的边界,因而下次冒泡,仅对 0 ~ 边界 的元素冒泡即可大大减少循环次数

def bubble_sort3(collection):
    """
    bubble_sort2的基础上再优化。
    优化思路:
    在排序的过程中,数据可以从中间分为两段,一段是无序状态,另一段是有序状态。
    每一次循环的过程中,记录最后一个交换元素的位置(索引),它便是有序和无序状态的边界
    下一次仅循环到边界即可,从而减少循环次数,达到优化。
    """
    compare_count = 0
    last_change_index = 0  # 最后一个交换的位置
    border = len(collection) - 1     # 有序和无序的分界线
    for i in range(len(collection) - 1):
        swapped = False
        print(collection)
        for j in range(0, border):
            compare_count += 1
            if collection[j] > collection[j + 1]:
                swapped = True
                collection[j], collection[j + 1] = collection[j + 1], collection[j]
                last_change_index = j
        if not swapped:
            break  # 已经排序,就停止迭代,跳出循环体,后面的代码不再执行。

        border = last_change_index  # 最后一个交换的位置就是边界

    print(f"总循环次数{compare_count}")
    return collection

# 测试代码
print(bubble_sort3(collection))

执行结果如下:

[3, 4, 2, 1, 5, 6, 7, 8]
[3, 2, 1, 4, 5, 6, 7, 8]
[2, 1, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
总循环次数10
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值