Python 入门笔记6 :排序方法练习(冒泡排序 and 快速排序)

经过一段时间的学习,python的语法已经学了七七八八,又学习了数据结构相关知识,编写两种不同的排序算法验证一下这段时间学习的成果。

一、冒泡排序

作为最基础的排序算法,上次接触应该是在2011年 o !!

用python实现一下:

def bubble_sort(alist):
    length = len(alist)

    for loopout in range(length):

        for loopin in range(0, length - loopout - 1):

            if alist[loopin] > alist[loopin + 1]:
                alist[loopin], alist[loopin + 1] = alist[loopin + 1], alist[loopin]

Python确实很简洁!!

二、快速排序

2.1 快速排序的原理

快速排序的总体思想:确定每一个元素的位置
具体的实现过程分成两步:

  • Step1: 确定序列中第一个元素应该处于的位置,然后把他放到那个位置,并将比它大的放到右边,比它小的放到左边(默认是升序排列,降序就反一下)。以刚刚定位完的那个点为分界,分成前后两个序列。
  • Step2:将分好的两个序列再分别执行第一步。直到排完序。

在用程序实现的时候,我先将“Step1”用一个函数实现并封装起来,再在另一个函数中实现整个排序过程。

2.2 div_list()函数:实现“Step1” ——序列的分割

div_list()函数的功能如下图所示
在这里插入图片描述

div_list()函数的具体实现过程如下:
记我们待处理的序列为a,长度为n,a=[a[0], a[1], …, a[n-1]]

  • Step 1: 设置头游标指向除了第一个元素(记为a[0])之外的序列的头(即序列中的第二个元素a[1])和尾游标指向序列的尾(即序列最后一个元素a[n-1])

  • Step 2: 分别比较a[0]和头游标尾游标所指向元素(a[头]和a[尾])的大小,在不考虑“=” 的情况下,存在如下情况,进行相应的处理。
    如果a[0]>a[头] ,就将头游标后移一位,a[0]<a[尾]将尾游标前移一位。
    如果a[0]<a[头] ,就停止头游标,a[0]>a[尾],就停止尾游标
    如果头游标尾游标都停止了,就交换a[头] 和a[尾],再继续。直到两个游标相遇。

  • Step 3: 两个游标相遇的地方就是a[0]的位置。
    专门做了动图来展示一下这个过程。

Step1和Step2 的实现过程
在这里插入图片描述
在头尾游标相遇后,会存在下面两种情况:

  1. 头游标停止(变红),尾游标未停止。此时a[0]应该插在游标相遇处的前面
    在这里插入图片描述

  2. 头游标未停止,尾游标停止。此时a[0]应该插在游标相遇处的后面
    在这里插入图片描述

完成以上步骤后,会获得一个新的序列,该序列原来的a[0]位于正确的位置,左边的都比它小,右边都比他大。而原序列也将分为两个新的序列,即:比原a[0]小的序列,比原a[0]大的序列。

所编写的代码如下

def div_list(alist, start, end):

    """
    函数div_list(),实现功能:确定序列alist[start, end]中第一个元素的位置并返回之
    同时将该元素放到相应位置,并保证左边都比他小,右边都比他大
    """

    length = len(alist)         # 获得整个列表的长度
    cur_begin = start + 1       # 初始化头游标
    cur_end = end               # 初始化尾游标
    if end-start+1 > length:    # 长度判断,此处还应加入是否是数字,是否是超出什么的,偷个懒
        print("length wrong")
        return -1
    begin_finished = False      # 初始化游标停止标志位
    end_finished = False

    while cur_begin < cur_end:      # 只要头尾没有相遇就继续
        if not begin_finished and alist[start] >= alist[cur_begin]:     # 如果a[0]>a[头],将`头游标`后移一位
            cur_begin += 1                                              # 否则判定头游标停止
        else:                                                           # 为了应付等于的情况,此处将a[0]=a[头]
            if not begin_finished:                                      # 视为a[0]>a[头],而下面的a[0]=a[尾],
                begin_finished = True                                   # 则视为a[0]>a[尾]

        if not end_finished and alist[start] < alist[cur_end]:          # 如果a[0]<a[尾],将`尾游标`前移一位
            cur_end += -1                                               # 否则判定尾游标停止
        else:
            if not end_finished:
                end_finished = True

        if begin_finished and end_finished:                             # 如果头、尾游标都停止,交换元素
            alist[cur_begin], alist[cur_end] = alist[cur_end], alist[cur_begin]
            begin_finished = False
            end_finished = False

    if alist[start] <= alist[cur_end]:      # 此处是为了应付一种特殊情况
        begin_finished = True
    else:
        end_finished = True

    if not begin_finished and end_finished:     # 实现a[0]插入
        alist[start], alist[cur_end] = alist[cur_end], alist[start]
        return cur_end
    else:
        alist[start], alist[cur_end-1] = alist[cur_end-1], alist[start]
        return cur_end-1

实现的效果如下
测试程序:

import fastsort
import random

if __name__ == "__main__":

    testlist = []
    for loop in range(0, 10):
        testlist.append(random.randint(0, 100))
    print(testlist)
    position = fastsort.div_list(testlist, 0, len(testlist) - 1)
    print(testlist)
    print(position)

输出
测试输出

2.3 fast_sort() 函数:利用div_list()实现排序

实现了找一个序列第一个元素所处于的位置后,需要将其分开在继续后面的排序工作。具体实现过程如下图
后续步骤
代码如下:

def fast_sort(alist):
    
    istart_last = [0]           #初始化一个列表用于保存前一次的结果
    iend_last = [len(alist)-1]

    while istart_last:
        istart_temp = istart_last
        iend_temp = iend_last
        istart_last = []
        iend_last = []
        for i in range(0, len(istart_temp)):
            position_ok = div_list(alist, istart_temp[i], iend_temp[i])
            if position_ok - istart_temp[i] <= 1 and iend_temp[i] - position_ok <= 1:
                pass
            elif position_ok - istart_temp[i] <= 1 and iend_temp[i] - position_ok > 1:
                istart_temp[i] = istart_temp[i] + 1
                istart_last.append(position_ok + 1)
                iend_last.append(iend_temp[i])
            elif position_ok - istart_temp[i] > 1 and iend_temp[i] - position_ok <= 1:
                iend_temp[i] = iend_temp[i] - 1
                istart_last.append(istart_temp[i])
                iend_last.append(position_ok - 1)
            else:
                istart_last.append(istart_temp[i])
                iend_last.append(position_ok - 1)
                istart_last.append(position_ok + 1)
                iend_last.append(iend_temp[i])

运行结果:
在这里插入图片描述

2.4 与冒泡法的对比

对比程序:

import fastsort
import bubble
import random
import time

if __name__ == "__main__":

    begintime = time.time()
    for loopout in range(0, 100):
        testlist = []
        for loop in range(0, 1000):
            testlist.append(random.randint(0, 100))
        fastsort.fast_sort(testlist)
    endtime = time.time()
    print("快速排序用时:", endtime - begintime)

    begintime1 = time.time()
    for loopout in range(0, 100):
        testlist = []
        for loop in range(0, 1000):
            testlist.append(random.randint(0, 100))
        bubble.bubbleSort(testlist)
    endtime1 = time.time()

    print("冒泡排序用时:", endtime1 - begintime1)

结果如下:
在这里插入图片描述
测试样本是100组,每组1000个0~100的随机数。
可以看出快速排序确实很快

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值