冒泡排序与选择排序

冒泡排序(Bubble Sort):
输入:乱序n长数组
输出:排序好的n长数组
时间复杂度:O(n^2)
空间复杂度:O(1)


冒泡排序的原理是对数组多次扫描,每次扫描都对相邻的两个元素的顺序进行调整。假设我们按升序排列数组,那么相邻两个元素中如果左边的元素大于右边的元素,就交换这两个元素位置,否则不交换。依次扫描过数组中全部元素。可见第一次扫描就使得数组的最大值排在了数组的最后一个位置,第二次扫描使得数组中第二大的元素排在了数组的倒数第二个位置。。。以此类推。这样,最多需要进行n-1次扫描就能完成排序。我们来看一个具体的例子:


数组[6, 5, 3, 1, 8, 7, 2, 4]的第一次扫描过程如下:


6>5:交换位置->[5, 6, 3, 1, 8, 7, 2, 4]
6>3:交换位置->[5, 3, 6, 1, 8, 7, 2, 4]
6>1:交换位置->[5, 3, 1, 6, 8, 7, 2, 4]
6<8:不交换->[5, 3, 1, 6, 8, 7, 2, 4]
8>7:交换位置->[5, 3, 1, 6, 7, 8, 2, 4]
8>2:交换位置->[5, 3, 1, 6, 7, 2, 8, 4]
8>4:交换位置->[5, 3, 1, 6, 7, 2, 4, 8]


可以看出,经过第一次扫描,数组的最大值8移动到了数组的最后一个位置,扫描的过程就是依次比较相邻元素的大小,再做交换。大的元素像气泡一样最终“升至”数组“顶端”。
同理,第二次扫描我们只需要对数组的前n-1个元素做相同的扫描即可,使得前n-1个元素的最大值(也就是整个数组的第二大元素)排在数组的倒数第二的位置。
可见,最多只需要n-1次扫描就能排列整个数组。这里,之所以说“最多”,是因为,假如第x次扫描没有发生元素交换位置(也就是说当前所扫描的数组是排好序的),那么,很显然,我们当然没有必要再进行之后的扫描。一个简单的例子是:数组[2, 1, 3, 4],经过第一次扫描,变成[1, 2, 3, 4];第二次扫描没有发生元素交换,说明已经排好序,就没有必要再进行第三次扫描了。


代码可以这样写:

def bubble_sort(aList):
    # 用bool值Next判断是否还需要进行下一轮扫描
    Next = True
    n = len(aList)
    while Next:
        Next = False
        for i in range(0, n - 1):
            if aList[i] > aList[i + 1]:
                # 交换位置
                aList[i], aList[i + 1] = aList[i + 1], aList[i]
                Next = True
        n -= 1


其中,布尔变量Next用来判断是否需要进行下一轮扫描。第11行是Python常见的交换数组中两元素位置的写法。这个函数只是对数组原地排序,没有返回值。


选择排序(Selection Sort):

输入:乱序n长数组
输出:排序好的n长数组
时间复杂度:O(n^2)
空间复杂度:O(1)



从原理上讲,选择排序与冒泡排序是一样的,都是通过扫描数组找出数组的“最值”,然后将这些挑选出的元素依次排列。不同的是,冒泡是通过比较相邻元素的方法选出最大值,而选择排序是用更“简单粗暴”的方式选出最小值,将每次选出的最小值依次排列,从而完成排序。


举个简单例子:数组[3, 2, 1]。经过第一次扫描“选择”出最小值1,与数组的首元素3交换位置,变成[1, 2, 3],之后第二次扫描数组[2, 3]部分(显然,第一个元素已经安置好,不用扫描了),"选择"出[2, 3]部分最小元素(也是整个数组第二小元素)2,与2交换位置(这里是它本身,相当于不交换)。对于这个有三个元素的数组而言,需经过两次扫描,这一点与冒泡排序一样,都是对于n长数组需要进行n-1次排序,大家也就可以通过这一点计算出时间复杂度(过程我略了)。
那么,思路很清楚了,我们就能写出代码:


def selection_sort(aList):
    begin = 0
    n = len(aList)
    # begin表示开始扫描的位置,也是放置每次选出的最小值的位置
    while begin < n - 1:
        # min_index代表最小值所在的位置
        min_index = begin
        for i in range(begin, n):
            if aList[i] < aList[min_index]:
                min_index = i
        # 交换位置 
        aList[begin], aList[min_index] = aList[min_index], aList[begin]
        begin += 1


这里,一样是个没有返回值的函数。其实,这两种排序算法都不难,但是细节处还是得搞清楚,否则,也不容易一遍就写对。


下一节,我们就来看看另一种排序方法:插入排序


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值