python进阶-算法

谁都会走 提交于 2020-01-22 20:16:46
  • 算法:解决问题的方法和步骤

  • 评价算法的好坏:渐近时间复杂度和渐近空间复杂度。

  • 渐近时间复杂度的大O标记:

    •  - 常量时间复杂度 - 布隆过滤器 / 哈希存储
    •  - 对数时间复杂度 - 折半查找(二分查找)
    •  - 线性时间复杂度 - 顺序查找 / 桶排序
    •  - 对数线性时间复杂度 - 高级排序算法(归并排序、快速排序)
    •  - 平方时间复杂度 - 简单排序算法(选择排序、插入排序、冒泡排序)
    •  - 立方时间复杂度 - Floyd算法 / 矩阵乘法运算
    •  - 几何级数时间复杂度 - 汉诺塔
    •  - 阶乘时间复杂度 - 旅行经销商问题 - NP

排序算法(选择、冒泡和归并)和查找算法(顺序和折半)

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

函数:

def select_sort(origin_items, comp=lambda x, y: x < y):
    """简单选择排序"""
    items = origin_items[:]
    for i in range(len(items) - 1):
        min_index = i
        for j in range(i + 1, len(items)):
            if comp(items[j], items[min_index]):
                min_index = j
        items[i], items[min_index] = items[min_index], items[i]
    return items选择排序例子:
def select_sort(items):    for i in range(len(items)):        min_index = i        for j in range(i+1,len(items)):            if items[min_index] > items[j]:                min_index = j        items[i],items[min_index] = items[min_index],items[i]    print('选择排序后的数组:')    for i in range(len(items)):        print('%d ' %items[i],end=' ')def main():    items = [64, 25, 12, 22, 11]    select_sort(items)if __name__ == '__main__':    main()
冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。函数:
def bubble_sort(origin_items, comp=lambda x, y: x > y):
    """高质量冒泡排序(搅拌排序)"""
    items = origin_items[:]
    for i in range(len(items) - 1):
        swapped = False
        for j in range(i, len(items) - 1 - i):
            if comp(items[j], items[j + 1]):
                items[j], items[j + 1] = items[j + 1], items[j]
                swapped = True
        if swapped:
            swapped = False
            for j in range(len(items) - 2 - i, i, -1):
                if comp(items[j - 1], items[j]):
                    items[j], items[j - 1] = items[j - 1], items[j]
                    swapped = True
        if not swapped:
            break
    return items例子1:
def bubble_sort(items):    n = len(items)    for i in range(n):        for j in range(0,n-i-1):            if items[j] > items[j+1]:                items[j],items[j+1] = items[j+1],items[j]    print('冒泡排序后的数组:')    for i in range(len(items)):        print('%d' %items[i],end=' ')def main():    items = [64,34,25,12,22,11,90]    bubble_sort(items)if __name__ == '__main__':    main()例子2:
def bubble_sort(origin_items, comp=lambda x, y: x > y):    """高质量冒泡排序(搅拌排序)"""    items = origin_items[:]    for i in range(len(items) - 1):        swapped = False        for j in range(i, len(items) - 1 - i):            if comp(items[j], items[j + 1]):                items[j], items[j + 1] = items[j + 1], items[j]                swapped = True        if swapped:            swapped = False            for j in range(len(items) - 2 - i, i, -1):                if comp(items[j - 1], items[j]):                    items[j], items[j - 1] = items[j - 1], items[j]                    swapped = True        if not swapped:            break    return itemsdef main():    items = [64,34,25,12,22,11,90]    bubble_sort(items)    for i in range(len(items)):        print('%d' %items[i],end=' ')if __name__ == '__main__':    main()

归并排序(英语:Merge sort,或mergesort),是创建在归并操作上的一种有效的排序算法。

该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

分治法:

  • 分割:递归地把当前序列平均分割成两半。
  • 集成:在保持元素顺序的同时将上一步得到的子序列集成到一起(归并)。
函数:
def merge_sort(items, comp=lambda x, y: x <= y):
    """归并排序(分治法)"""
    if len(items) < 2:
        return items[:]
    mid = len(items) // 2
    left = merge_sort(items[:mid], comp)
    right = merge_sort(items[mid:], comp)
    return merge(left, right, comp)
