1. 程式人生 > 實用技巧 >鞏固複習(對以前的隨筆總結)_資料結構

鞏固複習(對以前的隨筆總結)_資料結構

單鏈表

# 實現單鏈表
class Node(object):
    '''定義一個節點'''
    def __init__(self,data):
        # 因為每次都需要生成一個節點,寫到類裡面便於儲存
        self.data = data
        # 儲存節點的值
        self.next = None
        # 預設將節點的指向為空
    # 二元組也可以實現節點 (data,next指標域) ,為了通用性不使用二元組

class DanLianBiao(object):
    # 定義一個單鏈表 將節點連線起來
    def
__init__(self,node = None): # 指向節點 如果沒傳遞則使用 None self._head = node # 定義頭節點,指向例項化類物件時傳遞的節點指向 def is_empty(self): '''連結串列是否為空''' return self._head == None def length(self): '''查詢連結串列長度''' cur = self._head # cur 為當前指向的指標 count = 0
# 記錄長度 while cur != None: # 當前指向不為 None count += 1 # 數量加 1 cur = cur.next # 將指標對節點進行移動 # 如果第一個節點為 None ,依舊是返回 0 return count # 返回節點數量 def travel(self): '''遍歷整個連結串列''' cur = self._head
while cur != None: # 如果不為空 則列印資料 print(cur.data) # 列印資料 cur = cur.next # 向下遍歷 def add(self,data): '''連結串列頭部新增元素''' node = Node(data) self._head = node # 將節點指向頭部 node.next = self._head # 將頭部作為節點的下一個元素 def append(self,data): '''連結串列尾部新增元素''' node = Node(data) # 建立一個節點 # 特殊情況 第一個節點為空 if self.is_empty(): self._head = node # 頭節點為 node else: cur = self._head while cur.next != None: cur = cur.next # cur.next.data = node.data # 不需要新增資料 cur.next = node # 新增節點 def insert(self,pos,data): '''指定位置新增元素''' # 如果為零位置 if pos <= 0: self.add(data) # 新增節點 elif pos > (self.length()-1): # 到最後一個元素 self.append(data) # 新增節點 else: node = Node(data) index = 0 cur = self._head while index < pos : # 遍歷到 pos 前一個位置 index += 1 cur = cur.next # 不斷向下移動 node.next = cur.next # 先和右面元素建立聯絡 防止與左面元素失聯 cur.next = node def remove(self,data): '''刪除節點''' cur = self._head pre = None # 設定遊標表示前一個遊標 while cur != None: if cur.data == data: # 如果 cur 指向的節點為要刪除的節點 if cur == self._head: # 如果資料為頭節點的資料 self._head = cur.next # 跳過 cur else: # 如果不是頭節點 pre.next = cur.next # 跳過 cur 指向的節點 break # 找到資料跳出迴圈 else: # 如果還沒有找到資料 pre = cur cur = cur.next # 向下移動 def search(self,data): '''查詢節點是否存在''' cur = self._head # 指向頭節點 while cur.next != None: # 如果下一個節點不為空 if cur.data == data: # 如果找到了資料 return True else: cur = cur.next # 繼續向下尋找 return False # 沒有找到該資料

雙鏈表

# 實現雙鏈表
class Node(object):
    # 前驅 資料 後繼
    def __init__(self,data):
        self.pre = None
        # 前驅
        self.data = self.data
        # 資料
        self.next = None
        # 後繼

