基于C#實現并查集

一、場景

有時候我們會遇到這樣的場景,比如:M={1,4,6,8},N={2,4,5,7},我的需求就是判斷{1,2}是否屬于同一個集合,當然實現方法有很多,一般情況下,普通青年會做出 O(MN)的復雜度,那么有沒有更輕量級的復雜度呢?并查集就是用來解決這個問題的。

二、操作

從名字可以出來,并查集其實只有兩種操作,并(Union)和查(Find),并查集是一種算法,所以我們要給它選擇一個好的數據結構,通常我們用樹來作為它的底層實現。

2.1、節點定義

 #region 樹節點/// <summary>/// 樹節點/// </summary>public class Node{/// <summary>/// 父節點/// </summary>public char parent;/// <summary>/// 節點的秩/// </summary>public int rank;}#endregion

2.2、Union 操作

<1> 原始方案
首先我們會對集合的所有元素進行打散,最后每個元素都是一個獨根的樹,然后我們 Union 其中某兩個元素,讓他們成為一個集合,最壞情況下我們進行 M 次的 Union 時會存在這樣的一個鏈表的場景。
image.png
從圖中我們可以看到,Union 時出現了最壞的情況,而且這種情況還是比較容易出現的,最終導致在 Find 的時候就相當復雜了,為 O(N)。
<2> 按秩合并
我們發現出現這種情況的原因在于我們 Union 時都是將合并后的大樹作為小樹的孩子節點存在,那么我們在 Union 時能不能判斷一下,將小樹作為大樹的孩子節點存在,最終也就降低了新樹的深度,比如圖中的 Union(D,{E,F})的時候可以做出如下修改。
image.png
可以看出,我們有效的降低了樹的深度,在 N 個元素的集合中,構建樹的深度不會超過 LogN 層。M 次操作的復雜度為 O(MlogN),從代碼上來說,我們用 Rank 來統計樹的秩,可以理解為樹的高度,獨根樹時 Rank=0,當兩棵樹的 Rank 相同時,可以隨意挑選合并,在新根中的 Rank++ 就可以了。

 #region 合并兩個不相交集合/// <summary>/// 合并兩個不相交集合/// </summary>/// <param name="root1"></param>/// <param name="root2"></param>/// <returns></returns>public void Union(char root1, char root2){char x1 = Find(root1);char y1 = Find(root2);//如果根節點相同則說明是同一個集合if (x1 == y1)return;//說明左集合的深度 < 右集合if (dic[x1].rank < dic[y1].rank){//將左集合指向右集合dic[x1].parent = y1;}else{//如果 秩 相等,則將 y1 并入到 x1 中,并將x1++if (dic[x1].rank == dic[y1].rank)dic[x1].rank++;dic[y1].parent = x1;}}#endregion

2.3、Find 操作

我們學算法,都希望能把一個問題優化到不能優化的地步,針對 logN 的級別,我們還能優化嗎?當然可以。
<1> 路徑壓縮
在 Union 和 Find 這兩種操作中,顯然我們在 Union 上面已經做到了極致,下面我們在 Find 上面考慮一下,是不是可以在 Find 上運用伸展樹的思想,這種伸展思想就是壓縮路徑。
image.png
從圖中我們可以看出,當我 Find(F)的時候,找到“F”后,我們開始一直回溯,在回溯的過程中給,把該節點的父親指向根節點。最終我們會形成一個壓縮后的樹,當我們再次 Find(F)的時候,只要 O(1)的時間就可以獲取,這里有個注意的地方就是 Rank,當我們在路徑壓縮時,最后樹的高度可能會降低,可能你會意識到原先的 Rank 就需要修改了,所以我要說的就是,當路徑壓縮時,Rank 保存的就是樹高度的上界,而不僅僅是明確的樹高度,可以理解成"伸縮椅"伸時候的長度。

 #region  查找x所屬的集合/// <summary>/// 查找x所屬的集合/// </summary>/// <param name="x"></param>/// <returns></returns>public char Find(char x){//如果相等,則說明已經到根節點了,返回根節點元素if (dic[x].parent == x)return x;//路徑壓縮(回溯的時候賦值,最終的值就是上面返回的"x",也就是一條路徑上全部被修改了)return dic[x].parent = Find(dic[x].parent);}#endregion

