在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

數據結構與算法中什么是最小生成樹

算法與數據結構 ? 來源:bigsai ? 作者:bigsai ? 2021-10-28 17:13 ? 次閱讀

前言

在數據結構與算法圖論中,(生成)最小生成樹算法是一種常用并且和生活貼切比較近的一種算法。但是可能很多人對概念不是很清楚,什么是最小生成樹?

一個有 n 個結點的連通圖的生成樹是原圖的極小連通子圖,且包含原圖中的所有 n 個結點,并且有保持圖連通的最少的邊。最小生成樹可以用kruskal(克魯斯卡爾)算法或prim(普里姆)算法求出。

通俗易懂的講就是最小生成樹包含原圖的所有節點而只用最少的邊最小的權值距離。因為n個節點最少需要n-1個邊聯通,而距離就需要采取某種策略選擇恰當的邊。

學習最小生成樹實現算法之前我們要先高清最小生成樹的結構和意義所在。咱么首先根據一些圖更好的祝你理解。

一個故事

在城市道路規劃中,是一門很需要科學的研究(只是假設學習不必當真)。在公路時代城市聯通的主要矛盾是時間慢,而造價相比運輸時間是次要矛盾。所以在公路時代我們盡量使得城市能夠直接聯通,縮短城市聯系時間,而稍微考慮建路成本!隨著科技發展、高級鐵路、信息傳輸相比公路運輸快非常非常多,從而事件的主要矛盾從運輸時間轉變為造價成本,故有時會關注聯通所有點的路程(最短),這就用到最小生成樹算法。

城市道路鋪設可能經歷以下幾個階段。

  • 初始,各個城市沒有高速公路(鐵路)。

  • 政府打算各個城市鋪設公路(鐵路),每個城市都想成為交通樞紐,快速到達其他城市,但每個城市都有這種想法,如果實現下去造價太昂貴。并且造成巨大浪費。

  • 最終國家選擇一些主要城市進行聯通,有個別城市只能稍微繞道而行,而繞道太遠的、人流量多的國家考慮新建公路(鐵路),適當提高效率。

不過上面鐵路規劃上由于龐大的人口可能不能夠滿足與"有鐵路"這個需求,人們對速度、距離、直達等條件一直在追求中……

但是你可以想象這個場景:有些東西造假非常非常昂貴,使用效率非常高,我這里假設成黃金鑲鉆電纜鋪設,所以各個城市只要求不給自己落下,能通上就行(沒人敢跳了吧)。

要從有環圖中選取代價和最小的路線一方面代價最小(總距離最小最省黃金)另一方面聯通所有城市

然而根據上圖我們可以得到以下最小生成樹,但是最么生成這個最小生成樹,就是下面要講的了。

而類似的還有局部區域島嶼聯通修橋海底通道這些高成本的都多多少少會運用。

Kruskal算法

上面介紹了最小生成樹是什么,現在需要掌握和理解最小生成樹如何形成。給你一個圖,用一個規則生成一個最小生成樹。而在實現最小生成樹方面有prim和kruskal算法,這兩種算法的策略有所區別,但是時間復雜度一致。

Kruskal算法,和前面講到的并查集關系很大,它的主要思想為:

先構造一個只含 n 個頂點、而邊集為空的子圖,把子圖中各個頂點看成各棵樹上的根結點,之后,從網的邊集 E 中選取一條權值最小的邊,若該條邊的兩個頂點分屬不同的樹,則將其加入子圖,即把兩棵樹合成一棵樹,反之,若該條邊的兩個頂點已落在同一棵樹上,則不可取,而應該取下一條權值最小的邊再試之。依次類推,直到森林中只有一棵樹,也即子圖中含有 n-1 條邊為止。

簡而言之,Kruskal算法進行調度的單位是邊,它的信仰為:所有邊能小則小,算法的實現方面要用到并查集判斷兩點是否在同一集合。