class DoubleLianBiao(object):
    # 定義一個雙鏈表 將節點連線起來
    def __init__(self,node = None):
        # 指向節點 如果沒傳遞則使用 None
        self._head = node
        # 定義頭節點,指向例項化類物件時傳遞的節點指向

    def is_empty(self):
        '''連結串列是否為空'''
        return self._head is None

    def length(self):
        '''查詢連結串列長度'''
        cur = self._head
        # cur 為當前指向的指標
        count = 0
        # 記錄長度
        while cur != None:
            # 當前指向不為 None
            count += 1
            # 數量加 1
            cur = cur.next
            # 將指標對節點進行移動
        # 如果第一個節點為 None ,依舊是返回 0
        return count
        # 返回節點數量


    def travel(self):
        '''遍歷整個連結串列'''
        cur = self._head
        while cur != None:
            # 如果不為空 則列印資料
            print(cur.data,end = " ")
            # 列印資料
            cur = cur.next
            # 向下遍歷


    def add(self,data):
        '''連結串列頭部新增元素'''
        node = Node(data)
        # 將節點指向頭部
        node.next = self._head
        # 將頭部作為節點的下一個元素
        self._head = node
        # 將 node 作為頭節點
        node.next.pre = node
        # 牽右手 讓 node 後的節點指向node

    def append(self,data):
           '''連結串列尾部新增元素'''
           node = Node(data)
           # 建立一個節點

           # 特殊情況 第一個節點為空
           if self.is_empty():
               self._head = node
               # 頭節點為 node
           else:
               cur = self._head
               while cur.next != None:
                   cur = cur.next
               # cur.next.data = node.data
               # 不需要新增資料
               cur.next = node
               # 新增節點
               node.pre = cur
               # 連線左面的兩隻手

    def insert(self,pos,data):
           '''指定位置新增元素'''
           # 如果為零位置
           if pos <= 0:
               self.add(data)
               # 新增節點
           elif pos > (self.length()-1):
               # 到最後一個元素
               self.append(data)
               # 新增節點
           else:
               node = Node(data)
               index = 0
               cur = self._head
               while index < pos :
                   # 遍歷到 pos 前一個位置
                   index += 1
                   cur = cur.next
                   # 不斷向下移動
               node.next = cur
               # 右手:node 連線 當前指向的節點
               node.pre = cur.pre
               # 左手:node 的前一個節點為當前位置的前一個節點
               cur.pre.next = node
               # 左手:當前位置的前一個節點的下一個節點為 node 節點
               cur.pre = node
               # 右手:當前位置的前一個節點 為 node 節點

    def remove(self,data):
           '''刪除節點'''
           cur = self._head
           # 設定遊標表示前一個遊標
           while cur != None:
               if cur.data == data:
                   # 如果 cur 指向的節點為要刪除的節點
                   if cur == self._head:
                       # 如果資料為頭節點的資料
                       self._head = cur.next
                       # 跳過 cur
                       if cur.next != None:
                           # 如果只有一個節點,None 沒有pre屬性
                           cur.next.pre = None
                           # 刪除頭節點後 頭節點值為 None
                   else:
                       # 如果不是頭節點
                       cur.pre.next = cur.next
                       # 左手:當前節點的前一個節點的後一個節點為當前節點的後一個節點
                       if cur.next != None:
                           # 檢視是否是最後一個節點,None 沒有 pre 屬性
                           cur.next.pre = cur.pre
                           # 右手:當前節點的下一個節點的前一個節點為當前節點的前一個節點
                   break
                   # 找到資料跳出迴圈
               else:
                   # 如果還沒有找到資料
                   cur = cur.next
                   # 向下移動

    def search(self,data):
        '''查詢節點是否存在'''
        cur = self._head
        # 指向頭節點
        while cur.next != None:
            # 如果下一個節點不為空
            if cur.data == data:
                # 如果找到了資料
                return True
            else:
                cur = cur.next
                # 繼續向下尋找
        return False
        # 沒有找到該資料

單向迴圈連結串列

# 實現單向迴圈連結串列
class Node(object):
    '''定義一個節點'''
    def __init__(self,data):
        # 因為每次都需要生成一個節點,寫到類裡面便於儲存
        self.data = data
        # 儲存節點的值
        self.next = None
        # 預設將節點的指向為空

class DanLianBiao_Cycle(object):
    # 定義一個單向迴圈連結串列 將節點連線起來
    def __init__(self,node = None):
        # 指向節點 如果沒傳遞則使用 None
        self._head = node
        # 定義頭節點,指向例項化類物件時傳遞的節點指向
        if node != None:
            # 如果傳遞過來的不是 None
            # 第一個節點時需要指向自身(不同之處)
            node.next = node
            # 指向自己

    def is_empty(self):
        '''連結串列是否為空'''
        return self._head == None


    def length(self):
        '''查詢連結串列長度'''
        if self.is_empty():
            return 0
        count = 1
        # 等於1 是因為如果為0 到最後不能夠加到足夠數目
        while cur.next != self._head:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        '''遍歷整個連結串列'''
        if self.is_empty():
            return
        cur = self._head
        while cur.next != self._head:
            print(cur.data)
            cur = cur.next
        print(cur.data)
        # 尾節點的下一個元素為頭節點,跳出迴圈了,列印尾節點資料


    def add(self,data):
        '''連結串列頭部新增元素'''
        node = Node(data)
        if self.is_empty():
            self._head = node
            # 頭節點指向 node 節點
            node.next = node
            # node 節點的下一個節點還為 node
        else:
            cur = self._head
            # 指定當前節點指向
            while cur.next != self._head:
                # 一直遍歷
                cur = cur.next
                # 不斷向下
            # cur 當前指向最後一個節點
            node.next = self._head
            # 右手:node 的下一個節點為頭節點
            self._head = node
            # 讓頭指標指向 node 節點
            cur.next = self._head
            # 尾指標的下一個節點為更新後的頭節點

    def append(self,data):
           '''連結串列尾部新增元素'''
           node = Node(data)
           if self.is_empty():
               self._head = node
               node.next = node
           else:
               cur = self._head
               while cur.next != self._head:
                   cur = cur.next
               node.next = cur.next
               # 右手:cur.next 為頭節點
            # 讓 node 作為尾節點指向頭節點
               cur.next = node
               # 左手:讓當前節點的下一個節點指向 node 節點

    def insert(self,pos,data):
           '''指定位置新增元素'''
           # 如果為零位置
           if pos <= 0:
               self.add(data)
               # 新增節點
           elif pos > (self.length()-1):
               # 到最後一個元素
               self.append(data)
               # 新增節點
           else:
               node = Node(data)
               index = 0
               cur = self._head
               while index < pos :
                   # 遍歷到 pos 前一個位置
                   index += 1
                   cur = cur.next
                   # 不斷向下移動
               node.next = cur.next
               # 先和右面元素建立聯絡 防止與左面元素失聯
               cur.next = node

    def remove(self,data):
           '''刪除節點'''
           if self.is_empty():
               return
           cur = self._head
           pre = None
           # 設定遊標表示前一個遊標
           while cur.next != self._head:
               if cur.data == data:
                   # 如果 cur 指向的節點為要刪除的節點
                   if cur == self._head:
                       # 如果資料為頭節點的資料
                       rear = self._head
                       # 定義一個可以找到尾節點的指標
                       while rear.next != self._head:
                           rear = rear.next
                       # 此時 rear 為尾節點
                       self._head = cur.next
                       # 跳過頭節點
                       rear.next = self._head
                       # 尾節點的下一個元素為頭節點的下一個元素
                   else:
                       # 如果不是頭尾節點,是中間節點
                       pre.next = cur.next
                       # 跳過 cur 指向的節點
                   return
                   # 找到資料並返回
               else:
                   # 如果還沒有找到資料
                   pre = cur
                   cur = cur.next
                   # 向下移動
           # cur 當前指向為尾節點
           if cur.data == data:
               if cur == self._head:
                   # 如果只有一個節點,cur 沒有改變過
                   self._head = None
               else:
                   # 尾部節點為要刪除的節點
                   pre.next = cur.next


    def search(self,data):
        '''查詢節點是否存在'''
        if self.is_empty():
            return False
        cur = self._head
        # 指向頭節點
        while cur.next != self._head:
            # 如果下一個節點不為空
            if cur.data == data:
                # 如果找到了資料
                return True
            else:
                cur = cur.next
                # 繼續向下尋找
        # 處理尾部節點
        if cur.data == data:
            return True
            # 如果找到了元素
        return False
        # 沒有找到該資料

