python常用算法总结(上)

目录

python常用算法总结

二分查找

希尔排序

桶排序

基数排序

计数排序

堆排序

归并排序

快速排序

插入排序

选择排序

冒泡排序

 拓扑排序

线性查找

广度优先搜索

深度优先搜索

Dijkstra算法

A*算法

Kruskal算法

Prim算法

Floyd-Warshall算法

贝尔曼-福特算法


python常用算法总结

二分查找

二分查找用于在有序数组中查找元素,通过反复将搜索范围缩小一半来找到目标元素。

def binary_search(arr, x):
    l = 0
    r = len(arr) - 1
    
    while l <= r:
        mid = l + (r - l) // 2
        if arr[mid] == x:
            return mid
        elif arr[mid] < x:
            l = mid + 1
        else:
            r = mid - 1
    return -1

# ⽰例
arr = [2, 3, 4, 10, 40]
x = 10
print(binary_search(arr, x))

希尔排序

希尔排序是插入排序的一种更高效的改进版本,通过初始使用大间隔的插入排序来减少数据量。

def shell_sort(arr):
    n = len(arr)
    gap = n // 2

    while gap > 0:
        for i in range(gap, n):
            temp = arr[i]
            j = i
            while j >= gap and arr[j - gap] > temp:
                arr[j] = arr[j - gap]
                j -= gap
            arr[j] = temp13 
        gap //= 2
    return arr

# ⽰例
print(shell_sort([12, 34, 54, 2, 3]))

桶排序

桶排序是另一种基于分布的排序算法,适用于均匀分布的数组

def bucket_sort(arr):
    bucket = []

    for i in range(len(arr)):
        bucket.append([])

    for j in arr:
        index_b = int(10 * j)
        bucket[index_b].append(j)

    for i in range(len(arr)):
        bucket[i] = sorted(bucket[i])

    k = 0
    for i in range(len(arr)):
        for j in range(len(bucket[i])):
            arr[k] = bucket[i][j]
            k += 1
    return arr

# ⽰例
print(bucket_sort([0.897, 0.565, 0.656, 0.123, 0.665, 0.343]))

基数排序

基数排序是一种非比较整数排序算法,通过按位分配和排序来处理数字

def counting_sort_exp(arr, exp1):
    n = len(arr)
    output = [0] * n
    count = [0] * 10

    for i in range(0, n):
        index = arr[i] // exp1
        count[index % 10] += 1

    for i in range(1, 10):
        count[i] += count[i - 1]

    i = n - 1
    while i >= 0:
        index = arr[i] // exp1
        output[count[index % 10] - 1] = arr[i]
        count[index % 10] -= 1
        i -= 1

    for i in range(0, len(arr)):
        arr[i] = output[i]

def radix_sort(arr):
    max1 = max(arr)
    exp = 1
    while max1 // exp > 0:
        counting_sort_exp(arr, exp)
        exp *= 10
    return arr

# ⽰例
print(radix_sort([170, 45, 75, 90, 802, 24, 2, 66]))

计数排序

计数排序适用于排序范围有限的整数数组。

def counting_sort(arr):
    max_val = max(arr)
    m = max_val + 1
    count = [0] * m

    for a in arr:
        count[a] += 1
    i = 0
    for a in range(m):
        for c in range(count[a]):
        arr[i] = a
        i += 1
    return arr
# ⽰例
print(counting_sort([4, 2, 2, 8, 3, 3, 1]))

堆排序

堆排序是一种基于堆数据结构的比较排序算法

def heapify(arr, n, i):
    largest = i
    l = 2 * i + 1
    r = 2 * i + 2

    if l < n and arr[i] < arr[l]:
        largest = l

    if r < n and arr[largest] < arr[r]:
        largest = r

    if largest != i:
        arr[i], arr[largest] = arr[largest], arr[i]
        heapify(arr, n, largest)