我們注意到,在路徑壓縮后,我們將 LogN 的復雜度降低到 Alpha(N),Alpha(N)可以理解成一個比 hash 函數還有小的常量,這就是算法的魅力。
image.png

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/166235.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/166235.shtml
英文地址,請注明出處:http://en.pswp.cn/news/166235.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Vatee萬騰科技的獨特力量:Vatee數字時代創新的新視野

在數字化時代的浪潮中&#xff0c;Vatee萬騰科技以其獨特而強大的創新力量&#xff0c;為整個行業描繪了一幅嶄新的視野。這不僅是一場科技創新的冒險&#xff0c;更是對未來數字時代發展方向的領先探索。 Vatee萬騰將創新視為數字時代發展的引擎&#xff0c;成為推動行業向前的…

ubuntu 安裝python3.13

列出 /usr/bin/ 目錄下所有以 python 開頭的文件和目錄 ls /usr/bin/python* 添加Python軟件源。您可以通過以下命令將Python的軟件源添加到您的系統中 sudo add-apt-repository ppa:deadsnakes/ppa 然后運行以下命令以更新軟件包列表&#xff1a; sudo apt-get update 安…

vue每個階段的生命周期做了什么

Vue 實例的生命周期可以分為創建階段、掛載階段、更新階段和銷毀階段。下面是每個階段具體干了什么的說明和對應的代碼示例&#xff1a; 創建階段 beforeCreate&#xff1a; 此階段在實例初始化之后&#xff0c;數據觀測 (data observer) 和 event/watcher 事件配置之前被調用…

Spring AOP 底層原理

Spring AOP 底層原理 aop 底層是采用動態代理機制實現的&#xff1a;接口實現類 &#xff08;1&#xff09;如果要代理的對象&#xff0c;實現了某個接口&#xff0c;那么 Spring AOP 會使用 JDK Proxy&#xff0c;去創建代理對象。 &#xff08;2&#xff09;沒有實現接口的對…

下一代ETL工具:微服務架構的全新數據集成平臺

當前對于大型企業來說數據的整合和加工變得越來越重要。隨著業務需求的不斷增長&#xff0c;企業數據量越來越大&#xff0c;數據管道越來越多&#xff0c;現有的ETL&#xff08;抽取、轉換、加載&#xff09;工具已不再滿足實時、高性能和微服務架構等現代化需求。因此&#x…

基于C#實現Prim算法

圖論在數據結構中是非常有趣而復雜的&#xff0c;作為 Web 碼農的我&#xff0c;在實際開發中一直沒有找到它的使用場景&#xff0c;不像樹那樣的頻繁使用&#xff0c;不過還是準備仔細的把圖論全部過一遍。 一、最小生成樹 圖中有一個好玩的東西叫做生成樹&#xff0c;就是用…

前端項目搭建Webpack的配置

本人這次是在搭建一個Typescript項目時候配置的Webpack。但是Typescript的項目本人看來和往常的Web(Vue)項目類似點很多的。那么我們就可以通過對該Typescript項目的略微調整即可挪到Web項目中....... 首先說明一下為什么要依賴WebPack來搭建項目&#xff1f;&#xff1f;&…

ES 萬條以外分頁檢索功能實現及注意事項

背景 以 ES 存儲日志&#xff0c;且需要對日志進行分頁檢索&#xff0c;當數據量過大時&#xff0c;就面臨 ES 萬條以外的數據檢索問題&#xff0c;如何利用滾動檢索實現這個需求呢&#xff1f;本文介紹 ES 分頁檢索萬條以外的數據實現方法及注意事項。 需求分析 用 ES 存儲數…

Redis 反序列化失敗

文章目錄 問題原序列化配置修改配置解決方法 問題 com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of org.springframework.security.core.authority.SimpleGrantedAuthority (although at least one Creator exists): cannot deser…

css圖片縮放屬性object-fit說明