class Stack(object):
    '''建立一個棧'''
    def __init__(self):
        self.__lst = []
        # 將列表設定為私有,不讓外界進行訪問

    def add(self,data):
        '''在尾部新增元素'''
        self.__lst.append(data)


    def pop(self):
        '''在尾部取出元素'''
        return self.__lst.pop()
        # pop 刪除最後一個物件,並返回值

    def peek(self):
        '''返回棧頂元素'''
        if self.__lst != []:
            # 如果不為空
            return self.__lst[-1]
            # 返回最後一個元素(後進先出)
        else:
            # 棧為空
            return None

    def is_empty(self):
        '''判斷連結串列是否為空'''
        return self.__lst == []
        # 不要直接返回 self.__lst 會導致外部得到私有成員

    def size(self):
        '''返回棧的元素個數'''
        return len(self.__lst)
        # self.__lst 為列表物件,使用 len 獲取長度

佇列

class  Queue(object):
    '''實現佇列'''
    def __init__(self):
        self.__lst = []
        # 建立一個容器容納佇列成員

    def append_data(self,data):
        # 新增元素
        self.__lst.append(data)

    def pop_headdata(self):
        # 從頭部刪除資料
        return self.__lst.pop()

    def is_empty(self):
        return self.__lst == []
        # 判斷是否為空

    def size(self):
        # 返回佇列長度
        return len(self.__lst)

雙端佇列

class  DoubleQueue(object):
    '''實現雙端佇列'''
    def __init__(self):
        self.__lst = []
        # 建立一個容器容納佇列成員

    def append_frontdata(self,data):
        '''在頭部新增元素'''
        self.__lst.insert(0,data)

    def append_reardata(self,data):
        '''在尾部新增元素'''
        self.__lst.append(data)

    def pop_headdata(self):
        # 從頭部刪除資料
        return self.__lst.pop(0)

    def pop_reardata(self):
        # 在尾部刪除資料
        return self.__lst.pop()

    def is_empty(self):
        return self.__lst == []
        # 判斷是否為空

    def size(self):
        # 返回佇列長度
        return len(self.__lst)

二叉樹的建立

'''
樹:
    每一個結點都有零個或多個子結點
    沒有父節點的節點稱為根節點
    每一個非根結點有且只有一個父結點
    除了根結點外,每一個子節點可以分為多個不相交的子樹
二叉樹性質:
    在二叉樹的第 i 層 最多有 2^(i-1) 個結點
    深度為 k 的二叉樹最多有 2^k - 1 個結點
    葉子結點數為 N0  度數為 2 的結點數為 N2
        N0 = N2 + 1
    具有 n 個結點的完全二叉樹的深度為 log2(n+1)
    完全二叉樹:
        編號為 i 的結點
            左孩子 -> 2i
            右孩子 -> 2i + 1
        左孩子 的 父結點 編號必為 i/2

'''
class Node(object):
    '''定義一個結點,有左孩子和右孩子'''
    def __init__(self,data):
        # 結點資料
        self.data = data
        # 左、右 孩子指向為空
        self.lchild = None
        self.rchild = None

