並查集的介紹
建立乙個 union_find 的類,並初始化。初始化兩個字典,乙個儲存節點的父節點,另外乙個儲存父節點的大小。初始化的時候,將節點的父節點設為自身,size 設為 1。
class
union_find
(object):
def__init__
(self, data_list)
: self.father_dict =
# 儲存節點的父節點
self.size_dict =
# 儲存父節點的大小
for node in data_list:
self.father_dict[node]
= node
self.size_dict[node]
=1
使用遞迴的方式來查詢父節點
def
find
(self, node)
: father = self.father_dict[node]
if(node != father)
:# 遞迴查詢父節點
father = self.find(father)
# 在查詢父節點的時候,順便把當前節點移動到父節點上面這個操作算是乙個優化
self.father_dict[node]
= father
return father
檢視兩個節點是不是在乙個集合裡面。通過呼叫 find 函式,判斷兩個節點是否是同乙個父節點,如果是則判斷兩個節點屬於乙個集合。
def
is_same_set
(self, node_a, node_b)
:return self.find(node_a)
== self.find(node_b)
將兩個集合合併在一起
def
union
(self, node_a, node_b)
:# 對合併的兩個節點做初步判斷,判斷是否為空
if node_a is
none
or node_b is
none
:return
# 分別查詢兩個節點的父節點
a_head = self.find(node_a)
b_head = self.find(node_b)
# 當兩個節點的父節點不一樣時,才能做合併操作
if(a_head != b_head)
: a_set_size = self.size_dict[a_head]
b_set_size = self.size_dict[b_head]
# 根據集合的大小做判斷,盡量使小集合並到大集合
if(a_set_size >= b_set_size)
: self.father_dict[b_head]
= a_head
self.size_dict[a_head]
= a_set_size + b_set_size
else
: self.father_dict[a_head]
= b_head
self.size_dict[b_head]
= a_set_size + b_set_size
例項應用
根據參考的 union_find ,完成以下功能的實現
在**中實現這些步驟:
初始 a = [1,2,3,4,5],並將其新增到並查集裡
分別合併[1,2] [3,5] [3,1]
然後判斷 2 5 是否為同乙個集合
**實現
class
union_find
(object):
def__init__
(self, data_list)
:# 儲存節點的父節點
self.father_dict =
# 儲存父節點的大小
self.size_dict =
# 把傳進來的資料,分別新增到兩個字典中
for node in data_list:
self.father_dict[node]
= node
self.size_dict[node]=1
deffind
(self, node)
: father = self.father_dict[node]
# 遞迴查詢父節點
if(node != father)
: father = self.find(father)
# 在查詢父節點的時候,順便把當前節點移動到父節點上面這個操作算是乙個優化
self.father_dict[node]
= father
return father
defis_same_set
(self, node_a, node_b)
:# 判斷兩個節點是否是同一父節點,是,則判斷兩個節點屬於乙個集合
return self.find(node_a)
== self.find(node_b)
defprint_dict
(self)
:# 輸出兩個字典中的資料
print
(self.father_dict, self.size_dict)
defunion
(self, node_a, node_b)
:# 對合併的兩個節點做初步判斷,判斷是否為空
if node_a is
none
or node_b is
none
:return
# 分別查詢兩個節點的父節點
a_head = self.find(node_a)
b_head = self.find(node_b)
# 當兩個節點的父節點不一樣時,才能做合併操作
if(a_head != b_head)
: a_set_size = self.size_dict[a_head]
b_set_size = self.size_dict[b_head]
# 根據集合的大小做判斷,盡量使小集合合併到大集合
if(a_set_size >= b_set_size)
:# a的集合數目大於等於b的,把b的父節點改為a的頭結點,即合併到a中去
self.father_dict[b_head]
= a_head
# 修改a集合的數目大小
self.size_dict[a_head]
= a_set_size + b_set_size
else
: self.father_dict[a_head]
= b_head
self.size_dict[b_head]
= a_set_size + b_set_size
if __name__ ==
'__main__'
: a =[1
,2,3
,4,5
] union_find = union_find(a)
union_find.union(1,
2)union_find.union(3,
5)union_find.union(3,
1)union_find.print_dict(
)print
(union_find.is_same_set(2,5))
執行結果如下
解析第乙個字典中,儲存的格式為【節點:父節點】
第二個字典中,儲存的格式為【父節點:子節點的數目】
我們需要判斷的是2與5是否是同乙個代表元
根據第乙個字典可得2的根節點查詢路徑為
2–1--3–3
5的根節點查詢路徑為
5–3最後比較,兩者的代表元相同為3,故返回true
python實現各種常用演算法之搜尋演算法(12)
順序搜尋也稱為線性搜尋,屬於無序查詢演算法。演算法原理 思路 從資料結構線性表的一端開始,順序掃瞄,依次將掃瞄到的結點關鍵字與給定值 k 相比較,若相等則表示查詢成功 若掃瞄結束仍沒有找到關鍵字等於 k 的結點,表示查詢失敗。複雜度分析 演算法實現 思路 從順序表的頭部依次遍歷元素,判斷是否匹配,若...
python實現各種常用演算法之資料結構(1)
棧 stack 又名堆疊,它是一種運算受限的線性表。其限制是僅允許在表的一端進行插入和刪除運算。棧允許進行插入和刪除操作的一端稱為棧頂 top 另一端為棧底 bottom 棧底固定,而棧頂浮動 棧中元素個數為零時稱為空棧。插入一般稱為進棧 push 刪除則稱為退棧 pop 由於堆疊資料結構只允許在一...
python實現各種常用演算法之資料結構(8)
字典樹的主要性質 根節點不包含字元,除根節點外每乙個節點都只包含乙個字元 從根節點到某一節點,路徑上經過的字元連線起來,為該節點對應的字串 每個節點的所有子節點包含的字元都不相同。基本功能實現 建立乙個 trienode 的類,構建內建字典結構 class trienode def init sel...