排序复习

# bubble sort
# 冒泡排序(交换排序)
"""
- 基本思想是 通过与相邻元素的比较和交换,把较小的元素交换到最前面。
- 时间复杂度 O(n^2), 空间复杂度 O(1)
"""

def bubble_sort(seq):
    n = len(seq)
    for i in range(n-1, -1, -1):
        for j in range(i):
            if seq[i] < seq[j]:
                seq[i], seq[j] = seq[j], seq[i]

    print(seq)


# select sort(选择排序)
"""
- 基本思想 每次选出待排序序列中最小的元素与排好序的最后一个元素做比较
- 时间复杂度 O(n^2), 空间复杂度 O(1)
"""
def select_sort(seq):
    for i in range(len(seq)):
        min_idx = i
        for j in range(i+1, len(seq)):
            if seq[j] < seq[min_idx]:
                min_idx = j
        if i != min_idx:
            seq[min_idx], seq[i] = seq[i], seq[min_idx]
    print(seq)

# insert sort
"""
- 基本思想 每次从将待排序序列中的一个元素插入到有序序列中
- 时间复杂度 O(n^2), 空间复杂度 O(1)
"""

# 写法1
def insert_sort(seq):
    n = len(seq)
    for i in range(1, n):
        if seq[i] < seq[i-1]:
            temp = seq[i]
            index = i   # 待插入的下标
            for j in range(i-1, -1, -1):
                if seq[j] > temp:
                    seq[j + 1] = seq[j]
                    index = j
                else:
                    break
            seq[index] = temp
    print(seq)

# 写法2

def insert(seq):
    n = len(seq)
    for i in range(1, n):
        j = i - 1
        tmp = seq[i]
        while tmp < seq[j] and j>=0:
            seq[j+1] = seq[j]
            j -= 1
        seq[j+1] = tmp
    return seq

# quick sort
"""
- 基本思想 选择一个基准元素,将其余元素中比它大的放到右边,比它小的放到左边
- 时间复杂度 O(nlogn), 空间复杂度 O(nlogn)
"""
def quick_sort(seq):
    return qsort(seq, 0, len(seq)-1)

def qsort(seq, left, right):
    if left >= right:
        return seq
    x = seq[left]
    i, j = left+1, right
    while i < j:
        while j>i and seq[j]>=x:
            j -=1
        while i<j and seq[i]<=x:
            i += 1
        seq[i], seq[j] = seq[j], seq[i]
    seq[i], seq[left] = x, seq[i]
    qsort(seq, left, i-1)
    qsort(seq, j+1, right)
    return seq


# merge sort
"""
- 基本思想: 归并排序采用的是分治思想,将待排序序列划分为2个序列,再对每个子序列进行划分,直到每个子序列只有一个元素为止,最后对子序列进行排序,排序后两两归并并,最后得到一个有序序列。
- 时间复杂度: o(nlogn), 空间复杂度o(n)
- 划分数据+合并且排序
"""
def merge_sort(seq):
    if len(seq) <= 1:
        return seq
    mid = len(seq)//2
    # 将列表分为两个部分,并且分别返回排好序的列表
    left = merge_sort(seq[:mid])
    right = merge_sort(seq[mid:])
    return merge(left, right)

def merge(left, right):
    # 合并两个排好序的列表,产生一个已排好序的列表
    result = []
    i = j = 0   # 为两个列表中的指针,便于两两对比
    while i < len(left) and j < len(right):
        if left[i] <= right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
    result += left[i:]
    result += right[j:]
    return result

# heap sort
"""
- 基本思想: 
- 时间复杂度
"""

def heap_sort(seq):
    n = len(seq)
    first = int(n/2-1)       # 最后一个非叶子结点
    for i in range(first, -1, -1):      # 构造一个大根堆
        max_heapify(seq, i, n-1)
    for j in range(n-1, 0, -1):
        seq[j], seq[0] = seq[0], seq[j]
        max_heapify(seq, 0, j-1)
    return seq
#
#
# #最大堆调整:将堆的末端子节点作调整,使得子节点永远小于父节点
# #start为当前需要调整最大堆的位置,end为调整边界
def max_heapify(seq, start, end):
    root = start
    while 1:
        child = 2*root + 1
        if child > end:
            break
        if child+1 <= end and seq[child] < seq[child+1]:
            child += 1
        if seq[root] < seq[child]:
            seq[root], seq[child] = seq[child], seq[root]
            root = child
        else:
            break


def find_topk(seq, k):


    def build_min_heap(heap_array):
        for i in range(len(heap_array)//2-1, -1, -1):
            heapify(heap_array, i, len(heap_array)-1)

    def heapify(array, start, end):
        root = start   # 假设最初的点是较小者
        while True:
            child = root*2 + 1   # 左孩子结点
            if child > end:
                break
            if child + 1 <= end and array[child] > array[child+1]:   # 先找到两个子结点中的较小者
                child = child + 1
            if array[root] > array[child]:    # 再将较小者与父结点比较,找到较小者,交换
                array[child], array[root] = array[root], array[child]
                root = child
            else:
                break

    heap_array = []
    for i in range(k):
        heap_array.append(seq[i])
    build_min_heap(heap_array)
    for i in range(k, len(seq)):
        if seq[i] > heap_array[0]:
            heap_array[0] = seq[i]
            heapify(heap_array, 0, k-1)
    return heap_array


def quickselect(seq, k):
    if len(seq)<k:
        return seq
    pivort = seq[-1]
    right = [pivort] + [x for x in seq[:-1] if x >= pivort]
    rlen = len(right)
    if rlen == k:
        return right
    if rlen> k:
        return quickselect(right, k)
    else:
        left = [x for x in seq[:-1] if x < pivort]
        return quickselect(left, k-rlen) + right


if __name__=='__main__':
    seq = [3, 1, 2, 5, 2, 3, 9, 7, 11, -1]
    # bubble_sort(seq)
    # select_sort(seq)
    # insert_sort(seq)
    # s = quick_sort(seq)
    s1 = heap_sort(seq)
    print(s1)
    s2 = find_topk(seq, 5)
    print(s2)
    s3 = merge_sort(seq)
    print(s3)
    s4 = quickselect(seq, 5)
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值