class BinaryTree(object):
    '''定義二叉樹'''
    def __init__(self):
        # 根結點預設為空
        self.root = None

    def add(self,data):
        # 新增資料到二叉樹中 向最後進行新增資料
        # 處理順序:父結點 左孩子 右孩子
        node = Node(data)
        # 如果為空樹
        if self.root is None:
            self.root = node
            # 空樹,加入資料則放在根節點處
            return
        queue = [self.root]
        # 新增根節點,作為存在該結點的標誌
        while queue:
            # 如果 queue 不為空
            cur_node = queue.pop(0)
            # 當前結點指向根節點,取第一個元素
            if cur_node.lchild is None :
                # 如果左結點為空
                cur_node.lchild = node
                return
            else:
                # 新增到指標內,證明存在左結點
                queue.append(cur_node.lchild)
            if cur_node.rchild is None:
                # 如果右結點為空
                cur_node.rchild = node
                return
            else:
                # 新增到指標內,證明存在右結點
                queue.append(cur_node.rchild)

廣度遍歷

class Node(object):
    '''定義一個結點,有左孩子和右孩子'''
    def __init__(self,data):
        # 結點資料
        self.data = data
        # 左、右 孩子指向為空
        self.lchild = None
        self.rchild = None

class BinaryTree(object):
    '''定義二叉樹'''
    def __init__(self):
        # 根結點預設為空
        self.root = None

    def add(self,data):
        # 新增資料到二叉樹中 向最後進行新增資料
        # 處理順序:父結點 左孩子 右孩子
        node = Node(data)
        # 如果為空樹
        if self.root is None:
            self.root = node
            # 空樹,加入資料則放在根節點處
            return
        queue = [self.root]
        # 新增根節點,作為存在該結點的標誌
        while queue:
            # 如果 queue 不為空
            cur_node = queue.pop(0)
            # 當前結點指向根節點,取第一個元素
            if cur_node.lchild is None :
                # 如果左結點為空
                cur_node.lchild = node
                return
            else:
                # 新增到指標內,證明存在左結點
                queue.append(cur_node.lchild)
            if cur_node.rchild is None:
                # 如果右結點為空
                cur_node.rchild = node
                return
            else:
                # 新增到指標內,證明存在右結點
                queue.append(cur_node.rchild)


    def bread_travel(self):
        '''廣度遍歷'''
        if self.root is None:
            # 如果為空樹,則直接返回
            return
        queue = [self.root]
        # 儲存存在的元素,通過 cur_node 驗證
        while queue:
            # pop 方法直到為 [] 為止
            cur_node = queue.pop(0)
            # 取出第一個元素
            print(cur_node.data)
            # 輸出結點
            if cur_node.lchild is not None:
                # 如果存在左結點
                queue.append(cur_node.lchild)
                # 新增到列表後
            if cur_node.rchild is not None:
                # 如果存在右結點
                queue.append(cur_node.rchild)
                # 新增到列表後

深度遍歷

class Node(object):
    '''定義一個結點,有左孩子和右孩子'''
    def __init__(self,data):
        # 結點資料
        self.data = data
        # 左、右 孩子指向為空
        self.lchild = None
        self.rchild = None

class BinaryTree(object):
    '''二叉樹'''
    def __init__(self):
        # 根結點預設為空
        self.root = None

    def add(self,data):
        # 新增資料到二叉樹中 向最後進行新增資料
        # 處理順序:父結點 左孩子 右孩子
        node = Node(data)
        # 如果為空樹
        if self.root is None:
            self.root = node
            # 空樹,加入資料則放在根節點處
            return
        queue = [self.root]
        # 新增根節點,作為存在該結點的標誌
        while queue:
            # 如果 queue 不為空
            cur_node = queue.pop(0)
            # 當前結點指向根節點,取第一個元素
            if cur_node.lchild is None :
                # 如果左結點為空
                cur_node.lchild = node
                return
            else:
                # 新增到指標內,證明存在左結點
                queue.append(cur_node.lchild)
            if cur_node.rchild is None:
                # 如果右結點為空
                cur_node.rchild = node
                return
            else:
                # 新增到指標內,證明存在右結點
                queue.append(cur_node.rchild)

    def pre_order(self,node):
        '''先序遍歷 -> 根左右'''
        if node is None:
            return
        print(node.data,end = " ")
        self.pre_order(node,lchild)
        # 一直遞迴左面結點,返回後遍歷右面
        self.pre_order(node,rchild)
        # 開始遍歷右側,直到為空

    def in_order(self,node):
        '''中序遍歷 -> 左根右'''
        if node is None:
            return
        self.in_order(node,lchild)
        # 一直遞迴左面結點
        print(node.data,end = " ")
        # 列印輸出資料
        self.in_order(node,rchild)
        # 遍歷右側資料


    def post_order(self,node):
        '''後序遍歷 -> 左右根'''
        if node is None:
            return
        self.post_order(node,lchild)
        # 一直遞迴左面結點
        self.post_order(node,rchild)
        # 一直遞迴右面結點
        print(node.data,end = " ")

