程式設計師必須掌握的資料結構 2

SpikeKing發表於2018-11-05

無論是任何程式設計師,不論是演算法,還是其他,都需要掌握一定的資料結構。本文以最優雅的方式,基於Python,完成演算法,不要問,背下來就好。程式碼量更少,更好背。

原始碼:github.com/SpikeKing

第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!

相關文章