Алгоритмы и структуры данных на Python с примерами кода
Алгоритм Кнута-Морриса-Пратта (КМП-алгоритм) | Алгоритмы на Python
t = "лилила"
p = [0]*len(t)
j = 0
i = 1
while i < len(t):
if t[j] == t[i]:
p[i] = j+1
i += 1
j += 1
else:
if j == 0:
p[i] = 0;
i += 1
else:
j = p[j-1]
print(p)
a = "лилилось лилилась"
m = len(t)
n = len(a)
i = 0
j = 0
while i < n:
if a[i] == t[j]:
i += 1
j += 1
if j == m:
print("образ найден")
break
else:
if j > 0:
j = p[j-1]
else:
i += 1
if i == n and j != m:
print("образ не найден")
Алгоритм Бойера-Мура-Хорспула | Алгоритмы на Python
t = "данные"
# Этап 1: формирование таблицы смещений
S = set() # уникальные символы в образе
M = len(t) # число символов в образе
d = {} # словарь смещений
for i in range(M-2, -1, -1): # итерации с предпоследнего символа
if t[i] not in S: # если символ еще не добавлен в таблицу
d[t[i]] = M-i-1
S.add(t[i])
if t[M-1] not in S: # отдельно формируем последний символ
d[t[M-1]] = M
d['*'] = M # смещения для прочих символов
print(d)
# Этап 2: поиск образа в строке
a = "метеоданные"
N = len(a)
if N >= M:
i = M-1 # счетчик проверяемого символа в строке
while(i < N):
k = 0
j = 0
flBreak = False
for j in range(M-1, -1, -1):
if a[i-k] != t[j]:
if j == M-1:
off = d[a[i]] if d.get(a[i], False) else d['*'] # смещение, если не равен последний символ образа
else:
off = d[t[j]] # смещение, если не равен не последний символ образа
i += off # смещение счетчика строки
flBreak = True # если несовпадение символа, то flBreak = True
break
k += 1 # смещение для сравниваемого символа в строке
if not flBreak: # если дошли до начала образа, значит, все его символы совпали
print(f"образ найден по индексу {i-k+1}")
break
else:
print("образ не найден")
else:
print("образ не найден")
Алгоритм Дейкстры (Dijkstra’s algorithm) | Алгоритмы на Python
import math
def arg_min(T, S):
amin = -1
m = math.inf # максимальное значение
for i, t in enumerate(T):
if t < m and i not in S:
m = t
amin = i
return amin
D = ((0, 3, 1, 3, math.inf, math.inf),
(3, 0, 4, math.inf, math.inf, math.inf),
(1, 4, 0, math.inf, 7, 5),
(3, math.inf, math.inf, 0, math.inf, 2),
(math.inf, math.inf, 7, math.inf, 0, 4),
(math.inf, math.inf, 5, 2, 4, 0))
N = len(D) # число вершин в графе
T = [math.inf]*N # последняя строка таблицы
v = 0 # стартовая вершина (нумерация с нуля)
S = {v} # просмотренные вершины
T[v] = 0 # нулевой вес для стартовой вершины
M = [0]*N # оптимальные связи между вершинами
while v != -1: # цикл, пока не просмотрим все вершины
for j, dw in enumerate(D[v]): # перебираем все связанные вершины с вершиной v
if j not in S: # если вершина еще не просмотрена
w = T[v] + dw
if w < T[j]:
T[j] = w
M[j] = v # связываем вершину j с вершиной v
v = arg_min(T, S) # выбираем следующий узел с наименьшим весом
if v >= 0: # выбрана очередная вершина
S.add(v) # добавляем новую вершину в рассмотрение
#print(T, M, sep="\n")
# формирование оптимального маршрута:
start = 0
end = 4
P = [end]
while end != start:
end = M[P[-1]]
P.append(end)
print(P)
Алгоритм Флойда (Floyd’s algorithm) | Алгоритмы на Python
import math
def get_path(P, u, v):
path = [u]
while u != v:
u = P[u][v]
path.append(u)
return path
V = [[0, 2, math.inf, 3, 1, math.inf, math.inf, 10],
[2, 0, 4, math.inf, math.inf, math.inf, math.inf, math.inf],
[math.inf, 4, 0, math.inf, math.inf, math.inf, math.inf, 3],
[3, math.inf, math.inf, 0, math.inf, math.inf, math.inf, 8],
[1, math.inf, math.inf, math.inf, 0, 2, math.inf, math.inf],
[math.inf, math.inf, math.inf, math.inf, 2, 0, 3, math.inf],
[math.inf, math.inf, math.inf, math.inf, math.inf, 3, 0, 1],
[10, math.inf, 3, 8, math.inf, math.inf, 1, 0],
]
N = len(V) # число вершин в графе
P = [[v for v in range(N)] for u in range(N)] # начальный список предыдущих вершин для поиска кратчайших маршрутов
for k in range(N):
for i in range(N):
for j in range(N):
d = V[i][k] + V[k][j]
if V[i][j] > d:
V[i][j] = d
P[i][j] = k # номер промежуточной вершины при движении от i к j
# нумерацця вершин начинается с нуля
start = 1
end = 4
print(get_path(P, end, start))
Алгоритм Форда-Фалкерсона | Алгоритмы на Python
import math
def get_max_vertex(k, V, S):
m = 0 # наименьшее допустимое значение
v = -1
for i, w in enumerate(V[k]):
if i in S:
continue
if w[2] == 1: # движение по стрелке
if m < w[0]:
m = w[0]
v = i
else: # движение против стрелки
if m < w[1]:
m = w[1]
v = i
return v
def get_max_flow(T):
w = [x[0] for x in T]
return min(*w)
def updateV(V, T, f):
for t in T:
if t[1] == -1: # это исток
continue
sgn = V[t[2]][t[1]][2] # направление движения
# меняем веса в таблице для (i,j) и (j,i)
V[t[1]][t[2]][0] -= f * sgn
V[t[1]][t[2]][1] += f * sgn
V[t[2]][t[1]][0] -= f * sgn
V[t[2]][t[1]][1] += f * sgn
V = [[[0,0,1], [20,0,1], [30,0,1], [10,0,1], [0,0,1]],
[[20,0,-1], [0,0,1], [40,0,1], [0,0,1], [30,0,1]],
[[30,0,-1], [40,0,-1], [0,0,1], [10,0,1], [20,0,1]],
[[10,0,-1], [0,0,1], [10,0,-1], [0,0,1], [20,0,1]],
[[0,0,1], [30,0,-1], [20,0,-1], [20,0,-1], [0,0,1]],
]
N = len(V) # число вершин в графе
init = 0 # вершина истока (нумерация с нуля)
end = 4 # вершина стока
Tinit = (math.inf, -1, init) # первая метка маршруто (a, from, vertex)
f = [] # максимальные потоки найденных маршрутов
j = init
while j != -1:
k = init # стартовая вершина (нумерация с нуля)
T = [Tinit] # метки маршрута
S = {init} # множество просмотренных вершин
while k != end: # пока не дошли до стока
j = get_max_vertex(k, V, S) # выбираем вершину с наибольшей пропускной способностью
if j == -1: # если следующих вершин нет
if k == init: # и мы на истоке, то
break # завершаем поиск маршрутов
else: # иначе, переходим к предыдущей вершине
k = T.pop()[2]
continue
c = V[k][j][0] if V[k][j][2] == 1 else V[k][j][1] # определяем текущий поток
T.append((c, j, k)) # добавляем метку маршрута
S.add(j) # запоминаем вершину как просмотренную
if j == end: # если дошди до стока
f.append(get_max_flow(T)) # находим максимальную пропускную способность маршрута
updateV(V, T, f[-1]) # обновляем веса дуг
break
k = j
F = sum(f)
print(f"Максимальный поток равен: {F}")
Алгоритм Краскала (Kruskal’s algorithm) | Алгоритмы на Python
#-------------------------------------------------
# Алгоритм Краскала поиска минимального остова графа
#-------------------------------------------------
# список ребер графа (длина, вершина 1, вершина 2)
R = [(13, 1, 2), (18, 1, 3), (17, 1, 4), (14, 1, 5), (22, 1, 6),
(26, 2, 3), (22, 2, 5), (3, 3, 4), (19, 4, 6)]
Rs = sorted(R, key=lambda x: x[0])
U = set() # список соединенных вершин
D = {} # словарь списка изолированных групп вершин
T = [] # список ребер остова
for r in Rs:
if r[1] not in U or r[2] not in U: # проверка для исключения циклов в остове
if r[1] not in U and r[2] not in U: # если обе вершины не соединены, то
D[r[1]] = [r[1], r[2]] # формируем в словаре ключ с номерами вершин
D[r[2]] = D[r[1]] # и связываем их с одним и тем же списком вершин
else: # иначе
if not D.get(r[1]): # если в словаре нет первой вершины, то
D[r[2]].append(r[1]) # добавляем в список первую вершину
D[r[1]] = D[r[2]] # и добавляем ключ с номером первой вершины
else:
D[r[1]].append(r[2]) # иначе, все то же самое делаем со второй вершиной
D[r[2]] = D[r[1]]
T.append(r) # добавляем ребро в остов
U.add(r[1]) # добавляем вершины в множество U
U.add(r[2])
for r in Rs: # проходим по ребрам второй раз и объединяем разрозненные группы вершин
if r[2] not in D[r[1]]: # если вершины принадлежат разным группам, то объединяем
T.append(r) # добавляем ребро в остов
gr1 = D[r[1]]
D[r[1]] += D[r[2]] # объединем списки двух групп вершин
D[r[2]] += gr1
print(T)
Алгоритм Прима (ближайшего соседа) | Алгоритмы на Python
#-------------------------------------------------
# Алгоритм Прима поиска минимального остова графа
#-------------------------------------------------
import math
def get_min(R, U):
rm = (math.inf, -1, -1)
for v in U:
rr = min(R, key=lambda x: x[0] if (x[1] == v or x[2] == v) and (x[1] not in U or x[2] not in U) else math.inf)
if rm[0] > rr[0]:
rm = rr
return rm
# список ребер графа (длина, вершина 1, вершина 2)
# первое значение возвращается, если нет минимальных ребер
R = [(math.inf, -1, -1), (13, 1, 2), (18, 1, 3), (17, 1, 4), (14, 1, 5), (22, 1, 6),
(26, 2, 3), (19, 2, 5), (30, 3, 4), (22, 4, 6)]
N = 6 # число вершин в графе
U = {1} # множество соединенных вершин
T = [] # список ребер остова
while len(U) < N:
r = get_min(R, U) # ребро с минимальным весом
if r[0] == math.inf: # если ребер нет, то остов построен
break
T.append(r) # добавляем ребро в остов
U.add(r[1]) # добавляем вершины в множество U
U.add(r[2])
print(T)
Сортировка выбором | Алгоритмы на Python
#-------------------------------------------------
# Алгоритм сортировки выбором
#-------------------------------------------------
a = [-3, 5, 0, -8, 1, 10]
N = len(a) # число элементов в списке
for i in range(N-1):
m = a[i] # запоминаем минимальное значение
p = i # запоминаем индекс минимального значения
for j in range(i+1, N): # поиск миимального среди оставшихся элементов
if m > a[j]:
m = a[j]
p = j
if p != i: # обмен значениями, если был найден минимальный не в i-й позиции
t = a[i]
a[i] = a[p]
a[p] = t
print(a)
Сортировка вставками | Алгоритмы на Python
#-------------------------------------------------
# Алгоритм сортировки вставками
#-------------------------------------------------
a = [-3, 5, 0, -8, 1, 10]
N = len(a) # число элементов в списке
for i in range(1, N):
for j in range(i, 0, -1):
if a[j] < a[j-1]:
a[j], a[j-1] = a[j-1], a[j]
else:
break
print(a)
Сортировка пузырьком (метод всплывающего пузырька) | Алгоритмы на Python
#-------------------------------------------------
# Алгоритм сортировки пузырьком
#-------------------------------------------------
a = [7, 5, -8, 0, 10, 1]
N = len(a) # число элементов в списке
for i in range(0, N-1): # N-1 итераций работы алгоритма
for j in range(0, N-1-i): # проход по оставшимся не отсортированным парам массива
if a[j] > a[j+1]:
a[j], a[j+1] = a[j+1], a[j]
print(a)
Слияние двух упорядоченных списков | Алгоритмы на Python
#-------------------------------------------------
# Метод слияния двух списков
#-------------------------------------------------
a = [1, 4, 10, 11]
b = [2, 3, 3, 4, 8]
c = []
N = len(a)
M = len(b)
i = 0
j = 0
while i < N and j < M:
if a[i] <= b[j]:
c.append(a[i])
i += 1
else:
c.append(b[j])
j += 1
c += a[i:] + b[j:]
# if i < N:
# for k in range(i, N):
# c.append(a[k])
# elif j < M:
# for k in range(j, M):
# c.append(b[k])
print(c)
Быстрая сортировка слиянием (merge sort) | Алгоритмы на Python
#-------------------------------------------------
# Сортировка слиянием
#-------------------------------------------------
# функция слияния двух отсортированных списков
def merge_list(a, b):
c = []
N = len(a)
M = len(b)
i = 0
j = 0
while i < N and j < M:
if a[i] <= b[j]:
c.append(a[i])
i += 1
else:
c.append(b[j])
j += 1
c += a[i:] + b[j:]
return c
# функция деления списка и слияния списков в общий отсортированный список
def split_and_merge_list(a):
N1 = len(a) // 2
a1 = a[:N1] # деление массива на два примерно равной длины
a2 = a[N1:]
if len(a1) > 1: # если длина 1-го списка больше 1, то делим дальше
a1 = split_and_merge_list(a1)
if len(a2) > 1: # если длина 2-го списка больше 1, то делим дальше
a2 = split_and_merge_list(a2)
return merge_list(a1, a2) # слияние двух отсортированных списков в один
a = [9, 5, -3, 4, 7, 8, -8]
a = split_and_merge_list(a)
print(a)
Быстрая сортировка Хоара | Алгоритмы на Python
#-------------------------------------------------
# Быстрая сортировка Хоара через рекурсию
#-------------------------------------------------
import random
def quick_sort(a):
if len(a) > 1:
x = a[random.randint(0, len(a)-1)] # случайное пороговое значение (для разделения на малые и большие)
low = [u for u in a if u < x]
eq = [u for u in a if u == x]
hi = [u for u in a if u > x]
a = quick_sort(low) + eq + quick_sort(hi)
return a
a = [9, 5, -3, 4, 7, 8, -8]
a = quick_sort(a)
print(a)
Стек типа LIFO (Last-In-First-Out) | Алгоритмы на Python
# Пример использования стека типа LIFO
a = input("Введите строку: ")
stack = []
flVerify = True
for lt in a:
if lt in "([{":
stack.append(lt)
elif lt in ")]}":
if len(stack) == 0:
flVerify = False
break
br = stack.pop()
if br == '(' and lt == ')':
continue
if br == '[' and lt == ']':
continue
if br == '{' and lt == '}':
continue
flVerify = False
break
if flVerify and len(stack) == 0: # стек по итогам проверок должен быть пустым
print("Yes")
else:
print("No")
Делаем очередь (queue) | Алгоритмы на Python
Возможно вам будет интересно:

