單鏈表
'''
is_empty()          連結串列是否為空
length()            查詢連結串列長度
travel()            遍歷整個連結串列
add(item)           連結串列頭部新增元素
append(item)        連結串列尾部新增元素
insert(pos,item)    指定位置新增元素
remove(item)        刪除節點
search(item)        查詢節點是否存在
'''
class SingleNode(object):
    '''單鏈表的節點'''
    def __init__(self,item):
        self.item = item
        # 資料域
        self.next = None
        # 指標域next指向下一個節點

    def is_empty(self):
        '''判斷連結串列是否為空,看頭結點是否為空'''
        return self._head == None

    def length(self):
        '''連結串列長度,遍歷連結串列,每遍歷一次就進行加一操作'''
        cur = self._head
        #令cur當前指向頭節點位置
        count = 0  #count用來返回單鏈表長度
        while cur != None:
            count = count + 1
            cur = cur.next #到達下一個指標域
        return count

    def travel(self):
        '''遍歷單鏈表,對遍歷到的單鏈表元素取出資料域輸出'''
        cur = self._head#指向頭結點
        while cur != None:
            print(cur.item)#輸出當前節點的元素
            cur = cur.next#指向下一個節點
        print(" ")

    def add(self,item):
        '''在單鏈表頭部新增資料域為item元素的節點,
        使包含有item元素的節點的下一個節點為頭結點(沒進行新增之前的)'''
        node = SingleNode(item)
        # 建立連線,使頭結點為第二個節點
        node.next = self._head
        # 對頭結點進行重新命名
        self._head = node

    def append(self,item):
        '''尾部新增元素,當單鏈表為空時,直接新增。
            當單鏈表不為空時,在尾部新增(進行遍歷操作,直到最後一個節點)'''
        # 建立節點元素存放item元素
        node = SingleNode(item)
        if self.is_empty():#如果連結串列為空
            self._head = node
        else:
            cur = self._head  #令指標指向頭結點
            while cur.next != None:#進行遍歷
                cur = cur.next#依次向下進行遍歷,直到最後一個節點
            cur.next = node#讓最後一個節點為node,包含有item的元素的節點

    def insert(self,pos,item):
        '''在指定pos位置,新增包含有item元素的節點'''
        if pos <= 0:
            #當pos為小於等於0的位置時,將item新增在頭部
            self.add(item)
        elif pos >= self.length():
            # 當pos大於等於連結串列長度時,將item新增在尾部
            self.append(item)
        else:#既不在頭部,又不在尾部
            '''建立pre指標,指向pos的前一個位置'''
            node = SingleNode(item)
            # 儲存item元素的節點
            count = 0
            # pre用來指向位置pos的前一個位置pos-1,從頭結點開始
            pre = self._head
            while count < pos - 1:
                # 當count為pos-1時,pre為要插入位置的前一個節點
                count += 1
                pre = pre.next
            node.next = pre.next #先連線原來連結串列中pos位置後面節點左面的線
            pre.next = node#連線原來連結串列中前一個節點的右面的線

    def remove(self,item):
        cur = self._head
        pre = None
        while cur != None:
            # 當單鏈表不為空時
            if cur.item == item:
                # 如果cur所指向的節點的元素item與要刪除的item元素一致
                if not pre:
                    # pre 如果還是None 說明是頭結點
                    # pre = None
                    # print(not pre) # True
                    self._head = cur.next#當前cur指向第一個節點
                #   cur.next為原連結串列的第二個節點
                else:
                    #cur為要刪除的節點,但不是頭結點
                    '''pre為cur的前一個節點,cur為要刪除的節點
                       使用cur節點的後一個節點的左連線連線刪除節點的前一個元素的右連線'''
                    pre.next = cur.next
            else:#當cur指向的節點所包含的item元素不是要尋找的item時
                pre = cur
                cur = cur.next #繼續向下尋找

    def search(self,item):
        '''檢視連結串列中是否存在item元素,通過遍歷進行查詢'''
        cur = self._head #指向頭結點
        while cur != None:#當cur指向的不為空時
            if cur.item == item:#當找到該元素時
                return True
            cur = cur.next#在while迴圈內部,不斷進行遍歷
        return False

單向迴圈連結串列
'''
is_empty()          連結串列是否為空
length()            查詢連結串列長度
travel()            遍歷整個連結串列,到頭節點結束
add(item)           連結串列頭部新增元素(頭節點作為下一個節點,最後一個節點為node節點)
append(item)        連結串列尾部新增元素,頭節點為node的下一個節點
insert(pos,item)    指定位置新增元素
remove(item)        刪除節點
search(item)        查詢節點是否存在
'''
class Node(object):
    """節點"""
    def __init__(self, item):
        self.item = item
        self.next = None


