乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      C#數(shù)據(jù)結(jié)構(gòu)與算法揭秘15

       黃金屋1 2017-04-10

      這節(jié),我們主要討論,一下克魯斯卡爾算法實(shí)現(xiàn) 最小生成樹。

       克魯斯卡爾算法的基本思想是:對一個(gè)有 n個(gè)頂點(diǎn)的無向連通網(wǎng),將圖中的邊按權(quán)值大小依次選取,若選取的邊使生成樹不形成回路,則把它加入到樹中;若形成回路,則將它舍     棄。如此進(jìn)行下去,直到樹中包含有 n-1條邊為止。

      以下圖 (a)為例說明用克魯斯卡爾算法求無向連通網(wǎng)最小生成樹的過程。
      第一步:首先比較網(wǎng)中所有邊的權(quán)值,找到最小的權(quán)值的邊(D,E),加入到生成樹的邊集 TE 中,TE={(D,E)}。
      第二步:再比較圖中除邊(D,E)的邊的權(quán)值,又找到最小權(quán)值的邊(A,D)并且不會形成回路,加入到生成樹的邊集 TE 中,TE={(A,D),(D,E)}。
      第三步: 再比較圖中除 TE 以外的所有邊的權(quán)值, 找到最小的權(quán)值的邊(A,B) 并且不會形成回路,加入到生成樹的邊集 TE 中,TE={(A,D),(D,E),(A,B)}。
      第四步:再比較圖中除 TE 以外的所有邊的權(quán)值,找到最小的權(quán)值的邊(E,C) 并且不會形成回路,加入到生成樹的邊集 TE 中,TE={(A,D),(D,E),(A,B),(E,C)}。 此時(shí),邊集 TE 中已經(jīng)有 n-1條邊,如下圖(b) 所示。這個(gè)結(jié)果與用普里姆算法得到的結(jié)果相同。 

       

       

      實(shí)現(xiàn)源代碼如下:

      復(fù)制代碼
      public int[] Klausi() 
          { 
              int[] lowcost = new int[nodes.Length];   //權(quán)值數(shù)組 保存權(quán)值的數(shù)組
              int[] closevex = new int[nodes.Length];  //頂點(diǎn)數(shù)組 保存 相應(yīng)各個(gè)頂點(diǎn)的數(shù)組
              int mincost = int.MaxValue;              //最小權(quán)值 默認(rèn)是 int的最大值 表示無窮大
       
              //輔助數(shù)組初始化   對摸個(gè)  權(quán)值數(shù)組賦值   保存 最小值
              for (int i = 1; i < nodes.Length; ++i) 
              { 
                  lowcost[i] = matrix[0, i]; 
                  closevex[i] = 0; 
              } 
       
              //某個(gè)頂點(diǎn)加入集合U 
              lowcost[0] = 0; 
              closevex[0] = 0; 
             //判斷最小的權(quán)值通過的頂點(diǎn)的循環(huán)就此開始
            for(int i=0; i<nodes.Length; ++i) 
              { 
                  int k = 1; 
                  int j = 1; 
       
                  //選取權(quán)值最小的邊和相應(yīng)的頂點(diǎn) 
                  while(j < nodes.Length) 
                  { 
                      if (lowcost[j] < mincost && lowcost[j] != 0) 
                      { 
                          k = j; 
                      } 
                      ++j; 
                  } 
       
                  //新頂點(diǎn)加入集合U 
                  lowcost[k] = 0; 
       
                  //重新計(jì)算該頂點(diǎn)到其余頂點(diǎn)的邊的權(quán)值    
                  for (j = 1; j < nodes.Length; ++j) 
                  { 
                      if (matrix[k, j] < lowcost[j]) 
                      { 
                          lowcost[j] = matrix[k, j]; 
                          closevex[j] = k; 
                      } 
                  } 
              } 
       
              return closevex; 
        
      } 
      //我們明顯的看出來,由于用到了雙重循環(huán),其算法的時(shí)間的復(fù)雜度是O(n^2)
      復(fù)制代碼

        介紹了最短路徑的概念

      最短路徑問題是圖的又一個(gè)比較典型的應(yīng)用問題。例如,n個(gè)城市之間的一個(gè)公路網(wǎng),給定這些城市之間的公路的距離,能否找到城市 A 到城市 B 之間一條距離最近的通路呢?如果城市用頂點(diǎn)表示,城市間的公路用邊表示,公路的長度作為邊的權(quán)值。那么,這個(gè)問題就可歸結(jié)為在網(wǎng)中求頂點(diǎn) A 到頂點(diǎn) B 的所有路徑中邊的權(quán)值之和最小的那一條路徑, 這條路徑就是兩個(gè)頂點(diǎn)之間的最短路徑(Shortest Path),并稱路徑上的第一個(gè)頂點(diǎn)為源點(diǎn)(Source) ,最后一個(gè)頂點(diǎn)為終點(diǎn)(Destination) 。在不帶權(quán)的圖中,最短路徑是指兩個(gè)頂點(diǎn)之間經(jīng)歷的邊數(shù)最少的路徑。 最短路徑可以是求某個(gè)源點(diǎn)出發(fā)到其它頂點(diǎn)的最短路徑, 也可以是求網(wǎng)中任意兩個(gè)頂點(diǎn)之間的最短路徑。這里只討論單源點(diǎn)的最短路徑問題,感興趣的讀者可參考有關(guān)文獻(xiàn),了解每一對頂點(diǎn)之間的最短路徑。 網(wǎng)分為無向網(wǎng)和有向網(wǎng),當(dāng)把無向網(wǎng)中的每一條邊(vi,vj)都定義為弧<vi,vj>和弧<vj,vi>,則有向網(wǎng)就變成了無向網(wǎng)。因此,不失一般性,我們這里只討論有向網(wǎng)上的最短路徑問題。 下圖是一個(gè)有向網(wǎng)及其鄰接矩陣。該網(wǎng)從頂點(diǎn) A 到頂點(diǎn) D 有 4條路徑,分別是:路徑(A,D) ,其帶權(quán)路徑長度為 30;路徑(A,C,F,D) ,其帶權(quán)路徑長度為 22;路徑(A,C,B,E,D) ,其帶權(quán)路徑長度為 32;路徑(A,C,F,E,D) ,其帶權(quán)路徑長度為 34。路徑(A,C,F,D)稱為最短路徑,其帶權(quán)路徑長度 22稱為最短距離。 

      他用的是狄克斯特拉(Dikastra)算法

      對于求單源點(diǎn)的最短路徑問題,狄克斯特拉(Dikastra)提出了一個(gè)按路徑長度遞增的順序逐步產(chǎn)生最短路徑的構(gòu)造算法。狄克斯特拉的算法思想是:設(shè)置兩個(gè)頂點(diǎn)的集合 S 和T, 集合 S 中存放已找到最短路徑的頂點(diǎn), 集合 T 中存放當(dāng)前還未找到最短路徑的頂點(diǎn)。初始狀態(tài)時(shí),集合 S 中只包含源點(diǎn),設(shè)為 v0,然后從集合 T 中選擇到源點(diǎn) v0路徑長度最短的頂點(diǎn) u加入到集合 S 中,集合 S 中每加入一個(gè)新的頂點(diǎn) u都要修改源點(diǎn) v0到集合 T 中剩余頂點(diǎn)的當(dāng)前最短路徑長度值,集合 T 中各頂點(diǎn)的新的最短路徑長度值為原來的當(dāng)前最短路徑長度值與從源點(diǎn)過頂點(diǎn) u到達(dá)該頂點(diǎn)的新的最短路徑長度中的較小者。此過程不斷重復(fù),直到集合 T 中的頂點(diǎn)全部加到集合 S 中為止。

      以下圖為例說明用狄克斯特拉算法求有向網(wǎng)的從某個(gè)頂點(diǎn)到其余頂點(diǎn)最短路徑的過程。

      第一步:列出頂點(diǎn) A 到其余各頂點(diǎn)的路徑長度,它們分別為 0、∞、5、30、∞、∞。從中選取路徑長度最小的頂點(diǎn) C(從源點(diǎn)到頂點(diǎn) C 的最短路徑為 5) 。
      第二步:找到頂點(diǎn) C 后,再觀察從源點(diǎn)經(jīng)頂點(diǎn) C 到各個(gè)頂點(diǎn)的路徑是否比第一步所找到的路徑要?。ㄒ堰x取的頂點(diǎn)則不必考慮) ,可發(fā)現(xiàn),源點(diǎn)到頂點(diǎn) B的路徑長度更新為 20(A,C,B) ,源點(diǎn)到頂點(diǎn) F 的路徑長度更新為 12(A,C,F(xiàn)) , 其余的路徑則不變。 然后, 從已更新的路徑中找出路徑長度最小的頂點(diǎn) F (從源點(diǎn)到頂點(diǎn) F 的最短路徑為 12) 。
      第三步:找到頂點(diǎn) C、F 以后,再觀察從源點(diǎn)經(jīng)頂點(diǎn) C、F 到各頂點(diǎn)的路徑是否比第二步所找到的路徑要小(已被選取的頂點(diǎn)不必考慮) ,可發(fā)現(xiàn),源點(diǎn)到頂點(diǎn) D 的路徑長度更新為 22(A,C,F(xiàn),D) ,源點(diǎn)到頂點(diǎn) E 的路徑長度更新為30(A,C,F(xiàn),E) ,其余的路徑不變。然后,從已更新的路徑中找出路徑長短最小的頂點(diǎn) D(從源點(diǎn)到頂點(diǎn) D 的最短路徑為 22) 。
      第四步:找到頂點(diǎn) C、F、D 后,現(xiàn)在只剩下最后一個(gè)頂點(diǎn) E 沒有找到最短路徑了,再觀察從源點(diǎn)經(jīng)頂點(diǎn) C、F、D 到頂點(diǎn) E 的路徑是否比第三步所找到的路徑要?。ㄒ堰x取的頂點(diǎn)則不必考慮) ,可以發(fā)現(xiàn),源點(diǎn)到頂點(diǎn) E 的路徑長度更新為 28(A,B,E) ,其余的路徑則不變。然后,從已更新的路徑中找出路徑長度最小的頂點(diǎn) E(從源點(diǎn)到頂點(diǎn) E 的最短路徑為 28)。

      、有向網(wǎng)的鄰接矩陣類的實(shí)現(xiàn)
      本書以有向網(wǎng)的鄰接矩陣類 DirecNetAdjMatrix<T>來實(shí)現(xiàn)狄克斯特拉算法。DirecNetAdjMatrix<T>有三個(gè)成員字段, 一個(gè)是 Node<T>類型的一維數(shù)組 nodes,存放有向網(wǎng)中的頂點(diǎn)信息,一個(gè)是整型的二維數(shù)組 matirx,表示有向網(wǎng)的鄰接矩陣,存放弧的信息,一個(gè)是整數(shù) numArcs,表示有向網(wǎng)中弧的數(shù)目,有向網(wǎng)的鄰接矩陣類 DirecNetAdjMatrix<T>源代碼的實(shí)現(xiàn)如下所示。

      復(fù)制代碼
      public class DirecNetAdjMatrix<T> : IGraph<T>//繼承圖形的接口
      {  
       private Node<T>[] nodes;      //頂點(diǎn)數(shù)組     存取相應(yīng)的結(jié)點(diǎn)的 泛型數(shù)組
              private int numEdges;         //邊的數(shù)目     上圖邊數(shù)字是6
              private int[,] matrix;       //鄰接矩陣數(shù)組      存取相應(yīng)的互相的權(quán)值
       
              //構(gòu)造器  進(jìn)行數(shù)據(jù)的初始化  邊的數(shù)目是0
              public NetAdjMatrix (int n) 
              { 
                  nodes = new Node<T>[n]; 
                  matrix = new int[n,n]; 
                  numEdges = 0; 
              } 
       
              //獲取索引為index的頂點(diǎn)的信息    算法的時(shí)間復(fù)雜度是O(1)
              public Node<T> GetNode(int index) 
              { 
                  return nodes[index]; 
              } 
       
              //設(shè)置索引為index的頂點(diǎn)的信息  算法的時(shí)間復(fù)雜度是O(1)
              public void SetNode(int index, Node<T> v)
             { 
               nodes[index] = v; 
             }
              //邊的數(shù)目屬性 可讀可寫的屬性 
               public int NumEdges 
               {
      get 
                { 
                 return numEdges; 
                } 
                set 
                {
                 numEdges = value; 
                } 
               }
               //獲取matrix[index1, index2]的值 算法的時(shí)間復(fù)雜度是O(1)
               public int GetMatrix(int index1, int index2)
               {
                return matrix[index1, index2];
               }
               //設(shè)置matrix[index1, index2]的值 算法的復(fù)雜度是O(1) 
               public void SetMatrix(int index1, int index2, int v) 
               { 
                 matrix[index1, index2] = v; 
               } 
                //獲取頂點(diǎn)的數(shù)目 算法的時(shí)間的復(fù)雜度是O(1)
                 public int GetNumOfVertex() 
                { 
                 return nodes.Length; 
                } 
                //獲取邊的數(shù)目 算法的時(shí)間的復(fù)雜度是O(1) 
              public int GetNumOfEdge() 
              {
                  return numEdges;
               }
               //v是否是無向網(wǎng)的頂點(diǎn) 
               //如果包含這個(gè)頂點(diǎn)  返回為真,否則返回為假。
               //由于這是一層循環(huán),算法的復(fù)雜度是O(n)
              public bool IsNode(Node<T> v) 
              { 
                  //遍歷頂點(diǎn)數(shù)組 
                  foreach (Node<T> nd in nodes) 
                  { 
                      //如果頂點(diǎn)nd與v相等,則v是圖的頂點(diǎn),返回true 
                      if (v.Equals(nd)) 
                      { 
                          return true; 
                      } 
                  } 
       
                  return false; 
              } 
       
              //獲得頂點(diǎn)v在頂點(diǎn)數(shù)組中的索引 
              //  如果相等,返回相應(yīng)的索引。
              //由于是一層循環(huán),時(shí)間的復(fù)雜度是O(n)
      
              public int GetIndex(Node<T> v) 
              { 
                  int i = -1; 
       
                  //遍歷頂點(diǎn)數(shù)組 
                  for (i = 0; i < nodes.Length; ++i) 
                  { 
                      //如果頂點(diǎn)nd與v相等,則v是圖的頂點(diǎn),返回索引值 
                      if (nodes[i].Equals(v)) 
                      { 
                          return i; 
                      } 
        } 
                  return i; 
              } 
       
              //在頂點(diǎn)v1、v2之間添加權(quán)值為v的邊 
              //添加相應(yīng)的權(quán)值的v的邊,  這是一個(gè)對稱矩陣。
      
              public void SetEdge(Node<T> v1, Node<T> v2, int v) 
              { 
                  //v1或v2不是無向網(wǎng)的頂點(diǎn) 
                  if (!IsNode(v1) || !IsNode(v2)) 
                  { 
                      Console.WriteLine("Node is not belong to Graph!"); 
                      return; 
                  } 
       
                  //矩陣是對稱矩陣 
                  matrix[GetIndex(v1), GetIndex(v2)] = v; 
                  matrix[GetIndex(v2), GetIndex(v1)] = v; 
                  ++numEdges; 
              } 
       
              //刪除v1和v2之間的邊 
             // 刪除對稱矩陣。
      
              public void DelEdge(Node<T> v1, Node<T> v2) 
              { 
                  //v1或v2不是無向網(wǎng)的頂點(diǎn) 
                  if (!IsNode(v1) || !IsNode(v2)) 
                  { 
                      Console.WriteLine("Node is not belong to Graph!"); 
                      return; 
                  } 
       
                  //v1和v2之間存在邊 
                  if (matrix[GetIndex(v1), GetIndex(v2)] != int.MaxValue) 
                  { 
                      //矩陣是對稱矩陣 
                      matrix[GetIndex(v1), GetIndex(v2)] = int.MaxValue; 
                      matrix[GetIndex(v2), GetIndex(v1)] = int.MaxValue; 
                      --numEdges; 
                  } 
              } 
       
              //判斷v1和v2之間是否存在邊 
              //判斷相應(yīng)  不是 最大值  返回為真 否則 為假 算法的時(shí)間復(fù)雜度O(1)
              public bool IsEdge(Node<T> v1, Node<T> v2) 
              { 
                  //v1或v2不是無向網(wǎng)的頂點(diǎn) 
                  if (!IsNode(v1) || !IsNode(v2)) 
                  { 
                      Console.WriteLine("Node is not belong to Graph!"); 
                      return false; 
                  } 
       
                  //v1和v2之間存在邊 
                  if (matrix[GetIndex(v1), GetIndex(v2)] != int.MaxValue) 
                  { 
                      return true; 
                  } 
                  Else  //v1和v2之間不存在邊 
                  { 
                      return false; 
                  } 
              } 
      } 
      復(fù)制代碼

      為實(shí)現(xiàn)狄克斯特拉算法,引入兩個(gè)數(shù)組,一個(gè)一維數(shù)組 ShortPathArr,用來保存從源點(diǎn)到各個(gè)頂點(diǎn)的最短路徑的長度,一個(gè)二維數(shù)組 PathMatrixArr,用來保存從源點(diǎn)到某個(gè)頂點(diǎn)的最短路徑上的頂點(diǎn),如 PathMatrix[v][w]為 true,則 w從源點(diǎn)到頂點(diǎn) v 的最短路徑上的頂點(diǎn)。為了該算法的結(jié)果被其他算法使用,把這兩個(gè)數(shù)組作為算法的參數(shù)使用。另外,為了表示某頂點(diǎn)的最短路徑是否已經(jīng)找到,在算法中設(shè)了一個(gè)一維數(shù)組 final,如果 final[i]為 true,則表示已經(jīng)找到第 i 個(gè)頂點(diǎn)的最短路徑。i 是該頂點(diǎn)在鄰接矩陣中的序號。同樣,把該算法作為類DirecNetAdjMatrix<T>的成員方法來實(shí)現(xiàn)。

      復(fù)制代碼
      //pathMatricArr用來保存從源點(diǎn)到某個(gè)頂點(diǎn)的最短路徑上的頂點(diǎn)
      //ShortPathArr用來保存從源點(diǎn)到各個(gè)頂點(diǎn)的最短路徑的長度
      //n 結(jié)點(diǎn)的泛型數(shù)組
      1
      public void Dijkstra(ref bool[,] pathMatricArr, 2 ref int[] shortPathArr, Node<T> n) 3 { 4 int k = 0;
      //結(jié)點(diǎn)是否訪問 5 bool[] final = new bool[nodes.Length]; 6 7 //初始化 8 for (int i = 0; i < nodes.Length; ++i) 9 { 10 final[i] = false; 11 shortPathArr[i] = matrix[GetIndex(n),i]; 12 13 for (int j = 0; j < nodes.Length; ++j) 14 { 15 pathMatricArr[i,j] = false; 16 } 17 if (shortPathArr[i] != 0 && shortPathArr[i] < int.MaxValue) 18 { 19 pathMatricArr[i,GetIndex(n)] = true; 20 pathMatricArr[i,i] = true; 21 } 22 } 23 24 // n為源點(diǎn) 25 shortPathArr[GetIndex(n)] = 0; 26 final[GetIndex(n)] = true; 27 28 //處理從源點(diǎn)到其余頂點(diǎn)的最短路徑 29 for (int i = 0; i < nodes.Length; ++i) 30 { 31 int min = int.MaxValue; 32 33 //比較從源點(diǎn)到其余頂點(diǎn)的路徑長度 34 for (int j = 0; j < nodes.Length; ++j) 35 { 36 //從源點(diǎn)到j(luò)頂點(diǎn)的最短路徑還沒有找到 37 if (!final[j]) 38 { 39 /從源點(diǎn)到j(luò)頂點(diǎn)的路徑長度最小 40 if (shortPathArr[j] < min) 41 { 42 k = j; 43 min = shortPathArr[j]; 44 } 45 } 46 } 47 48 //源點(diǎn)到頂點(diǎn)k的路徑長度最小 49 final[k] = true; 50 51 //更新當(dāng)前最短路徑及距離 52 for (int j = 0; j < nodes.Length; ++j) 53 { 54 if (!final[j] && (min + matrix[k,j] < shortPathArr[j])) 55 { 56 shortPathArr[j] = min + matrix[k,j]; 57 for (int w = 0; w < nodes.Length; ++w) 58 { 59 pathMatricArr[j,w] = pathMatricArr[k,w]; 60 } 61 pathMatricArr[j,j] = true; 62 } 63 } 64 } 65 }
      //由于是,雙層循環(huán) 時(shí)間復(fù)雜度是O(n2)
      復(fù)制代碼

      如圖所示:

       當(dāng)然,圖的應(yīng)用還有很多了,點(diǎn)到為止。

      至于圖的總結(jié)是:

       

       

      所謂的圖是圖狀結(jié)構(gòu)簡稱圖,是另一種非線性結(jié)構(gòu),它比樹形結(jié)構(gòu)更復(fù)雜。樹形結(jié)構(gòu)中的結(jié)點(diǎn)是一對多的關(guān)系,結(jié)點(diǎn)間具有明顯的層次和分支關(guān)系。每一層的結(jié)點(diǎn)可以和下一層的多個(gè)結(jié)點(diǎn)相關(guān),但只能和上一層的一個(gè)結(jié)點(diǎn)相關(guān)。而圖中的頂點(diǎn)(把圖中的數(shù)據(jù)元素稱為頂點(diǎn))是多對多的關(guān)系,即頂點(diǎn)間的關(guān)系是任意的,圖中任意兩個(gè)頂點(diǎn)之間都可能相關(guān)。也就是說,圖的頂點(diǎn)之間無明顯的層次關(guān)系,這種關(guān)系在現(xiàn)實(shí)世界中大量存在。因此,圖的應(yīng)用相當(dāng)廣泛,在自然科學(xué)、社會科學(xué)和人文科學(xué)等許多領(lǐng)域都有著非常廣泛的應(yīng)用。例如搜索引擎,地圖等等。

        本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多