def merge(items1, items2, comp):
    """合并(将两个有序的列表合并成一个有序的列表)"""
    items = []
    index, index2 = 0, 0
    while index1 < len(items1) and index2 < len(items2):
        if comp(items1[index1], items2[index2]):
            items.append(items1[index1])
            index1 += 1
        else:
            items.append(items2[index2])
            index2 += 1
    items += items1[index1:]
    items += items2[index2:]
    return items例子:
def merge_sort(items, comp=lambda x, y: x <= y):    """归并排序(分治法)"""    if len(items) < 2:        return items[:]    mid = len(items) // 2    left = merge_sort(items[:mid], comp)    right = merge_sort(items[mid:], comp)    return merge(left, right, comp)def merge(items1, items2, comp):    """合并(将两个有序的列表合并成一个有序的列表)"""    items = []    index1, index2 = 0, 0    while index1 < len(items1) and index2 < len(items2):        if comp(items1[index1], items2[index2]):            items.append(items1[index1])            index1 += 1        else:            items.append(items2[index2])            index2 += 1    items += items1[index1:]    items += items2[index2:]    return itemsdef main():    items = [64,34,25,12,22,11,90]    merge_sort(items)    for i in range(len(items)):        print('%d' %items[i],end=' ')if __name__ == '__main__':    main()例子2:
def merge(arr, l, m, r):    n1 = m - l + 1    n2 = r - m    # 创建临时数组    L = [0] * (n1)    R = [0] * (n2)    # 拷贝数据到临时数组 arrays L[] 和 R[]    for i in range(0, n1):        L[i] = arr[l + i]    for j in range(0, n2):        R[j] = arr[m + 1 + j]        # 归并临时数组到 arr[l..r]    i = 0  # 初始化第一个子数组的索引    j = 0  # 初始化第二个子数组的索引    k = l  # 初始归并子数组的索引    while i < n1 and j < n2:        if L[i] <= R[j]:            arr[k] = L[i]            i += 1        else:            arr[k] = R[j]            j += 1        k += 1    # 拷贝 L[] 的保留元素    while i < n1:        arr[k] = L[i]        i += 1        k += 1    # 拷贝 R[] 的保留元素    while j < n2:        arr[k] = R[j]        j += 1        k += 1def mergeSort(arr, l, r):    if l < r:        m = int((l + (r - 1)) / 2)        mergeSort(arr, l, m)        mergeSort(arr, m + 1, r)        merge(arr, l, m, r)arr = [12, 11, 13, 5, 6, 7]n = len(arr)print("给定的数组")for i in range(n):    print("%d" % arr[i])mergeSort(arr, 0, n - 1)print("\n\n排序后的数组")for i in range(n):    print("%d" % arr[i])
顺序查找指按一定的顺序检查数组中每一个元素,直到找到所要寻找的特定值为止。函数:
def seq_search(items, key):
    """顺序查找"""
    for index, item in enumerate(items):
        if item == key:
            return index
    return -1例子:
def seq_search(items,n,key):    for i in range(0,n):        if items[i] == key:            return i    return -1def main():    items = [64,34,25,12,22,11]    key = 22    n = len(items)    result = seq_search(items,n,key)    if result == -1:        print('元素不在数组中!')    else:        print("元素在数组中的索引为",result)if __name__ == '__main__':    main()
二分搜索是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。函数:def bin_search(items, key):
    """折半查找"""
    start, end = 0, len(items) - 1
    while start <= end:
        mid = (start + end) // 2
        if key > items[mid]:
            start = mid + 1
        elif key < items[mid]:
            end = mid - 1
        else:
            return mid
    return -1例子:

# 返回 x 在 arr 中的索引,如果不存在返回 -1def binarySearch(arr, l, r, x):    # 基本判断    if r >= l:        mid = int(l + (r - l) / 2)        # 元素整好的中间位置        if arr[mid] == x:            return mid            # 元素小于中间位置的元素,只需要再比较左边的元素        elif arr[mid] > x:            return binarySearch(arr, l, mid - 1, x)            # 元素大于中间位置的元素,只需要再比较右边的元素        else:            return binarySearch(arr, mid + 1, r, x)    else:        # 不存在        return -1def main():    # 测试数组    arr = [2, 3, 4, 10, 40]    x = 10    # 函数调用    result = binarySearch(arr, 0, len(arr) - 1, x)    if result != -1:        print("元素在数组中的索引为 %d" % result)    else:        print("元素不在数组中")if __name__ == '__main__':    main()
 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!