class SinCycLinkedlist(object):
    """單向迴圈連結串列"""
    def __init__(self):
        self._head = None

    def is_empty(self):
        """判斷連結串列是否為空"""
        return self._head == None

    def length(self):
        """返回連結串列的長度"""
        # 如果連結串列為空,返回長度0
        if self.is_empty():
            return 0
        count = 1
        cur = self._head
        while cur.next != self._head:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        """遍歷連結串列"""
        if self.is_empty():
            return
        cur = self._head
        print (cur.item,)
        while cur.next != self._head:
            cur = cur.next
            print(cur.item,)
        print ("")


    def add(self, item):
        """頭部新增節點"""
        node = Node(item)
        if self.is_empty():
            self._head = node
            node.next = self._head
        else:
            #新增的節點指向_head
            node.next = self._head
            # 移到連結串列尾部,將尾部節點的next指向node
            cur = self._head
            while cur.next != self._head:
                cur = cur.next
            cur.next = node
            #_head指向新增node的
            self._head = node

    def append(self, item):
        """尾部新增節點"""
        node = Node(item)
        if self.is_empty():
            self._head = node
            node.next = self._head
        else:
            # 移到連結串列尾部
            cur = self._head
            while cur.next != self._head:
                cur = cur.next
            # 將尾節點指向node
            cur.next = node
            # 將node指向頭節點_head
            node.next = self._head

    def insert(self, pos, item):
        """在指定位置新增節點"""
        if pos <= 0:
            self.add(item)
        elif pos > (self.length()-1):
            self.append(item)
        else:
            node = Node(item)
            cur = self._head
            count = 0
            # 移動到指定位置的前一個位置
            while count < (pos-1):
                count += 1
                cur = cur.next
            node.next = cur.next
            cur.next = node

    def remove(self, item):
        """刪除一個節點"""
        # 若連結串列為空,則直接返回
        if self.is_empty():
            return
        # 將cur指向頭節點
        cur = self._head
        pre = None
        # 若頭節點的元素就是要查詢的元素item
        if cur.item == item:
            # 如果連結串列不止一個節點
            if cur.next != self._head:
                # 先找到尾節點,將尾節點的next指向第二個節點
                while cur.next != self._head:
                    cur = cur.next
                # cur指向了尾節點
                cur.next = self._head.next
                self._head = self._head.next
            else:
                # 連結串列只有一個節點
                self._head = None
        else:
            pre = self._head
            # 第一個節點不是要刪除的
            while cur.next != self._head:
                # 找到了要刪除的元素
                if cur.item == item:
                    # 刪除
                    pre.next = cur.next
                    return
                else:
                    pre = cur
                    cur = cur.next
            # cur 指向尾節點
            if cur.item == item:
                # 尾部刪除
                pre.next = cur.next

    def search(self, item):
        """查詢節點是否存在"""
        if self.is_empty():
            return False
        cur = self._head
        if cur.item == item:
            return True
        while cur.next != self._head:
            cur = cur.next
            if cur.item == item:
                return True
        return False

雙向連結串列
'''
is_empty()          連結串列是否為空
length()            查詢連結串列長度
travel()            遍歷整個連結串列
add(item)           連結串列頭部新增元素
append(item)        連結串列尾部新增元素
insert(pos,item)    指定位置新增元素
remove(item)        刪除節點
search(item)        查詢節點是否存在
'''
class Node(object):
    """雙向連結串列節點"""
    def __init__(self, item):
        self.item = item
        self.next = None
        self.pre = None


class DLinkList(object):
    """雙向連結串列"""
    def __init__(self):
        self._head = None

    def is_empty(self):
        """判斷連結串列是否為空"""
        return self._head == None

    def length(self):
        """返回連結串列的長度"""
        cur = self._head
        count = 0
        while cur != None:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        """遍歷連結串列"""
        cur = self._head
        while cur != None:
            print(cur.item,)
            cur = cur.next
        print(" ")

    def add(self, item):
        """頭部插入元素"""
        node = Node(item)
        if self.is_empty():
            # 如果是空連結串列,將_head指向node
            self._head = node
        else:
            # 將node的next指向_head的頭節點
            node.next = self._head
            # 將_head的頭節點的pre指向node
            self._head.pre = node
            # 將_head 指向node
            self._head = node

    def append(self, item):
        """尾部插入元素"""
        node = Node(item)
        if self.is_empty():
            # 如果是空連結串列,將_head指向node
            self._head = node
        else:
            # 移動到連結串列尾部
            cur = self._head
            while cur.next != None:
                cur = cur.next
            # 將尾節點cur的next指向node(先左後右)
            cur.next = node
            # 將node的pre指向cur
            node.pre = cur

    def search(self, item):
        """查詢元素是否存在"""
        cur = self._head
        while cur != None:
            if cur.item == item:
                return True
            cur = cur.next
        return False

    def insert(self, pos, item):
        """在指定位置新增節點"""
        if pos <= 0:
            self.add(item)
        elif pos > (self.length()-1):
            self.append(item)
        else:
            node = Node(item)
            cur = self._head
            count = 0
            # 移動到指定位置的前一個位置
            while count < (pos-1):
                count += 1
                cur = cur.next
            # 將node的pre指向cur(node左右,cur右左)
            node.pre = cur
            # 將node的next指向cur的下一個節點
            node.next = cur.next
            # 將cur的下一個節點的pre指向node
            cur.next.pre = node
            # 將cur的next指向node
            cur.next = node

    def remove(self, item):
            """刪除元素"""
            if self.is_empty():
                return
            else:
                cur = self._head
                if cur.item == item:
                    # 如果首節點的元素即是要刪除的元素
                    if cur.next == None:
                        # 如果連結串列只有這一個節點
                        self._head = None
                    else:
                        # 將第二個節點的pre設定為None
                        cur.next.pre = None
                        # 將_head指向第二個節點
                        self._head = cur.next
                    return
                while cur != None:
                    if cur.item == item:
                        # 將cur的前一個節點的next指向cur的後一個節點
                        cur.pre.next = cur.next
                        # 將cur的後一個節點的pre指向cur的前一個節點
                        cur.next.pre = cur.pre
                        break
                    cur = cur.next

