目錄
前言:現在在學這些算法的時候感覺也不是那麼難,相反感覺還有一絲容易。曾記否,大一暑假,在集訓隊學算法,被虐的那叫一個體無完膚,害,也不知道爲啥,可能吧,正是可能被虐開竅了,現在覺得這些東西挺容易的,當然我只說從理解的層面上說,真的要我自己寫可能還真的寫不出來。
現在學算法,我覺得先要知道這個算法的思想,要知道這個算法到底在幹嘛,它在怎麼做,它的過程是什麼,然後刷題,看別人的程序代碼時,把算法的思想結合進去看程序,有時候,你自己看着看着,你就知道別人下一步程序要幹什麼。當時年少無知,大一暑假的時候,頭可能比較鐵,當時學算法時,算法的思想沒怎麼理解,上來就開幹題目,一言不合就搜代碼,強行理解被人代碼的過程在幹嘛,當然過程痛苦的,唉,當初怎麼就那麼憨憨嘞,哈哈哈哈。
這篇總結一下做題時自己對這幾個算法的一些心得嗎,當然是指算法的思想。
建議瞭解思想後,找一些基礎題刷一刷
Kruskal(克魯斯卡爾)算法
最小生成樹,算法思想:首先按照邊的權值進行從小到大開始排序,每次從剩餘的邊中選擇權值較小的且邊的兩個頂點不在同一個集合內的邊,加入到生成樹,直到n-1條邊爲止。(並查集,並且在查找集合中涉及路徑壓縮)圖解如下
prime(普利姆)算法
最小生成樹
將頂點分爲兩類,樹頂點(已被選入生成樹的頂點),非樹頂點(還未被選入生成樹的頂點),首先選擇任意一個頂點加入生成樹,接下來要找出一條邊添加到生成樹,這需要枚舉每一個樹頂點到每一個非樹頂點的所有邊,然後找到最短邊加入到生成樹,照此方法,重複操作n-1次,直到將所有頂點加入到生成樹中
Floyd(弗洛伊德)算法
解決的是多源最短路徑的問題,就是任意兩點通過中轉點找到最短路徑
核心代碼:
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(e[i][j]>e[i][k]+e[k][j])
e[i][j] = e[i][k]+e[k][i];
這個還是得看過程理解,i號頂點到j號頂點只經過前k號作爲中轉點,類似於動態規劃的思想
Dijkstra(迪傑斯特拉)算法
單源最短路
思想:每次找到離源點最近的一個頂點,然後以該頂點爲中心進行擴展,最終得到源點到其餘所有點的最短距離
//點1到各個點的距離
for(i=1;i<=n;i++)
dis[i] = e[1][i];
for(i=1;i<=n-1;i++)
{
min = inf;//min設爲無限大
for(j=1;j<=n;j++)
{
if(book[j]==0&&dis[j]<min)//找到沒訪問的點,同時能夠到達的點
{
min = dis[j];//記錄最小值
u=j;//把最小的這個儲存到u中
}
}
book[u]=1;//標記u已經訪問過了
for(v = 1;v<=n;v++)
{
if(e[u][v]<inf)//找與這個點相連接的點
{
if(dis[v]>dis[u]+e[u][v])//如果經過u到達v點的距離比之前的距離要短
dis[v] = dis[u]+e[u][v];//更新dis
}
}
}