Python3谈算法之冒泡排序

日期:2020年1月7日
作者:Commas
注释:用Python3写的第一个算法博客,纪念一下
如果您想了解更多有关Python的知识,那么请点《我的Python浅谈系列目录》



一、原理及思路

1、原理

①若从小到大排序规则,则比较两个相邻的元素,值大的元素交换至右端,不断重复,直至无元素交换位置为止。
②若从大到小排序规则,则比较两个相邻的元素,值小的元素交换至右端,不断重复,直至无元素交换位置为止。

2、思路

① 两次遍历列表,分内外两层遍历;
② 内层遍历主要是将一个所谓的“最大值”送至右端,每次内层遍历结束,都会将一个“最大值”送至“最右端”,其次是遍历过程中,按照【原理】中的规则进行相邻值比较,会将所谓的“较大值”尽量往右端靠拢(值大交换,值小不变);
③外层遍历主要保证每次循环都进行了一趟“步骤②”的排序,产生一个所谓的“最大值”在所谓的“最右端”,当外层循环结束,则所有元素按照依次从小到大的顺序排列好。
注:“最大值”、“最右端”、“较大值”是相对而言,并非绝对存在,若不理解,可先参考输出结果理解;另外本思路是采用从小到大的排序规则进行解释的。

二、冒泡排序示例

1、常规版冒泡排序算法:

  • 应用版:
def bubble_sort(my_list, reverse=False):
    """
    冒泡排序算法
    :param my_list:需要排序的列表
    :param reverse: 默认为升序
    """
    
    for i in range(len(my_list)-1):
        for j in range(len(my_list)-1):
            if reverse:
                if my_list[j] < my_list[j+1]:
                    my_list[j], my_list[j+1] = my_list[j+1], my_list[j]
            else:
                if my_list[j] > my_list[j+1]:
                    my_list[j], my_list[j+1] = my_list[j+1], my_list[j]

  • 观察版:
def bubble_sort(my_list,reverse=True):
    """
    冒泡排序算法
    :param my_list:需要排序的列表
    :param reverse: 默认为升序
    """
    print("------冒泡排序开始------")
    for i in range(len(my_list)-1):
        for j in range(len(my_list)-1):
            if j == 0:
                print("\t第[{}]趟排序的第[{}]个动态:{}".format(i + 1, 0, my_list))
            if reverse:
                if my_list[j] < my_list[j+1]:
                    my_list[j], my_list[j+1] = my_list[j+1], my_list[j]
            else:
                if my_list[j] > my_list[j+1]:
                    my_list[j], my_list[j+1] = my_list[j+1], my_list[j]
            print("\t第[{}]趟排序的第[{}]个动态:{}".format(i+1, j + 1, my_list))
        print("*第[{}]趟排序结果:{}".format(i+1, my_list))
    print("------冒泡排序结束------")

2、调用常规版冒泡排序并输出结果

(1)从小到大排序:

  • 调用冒泡
if __name__ == '__main__':
    test_list = [7, 12, 9, 1, 15, 6]
    print("未排序的列表:{}".format(test_list))
    bubble_sort(test_list)
    print("冒泡排序后列表:{}".format(test_list))
  • 控制台输出
