排序 —— 插入排序、选择排序与冒泡排序

一、插入排序

    对含有 N 个元素的数组 \textit{\textbf{a}} 进行 N - 1 次遍历,第 \textit{i}(\textit{i}\geqslant 1) 次遍历将元素 \textit{\textbf{a}}\left [ i \right ] 插入到位置区间 [0,i) 中合适的位置上。

# !/usr/bin/python
# coding=utf-8

def insert_sort(a):
    loop_num = len(a) - 1
    if loop_num == -1:
        return
    for i in range(loop_num):
        tmp = a[i + 1]
        p = -1
        for j in range(i, -1, -1):
            if tmp >= a[j]:
                break
            a[j + 1] = a[j]
            p = j
        if p != -1:
            a[p] = tmp
    return a

def main():
    # 测试用例
    a = [34, 2, 14, 5, 6, 200, 122, 79]
    insert_sort(a)
    a = [2, 1]
    insert_sort(a)
    a = [1, 2]
    insert_sort(a)
    a = [1]
    insert_sort(a)
    a = []
    insert_sort(a)

if __name__ == '__main__':
    main()

最好情况:  有序,仅需n-1次比较

最坏情况:  逆序,需n * (n-1) / 2次比较和交换
时间复杂度: O(n*n)

 

二、选择排序

    对有 N 个元素的数组 \textit{\textbf{a}} 进行 N - 1 次遍历,第 \textit{i}(\textit{i}\geqslant 1) 次遍历顺序扫描子数组a[i...N-1],并将其中最小的元素与 \textit{\textbf{a}}\left [ i - 1\right ] 相交换。

# !/usr/bin/python
# coding=utf-8

def select_sort(a):
    loop_num = len(a) - 1
    if loop_num == -1:
        print('empty array!')
        return
    for i in range(loop_num):
        t = i
        for j in range(i + 1, loop_num + 1):
            if a[j] < a[t]: t = j
        a[i], a[t] = a[t], a[i]
    return a

def main():
    # 测试用例
    a = [34, 2, 14, 5, 6, 200, 122, 79]
    select_sort(a)
    a = [2, 1]
    select_sort(a)
    a = [1, 2]
    select_sort(a)
    a = [1]
    select_sort(a)
    a = []
    select_sort(a)

if __name__ == '__main__':
    main()

    最好情况: 有序,需n-1次比较
    最坏情况: 逆序,需n * (n-1) / 2次比较, 以及n - 1次交换
    时间复杂度: O(n*n)

 

三、冒泡排序

     对有 N 个元素的数组 \textit{\textbf{a}} 进行 N - 1 次遍历,第 \textit{i}(\textit{i}\geqslant 1) 次遍历将按顺序对子数组a[0...N-i]中所有毗邻元素对进行交换,交换原则是小元素排在大元素之前,最多执行 N-i 次交换,遍历结束后,a[N-i]成为子数组a[0...N-i]中的最大元素。

# !/usr/bin/python
# coding=utf-8

def bubble_sort(a):
    loop_num = len(a) - 1
    if loop_num == -1:
        print('empty array!')
        return
    for i in range(loop_num):
        for j in range(i, loop_num):
            if a[j] > a[j + 1]:
                a[j], a[j + 1] = a[j + 1], a[j]
    return a

def main():
    # 测试用例
    a = [34, 2, 14, 5, 6, 200, 122, 79]
    bubble_sort(a)
    a = [2, 1]
    bubble_sort(a)
    a = [1, 2]
    bubble_sort(a)
    a = [1]
    bubble_sort(a)
    a = []
    bubble_sort(a)

if __name__ == '__main__':
    main()

最好情况: 有序,需n-1次比较

最坏情况: 逆序,需n * (n-1) / 2次比较, 以及n * (n-1) / 2次交换
时间复杂度: O(n*n)
 

四、插入排序和冒泡排序的优劣性比较

        实质上,三种简单排序的性能与一个概念——逆序紧密相关。逆序定义为数组中 \textit{i}< \textit{j}A[i] > A[j]  的序偶<A[i],A[j]>,数组中序偶中的数量即执行插入排序需要进行的交换次数。情况总是这样,因为交换两个不按原序排序的元素恰好消除一个逆序,而一个排过序的数组没有逆序。

       一般来说,插入排序较冒泡排序性能更胜一筹,为什么那? 因为冒泡排序的交换次数插入排序的移动次数都是由逆序对的数量决定的,但是冒泡排序的数据交换要比插入排序的数据移动要复杂,冒泡排序需要 3 个赋值操作,而插入排序只需要 1 个。所以,插入排序的实际运行时间要优于冒泡排序。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值