而算法的具體步驟為:

  1. 將圖中所有邊對象(邊長、兩端點)依次加入集合(優先隊列)q1中。初始所有點相互獨立。

  2. 取出集合(優先隊列)q1最小邊,判斷邊的兩點是否聯通。

  3. 如果聯通說明兩個點已經有其它邊將兩點聯通了,跳過,如果不連通,則使用union(并查集合并)將兩個頂點合并,這條邊被使用(可以儲存或者計算數值)。

  4. 重復2,3操作直到集合(優先隊列)q1為空。此時被選擇的邊構成最小生成樹。

Prim算法

除了Kruskal算法以外,普里姆算法(Prim算法)也是常用的最小生成樹算法。雖然在效率上差不多。但是貪心的方式和Kruskal完全不同。

prim算法的核心信仰是:從已知擴散尋找最小。它的實現方式和Dijkstra算法相似但稍微有所區別,Dijkstra是求單源最短路徑,而每計算一個點需要對這個點重新更新距離,而prim不用更新距離。直接找已知點的鄰邊最小加入即可!primkruskal算法都是從邊入手處理。

對于具體算法具體步驟,大致為:

  1. 尋找圖中任意點,以它為起點,它的所有邊V加入集合(優先隊列)q1,設置一個boolean數組bool[]標記該位置(邊有兩個點,每次加入沒有被標記那個點的所有邊)。

  2. 從集合q1找到距離最小的那個邊v1判斷邊是否存在未被標記的一點`p`,如果p不存在說明已經確定過那么跳過當前邊處理,如果未被標(訪問)記那么標記該點p,并且與p相連的未知點(未被標記)構成的邊加入集合q1,邊v1(可以進行計算距離之類,該邊構成最小生成樹).

  3. 重復1,2直到q1為空,構成最小生成樹 !

大體步驟圖解為:

因為prim從開始到結束一直是一個整體在擴散,所以不需要考慮兩棵樹合并的問題,在這一點實現上稍微方便了一點。

當然,要注意的是最小生成樹并不唯一,甚至同一種算法生成的最小生成樹都可能有所不同,但是相同的是無論生成怎樣的最小生成樹:

  • 能夠保證所有節點連通(能夠滿足要求和條件)

  • 能夠保證所有路徑之和最小(結果和目的相同)

  • 最小生成樹不唯一,可能多樣的

代碼實現

上面分析了邏輯實現。下面我們用代碼簡單實現上述的算法。

prim

package圖論;

importjava.util.ArrayList;
importjava.util.Arrays;
importjava.util.Comparator;
importjava.util.List;
importjava.util.PriorityQueue;
importjava.util.Queue;

publicclassprim{

publicstaticvoidmain(String[]args){
intminlength=0;//最小生成樹的最短路徑長度
intmax=66666;
Stringcityname[]={"北京","武漢","南京","上海","杭州","廣州","深圳"};
intcity[][]={
{max,8,7,max,max,max,max},//北京和武漢南京聯通
{8,max,6,max,9,8,max},//武漢——北京、南京、杭州、廣州
{7,6,max,3,4,max,max},//南京——北京、武漢、上海、杭州
{max,max,3,max,2,max,max},//上?!暇?、杭州
{max,9,4,2,max,max,10},//杭州——武漢、南京、上海、深圳
{max,8,max,max,max,max,2},//廣州——武漢、深圳
{max,max,max,max,10,2,max}//深圳——杭州、廣州
};//地圖

booleanistrue[]=newboolean[7];
//南京
Queueq1=newPriorityQueue(newComparator(){
publicintcompare(sideo1,sideo2){
//TODOAuto-generatedmethodstub
returno1.lenth-o2.lenth;
}
});
for(inti=0;i<7;i++)
{
if(city[2][i]!=max)
{
istrue[2]=true;
q1.add(newside(city[2][i],2,i));
}
}
while(!q1.isEmpty())
{
sidenewside=q1.poll();//拋出
if(istrue[newside.point1]&&istrue[newside.point2])
{
continue;
}
else{
if(!istrue[newside.point1])
{
istrue[newside.point1]=true;
minlength+=city[newside.point1][newside.point2];
System.out.println(cityname[newside.point1]+""+cityname[newside.point2]+"聯通");
for(inti=0;i<7;i++)
{
if(!istrue[i])
{
q1.add(newside(city[newside.point1][i],newside.point1,i));
}
}
}
else{
istrue[newside.point2]=true;
minlength+=city[newside.point1][newside.point2];
System.out.println(cityname[newside.point2]+""+cityname[newside.point1]+"聯通");
for(inti=0;i<7;i++)
{
if(!istrue[i])
{
q1.add(newside(city[newside.point2][i],newside.point2,i));
}
}
}
}

}
System.out.println(minlength);
}

staticclassside//邊
{
intlenth;
intpoint1;
intpoint2;
publicside(intlenth,intp1,intp2){
this.lenth=lenth;
this.point1=p1;
this.point2=p2;
}
}

}