------冒泡排序开始------[1]趟排序的第[0]个动态:[7, 12, 9, 1, 15, 6][1]趟排序的第[1]个动态:[12, 7, 9, 1, 15, 6][1]趟排序的第[2]个动态:[12, 9, 7, 1, 15, 6][1]趟排序的第[3]个动态:[12, 9, 7, 1, 15, 6][1]趟排序的第[4]个动态:[12, 9, 7, 15, 1, 6][1]趟排序的第[5]个动态:[12, 9, 7, 15, 6, 1]
*[1]趟排序结果:[12, 9, 7, 15, 6, 1][2]趟排序的第[0]个动态:[12, 9, 7, 15, 6, 1][2]趟排序的第[1]个动态:[12, 9, 7, 15, 6, 1][2]趟排序的第[2]个动态:[12, 9, 7, 15, 6, 1][2]趟排序的第[3]个动态:[12, 9, 15, 7, 6, 1][2]趟排序的第[4]个动态:[12, 9, 15, 7, 6, 1][2]趟排序的第[5]个动态:[12, 9, 15, 7, 6, 1]
*[2]趟排序结果:[12, 9, 15, 7, 6, 1][3]趟排序的第[0]个动态:[12, 9, 15, 7, 6, 1][3]趟排序的第[1]个动态:[12, 9, 15, 7, 6, 1][3]趟排序的第[2]个动态:[12, 15, 9, 7, 6, 1][3]趟排序的第[3]个动态:[12, 15, 9, 7, 6, 1][3]趟排序的第[4]个动态:[12, 15, 9, 7, 6, 1][3]趟排序的第[5]个动态:[12, 15, 9, 7, 6, 1]
*[3]趟排序结果:[12, 15, 9, 7, 6, 1][4]趟排序的第[0]个动态:[12, 15, 9, 7, 6, 1][4]趟排序的第[1]个动态:[15, 12, 9, 7, 6, 1][4]趟排序的第[2]个动态:[15, 12, 9, 7, 6, 1][4]趟排序的第[3]个动态:[15, 12, 9, 7, 6, 1][4]趟排序的第[4]个动态:[15, 12, 9, 7, 6, 1][4]趟排序的第[5]个动态:[15, 12, 9, 7, 6, 1]
*[4]趟排序结果:[15, 12, 9, 7, 6, 1][5]趟排序的第[0]个动态:[15, 12, 9, 7, 6, 1][5]趟排序的第[1]个动态:[15, 12, 9, 7, 6, 1][5]趟排序的第[2]个动态:[15, 12, 9, 7, 6, 1][5]趟排序的第[3]个动态:[15, 12, 9, 7, 6, 1][5]趟排序的第[4]个动态:[15, 12, 9, 7, 6, 1][5]趟排序的第[5]个动态:[15, 12, 9, 7, 6, 1]
*[5]趟排序结果:[15, 12, 9, 7, 6, 1]
------冒泡排序结束------
冒泡排序后列表:[15, 12, 9, 7, 6, 1]

(2)从大到小排序:

  1. 调用冒泡
if __name__ == '__main__':
    test_list = [7, 12, 9, 1, 15, 6]
    print("未排序的列表:{}".format(test_list))
    bubble_sort(test_list, True)
    print("冒泡排序后列表:{}".format(test_list))
  1. 控制台输出
未排序的列表:[7, 12, 9, 1, 15, 6]
------冒泡排序开始------[1]趟排序的第[0]个动态:[7, 12, 9, 1, 15, 6][1]趟排序的第[1]个动态:[12, 7, 9, 1, 15, 6][1]趟排序的第[2]个动态:[12, 9, 7, 1, 15, 6][1]趟排序的第[3]个动态:[12, 9, 7, 1, 15, 6][1]趟排序的第[4]个动态:[12, 9, 7, 15, 1, 6][1]趟排序的第[5]个动态:[12, 9, 7, 15, 6, 1]
*[1]趟排序结果:[12, 9, 7, 15, 6, 1][2]趟排序的第[0]个动态:[12, 9, 7, 15, 6, 1][2]趟排序的第[1]个动态:[12, 9, 7, 15, 6, 1][2]趟排序的第[2]个动态:[12, 9, 7, 15, 6, 1][2]趟排序的第[3]个动态:[12, 9, 15, 7, 6, 1][2]趟排序的第[4]个动态:[12, 9, 15, 7, 6, 1][2]趟排序的第[5]个动态:[12, 9, 15, 7, 6, 1]
*[2]趟排序结果:[12, 9, 15, 7, 6, 1][3]趟排序的第[0]个动态:[12, 9, 15, 7, 6, 1][3]趟排序的第[1]个动态:[12, 9, 15, 7, 6, 1][3]趟排序的第[2]个动态:[12, 15, 9, 7, 6, 1][3]趟排序的第[3]个动态:[12, 15, 9, 7, 6, 1][3]趟排序的第[4]个动态:[12, 15, 9, 7, 6, 1][3]趟排序的第[5]个动态:[12, 15, 9, 7, 6, 1]
*[3]趟排序结果:[12, 15, 9, 7, 6, 1][4]趟排序的第[0]个动态:[12, 15, 9, 7, 6, 1][4]趟排序的第[1]个动态:[15, 12, 9, 7, 6, 1][4]趟排序的第[2]个动态:[15, 12, 9, 7, 6, 1][4]趟排序的第[3]个动态:[15, 12, 9, 7, 6, 1][4]趟排序的第[4]个动态:[15, 12, 9, 7, 6, 1][4]趟排序的第[5]个动态:[15, 12, 9, 7, 6, 1]
*[4]趟排序结果:[15, 12, 9, 7, 6, 1][5]趟排序的第[0]个动态:[15, 12, 9, 7, 6, 1][5]趟排序的第[1]个动态:[15, 12, 9, 7, 6, 1][5]趟排序的第[2]个动态:[15, 12, 9, 7, 6, 1][5]趟排序的第[3]个动态:[15, 12, 9, 7, 6, 1][5]趟排序的第[4]个动态:[15, 12, 9, 7, 6, 1][5]趟排序的第[5]个动态:[15, 12, 9, 7, 6, 1]
*[5]趟排序结果:[15, 12, 9, 7, 6, 1]
------冒泡排序结束------
冒泡排序后列表:[15, 12, 9, 7, 6, 1]