def heap_sort(arr):
    n = len(arr)

    for i in range(n // 2 - 1, -1, -1):
        heapify(arr, n, i)

    for i in range(n-1, 0, -1):
        arr[i], arr[0] = arr[0], arr[i]
        heapify(arr, i, 0)
    return arr

# ⽰例
print(heap_sort([12, 11, 13, 5, 6, 7]))

归并排序

归并排序是一种分治算法,首先将数组分成两个小数组,分别进行排序,然后将排好序的子数组合并成一个有序的数组。

def merge_sort(arr):
    if len(arr) > 1:
        mid = len(arr) // 2
        L = arr[:mid]
        R = arr[mid:]

        merge_sort(L)
        merge_sort(R)

        i = j = k = 0

        while i < len(L) and j < len(R):
            if L[i] < R[j]:
                arr[k] = L[i]
                i += 1
            else:
                arr[k] = R[j]
                j += 1
            k += 1

        while i < len(L):
            arr[k] = L[i]
            i += 1
            k += 1

        while j < len(R):
            arr[k] = R[j]
            j += 1
            k += 1
    return arr

# ⽰例
print(merge_sort([12, 11, 13, 5, 6, 7]))

快速排序

快速排序是一种分治算法,它选择一个基准元素,分区操作使得比基准元素小的元素放在左边,比基准元素大的元素放在右边,然后递归地对两边进行排序。

def quick_sort(arr):
    if len(arr) <= 1:
        return arr
    else:
        pivot = arr[len(arr) // 2]
        left = [x for x in arr if x < pivot]
        middle = [x for x in arr if x == pivot]
        right = [x for x in arr if x > pivot]
        return quick_sort(left) + middle + quick_sort(right)

# ⽰例
print(quick_sort([3, 6, 8, 10, 1, 2, 1]))

插入排序

插入排序的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

def insertion_sort(arr):
    for i in range(1, len(arr)):
        key = arr[i]
        j = i-1
        while j >= 0 and key < arr[j]:
            arr[j + 1] = arr[j]
            j -= 1
        arr[j + 1] = key
    return arr

# ⽰例
print(insertion_sort([12, 11, 13, 5, 6]))

选择排序

选择排序的工作原理是不断地从未排序部分选择最小(或最大)的元素,放到已排序部分的末尾。

def selection_sort(arr):
    for i in range(len(arr)):
        min_idx = i
        for j in range(i+1, len(arr)):
            if arr[j] < arr[min_idx]:
                min_idx = j
        arr[i], arr[min_idx] = arr[min_idx], arr[i]
    return arr

# ⽰例
print(selection_sort([64, 25, 12, 22, 11]))

冒泡排序

冒泡排序是最简单的排序算法之一。它重复地遍历要排序的列表,比较相邻的元素并交换它们的位置,如果它们的顺序错误。

def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        for j in range(0, n-i-1):
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
    return arr

# ⽰例
print(bubble_sort([64, 34, 25, 12, 22, 11, 90]))

 拓扑排序

拓扑排序用于有向无环图(DAG)中的顶点排序。

from collections import defaultdict

def topological_sort_util(v, visited, stack, graph):
    visited[v] = True

    for i in graph[v]:
        if not visited[i]:
            topological_sort_util(i, visited, stack, graph)

    stack.insert(0, v)

def topological_sort(graph):
    visited = {i: False for i in graph}
    stack = []

    for i in graph:
        if not visited[i]:
            topological_sort_util(i, visited, stack, graph)

    return stack

# ⽰例
graph = {
    'A': ['C'],
    'B': ['C', 'D'],
    'C': ['E'],
    'D': ['F'],
    'E': ['H', 'F'],
    'F': ['G'],
    'G': [],
    'H': []
}
print(topological_sort(graph))

线性查找

线性查找是最简单的查找算法,通过遍历数组找到目标元素

def linear_search(arr, x):
    for i in range(len(arr)):
        if arr[i] == x:
            return i
    return -1

# ⽰例
arr = [2, 3, 4, 10, 40]
x = 10
print(linear_search(arr, x))

广度优先搜索

广度优先搜索用于遍历或搜索树或图的节点

from collections import deque

def bfs(graph, start):
    visited = set()
    queue = deque([start])
    visited.add(start)

    while queue:
        vertex = queue.popleft()
        print(vertex, end=" ")

        for neighbour in graph[vertex]:
            if neighbour not in visited:
                visited.add(neighbour)
                queue.append(neighbour)

# ⽰例
graph = {
    'A': ['B', 'C', 'D'],
    'B': ['E', 'F'],
    'C': ['G'],
    'D': [],
    'E': [],
    'F': [],
    'G': []
}
bfs(graph, 'A')

深度优先搜索

深度优先搜索用于遍历或搜索树或图的节点。

def dfs(graph, start, visited=None):
    if visited is None:
        visited = set()
    visited.add(start)

    print(start, end=" ")

    for next in graph[start] - visited:
        dfs(graph, next, visited)
    return visited

# ⽰例
graph = {
    'A': set(['B', 'C']),
    'B': set(['A', 'D', 'E']),
    'C': set(['A', 'F']),
    'D': set(['B']),
    'E': set(['B', 'F']),
    'F': set(['C', 'E'])
}
dfs(graph, 'A')

Dijkstra算法

Dijkstra算法用于查找加权图中从单个顶点到其他顶点的最短路径。

import sys

def dijkstra(graph, start):
    shortest_paths = {start: (None, 0)}
    current_node = start
    visited = set()

    while current_node is not None:
        visited.add(current_node)
        destinations = graph[current_node]
        weight_to_current_node = shortest_paths[current_node][1]

        for next_node, weight in destinations.items():
            weight = weight_to_current_node + weight
            if next_node not in shortest_paths:
                shortest_paths[next_node] = (current_node, weight)
            else:
                current_shortest_weight = shortest_paths[next_node][1]
                if current_shortest_weight > weight:
                    shortest_paths[next_node] = (current_node, weight)

        next_destinations = {node: shortest_paths[node] for node in shortest_paths if node not in visited}
        if not next_destinations:
            return shortest_paths

        current_node = min(next_destinations, key=lambda k: next_destinations[k][1])

# ⽰例
graph = {
    'A': {'B': 1, 'C': 4},
    'B': {'A': 1, 'C': 2, 'D': 5},
    'C': {'A': 4, 'B': 2, 'D': 1},
    'D': {'B': 5, 'C': 1}
}
start = 'A'
print(dijkstra(graph, start))

A*算法

A*算法用于在加权图中查找从起点到目标的最短路径。

from queue import PriorityQueue

def heuristic(a, b):
    return abs(b[0] - a[0]) + abs(b[1] - a[1])

def a_star(graph, start, goal):
    q = PriorityQueue()
    pq.put((0, start))
    came_from = {}
    cost_so_far = {}
    came_from[start] = None
    cost_so_far[start] = 0

    while not pq.empty():
        current = pq.get()[1]

        if current == goal:
            break

        for next in graph[current]:
            new_cost = cost_so_far[current] + graph[current][next]
            if next not in cost_so_far or new_cost < cost_so_far[next]:
                cost_so_far[next] = new_cost
                priority = new_cost + heuristic(goal, next)
                pq.put((priority, next))
                came_from[next] = current

    return came_from, cost_so_far

# ⽰例
graph = {
    'A': {'B': 1, 'C': 3},
    'B': {'A': 1, 'C': 1, 'D': 6},
    'C': {'A': 3, 'B': 1, 'D': 2, 'E': 4},
    'D': {'B': 6, 'C': 2, 'E': 1},
    'E': {'C': 4, 'D': 1}
}
start = 'A'
goal = 'E'
came_from, cost_so_far = a_star(graph, start, goal)
print(came_from)
print(cost_so_far)

Kruskal算法

Kruskal算法用于查找加权无向图的最小生成树。

class Graph:
    def __init__(self, vertices): 
        self.V = vertices
        self.graph = []

    def add_edge(self, u, v, w):
        self.graph.append([u, v, w])

    def find(self, parent, i):
        if parent[i] == i:
            return i
        return self.find(parent, parent[i])

    def union(self, parent, rank, x, y):
        xroot = self.find(parent, x)
        yroot = self.find(parent, y)

        if rank[xroot] < rank[yroot]:
            parent[xroot] = yroot
        elif rank[xroot] > rank[yroot]:
            parent[yroot] = xroot
        else:
            parent[yroot] = xroot
            rank[xroot] += 1

    def kruskal_mst(self):
        result = []
        i = 0
        e = 0
        self.graph = sorted(self.graph, key=lambda item: item[2])
        parent = []
        rank = []

        for node in range(self.V):
            parent.append(node)
            rank.append(0)

        while e < self.V - 1:
            u, v, w = self.graph[i]
            i = i + 1
            x = self.find(parent, u)
            y = self.find(parent, v)

            if x != y:
                e = e + 1
                result.append([u, v, w])
                self.union(parent, rank, x, y)

        return result50
# ⽰例
g = Graph(4)
g.add_edge(0, 1, 10)
g.add_edge(0, 2, 6)
g.add_edge(0, 3, 5)
g.add_edge(1, 3, 15)
g.add_edge(2, 3, 4)
print(g.kruskal_mst())

Prim算法

Prim算法用于查找加权无向图的最小生成树。

import sys

def min_key(key, mst_set, V):
    min = sys.maxsize
    for v in range(V):
        if key[v] < min and mst_set[v] == False:
            min = key[v]
            min_index = v
    return min_index

def prim_mst(graph, V):
    key = [sys.maxsize] * V
    parent = [None] * V
    key[0] = 0
    mst_set = [False] * V
    parent[0] = -1

    for cout in range(V):
        u = min_key(key, mst_set, V)
        mst_set[u] = True

        for v in range(V):
            if graph[u][v] and mst_set[v] == False and key[v] > graph[u][v]:
            key[v] = graph[u][v]
            parent[v] = u

    return parent

# ⽰例
graph = [
    [0, 2, 0, 6, 0],32 [2, 0, 3, 8, 5],
    [0, 3, 0, 0, 7],
    [6, 8, 0, 0, 9],
    [0, 5, 7, 9, 0]
]
V = 5
parent = prim_mst(graph, V)
for i in range(1, V):
    print(parent[i], "-", i, "\t", graph[i][parent[i]])

Floyd-Warshall算法

Floyd-Warshall算法用于查找所有顶点对之间的最短路径。

INF = float('inf')

def floyd_warshall(graph):
    dist = list(map(lambda i: list(map(lambda j: j, i)), graph))
    V = len(graph)

    for k in range(V):
        for i in range(V):
            for j in range(V):
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])

    return dist

# ⽰例
graph = [
    [0, 5, INF, 10],
    [INF, 0, 3, INF],
    [INF, INF, 0, 1],
    [INF, INF, INF, 0]
]
print(floyd_warshall(graph))

贝尔曼-福特算法

贝尔曼-福特算法用于查找带负权重的加权图中从单个顶点到其他顶点的最短路径。

def bellman_ford(graph, V, E, src):
    dist = [float("Inf")] * V
    dist[src] = 0

    for _ in range(V - 1):
        for u, v, w in graph:
            if dist[u] != float("Inf") and dist[u] + w < dist[v]:
                dist[v] = dist[u] + w

    for u, v, w in graph:
        if dist[u] != float("Inf") and dist[u] + w < dist[v]:
            print("Graph contains negative weight cycle")
            return

    return dist

# ⽰例
V = 5
E = 8
graph = [
    [0, 1, -1],
    [0, 2, 4],
    [1, 2, 3],
    [1, 3, 2],
    [1, 4, 2],
    [3, 2, 5],
    [3, 1, 1],
    [4, 3, -3]
]
print(bellman_ford(graph, V, E, 0))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心碎烤肠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值