python 数据结构和算法

时间:2020-05-18
本文章向大家介绍python 数据结构和算法,主要包括python 数据结构和算法使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
# heapq模块(堆排序):从列表中找出最大的或最小的N个元素
import heapq
list1 = [34, 25, 12, 99, 87, 63, 58, 78, 88, 92]
list2 = [
    {'name': 'IBM', 'shares': 100, 'price': 91.1},
    {'name': 'AAPL', 'shares': 50, 'price': 543.22},
    {'name': 'FB', 'shares': 200, 'price': 21.09},
]
print(heapq.nlargest(3, list1))   # nsmallest
print(heapq.nlargest(2, list2, key=lambda x: x['price']))

################################################################################################
import itertools
itertools.permutations('ABCD')      # 产生ABCD的全排列
itertools.combinations('ABCDE', 3)  # 产生ABCDE的五选三组合
itertools.product('ABCD', '123')    # 产生ABCD和123的笛卡尔积
itertools.cycle(('A', 'B', 'C'))    # 产生ABC的无限循环序列


# collections模块常用的工具类:
# namedtuple:命令元组,它是一个类工厂,接受类型的名称和属性列表来创建一个类。
# deque:双端队列,是列表的替代实现。Python中列表底层是基于数组来实现的,而deque底层是双向链表,因此当你需要在头尾添加和删除元素是,deque会表现出更好的性能,渐近时间复杂度为O(1)。
# Counter:dict子类,键是元素,值是元素的计数,它的most_common()方法获取出现频率最高的元素。Counter和dict的继承关系值得商榷的,按照CARP原则,Counter跟dict的关系应该设计为关联关系更为合理。
# OrderedDict:dict的子类,它记录键值对插入的顺序,看起来既有字典的行为,也有链表的行为。
# defaultdict:类似于字典类型,但是可通过默认的工厂函数来获得键对应的默认值,相比字典中的setdefault()方法,这种做法更加高效。

from collections import Counter
words = [
    'look', 'into', 'my', 'eyes','the', 'eyes', "don't", 'look', 'around', 'the', 'eyes', 'look', 'into', 'my', 'eyes', "you're", 'under'
]
counter = Counter(words)
print(counter.most_common(3))   # 找出序列中出现次数最多的元素

 

数据结构和算法

  • 算法:解决问题的方法和步骤

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

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

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

常用算法:

  • 穷举法 - 又称为暴力破解法,对所有的可能性进行验证,直到找到正确答案。
  • 贪婪法 - 在对问题求解时,总是做出在当前看来
  • 最好的选择,不追求最优解,快速找到满意解。
  • 分治法 - 把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题,直到可以直接求解的程度,最后将子问题的解进行合并得到原问题的解。
  • 回溯法 - 回溯法又称为试探法,按选优条件向前搜索,当搜索到某一步发现原先选择并不优或达不到目标时,就退回一步重新选择。
  • 动态规划 - 基本思想也是将待求解问题分解成若干个子问题,先求解并保存这些子问题的解,避免产生大量的重复运算。

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

def select_sort(items, comp=lambda x, y: x < y):
    """简单选择排序"""
    items = 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 bubble_sort(items, comp=lambda x, y: x > y): """冒泡排序""" items = 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 not swapped: break return items
def bubble_sort(items, comp=lambda x, y: x > y): """搅拌排序(冒泡排序升级版)""" items = 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

def merge(items1, items2, comp=lambda x, y: x < y): """合并(将两个有序的列表合并成一个有序的列表)""" 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 items def merge_sort(items, comp=lambda x, y: x < y): return _merge_sort(list(items), comp) def _merge_sort(items, comp): """归并排序""" 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 seq_search(items, key): """顺序查找""" for index, item in enumerate(items): if item == key: return index return -1
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

 贪婪

回溯法例子:骑士巡逻

动态规划例子:子列表元素之和的最大值。

def main():
    items = list(map(int, input().split()))
    overall = partial = items[0]
    for i in range(1, len(items)):
        partial = max(items[i], partial + items[i])
        overall = max(partial, overall)
    print(overall)

分治法:快速排序

"""快速排序 - 选择枢轴对元素进行划分,左边都比枢轴小右边都比枢轴大"""
def quick_sort(items, comp=lambda x, y: x <= y):
    items = list(items)[:]
    _quick_sort(items, 0, len(items) - 1, comp)
    return items

def _quick_sort(items, start, end, comp):
    if start < end:
        pos = _partition(items, start, end, comp)
        _quick_sort(items, start, pos - 1, comp)
        _quick_sort(items, pos + 1, end, comp)

def _partition(items, start, end, comp):
    pivot = items[end]
    i = start - 1
    for j in range(start, end):
        if comp(items[j], pivot):
            i += 1
            items[i], items[j] = items[j], items[i]
    items[i + 1], items[end] = items[end], items[i + 1]
    return i + 1

 

原文地址:https://www.cnblogs.com/bsszds930/p/12910643.html