3、优化版冒泡排序算法:

  1. 第一次优化:每趟排序都会在“最右端”出一个“最大值”,那么以后的每趟就少遍历后面排序好的元素。
def bubble_sort(my_list, reverse=False):
    """
    冒泡排序算法
    :param my_list:需要排序的列表
    :param reverse: 默认为升序
    """
    print("------冒泡排序开始------")
    last_swap_index = len(my_list)-1
    for i in range(len(my_list)-1):
        # 第一次优化:每一躺排序后,都已经出了一个“最大值”,所以无需再管后面排好的“最大值”
        # for j in range(len(my_list)-1):
        for j in range(last_swap_index):
            if j == 0:
                print("\t第[{}]趟排序的第[{}]个动态:{}".format(i + 1, 0, my_list))
            if reverse:
                if my_list[j] < my_list[j+1]:
                    my_list[j], my_list[j+1] = my_list[j+1], my_list[j]
                    last_swap_index = j
            else:
                if my_list[j] > my_list[j+1]:
                    my_list[j], my_list[j+1] = my_list[j+1], my_list[j]
                    last_swap_index = j
            print("\t第[{}]趟排序的第[{}]个动态:{}".format(i+1, j + 1, my_list))
        print("*第[{}]趟排序结果:{}".format(i+1, my_list))
    print("------冒泡排序结束------")


if __name__ == '__main__':
    test_list = [7, 12, 9, 1, 6, 15]
    print("未排序的列表:{}".format(test_list))
    bubble_sort(test_list)
    print("冒泡排序后列表:{}".format(test_list))
未排序的列表:[7, 12, 9, 1, 6, 15]
------冒泡排序开始------[1]趟排序的第[0]个动态:[7, 12, 9, 1, 6, 15][1]趟排序的第[1]个动态:[7, 12, 9, 1, 6, 15][1]趟排序的第[2]个动态:[7, 9, 12, 1, 6, 15][1]趟排序的第[3]个动态:[7, 9, 1, 12, 6, 15][1]趟排序的第[4]个动态:[7, 9, 1, 6, 12, 15][1]趟排序的第[5]个动态:[7, 9, 1, 6, 12, 15]
*[1]趟排序结果:[7, 9, 1, 6, 12, 15][2]趟排序的第[0]个动态:[7, 9, 1, 6, 12, 15][2]趟排序的第[1]个动态:[7, 9, 1, 6, 12, 15][2]趟排序的第[2]个动态:[7, 1, 9, 6, 12, 15][2]趟排序的第[3]个动态:[7, 1, 6, 9, 12, 15]
*[2]趟排序结果:[7, 1, 6, 9, 12, 15][3]趟排序的第[0]个动态:[7, 1, 6, 9, 12, 15][3]趟排序的第[1]个动态:[1, 7, 6, 9, 12, 15][3]趟排序的第[2]个动态:[1, 6, 7, 9, 12, 15]
*[3]趟排序结果:[1, 6, 7, 9, 12, 15][4]趟排序的第[0]个动态:[1, 6, 7, 9, 12, 15][4]趟排序的第[1]个动态:[1, 6, 7, 9, 12, 15]
*[4]趟排序结果:[1, 6, 7, 9, 12, 15][5]趟排序的第[0]个动态:[1, 6, 7, 9, 12, 15][5]趟排序的第[1]个动态:[1, 6, 7, 9, 12, 15]
*[5]趟排序结果:[1, 6, 7, 9, 12, 15]
------冒泡排序结束------
冒泡排序后列表:[1, 6, 7, 9, 12, 15]

  1. 第二次优化:从输出结果我们可以看出,不一定要排序到最后一趟才得到最终的结果,只要无元素交换,就说明已经排序好了,就不再执行剩余趟数的排序了。如上面示例输出的结果, 第[3]趟排序的第[2]个动态:[1, 6, 7, 9, 12, 15]就已经得到我们想要的结果,但是第[3]趟有元素交换,所以在第[4]趟应该提前结束排序,优化如下:
def bubble_sort(my_list, reverse=False):
    """
    冒泡排序算法
    :param my_list:需要排序的列表
    :param reverse: 默认为升序
    """
    print("------冒泡排序开始------")
    last_swap_index = len(my_list)-1
    for i in range(len(my_list)-1):
        no_swap = True
        # 第一次优化:每一躺排序后,都已经出了一个“最大值”,所以无需再管后面排好的“最大值”
        # for j in range(len(my_list)-1):
        for j in range(last_swap_index):
            if j == 0:
                print("\t第[{}]趟排序的第[{}]个动态:{}".format(i + 1, 0, my_list))
            if reverse:
                if my_list[j] < my_list[j+1]:
                    my_list[j], my_list[j+1] = my_list[j+1], my_list[j]
                    last_swap_index = j
                    no_swap = False
            else:
                if my_list[j] > my_list[j+1]:
                    my_list[j], my_list[j+1] = my_list[j+1], my_list[j]
                    last_swap_index = j
                    no_swap = False

            print("\t第[{}]趟排序的第[{}]个动态:{}".format(i+1, j + 1, my_list))
        print("*第[{}]趟排序结果:{}".format(i+1, my_list))
        # 第二次优化:当无元素再交换,说明排序工作已完成
        if no_swap:
            break
    print("------冒泡排序结束------")


if __name__ == '__main__':
    test_list = [7, 12, 9, 1, 6, 15]
    print("未排序的列表:{}".format(test_list))
    bubble_sort(test_list)
    print("冒泡排序后列表:{}".format(test_list))
未排序的列表:[7, 12, 9, 1, 6, 15]
------冒泡排序开始------[1]趟排序的第[0]个动态:[7, 12, 9, 1, 6, 15][1]趟排序的第[1]个动态:[7, 12, 9, 1, 6, 15][1]趟排序的第[2]个动态:[7, 9, 12, 1, 6, 15][1]趟排序的第[3]个动态:[7, 9, 1, 12, 6, 15][1]趟排序的第[4]个动态:[7, 9, 1, 6, 12, 15][1]趟排序的第[5]个动态:[7, 9, 1, 6, 12, 15]
*[1]趟排序结果:[7, 9, 1, 6, 12, 15][2]趟排序的第[0]个动态:[7, 9, 1, 6, 12, 15][2]趟排序的第[1]个动态:[7, 9, 1, 6, 12, 15][2]趟排序的第[2]个动态:[7, 1, 9, 6, 12, 15][2]趟排序的第[3]个动态:[7, 1, 6, 9, 12, 15]
*[2]趟排序结果:[7, 1, 6, 9, 12, 15][3]趟排序的第[0]个动态:[7, 1, 6, 9, 12, 15][3]趟排序的第[1]个动态:[1, 7, 6, 9, 12, 15][3]趟排序的第[2]个动态:[1, 6, 7, 9, 12, 15]
*[3]趟排序结果:[1, 6, 7, 9, 12, 15][4]趟排序的第[0]个动态:[1, 6, 7, 9, 12, 15][4]趟排序的第[1]个动态:[1, 6, 7, 9, 12, 15]
*[4]趟排序结果:[1, 6, 7, 9, 12, 15]
------冒泡排序结束------
冒泡排序后列表:[1, 6, 7, 9, 12, 15]

版权声明:本文为博主原创文章,如需转载,请给出:
原文链接:https://blog.csdn.net/qq_35844043/article/details/103873162

发布了26 篇原创文章 · 获赞 18 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_35844043/article/details/103873162
今日推荐