佇列
'''
Queue()         建立一個空佇列
enqueue(item)   新增元素
dequeue()       從佇列頭部刪除一個元素
is_empty()      判斷一個佇列是否為空
size()          返回佇列的大小
'''
class Queue(object):
    '''佇列'''
    def __init__(self):
        self.items = []

    def is_empty(self):
        return self.items == []

    def enqueue(self,item):
        '''進佇列'''
        self.items.insert(0,item)

    def dequeue(self):
        '''出佇列'''
        return self.items.pop()

    def size(self):
        '''返回佇列的大小'''
        return len(self.items)

雙端佇列
'''
Deque()             建立一個空的雙端佇列
add_front(item)     從隊頭加入一個item元素
add_rear(item)      從隊尾加入一個item元素
remove_front()      從隊頭刪除一個item元素
remove_rear()       從隊尾刪除一個item元素
is_empty()          判斷雙端佇列是否為空
size()              返回佇列的大小
'''

class Deque(object):
    '''雙端佇列'''
    def __init__(self):
        self.items = []

    def is_empty(self):
        """判斷佇列是否為空"""
        return self.items == []

    def add_front(self,item):
        """在隊頭新增元素"""
        self.items.insert(0,item)

    def add_rear(self,item):
        """在隊尾新增元素"""
        self.items.append(item)

    def remove_front(self):
        """從隊頭刪除元素"""
        return self.items.pop(0)

    def remove_rear(self):
        """從隊尾刪除元素"""
        return self.items.pop()

    def size(self):
        """返回佇列大小"""
        return len(self.items)

'''
Stack()         建立一個新的空棧
push(item)      新增一個新的元素item到棧頂
pop()           彈出棧頂元素
peek()          返回棧頂元素
is_empty()      判斷棧是否為空
size()          返回棧的元素個數
'''
class Stack(object):
    ''''''
    def __init__(self):
        self.items = []

    def is_empty(self):
        """判斷是否為空"""
        return self.items == []

    def push(self,item):
        """加入元素"""
        self.items.append(item)

    def pop(self):
        """彈出元素"""
        return self.items.pop()

    def peek(self):
        """返回棧頂元素"""
        return self.items[len(self.items)-1]

    def size(self):
        return len(self.items)

建立二叉樹
class Node(object):
    """節點類"""
    def __init__(self, elem=-1, lchild=None, rchild=None):
        self.elem = elem
        self.lchild = lchild
        self.rchild = rchild

class Tree(object):
    """樹類"""
    def __init__(self, root=None):
        self.root = root

    def add(self, elem):
        """為樹新增節點"""
        node = Node(elem)
        #如果樹是空的,則對根節點賦值
        if self.root == None:
            self.root = node
        else:
            queue = []
            queue.append(self.root)
            #對已有的節點進行層次遍歷
            while queue:
                #彈出佇列的第一個元素
                cur = queue.pop(0)
                if cur.lchild == None:
                    cur.lchild = node
                    return
                elif cur.rchild == None:
                    cur.rchild = node
                    return
                else:
                    #如果左右子樹都不為空,加入佇列繼續判斷
                    queue.append(cur.lchild)
                    queue.append(cur.rchild)

二叉樹的層次遍歷

def breadth_travel(self, root):
    """利用佇列實現樹的層次遍歷"""
    if root == None:
        return
    queue = []
    queue.append(root)
    while queue:
        node = queue.pop(0)
        print(node.elem,)
        if node.lchild != None:
            queue.append(node.lchild)
        if node.rchild != None:
            queue.append(node.rchild)

二叉樹的深度遍歷
def preorder(self, root):
    """遞迴實現先序遍歷"""
    if root == None:
        return
    print(root.elem)
    self.preorder(root.lchild)
    self.preorder(root.rchild)


def inorder(self, root):
    """遞迴實現中序遍歷"""
    if root == None:
        return
    self.inorder(root.lchild)
    print(root.elem)
    self.inorder(root.rchild)


def postorder(self, root):
    """遞迴實現後序遍歷"""
    if root == None:
        return
    self.postorder(root.lchild)
    self.postorder(root.rchild)
    print(root.elem)

鄰接矩陣
class Vertex:
    def __init__(self, node):
        self.id = node
        # Mark all nodes unvisited        
        self.visited = False  

    def addNeighbor(self, neighbor, G):
        G.addEdge(self.id, neighbor)

    def getConnections(self, G):
        return G.adjMatrix[self.id]

    def getVertexID(self):
        return self.id

    def setVertexID(self, id):
        self.id = id

    def setVisited(self):
        self.visited = True

    def __str__(self):
        return str(self.id)

