演算法學習05 雜湊 並查集

2021-09-12 08:42:08 字數 2103 閱讀 7944

經典雜湊函式:

輸入域無窮大的,輸出域有窮盡的,

輸入引數固定時,返回值一定是一樣的

輸入值不同時,有可能得到相同的返回值,(雜湊碰撞)

雜湊函式的離散性:給我很多不同的書的話,我將在整個s域上均勻返回其輸出值

對於分布式系統,需要將雜湊結果 限制在[0-232]以內,然後將雜湊結果區間平均分配給幾個伺服器.

並查集主要解決兩個問題:

判斷某元素是否存在於集合中

集合的合併

並查集的結構: 每個節點都有乙個父指標指向自己的父節點,父子節點屬於同乙個集合,根節點作為乙個集合的代表節點.

並查集的構造: 初始時每乙個點自成乙個集合,每乙個節點的父指標都指向自己,每乙個集合的代表節點為集合元素自身.

集合的合併: 是把乙個集合的代表節點的父節點指向另乙個節點的代表節點.

並查集的路徑壓縮: 查詢根節點時順便做路徑壓縮操作: 將沿途節點的父指標設為所查詢到的根節點.

並查集是用map實現的,某節點的fathermap值表示該節點的父指標

public

class

unionfind

// 並查集類

public

static

class

unionfindset

// 初始化並查集(使用node列表)

public

void

unionfindset

(list

nodes)

}// 找到並查集代表節點(路徑壓縮)

private node findhead

(node node)

fathermap.

put(node, father)

;return father;

}// 判斷是否是同乙個並查集

public

boolean

issameset

(node a, node b)

// 合併並查集

public

void

union

(node a, node b)

node ahead =

findhead

(a);

node bhead =

findhead

(b);

if(ahead != bhead)

else}}

}}

當節點數量足夠多時,並查集單次查詢和合併的效率是o(1),與資料規模無關.

乙個矩陣中只有0和1兩種值,每個位置都可以和自己的上、下、左、右四個位置相連,如果有一片1連在一起,這個部分叫做乙個島,求乙個矩陣中有多少個島?

舉例:

0 0 1 0 1 0

1 1 1 0 1 0

1 0 0 1 0 0

0 0 0 0 0 0

這個矩陣中有三個島。

解法作為經典問題,比較好做:一頓遍歷,若遍歷到1,就進入感染函式,將與其相連的部分感染成2,島嶼數量加一.

public

static

void

infect

(char

grid,

int y,

int x)

}}

若資料量很大,需要並行運算求解,就不太好做了,難點在於多cpu計算結果的合併.

合併時要考慮將邊界有重合的島合併,但問題在於我們不知道多個重合邊是否屬於同乙個島.

考慮如下情況:有乙個大c字形島嶼,被一刀切成三塊了,那麼在合併的時候遇到兩條邊,但我們不知道到底有幾個島(要合併幾次).

應用並查集結構,將乙個島嶼構造成乙個並查集,遇到相同邊的時候合併進同乙個並查集中,這樣避免了重複合併的問題.

演算法學習 並查集

大家肯定有聽說過社交網路裡面的六人理論吧,說是可以通過六個人的聯絡認識世界上的任意乙個人。比如我想認識一下機械系的系花,我先找到機械系的朋友,然後通過朋友介紹認識。這樣可以發現我們的社交圈子其實是有部分重疊的。當然也有可能是我的圈子太小,根本沒有什麼朋友認識那個圈子裡面的人,也有很大可能是機械系花4...

演算法學習之並查集

並查集是一種樹型的結構,常常用來處理一些不相交的集合的合併和查詢問題。查詢 確定元素所在的集合。合併 將兩個集合合併成乙個集合。查詢v所在集合的根節點 int find int v 合併 void merge int x,int y 優化1 int find int x k x while k r ...

演算法學習之 並查集

並查集用於解決連線類問題,判斷網路中節點間的連線狀態。與路徑類問題相比,並查集只回答了節點之間是否連通,而具體的連通路徑並不能確定,因此並查集在某些場景下非常高效。如前所述,此處的並查集實現只提供兩個介面 是否連線,元素合併。下面 使用乙個陣列來記錄每個元素所對應的類別,如果兩個元素的類別相同,則稱...