排序算法及稳定性

一、冒泡排序

1、冒泡排序,从前往后,两两进行比较,最大的放在最后面
2、稳定
3、时间复杂度o(n^2) 最优是不排序o(n)

# 排序算法
# 1、冒泡排序,从前往后,两两进行比较,最大的放在最后面
# 2、稳定
# 3、时间复杂度o(n^2) 最优是不排序o(n)
def bubble(lst):
    n = len(lst)
    for i in range(n-1): # 只需要遍历前n-1个元素
        for j in range(n-i-1): # 从0-n-1,从1-n-2
            if lst[j] > lst[j+1]: # 这里i控制起始的位置,j控制两两比较移动的位置
                lst[j], lst[j + 1] = lst[j+1], lst[j] # 如果出现前面的比后面大,就交换,继续到下一个遍历
    return lst
lst = bubble([3,2,14,6])
print(lst)

二、选择排序

1、选择排序,从未排序的列表中选择最小的向已排序的列表中插入
从未排序序列中找到最小(大)的元素,放到序列起始位置,然后在剩下的元素中继续找,
依次类推,平均时间复杂度为 o(n^2)最坏时间复杂度相同
2、不稳定 5 8 5 2

# 选择排序
# 从未排序的列表中选择最小的向已排序的列表中插入
# 不稳定  5 8 5 2
def select(nums):
    n = len(nums)
    for i in range(n-1):
        minindex = i
        for j in range(i+1, n):
            if nums[minindex] > nums[j]:
                minindex = j
        if i != minindex:
            nums[minindex], nums[i] = nums[i], nums[minindex]
    return nums
lst = select([2, 1, 5, 3, 6, 9, 4])
print(lst)

三、插入排序

1、插入排序,从未排序的列表中向已排序的列表中插入元素,确定当前索引j,然后与已排序的列表一一对比,最终交换使得变为排序好的列表
2、稳定的 [5, 5, 2]

# 插入排序
# 从未排序的列表中向已排序的列表中插入元素,确定当前索引j,然后与已排序的列表一一对比,最终交换使得变为排序好的列表
# 稳定 [5, 5, 2]
def insert(nums):
    n = len(nums)
    for i in range(1, n): # 从第二个开始遍历
        j = i
        while j > 0:
            if nums[j] < nums[j-1]: # 如果后面的比前面的小
                nums[j], nums[j-1] = nums[j-1], nums[j] # 交换
                j -= 1
            else: # 如果后面的比前面的大,直接退出循环
                break
    return nums
lst = insert([5, 5, 2])
print(lst)
# 插入排序
def maopao(lst):
    n = len(lst)
    for i in range(1, n):
        j = i
        for j in range(i, 0, -1): # 这里有繁琐遍历
            if lst[j] < lst[j-1]:
                lst[j], lst[j-1] = lst[j-1], lst[j]
            else:
                break # 退出当前循环
    return lst
lst = maopao([4,3,1,7,9,2])
print(lst)

四、归并排序

自上而下分成小块,排序完成,自下而上的合并
稳定

# 归并排序
# 自上而下分成小块,排序完成,自下而上的合并
# 不稳定
def join(lst):
    # 分一半 显示[3,6,2] 继续分[3] [6,2] 继续分 [3],[6] [2] 排序后[3] [2,6] 继续进行排序 [2,3,6]
    n = len(lst)
    if n <= 1:
        return lst
    mid = n//2
    left = join(lst[:mid]) # 递归运行
    right = join(lst[mid:])
    leftpoint, rightpoint = 0, 0
    ret = []
    while leftpoint < len(left)  and rightpoint < len(right):
        if left[leftpoint] > right[rightpoint]:
            ret.append(right[rightpoint])
            rightpoint += 1
        else:
            ret.append(left[leftpoint])
            leftpoint += 1
    ret += left[leftpoint:]
    ret += right[rightpoint:]
    return ret # 这里每次递归都是返回一个ret,那么作为下次递归的结果,与中间的ret=[]不会互相干扰

lst = join([3,6,2,9,5,7])
print(lst)

五、快速排序

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

def quick_sort(alist, first, last):
    # 快速排序
    if first >= last:
        return
    mid_value = alist[first]
    low = first
    high = last

    while low < high:
    # high 游标左移,停止条件遇到比中间值小的
        while low < high and alist[high] >= mid_value:
            high -= 1
        alist[low] = alist[high]  # 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 左边的列表执行快速排序
    quick_sort(alist, first, low - 1)
    # 对 low 右边的列表执行快速排序
    quick_sort(alist, low + 1, last)


if __name__ == '__main__':
    li = [4,2,7,5,9,0]
    print(li)
    quick_sort(li, 0, len(li) - 1)
    print(li)

猜你喜欢

转载自blog.csdn.net/weixin_44697051/article/details/119024689