算法--排序

#堆排
def
sift(li, low, high): ''' :param li:树 :param low: 树的根节点 :param high: 树的最后一个节点 :return:向下调整树 ''' tmp = li[low] # 去除树根作为临时变量 i = low # i指向空位 j = 2 * i + 1 # 第一次 j指向根节点的左孩子 while j <= high: # 循环继续的条件:j不越界;This the second end condition:j越界 # 1.比较左右子节点 if j + 1 <= high and li[j] < li[j + 1]: # 右节点存在,才进行左右比较 j += 1 # 将j指向j+1 if li[j] > tmp: # 调整位置 li[i] = li[j] # 空位的元素填成j下标的元素,所谓的调整 i = j # 向下调整 j = 2 * j + 1 # 从当前j节点找左孩子 else: break # j位置的元素>tmp 停止循环,This the first end condition li[i] = tmp # 结束循环,空位填充tmp #堆排 def heak_sort(li): n = len(li) # 1.构造堆 for low in range((n - 2) // 2, -1, -1): # 根据子节点找父节点i-->(i-1)//2 sift(li, low, n - 1) print(li) # 2.挨个出数 for high in range(n - 1, -1, -1): li[0], li[high] = li[high], li[0] sift(li, 0, high - 1) # 排除堆中的最后一个元素 li = [8, 1, 2, 6, 3, 7] heak_sort(li) print(li) # [1, 2, 3, 6, 7, 8]

 

#冒泡排序 时间复杂度O(n*n)
def bubble_sort(li):
    for i in range(len(li)):  # 表示躺数n躺
        flag = False
        for j in range(len(li) - 1 - i):  # 表示第n躺无序区的范围  0--n-i-1
            if li[j] > li[j + 1]:
                li[j], li[j + 1] = li[j + 1], li[j]
                flag = True
        if not flag:  # 表示无序区已经有序
            break
    return li

 

 

# 选择排序
'''思路:选择一个最小的val,和无序区的第一个元素进行,交换.时间复杂度O(n*n)'''
def select_sort(li):
    for i in range(len(li)):
        min_pos = i
        for j in range(i + 1, len(li)):
            if li[j] < li[min_pos]:
                min_pos = j  # 更新最小值的下标
        li[i], li[min_pos] = li[min_pos], li[i]
    return li

 

 

# 插入排序
'''思路:选择一个数,和有序区的元素进行比较,如果小于有序区的元素,就将每一个元素向后挪(1.比较的下标<0;2.比较的数>选择的数),依次比较最后插入位置'''


def insert_sort(li):
    for i in range(1, len(li)):  # 无序区的范围
        tmp = li[i]  # 默认取无序区的第一个元素和前面的每个元素进行比较
        j = i - 1  # 有序区的最后一个元素下标
        while j >= 0 and li[j] > tmp:  # ***必须是j>=0 and li[j]>tmp  否则li[-1]会error
            li[j + 1] = li[j]  # 向后挪
            j -= 1  # 向前找一个
        li[j + 1] = tmp  # 找到符合条件的下标j,后面一个空位即tmp的位置
    return li

 

# 快速排序
def quick_sort(li, left, right):
    '''nlogn'''
    if left < right:
        # 归为元素下标
        mid = partition(li, left, right)  # 归位
        quick_sort(li, left, mid - 1)  # 排 mid 左边的元素
        quick_sort(li, mid + 1, right)  # 排mid右边元素
    return li

def partition(li, left, right):
    '''O(n)'''
    tmp = li[left]
    while left < right:  # 排序区至少有2个元素
        while left < right and li[right] > tmp:  # 从右边往左走,
            # if left == right:
            #     break
            right -= 1
        li[left] = li[right]  # 丢到左边
        while left < right and li[left] < tmp:  # left=3 越界 此时li[2]=li[3]
            # if left == right:
            #     break
            left += 1  # 加等完事儿后注意越界问题,left!!!
        li[right] = li[left]  # 丢到右边 越界导致问题----

    # 退出循环left == right ==mid
    li[left] = tmp  # 丢到右边 越界导致问题---- li[3]=tmp 导致【1,2,4,3,5】
    return left


print(quick_sort([2,1,4,3,5],0,4))

 

 

# 归并排序.:先分解在merge
# 归并:时间复杂度O(n);空间复杂度O(n)  条件:一个列表中前后部分是有序的的[2,5,7,8,9,1,3,4,6,]
def merge(li, low, mid, high):
    """
    思路:分别比较两段列表的每个元素的位置,如果谁小,谁添加进li_tmp;最后两边的列表会剩下,依次循环append即可
    :param li:排序的列表
    :param low: 开始的位置
    :param mid: 有序的分段的位置
    :param high: 结尾的位置
    :return:
    """
    li_tmp = []
    i = low
    j = mid + 1
    while i <= mid and j <= high:  # 考虑 = 的情况,最后j+1后 j=8;所有必须<=防止少
        if li[i] < li[j]:
            li_tmp.append(li[i])
            i += 1
        if li[j] < li[i]:
            li_tmp.append(li[j])
            j += 1
    # 剩下的元素
    while i <= mid:
        li_tmp.append(li[i])
        i += 1
    while j <= high:
        li_tmp.append(li[j])
        j += 1
    li[low:high + 1] = li_tmp
    return li


# 归并排序O(nlog(n))
def merge_sort(li, low, high):
    if low < high:
        mid = (low + high) // 2
        # print(li[low: mid + 1], li[mid + 1: high])
        # 分解左边
        merge_sort(li, low, mid)
        # 分解右边
        merge_sort(li, mid + 1, high)
        # print(li[low: mid + 1], li[mid + 1: high])
        # 归并
        merge(li, low, mid, high)
        print(li[low: mid + 1], li[mid + 1: high])


li = [2, 5, 7, 8, 9, 1, 3, 4, 6]
merge_sort(li, 0, 8)
print(li)

 

posted @ 2020-04-08 14:32  烧刘病  阅读(134)  评论(0编辑  收藏  举报
回到页首