object-fit 屬性可以設置以下值&#xff1a; 屬性值說明例子fill填充容器&#xff0c;可能會改變圖片的比例。object-fit: fill;contain保持圖片的原始比例&#xff0c;確保圖片完全包含在容器內。object-fit: contain;cover保持圖片的原始比例&#xff0c;確保圖片覆蓋整個容…

性能優化中使用Profiler進行頁面卡頓的排查及解決方式

文章目錄 一、前言二、頁面卡頓的排查方式1、耗時操作的監控2、頁面卡頓的監控 三、參考鏈接 一、前言 程序的優化在做過線上bug處理&#xff0c;布局層級優化&#xff0c;項目依賴庫版本更新&#xff0c;重復庫合并&#xff0c;刪除未使用的資源&#xff0c;刪除冗余的庫&…

機器學習【01】相關環境的安裝

學習實例 參考資料&#xff1a;聯邦學習實戰{楊強}https://book.douban.com/subject/35436587/ 項目地址&#xff1a;https://github.com/FederatedAI/Practicing-Federated-Learning/tree/main/chapter03_Python_image_classification 一、環境準備 GPU安裝CUDA、cuDNN pytho…

ComboGrid中快捷鍵Enter使用

為了實現當前元素&#xff0c;回車時有值跳轉到下一個元素&#xff0c;無值則查詢。 定義元素時使用快捷鍵 $.fn.combogrid.defaults.keyHandler.up.call(this);調用combogrid默認的快捷鍵 $(#cs).combogrid({width: 360,placeholder: 測試...,panelWidth: 1000,qParams: {pJ…

letcode::數組中的第k個最大元素

數組中的第k個最大元素 給定整數數組 nums 和整數 k&#xff0c;請返回數組中第 k 個最大的元素。 請注意&#xff0c;你需要找的是數組排序后的第 k 個最大的元素&#xff0c;而不是第 k 個不同的元素。 你必須設計并實現時間復雜度為 O(n) 的算法解決此問題。 示例 1: 輸入: …

PHP 語法||PHP 變量

PHP 腳本在服務器上執行&#xff0c;然后將純 HTML 結果發送回瀏覽器。 基本的 PHP 語法 PHP 腳本可以放在文檔中的任何位置。 PHP 腳本以 <?php 開始&#xff0c;以 ?> 結束&#xff1a; <?php // PHP 代碼 ?> 值得一提的是&#xff0c;通過設定php.ini的相…

nvm-切換node版本工具安裝-方便好用

去官網下載&#xff1a; https://github.com/coreybutler/nvm-windows#installation--upgrades 網站進去后點擊下載&#xff0c;點擊那個exe文件就下載本地&#xff0c;然后雙擊安裝 安裝nvm 就直接按照窗口提示的下一步就行&#xff0c;如果改了某些地方會不成功&#xf…

數字孿生技術:提升UI交互性與個性化設計

隨著數字化時代的到來&#xff0c;數字孿生技術正在逐漸改變我們的生活和工作方式。數字孿生是一種復制現實世界系統或實體的技術&#xff0c;通過創建數字模型來模擬現實世界中的各種行為和事件。這種技術不僅為人們提供了一個全新的視角來看待和解決問題&#xff0c;同時也為…

內衣專用洗衣機怎么樣?口碑最好的小型洗衣機

隨著人們的生活水平的提升&#xff0c;越來越多小伙伴來開始追求更高的生活水平&#xff0c;一些智能化的小家電就被發明出來&#xff0c;而且內衣洗衣機是其中一個。現在通過內衣褲感染到細菌真的是越來越多&#xff0c;所以我們對內衣褲的清洗頻次會高于普通衣服&#xff0c;…

Spring Boot 3.2發布:大量Java 21的支持上線,改進可觀測性

就在今天凌晨&#xff0c;Spring Boot 3.2正式發布了&#xff01;該版本是在Java 21正式發布之后的重要支持版本&#xff0c;所以在該版本中包含大量對Java 21支持的優化。 下面&#xff0c;我們分別通過Spring官方發布的博文和Josh Long長達80分鐘的介紹視頻&#xff0c;一起…