python實現各種常用演算法之資料結構(7)

2021-10-01 19:33:57 字數 4237 閱讀 3172

並查集的介紹

建立乙個 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...