最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python實(shí)現(xiàn)一個(gè)簡(jiǎn)單的并查集的示例代碼

 更新時(shí)間:2018年03月19日 14:22:41   作者:黃天浩  
本篇文章主要介紹了python實(shí)現(xiàn)一個(gè)簡(jiǎn)單的并查集的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

并查集是一種樹型的數(shù)據(jù)結(jié)構(gòu),用于處理一些不相交集合的合并及查詢問題。常常在使用中以森林來表示。

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

用UnionFind類來表示一個(gè)并查集,在構(gòu)造函數(shù)中,初始化一個(gè)數(shù)組parent,parent[i]表示的含義為,索引為i的節(jié)點(diǎn),它的直接父節(jié)點(diǎn)為parent[i]。初始化時(shí)各個(gè)節(jié)點(diǎn)都不相連,因此初始化parent[i]=i,讓自己成為自己的父節(jié)點(diǎn),從而實(shí)現(xiàn)各節(jié)點(diǎn)不互連。

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

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

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

    return i

接下來可以通過來比較根節(jié)點(diǎn)是否相同來判斷兩節(jié)點(diǎn)是否連通。

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

當(dāng)要連通兩個(gè)節(jié)點(diǎn)時(shí),我們要將其中一個(gè)節(jié)點(diǎn)的根節(jié)點(diǎn)的parent,設(shè)置為另一個(gè)節(jié)點(diǎn)的根節(jié)點(diǎn)。注意,連通兩個(gè)節(jié)點(diǎn)并非僅僅讓兩節(jié)點(diǎn)自身相連,實(shí)際上是讓它們所屬的集合實(shí)現(xiàn)合并。

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

接下來我們做兩個(gè)小優(yōu)化。

由于調(diào)用get_root時(shí)需要通過不斷找自己的直接父節(jié)點(diǎn),來尋找根節(jié)點(diǎn),如果這棵樹的層級(jí)過深,會(huì)導(dǎo)致性能受到嚴(yán)重影響。因此我們需要在union時(shí),盡可能的減小合并后的樹的高度。

在構(gòu)造函數(shù)中新建一個(gè)數(shù)組rank,rank[i]表示節(jié)點(diǎn)i所在的集合的樹的高度。

因此,當(dāng)合并樹時(shí),分別獲得節(jié)點(diǎn)i和節(jié)點(diǎn)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

通過對(duì)union操作的改良可以防止樹的高度過高。我們還可以對(duì)get_root操作本身進(jìn)行優(yōu)化。

當(dāng)前每次執(zhí)行g(shù)et_root時(shí),需要一層一層的找到自己的父節(jié)點(diǎn),很費(fèi)時(shí)。由于根節(jié)點(diǎn)沒有父節(jié)點(diǎn),并且文章開始處提到過如果一個(gè)節(jié)點(diǎn)沒有父節(jié)點(diǎn),那么它的父節(jié)點(diǎn)就是自己,因此可以說只有根節(jié)點(diǎn)的父節(jié)點(diǎn)是自己本身?,F(xiàn)在我們加上一個(gè)判斷,判斷當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)是否為根節(jié)點(diǎn),如果不為根節(jié)點(diǎn),就遞歸地將自己的父節(jié)點(diǎn)設(shè)置為根節(jié)點(diǎn),最后返回自己的父節(jié)點(diǎn)。

  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實(shí)現(xiàn)一個(gè)簡(jiǎn)單的并查集的方式。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論

平和县| 南华县| 永安市| 元阳县| 大姚县| 米林县| 长宁县| 门头沟区| 茂名市| 碌曲县| 威信县| 长治市| 霍城县| 易门县| 广丰县| 渝中区| 福鼎市| 恭城| 迭部县| 林西县| 新昌县| 镇康县| 黑河市| 湘西| 大埔区| 浮山县| 靖江市| 丰顺县| 岚皋县| 平泉县| 沅陵县| 大埔区| 丹棱县| 聊城市| 都江堰市| 莎车县| 香格里拉县| 赣榆县| 萍乡市| 方正县| 苗栗市|