数据结构与算法——排序——Celia

排序算法的稳定性

在这里插入图片描述

冒泡排序

比选择排序更稳定

def bubble_sort(alist):
    """冒泡排序"""
    n = len(alist)
    for j in range(0, n-1):
        # 注意这里,到n-2截止所以最后一个应是n-1
        # 而冒泡排序
        for i in range(0, n-1-j):
            if alist[i] > alist[i+1]:
                alist[i], alist[i+1] = alist[i+1], alist[i]

if __name__ == "__main__":
    li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    print(li)
    bubble_sort(li)  # 调用方法的时候直接写即可
    print(li)

或者

def bubble_sort(alist):
    """冒泡排序"""
    n = len(alist)
    for j in range(len(alist)-1, 0, 1):  # j范围表示方法变动
        # 注意这里,到n-2截止所以最后一个应是n-1
        # 而冒泡排序
        for i in range(0, n-1-j):
            if alist[i] > alist[i+1]:
                alist[i], alist[i+1] = alist[i+1], alist[i]

if __name__ == "__main__":
    li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    print(li)
    bubble_sort(li)  # 调用方法的时候直接写即可
    print(li)

此时算法复杂度为o(n^2)
改进:考虑如果一开始就是有序数列不需要排序,则可以这样

def bubble_sort(alist):
    """冒泡排序"""
    n = len(alist)
    for j in range(0, n-1):  
        count = 0  # “班长”从头到尾走一遍,如果直接可行即退出
        for i in range(0, n-1-j):
            if alist[i] > alist[i+1]:
                alist[i], alist[i+1] = alist[i+1], alist[i]
                count += 1
        if count == 0:
            return

改进后最坏时间复杂度没变,最优时间复杂度变为o(n)

选择排序

def select_sort(alist):
    n = len(alist)
    for j in range(0, n-1):
        min_index = j
        for i in range(j+1, n):
            if alist[min_index] > alist[i]:
                min_index = i
        alist[min_index], alist[j] = alist[j], alist[min_index]

if __name__ == "__main__":
    li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    print(li)
    select_sort(li)
    print(li)

或者

def select_sort(alist):
    n = len(alist)
    for j in range(0, n-1):
        min_index = j
        for i in range(j+1, n):
            if alist[min_index] > alist[i]:
                # min_index = i
                alist[i], alist[j] = alist[j], alist[i]

if __name__ == "__main__":
    li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    print(li)
    select_sort(li)
    print(li)

插入排序

注意:插入排序前面已排好的数列是有序的,后续排列过程中,某数alist[i]在找到比它小的数alist[i-1]时,该数的插入排序即完成。

def insert_sort(alist):
    """插入排序"""
    n = len(alist)

    for i in range(1, n):
        # 从右边的无序序列中取出一个元素,从小到大插入到相应位置
        while i > 0:
            if alist[i-1] > alist[i]:
                alist[i], alist[i-1] = alist[i-1], alist[i]
                i -= 1  # 因为前面数列已是有序数列,所以
            else:
                break  # 检测到某alist[1-1]<alist[i]之后即可停止


if __name__ == "__main__":
    li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    print(li)
    insert_sort(li)
    print(li)

时间复杂度:o(n^2)

希尔排序

gap表示一个间隔,前gap个数的顺序不用特意考虑。
gap需要分别取len(alist)折半取整、再折半取整……1,多次执行希尔排序

def shell_sort(alist):
    """希尔排序"""
    n = len(alist)
    gap = n//2
    while gap > 0:
        for i in range(gap, n):
            # 从右边的无序序列中取出一个元素,从小到大插入到相应位置
            while i > 0:
                if alist[i-gap] > alist[i]:
                    alist[i], alist[i-gap] = alist[i-gap], alist[i]
                    i -= gap  # 因为前面数列已是有序数列,所以
                else:
                    break
        gap //= 2


if __name__ == "__main__":
    li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    print(li)
    shell_sort(li)
    print(li)

最坏时间复杂度因gap取值不同而不同
时间复杂度:o(n^2)
稳定性:不稳定

快速排序

def quick_sort(alist, first, last):
    """快速排序"""
    if first >= last:
        return

    mid_value = alist[first]
    low = first
    high = last

    while low < high:
        while low < high and alist[high] >= mid_value:  # 当存在多个与mid相等的值时统一放到mid的一边
            high -= 1
        alist[low] = alist[high]  # 若遇到一个比mid小的alist[high]则放到low上
        # low += 1

        while low<high and alist[low] < mid_value:
            low += 1
        alist[high] = alist[low]
        # high += 1
    # 从循环退出时low == high
    alist[low] = mid_value

    # 这时分割成出去low索引处元素的从头开始的alist[:low-1]和直到最后的alist[low+1:]
    # 可以执行递归嵌套
    # 注意不要用新的列表,要在原列表上排序quick_sort(alist[:low-1])
    # quick_sort(alist[low+1:])
    # 对low左边的列表执行排序
    quick_sort(alist, first, low-1)
    # 对low右边的列表执行排序
    quick_sort(alist, low+1, last)

if __name__ == "__main__":
    li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    print(li)
    quick_sort(li, 0, len(li)-1)
    print(li)

最优时间复杂度o(nlogn)
最坏时间复杂度o(n^2)
稳定性:不稳定

归并排序

二分查找

只能作用在***有序***顺序表上(已排序完成的有序列表)
递归版本:

def binary_search(alist, item):
    """二分查找递归"""
    n = len(alist)
    if n > 0:
        mid = n//2
        if item == alist[mid]:
            return True
        elif item < alist[mid]:
            return binary_search(alist[:mid], item)
        else:
            return binary_search(alist[mid+1:], item)
    return False


if __name__ == "__main__":
    li = [17, 20, 26, 31, 44, 54, 55, 77, 93]
    print(binary_search(li, 100))
    print(binary_search(li, 54))

非递归版本

def binary_search(alist, item):
    """二分查找非递归"""
    n = len(alist)
    first = 0
    last = n-1
    while first <= last:
        mid = (first + last)//2
        if alist[mid] == item:
            return True
        elif item < alist[mid]:
            last = mid - 1
        else:
            first = mid + 1
    return False




if __name__ == "__main__":
    li = [17, 20, 26, 31, 44, 54, 55, 77, 93]
    print(binary_search(li, 100))
    print(binary_search(li, 54))

常见排序算法效率比较

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值