python常见算法的实现

排序:

1.堆排序:

堆是一种特殊的数据结构,它的通常的表示是它的根结点的值最大或者是最小。python标准库模块heapq提供了相关堆排序的实现
heapq的常见用法

heapq=[]  #创建一个堆
heapq.heappush(heap,item)#往堆中插入一条新的值
heapq.heappop(heap)#弹出最小的值
heap.heapify(list)#将转换列表成为堆结构
heap[0] # 如果只是想获取最小值而不是弹出,使用heap[0]
heap.heapreplace(heap,item)#弹出一个最小的值,然后将item插入到堆当中。堆的整体的结构不会发生改变。
heapq.heappoppush()#弹出最小的值,并且将新的值插入其中
heapq.nlargest(n , iterbale, key=None)#从堆中找出做大的N个数,key的作用和sorted( )方法里面的key类似,用列表元素的某个属性和函数作为关键字
heapq.merge(*iterables) #方法,用于合并多个排序后的序列成一个排序后的序列, 返回排序后的值的迭代器。
1.创建一个堆:

两种方法,第一种就是创建空列表,然后用heapq.heappush()方法把值加入堆中;第二种就是用heap.heapify(list)方法转换列表成为堆结构;

import heapq
lis=[2, 3, 5, 1, 54, 23, 132]
heap = []
for num in lis:
    heapq.heappush(heap, num)    #第一种方式
    
print([heapq.heappop(heap) for _ in range(len(lis))])  # 堆排序结果
# out: [1, 2, 3, 5, 23, 54, 132]

lis = [2, 3, 5, 1, 54, 23, 132]
heapq.heapify(lis)# 第二种方式
print([heapq.heappop(nums) for _ in range(len(nums))])  # 堆排序结果
# out: [1, 2, 3, 5, 23, 54, 132]

#通过heapq.merge(*iterables) 方法,合并多个排序后的序列成一个排序后的序列, 返回排序后的值的迭代器。
n1=[32, 3, 5, 34, 54, 23, 132]
n2=[23, 2, 12, 656, 324, 23, 54]
n1=sorted(n1)
n2=sorted(n2)
me=heapq.merge(n1, n2)
print(list(me))
#out: [2, 3, 5, 12, 23, 23, 23, 32, 34, 54, 54, 132, 324, 656]

2.获取堆的最大或最小值:
"""
从列表中找出最大的或最小的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},
    {
    
    'name': 'HPQ', 'shares': 35, 'price': 31.75},
    {
    
    'name': 'YHOO', 'shares': 45, 'price': 16.35},
    {
    
    'name': 'ACME', 'shares': 75, 'price': 115.65}
]
print(heapq.nlargest(3, list1))
print(heapq.nsmallest(3, list1))
"""
输出:
[99, 92, 88]
[12, 25, 34]
"""
print(heapq.nlargest(2, list2, key=lambda x: x['price']))
print(heapq.nlargest(2, list2, key=lambda x: x['shares']))
"""
输出:
[{'name': 'YHOO', 'price': 16.35, 'shares': 45},
 {'name': 'FB', 'price': 21.09, 'shares': 200},
 {'name': 'HPQ', 'price': 31.75, 'shares': 35}]
[{'name': 'AAPL', 'price': 543.22, 'shares': 50},
 {'name': 'ACME', 'price': 115.65, 'shares': 75},
 {'name': 'IBM', 'price': 91.1, 'shares': 100}]
