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

1212-王同学

发表文章数:21

首页 » 数据结构 » 正文

排序算法的稳定性

数据结构与算法——排序——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))

常见排序算法效率比较

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

未经允许不得转载:作者:1212-王同学, 转载或复制请以 超链接形式 并注明出处 拜师资源博客
原文地址:《数据结构与算法——排序——Celia》 发布于2020-11-15

分享到:
赞(0) 打赏

评论 抢沙发

评论前必须登录!

  注册



长按图片转发给朋友

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

Vieu3.3主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录