鞏固複習(對以前的隨筆總結)_資料結構
阿新 • • 發佈:2020-07-25
單鏈表
# 實現單鏈表
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