class Graph:
    def __init__(self, numVertices=10, directed=False):
        self.adjMatrix = [[None] * numVertices for _ in range(numVertices)]
        self.numVertices = numVertices
        self.vertices = []
        self.directed = directed
        for i in range(0, numVertices):
            newVertex = Vertex(i)
            self.vertices.append(newVertex)

    def addVertex(self, vtx, id):  #增加點,這個function沒有擴充套件功能
        if 0 <= vtx < self.numVertices:
            self.vertices[vtx].setVertexID(id)

    def getVertex(self, n):
        for vertxin in range(0, self.numVertices):
            if n == self.vertices[vertxin].getVertexID():
                return vertxin
        return None

    def addEdge(self, frm, to, cost=0): #返回全部連線/航線
        #print("from",frm, self.getVertex(frm))
        #print("to",to, self.getVertex(to))
        if self.getVertex(frm) is not None and self.getVertex(to) is not None:
            self.adjMatrix[self.getVertex(frm)][self.getVertex(to)] = cost
            if not self.directed:
                # For directed graph do not add this
                self.adjMatrix[self.getVertex(to)][self.getVertex(frm)] = cost  

    def getVertices(self):
        vertices = []
        for vertxin in range(0, self.numVertices):
            vertices.append(self.vertices[vertxin].getVertexID())
        return vertices

    def printMatrix(self):
        for u in range(0, self.numVertices):
            row = []
            for v in range(0, self.numVertices):
                row.append(str(self.adjMatrix[u][v]) if self.adjMatrix[u][v] is not None else '/')
            print(row)

    def getEdges(self):
        edges = []
        for v in range(0, self.numVertices):
            for u in range(0, self.numVertices):
                if self.adjMatrix[u][v] is not None:
                    vid = self.vertices[v].getVertexID()
                    wid = self.vertices[u].getVertexID()
                    edges.append((vid, wid, self.adjMatrix[u][v]))
        return edges
    
    def getNeighbors(self, n):
        neighbors = []
        for vertxin in range(0, self.numVertices):
            if n == self.vertices[vertxin].getVertexID():
                for neighbor in range(0, self.numVertices):
                    if (self.adjMatrix[vertxin][neighbor] is not None):
                        neighbors.append(self.vertices[neighbor].getVertexID())
        return neighbors
    
    def isConnected(self, u, v):
        uidx = self.getVertex(u) 
        vidx = self.getVertex(v)
        return self.adjMatrix[uidx][vidx] is not None
    
    def get2Hops(self, u): #轉一次機可以到達哪裡
        neighbors = self.getNeighbors(u)
        print(neighbors)
        hopset = set()
        for v in neighbors:
            hops = self.getNeighbors(v)
            hopset |= set(hops)
        return list(hopset)

鄰接表
import sys
class Vertex:
    def __init__(self, node):
        self.id = node
        self.adjacent = {}
        #為所有節點設定距離無窮大
        self.distance = sys.maxsize
        # 標記未訪問的所有節點     
        self.visited = False  
        # Predecessor
        self.previous = None

    def addNeighbor(self, neighbor, weight=0):
        self.adjacent[neighbor] = weight

    # returns a list 
    def getConnections(self): # neighbor keys
        return self.adjacent.keys()  

    def getVertexID(self):
        return self.id

    def getWeight(self, neighbor):
        return self.adjacent[neighbor]

    def setDistance(self, dist):
        self.distance = dist

    def getDistance(self):
        return self.distance

    def setPrevious(self, prev):
        self.previous = prev

    def setVisited(self):
        self.visited = True

    def __str__(self):
        return str(self.id) + ' adjacent: ' + str([x.id for x in self.adjacent])
    
    def __lt__(self, other):
        return self.distance < other.distance and self.id < other.id    

class Graph:
    def __init__(self, directed=False):
        # key is string, vertex id
        # value is Vertex
        self.vertDictionary = {}
        self.numVertices = 0
        self.directed = directed
        
    def __iter__(self):
        return iter(self.vertDictionary.values())

    def isDirected(self):
        return self.directed
    
    def vectexCount(self):
        return self.numVertices

    def addVertex(self, node):
        self.numVertices = self.numVertices + 1
        newVertex = Vertex(node)
        self.vertDictionary[node] = newVertex
        return newVertex

    def getVertex(self, n):
        if n in self.vertDictionary:
            return self.vertDictionary[n]
        else:
            return None

    def addEdge(self, frm, to, cost=0):
        if frm not in self.vertDictionary:
            self.addVertex(frm)
        if to not in self.vertDictionary:
            self.addVertex(to)

        self.vertDictionary[frm].addNeighbor(self.vertDictionary[to], cost)
        if not self.directed:
            # For directed graph do not add this
            self.vertDictionary[to].addNeighbor(self.vertDictionary[frm], cost)

    def getVertices(self):
        return self.vertDictionary.keys()

    def setPrevious(self, current):
        self.previous = current

    def getPrevious(self, current):
        return self.previous

    def getEdges(self):
        edges = []
        for key, currentVert in self.vertDictionary.items():
            for nbr in currentVert.getConnections():
                currentVertID = currentVert.getVertexID()
                nbrID = nbr.getVertexID()
                edges.append((currentVertID, nbrID, currentVert.getWeight(nbr))) # tuple
        return edges
    
    def getNeighbors(self, v):
        vertex = self.vertDictionary[v]
        return vertex.getConnections()

鄰接矩陣和鄰接表的原文連結:
https://www.cnblogs.com/kumata/p/9246502.html

2020-07-25