無論是任何程式設計師,不論是演算法,還是其他,都需要掌握一定的資料結構。本文以最優雅的方式,基於Python,完成演算法,不要問,背下來就好。程式碼量更少,更好背。
第2篇 棧與佇列:括號匹配(棧)、二進位制轉換(棧)、燙手的山芋(佇列)、迴文(雙端佇列)、反轉連結串列(連結串列);
1. 括號匹配
括號匹配,判斷字串中括號是否匹配。當為左括號時入棧,為右括號時出棧,最後,判斷棧是否為空,為空則括號匹配,否則不匹配。Python的list就可以實現棧的功能。演算法共14行。
def par_checker(symbol_str):
"""
括號匹配,list包含棧的功能
append是新增,pop是刪除
https://docs.python.org/2/tutorial/datastructures.html
14行
:param symbol_str: 符號字串
:return: 是否
"""
s = list() # python的list可以實現stack功能
idx = 0
while idx < len(symbol_str):
symbol = symbol_str[idx]
if symbol == '(':
s.append(symbol)
elif symbol == ')':
s.pop()
idx += 1
if not s:
return True
else:
return False
def test_of_par_checker():
print(par_checker('(())'))
print(par_checker('((()'))
print(par_checker('(a)()((()))'))
if __name__ == '__main__':
test_of_par_checker()
複製程式碼
2. 二進位制轉換
將二進位制數除以base,輸入佇列中,再倒序輸出,恰好是棧的功能。將數字新增至字串中,即可。演算法共11行。
def base_converter(num, base):
"""
將二進位制轉換為其他進位制
:param num: 數字
:param base: 基數
:return: 數字的字串
"""
digs = '0123456789ABCDEF' # 支援16位
base_stack = list()
while num > 0:
rem = num % base
base_stack.append(rem)
num //= base # 遞減一直到0
res_str = '' # 轉換為str
while base_stack:
res_str += digs[base_stack.pop()]
return res_str
if __name__ == '__main__':
print(base_converter(25, 2))
print(base_converter(25, 16))
複製程式碼
3. 燙手的山芋
點名,點到誰,誰出圈,迴圈使用佇列,最後一個出隊。演算法共10行。
from queue import Queue
def hot_potato(name_list, num):
"""
燙手的山芋,迴圈去除
:param name_list: 名字列表
:param num: 迴圈數
:return: 最後剩下的人
"""
q = Queue()
for name in name_list:
q.put(name)
while q.qsize() > 1:
for i in range(num - 1): # 每次都死一個迴圈,最後一個死亡
live = q.get()
q.put(live)
dead = q.get() # 輸出死亡
print('Dead: {}'.format(dead))
return q.get()
def test_of_hot_potato():
name_list = ['Bill', 'David', 'Susan', 'Jane', 'Kent', 'Brad']
num = 3
print(hot_potato(name_list, num))
if __name__ == '__main__':
test_of_hot_potato()
複製程式碼
4. 迴文
雙端佇列,隊首和隊尾的輸出是否相等。演算法共12行。
from collections import deque
def pal_checker(a_str):
"""
迴文,雙端佇列
:param a_str: 輸入字串
:return: 是否迴文
"""
q_char = deque()
for ch in a_str:
q_char.append(ch)
equal = True
# while的終止條件長度或者Bool
while len(q_char) > 1:
first = q_char.pop()
last = q_char.popleft()
if first != last:
equal = False
break
return equal
def test_of_pal_checker():
print(pal_checker('lsdkjfskf'))
print(pal_checker('radar'))
if __name__ == '__main__':
test_of_pal_checker()
複製程式碼
5. 連結串列反轉
連結串列反轉,prev_node保留頭結點,臨時變數next_node,保留當前結點之後的結點。演算法共8行。
class Node:
def __init__(self, data=None):
self.data = data
self.next_node = None
def reverse_list(node_head):
"""
連結串列逆序,交換連結串列
:param node_head: 連結串列頭
:return: 新的連結串列的頭結點
"""
prev_node = None
while node_head:
next_node = node_head.next_node
node_head.next_node = prev_node
prev_node = node_head
node_head = next_node
return prev_node
def init_list():
n1 = Node(1)
n2 = Node(2)
n3 = Node(3)
n4 = Node(4)
n5 = Node(5)
n1.next_node = n2
n2.next_node = n3
n3.next_node = n4
n4.next_node = n5
return n1
def show_list(node_head):
head = node_head
while head:
print(head.data, end=' ')
head = head.next_node
def test_of_reverse_list():
head_node = init_list()
show_list(head_node)
print()
head_node = reverse_list(head_node)
show_list(head_node)
if __name__ == '__main__':
test_of_reverse_list()
複製程式碼
OK, that's all! Enjoy it!