輸出結果:

上海 南京 聯通
杭州 上海 聯通
武漢 南京 聯通
北京 南京 聯通
廣州 武漢 聯通
深圳 廣州 聯通
28

Kruskal:
package圖論;

importjava.util.Comparator;
importjava.util.PriorityQueue;
importjava.util.Queue;

import圖論.prim.side;
/*
*作者:bigsai(公眾號)
*/
publicclasskruskal{

staticinttree[]=newint[10];//bing查集
publicstaticvoidinit(){
for(inti=0;i<10;i++)//初始
{
tree[i]=-1;
}
}
publicstaticintsearch(inta)//返回頭節點的數值
{
if(tree[a]>0)//說明是子節點
{
returntree[a]=search(tree[a]);//路徑壓縮
}
else
returna;
}
publicstaticvoidunion(inta,intb)//表示a,b所在的樹合并小樹合并大樹(不重要)
{
inta1=search(a);//a根
intb1=search(b);//b根
if(a1==b1){//System.out.println(a+"和"+b+"已經在一棵樹上");
}
else{
if(tree[a1]//這個是負數,為了簡單減少計算,不在調用value函數
{
tree[a1]+=tree[b1];//個數相加注意是負數相加
tree[b1]=a1;//b樹成為a的子樹,直接指向a;
}
else
{
tree[b1]+=tree[a1];//個數相加注意是負數相加
tree[a1]=b1;//b樹成為a的子樹,直接指向a;
}
}
}
publicstaticvoidmain(String[]args){
//TODOAuto-generatedmethodstub
init();
intminlength=0;//最小生成樹的最短路徑長度
intmax=66666;
Stringcityname[]={"北京","武漢","南京","上海","杭州","廣州","深圳"};
booleanjud[][]=newboolean[7][7];//加入邊需要防止重復比如ba和ab等價的
intcity[][]={
{max,8,7,max,max,max,max},
{8,max,6,max,9,8,max},
{7,6,max,3,4,max,max},
{max,max,3,max,2,max,max},
{max,9,4,2,max,max,10},
{max,8,max,max,max,max,2},
{max,max,max,max,10,2,max}
};//地圖
booleanistrue[]=newboolean[7];
//南京
Queueq1=newPriorityQueue(newComparator(){//優先隊列存邊+
publicintcompare(sideo1,sideo2){
//TODOAuto-generatedmethodstub
returno1.lenth-o2.lenth;
}
});
for(inti=0;i<7;i++)
{
for(intj=0;j<7;j++)
{
if(!jud[i][j]&&city[i][j]!=max)//是否加入隊列
{
jud[i][j]=true;jud[j][i]=true;
q1.add(newside(city[i][j],i,j));
}
}
}
while(!q1.isEmpty())//執行算法
{
sidenewside=q1.poll();
intp1=newside.point1;
intp2=newside.point2;
if(search(p1)!=search(p2))
{
union(p1,p2);
System.out.println(cityname[p1]+""+cityname[p2]+"聯通");
minlength+=newside.lenth;
}
}
System.out.println(minlength);


}
staticclassside//邊
{
intlenth;
intpoint1;
intpoint2;
publicside(intlenth,intp1,intp2){
this.lenth=lenth;
this.point1=p1;
this.point2=p2;
}
}
}

輸出結果

上海 杭州 聯通
廣州 深圳 聯通
南京 上海 聯通
武漢 南京 聯通
北京 南京 聯通
武漢 廣州 聯通
28

總結

最小生成樹算法理解起來也相對簡單,實現起來也不是很難。Kruskal和Prim主要是貪心算法的兩種角度。一個從整體開始找最小邊,遇到關聯不斷合并,另一個從局部開始擴散找身邊的最小不斷擴散直到生成最小生成樹。在學習最小生成樹之前最好學習一下dijkstra算法和并查集,這樣在實現起來能夠快一點,清晰一點。

力扣1584就是一個最小生成樹的入門題,不過哪個有點區別的就是默認所有點是聯通的,所以需要你剪枝優化。

責任編輯:haq
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 數據
    +關注

    關注

    8

    文章

    7247

    瀏覽量

    91309
  • 算法
    +關注

    關注

    23

    文章

    4702

    瀏覽量

    94941

原文標題:最小生成樹,秒懂!

文章出處:【微信號:TheAlgorithm,微信公眾號:算法與數據結構】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦
    熱點推薦

    程序設計與數據結構

    的地址)出發,采用推導的方式,深入淺出的分析了廣大C程序員學習和開發遇到的難點。 2. 從方法論的高度對C語言在數據結構算法方面的應用進行了深入講解和闡述。 3. 講解了絕大多數C程序員開發
    發表于 05-13 16:45

    PanDao:實際約束條件下成像系統的初始結構生成

    的是,尋找合適的初始設計方案以進行后續適配與優化,已經被證明是一項艱巨的工作。為避免這一耗時流程,本次研究的目標是從既定規格與約束條件中直接生成多種優質的初始結構。此研究將會為光學設計師帶來兩大好處:其一
    發表于 05-07 08:57

    科技在物聯網方面

    。 人工智能算法優化:宇科技不斷優化其機器人的人工智能算法,使其能夠在物聯網環境更好地進行智能決策。通過機器學習、深度學習等技術,機器人可以從大量的
    發表于 02-04 06:48

    使用TFTP加載內核設備

    在嵌入式項目開發,為了適配新外設、調整硬件資源分配或修復驅動問題,需要頻繁修改設備和內核。修改完成后,通常需要重新編譯生成鏡像,并將其燒錄到開發板上進行測試。然而,傳統的燒錄方式不僅需要連接物理接口,還可能因為鏡像體積較大而
    的頭像 發表于 01-17 15:52 ?1338次閱讀
    使用TFTP加載內核設備<b class='flag-5'>樹</b>

    嵌入式學習-飛凌嵌入式ElfBoard ELF 1板卡-初識設備之設備組成和結構

    的一項技能。設備的起源設備(Device Tree)是一種描述硬件資源的數據結構,它由uboot傳遞給Linux內核,被內核解析,內核根據設備
    發表于 01-08 08:32

    飛凌嵌入式ElfBoard ELF 1板卡-初識設備之設備組成和結構

    的一項技能。設備的起源設備(Device Tree)是一種描述硬件資源的數據結構,它由uboot傳遞給Linux內核,被內核解析,內核根據設備
    發表于 01-07 09:16

    AIGC與傳統內容生成的區別 AIGC的優勢和挑戰

    、AIGC與傳統內容生成的區別 數據類型與處理 : AIGC主要面向非結構數據生成,如自然語言文本、圖像、音頻、視頻等。這類
    的頭像 發表于 11-22 16:04 ?1320次閱讀

    DDC264配置寄存器數據寫入和320 DCLK時鐘脈沖后的回讀數據結構是什么?

    配置寄存器數據寫入和320 DCLK時鐘脈沖后的回讀數據結構是什么? 根據注和表9,16位配置寄存器數據,4位修訂ID, 300位校驗模式,怎么可能有1024 TOTAL READBACK BITS, format = 0
    發表于 11-19 07:58

    RNN在圖片描述生成的應用

    輸入圖像的內容。 RNN的基本原理 RNN是一種用于處理序列數據的神經網絡,它通過循環結構來處理序列的每個元素,并保持前一個元素的信息。RNN的主要特點是它能夠處理任意長度的序列,并且能夠捕捉序列
    的頭像 發表于 11-15 09:58 ?908次閱讀

    視覺軟件HALCON的數據結構

    在研究機器視覺算法之前,我們需要先了解機器視覺應用涉及的基本數據結構。Halcon數據結構主要有圖像參數和控制參數兩類參數。圖像參數包括:image、region、XLD,控制參數包
    的頭像 發表于 11-14 10:20 ?1170次閱讀
    視覺軟件HALCON的<b class='flag-5'>數據結構</b>

    AIGC與傳統內容生成的區別

    AIGC : 主要面向非結構數據生成,如自然語言文本、圖像、音頻、視頻等。 這類數據規模更大,內在結構更復雜,對處理技術提出了更高要求
    的頭像 發表于 10-25 15:13 ?1159次閱讀

    什么是默克爾(Merkle Tree)?如何計算默克爾根?

    01 默克爾的概念 默克爾(Merkle Tree)是一種特殊的二叉,它的每個節點都存儲了一個數據塊的哈希值。哈希值是一種可以將任意長度的數據
    的頭像 發表于 09-30 18:22 ?2119次閱讀
    什么是默克爾<b class='flag-5'>樹</b>(Merkle Tree)?如何計算默克爾根?

    嵌入式常用數據結構有哪些

    在嵌入式編程,數據結構的選擇和使用對于程序的性能、內存管理以及開發效率都具有重要影響。嵌入式系統由于資源受限(如處理器速度、內存大小等),因此對數據結構的選擇和使用尤為關鍵。以下是嵌入式編程中常用的幾種
    的頭像 發表于 09-02 15:25 ?973次閱讀

    基于神經網絡的全息圖生成算法

    與優化提供了全新的解決方案。本文將從全息圖的基本原理、神經網絡在全息圖生成的應用、具體算法實現以及未來展望等方面進行詳細闡述。
    的頭像 發表于 07-09 15:54 ?984次閱讀

    生成對抗網絡(GANs)的原理與應用案例

    相互競爭的神經網絡——生成器(Generator)和判別器(Discriminator),實現了高效、靈活的數據生成能力。本文將從GANs的原理、核心算法、以及多個應用案例入手,深入探
    的頭像 發表于 07-09 11:34 ?2216次閱讀
    主站蜘蛛池模板: 美女扒开尿口让男人30视频 | 成人精品第一区二区三区 | 高清欧美日本视频免费观看 | 欧美成人性色xxxxx视频大 | 久久亚洲国产成人影院 | 国产激情久久久久影院小草 | va在线观看| 一区二区三区视频在线 | 午夜视频吧 | 国产精品视频网站你懂得 | 又黄又粗暴的120秒免费gif视频 | 免费鲁丝片一级观看 | 亚洲午夜久久久 | 国产aaa级一级毛片 国产ar高清视频+视频 | 91大神在线视频观看 | 4438x色 | 免费又黄又爽的禁片视频 | 成人爽a毛片在线视频 | 日本xxxx色视频在线观看免费 | 免费观看黄色网 | 国模小丫大尺度啪啪人体 | 手机看片日韩高清1024 | 淫香色香| 国产va在线观看 | 欧美资源在线 | 国模张文静啪啪私拍337p | 高清国产在线观看 | 亚洲理论片在线观看 | 一区二区影院 | 欧美一级www片免费观看 | 天堂网在线.www天堂在线 | 特黄黄三级视频在线观看 | 国产午夜视频在线观看第四页 | 色成人综合网 | 日本一区免费在线观看 | 深夜释放自己vlog糖心旧版本 | 干干干日日日 | 1024手机免费看 | 干成人网 | 色人久久 | 久久免费精品高清麻豆 |