"""
3.实现堆排序算法:
>>> def heapsort(iterable):
	h = []
	for value in iterable:
		heapq.heappush(h, value)
	return [heapq.heappop(h) for i in range(len(h))]

>>> heapsort([1,3,2,5,4,9,6,8,10])
[1, 2, 3, 4, 5, 6, 8, 9, 10]

2.简单选择排序:

>>> def select_sort(items, comp=lambda x, y: x < y):#默认参数用lambda表达式来规定排序规则
    """简单选择排序"""
    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

>>> select_sort([1,2,5,4,9,8,7,6])
[1, 2, 4, 5, 6, 7, 8, 9]

3.冒泡排序:

>>> def bubble_sort(items, comp=lambda x, y: x > y):#默认参数仍然选用lambda表达式规则
    """冒泡排序"""
    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

>>> bubble_sort([1,2,5,4,9,8,7,6])
[1, 2, 4, 5, 6, 7, 8, 9]

4.冒泡排序plus:

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

5.归并排序:

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):
    """归并排序"""
    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_sort(items, comp=lambda x, y: x < y):
    return _merge_sort(list(items), comp)

查找:

1.顺序查找:

顺序查找用到了一个python内置enumerate() 函数:
enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中
举例:

>>>seasons = ['Spring', 'Summer', 'Fall', 'Winter']
>>> list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
>>> list(enumerate(seasons, start=1))       # 下标从 1 开始
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]

顺序查找:

def seq_search(items, key):
    """顺序查找"""
    for index, item in enumerate(items):
        if item == key:
            return index
    return -1

2.折半查找:

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

常见算法:

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

穷举举例:

#穷举法:
'''鸡兔同笼问题:今有鸡兔同笼,上有三十五头,下有九十四足,问鸡兔各几只?
这个问题的大致意思是:在一个笼子里关着若干只鸡和若干只兔,从上面数共有35个头,从下面数共有94只脚。问笼中鸡和兔的数量各是多少?
'''
for i in range(1,35):
	for j in range(1,35):
    	if  (i*2 + j*4) == 94 and (i + j == 35):
        	print("There are %d chickens,and %d rabbits" % (i,j))

#列表推导式实现:
list = [(i,j) for i in range(1,35) for j in range(1,35) if (i*2 + j*4) == 94 and i + j ==35]

'''百钱百鸡问题: 公鸡5元一只 母鸡3元一只 小鸡1元三只,用100元买100只鸡 问公鸡/母鸡/小鸡各多少只'''
for x in range(20):
    for y in range(33):
        z = 100 - x - y
        if 5 * x + 3 * y + z // 3 == 100 and z % 3 == 0:
            print(x, y, z)

贪婪举例:
拍卖会,假有一个背包,最多能装20公斤物品,有如下表所示的物品。很显然,不能把所有物品都装进背包,所以必须装哪些物品,留下哪些物品。

名称 价格(¥) 重量(kg)
电脑 200 20
收音机 20 4
175 10
花瓶 50 2
10 1
油画 90 9
class Thing(object):
    """物品"""

    def __init__(self, name, price, weight):
        self.name = name
        self.price = price
        self.weight = weight

    @property
    def value(self):
        """价格重量比"""
        return self.price / self.weight


def input_thing():
    """输入物品信息"""
    name_str, price_str, weight_str = input().split()
    return name_str, int(price_str), int(weight_str)


def main():
    max_weight, num_of_things = map(int, input().split())
    all_things = []
    for _ in range(num_of_things):
        all_things.append(Thing(*input_thing()))
    all_things.sort(key=lambda x: x.value, reverse=True)
    total_weight = 0
    total_price = 0
    for thing in all_things:
        if total_weight + thing.weight <= max_weight:
            print(f'拿走了{thing.name}')
            total_weight += thing.weight
            total_price += thing.price
    print(f'总价值: {total_price}美元')


if __name__ == '__main__':
    main()

'''
输入:
20 6
电脑 200 20
收音机 20 4
钟 175 10
花瓶 50 2
书 10 1
油画 90 9
'''
'''
输出:
拿走了花瓶
拿走了钟
拿走了书
拿走了收音机
总价值: 255美元
'''

分治法举例:

"""
快速排序 - 选择枢轴对元素进行划分,左边都比枢轴小右边都比枢轴大
"""
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

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

子列表指的是列表中索引(下标)连续的元素构成的列表;列表中的元素是int类型,可能包含正整数、0、负整数;程序输入列表中的元素,输出子列表元素求和的最大值,例如:

输入:1 -2 3 5 -3 2

输出:8

输入:0 -2 3 5 -1 2

输出:9

输入:-9 -2 -3 -5 -3

输出:-2

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)


if __name__ == '__main__':
    main()

回溯法举例:
全排列问题:给定一个没有重复数字的序列,返回其所有可能的全排列

def DFS(res,sublist,nums):
    if len(sublist)==len(nums):
        res.append(sublist[:])
    for i in nums:
        if i in sublist:
            continue
        sublist.append(i)
        DFS(res,sublist,nums)#递归
        sublist.remove(i)#回溯

def main():
    res=[]
    sublist=[]
    nums=list(eval(input()))
    DFS(res,sublist,nums)
    print(res[:])

main()


'''
输入:1,2,3
输出:[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
'''

猜你喜欢

转载自blog.csdn.net/A52091/article/details/106113136