python中的冒泡、快速、堆排序及二分法查找

冒泡排序

它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素已经排序完成。

第一种

def bubble_sort(list):
    for index,element in enumerate(list):
        for sub_index in range(index):
            if list[sub_index] > list[sub_index + 1]:
                list[sub_index],list[sub_index + 1] = list[sub_index + 1],list[sub_index]
    return list
print(bubble_sort([3,9,1,5,6,20])) #[1, 3, 5, 6, 9, 20]

 第二种

def bubble(bubbleList):
    listLength = len(bubbleList)
    while listLength > 0:
        for i in range(listLength - 1):
            if bubbleList[i] > bubbleList[i + 1]:
                bubbleList[i],bubbleList[i + 1]= bubbleList[i+1],bubbleList[i]
        listLength -= 1
    print(bubbleList) #[0, 1, 2, 3, 4, 5, 8]


if __name__ == '__main__':
    bubbleList = [3, 4, 1, 2, 5, 8, 0]
    bubble(bubbleList) 

快速排序

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

第一种

# 首先从列表中挑出一个元素作为基准值key,所有小于key的值放right,大于的方left,分别递归左右侧元素
def quick_sort(list,left,right):
    # 在递归的过程在,如果发现left和right一致时,停滞递归,直接返回列表
    if left >= right:
        return list
    # 定义游标
    low = left
    high = right

    # 取参考值,最左边的列表
    key = list[low]
    while low < high:
        # 从最右侧向左,依次和标志元素对比,如果右侧的元素大于标志的元素
        while low < high and list[high] >= key:
            # 右侧减一
            high -= 1
        # 不然就把high赋值给low
        list[low] = list[high]

        # 从最左侧向右,依次和标志元素对比,如果左侧的元素大于标志的元素
        while low < high and list[low] <= key:
            # 左侧加一
            low += 1
        # 不然就把high赋值给low
        list[high] = list[low]
    # 最后给key的位置赋值
    list[high] = key

    # 处理左侧的元素
    quick_sort(list,left,low-1)
    # 处理右侧的元素
    quick_sort(list,low+1,right)
    return list
Dlist = [10,2,20,7,41,8,88,13]
print(quick_sort(Dlist,0,7)) #[2, 7, 8, 10, 13, 20, 41, 88]

 第二种

def quickSort(array):
    if len(array) < 2:  # 基线条件(停止递归的条件)
        return array
    else:  # 递归条件
        baseValue = array[0]  # 选择基准值
        # 由所有小于基准值的元素组成的子数组
        less = [m for m in array[1:] if m < baseValue]
        # 包括基准在内的同时和基准相等的元素,在上一个版本的百科当中,并没有考虑相等元素
        equal = [w for w in array if w == baseValue]
        # 由所有大于基准值的元素组成的子数组
        greater = [n for n in array[1:] if n > baseValue]
    return quickSort(less) + equal + quickSort(greater)
# 示例:
array = [2,3,5,7,1,4,6,15,5,2,7,9,10,15,9,17,12]
print(quickSort(array))
# 输出为[1, 2, 2, 3, 4, 5, 5, 6, 7, 7, 9, 9, 10, 12, 15, 15, 17]

堆排序

是指利用这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

在堆的数据结构中,堆中的最大值总是位于根节点(在优先队列中使用堆的话堆中的最小值位于根节点)。堆中定义以下几种操作:

  • 最大堆调整(Max Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点

  • 创建最大堆(Build Max Heap):将堆中的所有数据重新排序

  • 堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算

第一种

def heap_sort(list):
    def adjust(start,end):
        '''最大堆调整'''
        root = start
        while True:
            child = 2 * root + 1
            # 孩子的索引值超过数组最大长度
            if child > end:
                break
            # 确定最大的孩子节点的索引值
            if child + 1 <= end and list[child] < list[child + 1]:
                child += 1
            # 孩子节点最大值和根节点进行交换
            if list[root] < list[child]:
                list[root],list[child] = list[child],list[root]
                root = child
            else:
                break
    # 创建大根堆
    for start in range((len(list) - 2) // 2,-1,-1):
        adjust(start,len(list) - 1)

    for end in range(len(list) - 1,0,-1):
        # 首尾交换
        list[0],list[end] = list[end],list[0]
        # 重新排序
        adjust(0,end-1)
    return list
alist = [57,34,11,20,23,1,4,5]
print(heap_sort(alist)) #[1, 4, 5, 11, 20, 23, 34, 57]

第二种

def big_endian(arr, start, end):
    root = start
    while True:
        child = root * 2 + 1  # 左孩子
        if child > end:  # 孩子比最后一个节点还大 也就意味着最后一个叶子节点了 就得跳出去一次循环已经调整完毕
            break
        if child + 1 <= end and arr[child] < arr[child + 1]:  # 为了始终让其跟子元素的较大值比较 如果右边大就左换右,左边大的话就默认
            child += 1
        if arr[root] < arr[child]:  # 父节点小于子节点直接换位置 同时坐标也得换这样下次循环可以准确判断是否为最底层是不是调整完毕
            arr[root], arr[child] = arr[child], arr[root]
            root = child
        else:  # 父子节点顺序正常 直接过
            break


def heap_sort(arr):
    # 无序区大根堆排序
    first = len(arr) // 2 - 1
    for start in range(first, -1, -1):  # 从下到上,从右到左对每个节点进调整 循环得到非叶子节点
        big_endian(arr, start, len(arr) - 1)  # 去调整所有的节点
    for end in range(len(arr) - 1, 0, -1):
        arr[0], arr[end] = arr[end], arr[0]  # 顶部尾部互换位置
        big_endian(arr, 0, end - 1)  # 重新调整子节点的顺序  从顶开始调整
    return arr


def main():
    l = [3, 1, 4, 9, 6, 7, 5, 8, 2, 10]
    print(heap_sort(l))  # 原地排序 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


if __name__ == "__main__":
    main()

二分法查找

算法:二分法查找适用于数据量较大时,但是数据需要先排好顺序。主要思想是:(设查找的数组区间为array[low, high])

确定该区间的中间位置K(2)将查找的值T与array[k]比较。若相等,查找成功返回此位置;否则确定新的查找区域,继续二分查找。区域确定如下:a.array[k]>T 由数组的有序性可知array[k,k+1,……,high]>T;故新的区间为array[low,……,K-1]b.array[k]<T 类似上面查找区间为array[k+1,……,high]。每一次查找与中间值比较,可以确定是否查找成功,不成功当前查找区间将缩小一半,递归查找即可。

def dichotomy(list1, target):
    length = len(list1)
    index_low = 0
    index_high = length - 1

    while index_low <= index_high:
        index_midle = int((index_low + index_high) / 2)
        guess = list1[index_midle]
        if guess == target:
            return index_midle
        elif guess > target:
            index_high = index_midle - 1
        elif guess < target:
            index_low = index_midle + 1
    return None


list_1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
target_1 = 3
print(dichotomy(list_1, target_1)) #返回 2

猜你喜欢

转载自blog.csdn.net/ALLENsakaru/article/details/85018713