中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

python如何實現并查集

發布時間:2021-03-24 09:43:25 來源:億速云 閱讀:144 作者:小新 欄目:開發技術

這篇文章給大家分享的是有關python如何實現并查集的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

并查集是一種樹型的數據結構,用于處理一些不相交集合的合并及查詢問題。常常在使用中以森林來表示。

并查集有三種基本操作,獲得根節點,判斷兩節點是否連通,以及將兩不連通的節點相連(相當于將兩節點各自的集合合并)

用UnionFind類來表示一個并查集,在構造函數中,初始化一個數組parent,parent[i]表示的含義為,索引為i的節點,它的直接父節點為parent[i]。初始化時各個節點都不相連,因此初始化parent[i]=i,讓自己成為自己的父節點,從而實現各節點不互連。

  def __init__(self, n):
    self.parent = list(range(n))

由于parent[i]僅表示自己的直接父節點,查詢兩個節點是否相交需要比較它們的根節點是否相同。因此要封裝一個查詢自己根節點的方法。

  def get_root(self, i):
    while i != self.parent[i]:
      i = self.parent[i]

    return i

接下來可以通過來比較根節點是否相同來判斷兩節點是否連通。

  def is_connected(self, i, j):
    return self.get_root(i) == self.get_root(j)

當要連通兩個節點時,我們要將其中一個節點的根節點的parent,設置為另一個節點的根節點。注意,連通兩個節點并非僅僅讓兩節點自身相連,實際上是讓它們所屬的集合實現合并。

  def union(self, i, j):
    i_root = self.get_root(i)
    j_root = self.get_root(j)
    self.parent[i_root] = j_root

接下來我們做兩個小優化。

由于調用get_root時需要通過不斷找自己的直接父節點,來尋找根節點,如果這棵樹的層級過深,會導致性能受到嚴重影響。因此我們需要在union時,盡可能的減小合并后的樹的高度。

在構造函數中新建一個數組rank,rank[i]表示節點i所在的集合的樹的高度。

因此,當合并樹時,分別獲得節點i和節點j的root i_root和j_root之后,我們通過訪問rank[i_root]和rank[j_root]來比較兩棵樹的高度,將高度較小的那棵連到高度較高的那棵上。如果高度相等,則可以隨便,并將rank值加一。

  def union(self, i, j):
    i_root = self.get_root(i)
    j_root = self.get_root(j)

    if self.rank[i_root] == self.rank[j_root]:
      self.parent[i_root] = j_root
      self.rank[j_root] += 1
    elif self.rank[i_root] > self.rank[j_root]:
      self.parent[j_root] = i_root
    else:
      self.parent[i_root] = j_root

通過對union操作的改良可以防止樹的高度過高。我們還可以對get_root操作本身進行優化。

當前每次執行get_root時,需要一層一層的找到自己的父節點,很費時。由于根節點沒有父節點,并且文章開始處提到過如果一個節點沒有父節點,那么它的父節點就是自己,因此可以說只有根節點的父節點是自己本身。現在我們加上一個判斷,判斷當前節點的父節點是否為根節點,如果不為根節點,就遞歸地將自己的父節點設置為根節點,最后返回自己的父節點。

  def get_root(self, i):
    if self.parent[i] != self.parent[self.parent[i]]:
      self.parent[i] = self.get_root(self.parent[i])
    return self.parent[i]

感謝各位的閱讀!關于“python如何實現并查集”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

邵阳县| 平塘县| 波密县| 金山区| 红安县| 广昌县| 乌审旗| 阿拉善右旗| 普兰店市| 福海县| 丹寨县| 沛县| 双牌县| 克拉玛依市| 黔江区| 义乌市| 高州市| 安康市| 句容市| 新邵县| 资中县| 北流市| 阿坝县| 涟源市| 错那县| 雅江县| 方城县| 潢川县| 苍南县| 稷山县| 山东| 盐亭县| 英德市| 新郑市| 正镶白旗| 高密市| 色达县| 白城市| 甘德县| 广昌县| 江华|