以邻接表为存储结构的---图的算法实现

来源:互联网 发布:minecraft mac forge 编辑:程序博客网 时间:2024/06/04 17:55
  1.  using System;
  2. using System.Collections.Generic;
  3. using System.Collections.Specialized;
  4. namespace HBDiscover
  5. {
  6.     public class AdjacencyList<T>
  7.     {
  8.         List<Vertex<T>> items; //图的顶点集合
  9.         public bool IsCycle; //是否是环
  10.         public AdjacencyList() : this(10) { } //构造方法
  11.         public AdjacencyList(int capacity) //指定容量的构造方法
  12.         {
  13.             items = new List<Vertex<T>>(capacity);
  14.         }
  15.         public void AddVertex(T item) //添加一个顶点
  16.         {   //不允许插入重复值
  17.             if (Contains(item))
  18.             {
  19.                 throw new ArgumentException("插入了重复顶点!");
  20.             }
  21.             items.Add(new Vertex<T>(item));
  22.         }
  23.         public void AddVertex(params T[] vexs) //添加一个顶点
  24.         {
  25.             foreach (T temp in vexs)
  26.             {
  27.                 AddVertex(temp);
  28.             }
  29.         }
  30.         public void AddEdge(T from, T to, int weight) //添加无向边
  31.         {
  32.             Vertex<T> fromVer = Find(from); //找到起始顶点
  33.             if (fromVer == null)
  34.             {
  35.                 throw new ArgumentException("头顶点并不存在!");
  36.             }
  37.             Vertex<T> toVer = Find(to); //找到结束顶点
  38.             if (toVer == null)
  39.             {
  40.                 throw new ArgumentException("尾顶点并不存在!");
  41.             }
  42.             //无向边的两个顶点都需记录边信息
  43.             AddDirectedEdge(fromVer, toVer, weight);
  44.             AddDirectedEdge(toVer, fromVer, weight);
  45.         }
  46.         public void AddEdge(T from, T to) //添加无向边
  47.         {
  48.             AddEdge(from, to, 0);
  49.         }
  50.         public void AddDirectedEdge(T from, T to, int weight) //添加无向边
  51.         {
  52.             Vertex<T> fromVer = Find(from); //找到起始顶点
  53.             if (fromVer == null)
  54.             {
  55.                 throw new ArgumentException("头顶点并不存在!");
  56.             }
  57.             Vertex<T> toVer = Find(to); //找到结束顶点
  58.             if (toVer == null)
  59.             {
  60.                 throw new ArgumentException("尾顶点并不存在!");
  61.             }
  62.             AddDirectedEdge(fromVer, toVer, weight);
  63.         }
  64.         public void AddDirectedEdge(T from, T to)
  65.         {
  66.             AddDirectedEdge(from, to, 0);
  67.         }
  68.         public bool Contains(T item) //查找图中是否包含某项
  69.         {
  70.             return Find(item) != null;
  71.         }
  72.         private Vertex<T> Find(T item) //查找指定项并返回
  73.         {
  74.             foreach (Vertex<T> v in items)
  75.             {
  76.                 if (v.data.Equals(item))
  77.                 {
  78.                     return v;
  79.                 }
  80.             }
  81.             return null;
  82.         }
  83.         //添加有向边
  84.         private void AddDirectedEdge(Vertex<T> fromVer, Vertex<T> toVer,int weight)
  85.         {
  86.             if (fromVer.firstEdge == null//无邻接点时
  87.             {
  88.                 fromVer.firstEdge = new Edge(fromVer,toVer, weight);
  89.             }
  90.             else
  91.             {
  92.                 Edge edge = fromVer.firstEdge;
  93.                 while(edge.next!=null)
  94.                 {   
  95.                     //检查是否添加了重复边
  96.                     if (edge.adjvex.data.Equals(toVer.data))
  97.                     {
  98.                         throw new ArgumentException("添加了重复的边!");
  99.                     }
  100.                     edge = edge.next;
  101.                 }
  102.                 edge.next = new Edge(fromVer, toVer, weight); //添加到链表未尾
  103.                 //Edge toVerEdge = toVer.firstEdge;
  104.                 //while (toVerEdge!= null)
  105.                 //{
  106.                 //    //检查是否添加了重复边
  107.                 //    if (toVerEdge.adjvex.data.Equals(fromVer.data))
  108.                 //    {
  109.                 //        //是一个环
  110.                 //        IsCycle = true;
  111.                 //    }
  112.                 //    toVerEdge = toVerEdge.next;
  113.                 //}
  114.             }
  115.             fromVer.OutDegree += 1;
  116.             toVer.InDegree += 1;
  117.         }
  118.         //添加有向边
  119.         private void AddDirectedEdge(Vertex<T> fromVer, Vertex<T> toVer)
  120.         {
  121.             AddDirectedEdge(fromVer, toVer,0);
  122.         }
  123.         public override string ToString() //仅用于测试
  124.         {   //打印每个节点和它的邻接点
  125.             string s = string.Empty;
  126.             foreach (Vertex<T> v in items)
  127.             {
  128.                 s += v.data.ToString() + ":";
  129.                 if (v.firstEdge != null)
  130.                 {
  131.                     Edge tmp = v.firstEdge;
  132.                     while (tmp != null)
  133.                     {
  134.                         s += tmp.adjvex.data.ToString();
  135.                         tmp = tmp.next;
  136.                     }
  137.                 }
  138.                 s += "/r/n";
  139.             }
  140.             return s;
  141.         }
  142.         //嵌套类,表示链表中的边表结点
  143.         [Serializable()]
  144.         public class Edge : IComparable<Edge>
  145.         {
  146.             public Vertex<T> adjvex; //边的一个邻接点域
  147.             public Vertex<T> parentVex; //边的一个邻接点域
  148.             public Edge next; //下一个边
  149.             public int Wegit;
  150.             public Edge(Vertex<T> value)
  151.             {
  152.                 adjvex = value;
  153.             }
  154.             public Edge(Vertex<T> _parentVex, Vertex<T> _adjvex, int weight)
  155.             {
  156.                 Wegit = weight;
  157.                 adjvex = _adjvex;
  158.                 parentVex = _parentVex;
  159.             }
  160.             public int CompareTo(Edge other)
  161.             {
  162.                 return Wegit.CompareTo(other.Wegit);
  163.             }
  164.         }
  165.         //嵌套类,表示存放于数组中的表头(顶点)结点
  166.         [Serializable()]
  167.         public class Vertex<TValue>
  168.         {
  169.             public TValue data; //数据
  170.             public Edge firstEdge; //邻接点链表头指针
  171.             public Boolean visited; //访问标志,遍历时使用
  172.             public int InDegree;//入度
  173.             public int OutDegree;//出度
  174.             public Vertex(TValue value) //构造方法
  175.             {
  176.                 data = value;
  177.             }
  178.             //清除顶点的所有边
  179.             public void ClearEdges()
  180.             {
  181.                 Edge edge = this.firstEdge;
  182.                 while (edge != null)
  183.                 {
  184.                     edge.adjvex.InDegree -= 1;
  185.                     edge=edge.next;
  186.                 }
  187.                 this.firstEdge = null;
  188.             }
  189.         }
  190.         ///////////////////////////////// 图的遍历 /////////////////////////////////////////////////
  191.         /// <summary>
  192.         /// 深度优先遍历图
  193.         /// </summary>
  194.         /// <param name="vex"></param>
  195.         /// <param name="strBuilder"></param>
  196.         /// <returns></returns>
  197.         private void DepthSearch(Vertex<T> vex,System.Text.StringBuilder strBuilder)
  198.         {
  199.             strBuilder.Append(Convert.ToString(vex.data));
  200.             vex.visited = true;
  201.             Edge edge = vex.firstEdge;
  202.             while (edge!=null)
  203.             {
  204.                 if(!edge.adjvex.visited)
  205.                     DepthSearch(edge.adjvex, strBuilder);
  206.                 edge = edge.next;
  207.             }
  208.         }
  209.         public string DepthSearch()
  210.         {
  211.             return DepthSearch(this.items[0]);
  212.         }
  213.         public string DepthSearch(Vertex<T> vex)
  214.         {
  215.             System.Text.StringBuilder strBuilder = new System.Text.StringBuilder();
  216.             DepthSearch(vex, strBuilder);
  217.             return strBuilder.ToString();
  218.         }
  219.         /// <summary>
  220.         /// 广度优先遍历图
  221.         /// </summary>
  222.         /// <param name="vex"></param>
  223.         /// <param name="strBuilder"></param>
  224.         /// <returns></returns>
  225.         private void BreadthSearch(Vertex<T> vex, System.Text.StringBuilder strBuilder)
  226.         {
  227.             Queue<Vertex<T>> queue = new Queue<Vertex<T>>();
  228.             queue.Enqueue(vex);
  229.             vex.visited = true;
  230.             strBuilder.Append(vex.data.ToString());
  231.             while (queue.Count > 0)
  232.             {
  233.                 Edge edge = queue.Dequeue().firstEdge;
  234.                 while(edge != null)
  235.                 {
  236.                     Vertex<T> tempVex = edge.adjvex;
  237.                     if (!tempVex.visited)
  238.                     {
  239.                         queue.Enqueue(tempVex);
  240.                         tempVex.visited = true;
  241.                         strBuilder.Append(tempVex.data.ToString());
  242.                     }
  243.                     edge = edge.next;
  244.                 }
  245.             }
  246.         }
  247.         public string BreadthSearch(Vertex<T> vex)
  248.         {
  249.             System.Text.StringBuilder strBuilder = new System.Text.StringBuilder();
  250.             BreadthSearch(vex, strBuilder);
  251.             return strBuilder.ToString();
  252.         }
  253.         public string BreadthSearch()
  254.         {
  255.             return BreadthSearch(this.items[0]);
  256.         }
  257.         public void ResetVisitedStatus()
  258.         {
  259.             foreach (Vertex<T> vex in this.items)
  260.             {
  261.                 vex.visited = false;
  262.             }
  263.         }
  264.         ////////////////////////////////// 最小生成树部份(Minimal Spanning Trees) /////////////////////
  265.         public string GetMstByKruskal()
  266.         {
  267.             string strValue = string.Empty;
  268.             List<Edge> list = new List<Edge>();
  269.             foreach (Vertex<T> vex in this.items)
  270.             {
  271.                 Edge edge = vex.firstEdge;
  272.                 vex.visited = true;
  273.                 while (edge != null)
  274.                 {
  275.                     if(edge.adjvex!=null && !edge.adjvex.visited)
  276.                         list.Add(edge);
  277.                     edge = edge.next;
  278.                 }
  279.             }
  280.             list.Sort();
  281.             ResetVisitedStatus();
  282.             int i, k;
  283.             for (i=0,k=0;i<list.Count && k<this.items.Count-1;i++)
  284.             {
  285.                 Edge edge = list[i];
  286.                 if (edge.adjvex.visited)
  287.                     continue;
  288.                 strValue += edge.parentVex.data.ToString() + ":" + edge.adjvex.data.ToString()+"|";
  289.                 k++;
  290.             }
  291.             return strValue;
  292.         }
  293.         public string GetMstByPrim()
  294.         {
  295.             List<Vertex<T>> vexList = new List<Vertex<T>>();
  296.             //最小边的父顶点
  297.             Vertex<T> minEdgeParentVex = this.items[0];
  298.             List<Edge> edgeList = new List<Edge>();
  299.             string strValue = string.Empty;
  300.             vexList.Add(this.items[0]);
  301.             while (vexList.Count < this.items.Count)
  302.             {
  303.                 Edge minEdge = null;  
  304.                 //找到的最小边和它的父顶点
  305.                 foreach (Vertex<T> vex in vexList)
  306.                 {
  307.                     Edge edge = vex.firstEdge;
  308.                     while (edge != null)
  309.                     {
  310.                         if (!edge.adjvex.visited)
  311.                         {
  312.                             if (minEdge == null)
  313.                             {
  314.                                 minEdge = edge;
  315.                                 minEdgeParentVex = vex;
  316.                             }
  317.                             else
  318.                             {
  319.                                 if (edge.Wegit < minEdge.Wegit)
  320.                                 {
  321.                                     minEdge = edge;
  322.                                     minEdgeParentVex = vex;
  323.                                 }
  324.                             }
  325.                         }
  326.                         edge = edge.next;
  327.                     }
  328.                 }
  329.                 minEdgeParentVex.visited = true;
  330.                 minEdge.adjvex.visited = true;
  331.                 edgeList.Add(minEdge);
  332.                 vexList.Add(minEdge.adjvex);
  333.                 strValue += minEdge.parentVex.data + ":" + minEdge.adjvex.data.ToString() + "|";
  334.             }
  335.             return strValue;
  336.         }  
  337.         ///////////////////////////////// 最短路径 ///////////////////////////////////////////
  338.         private class PassedPathInfo
  339.         {
  340.             public int Weight;
  341.             public List<T> PassedVertexs;
  342.             public PassedPathInfo(int _Weight,T firstPath)
  343.             {
  344.                 Weight = _Weight;
  345.                 PassedVertexs = new List<T>();
  346.                 PassedVertexs.Add(firstPath);
  347.             }
  348.             public PassedPathInfo(int _Weight,List<T> list)
  349.             {
  350.                 Weight = _Weight;
  351.                 PassedVertexs = list;
  352.             }
  353.             public void ClearPath()
  354.             {
  355.                 PassedVertexs.Clear();
  356.             }
  357.             public void AddWeight(int _Weight)
  358.             {
  359.                 Weight += _Weight;
  360.             }
  361.             public void AddPath(T path)
  362.             {
  363.                 PassedVertexs.Add(path);
  364.             }
  365.         }
  366.         /// <summary>
  367.         /// dijkstra 算法
  368.         /// </summary>
  369.         /// <param name="originVertex"></param>
  370.         /// <param name="destVertex"></param>
  371.         /// <returns></returns>
  372.         public string GetMinPath(T originVertex,T destVertex)
  373.         {
  374.             if(originVertex.Equals(destVertex))
  375.                 throw new Exception("起始顶点不能是目标定顶");
  376.             Vertex<T> originVex = this.Find(originVertex);
  377.             Vertex<T> destVex = this.Find(destVertex);
  378.             if (originVex == null || destVex == null)
  379.             {
  380.                 throw new Exception("起始顶点或目标定顶未找到");
  381.             }
  382.             Dictionary<T, PassedPathInfo> vexPssedPaths = new Dictionary<T, PassedPathInfo>();
  383.             RecursiveFindMinPath(vexPssedPaths, originVex);
  384.             if (!vexPssedPaths.ContainsKey(destVertex))
  385.                 throw new Exception("起始顶点不能到达目标顶点");
  386.             //return vexPssedPaths[destVertex].Weight.ToString();
  387.             string strValue = string.Empty;
  388.             Dictionary<T, PassedPathInfo>.Enumerator e = vexPssedPaths.GetEnumerator();
  389.             while (e.MoveNext())
  390.             {
  391.                 strValue += e.Current.Key + ":"+e.Current.Value.Weight.ToString()+"|";
  392.                 if (e.Current.Value.PassedVertexs != null)
  393.                 {
  394.                     foreach (T vexStr in e.Current.Value.PassedVertexs)
  395.                     {
  396.                         strValue += "-->";
  397.                         strValue += vexStr;
  398.                     }
  399.                 }
  400.                 else
  401.                 {
  402.                     strValue += "无路径";
  403.                 }
  404.                 strValue += "/r/n";
  405.             }
  406.             return strValue;
  407.         }
  408.       
  409.         private void RecursiveFindMinPath(Dictionary<T, PassedPathInfo> vexPssedPaths, Vertex<T> originVex)
  410.         {
  411.             Edge edge = originVex.firstEdge;
  412.             while (edge != null)
  413.             {
  414.                 if (edge.adjvex.visited)
  415.                 {
  416.                     edge = edge.next;
  417.                     continue;
  418.                 }
  419.                 //当前边的父顶点是否已经完成访问,在路径集合体内就表示已经访问过了
  420.                 bool bParentVexVisited = vexPssedPaths.ContainsKey(edge.parentVex.data);
  421.                 //当前边的子顶点是否已经完成访问,在路径集合体内就表示已经访问过了
  422.                 bool bChildVexVisited = vexPssedPaths.ContainsKey(edge.adjvex.data);
  423.                 //当前边的子顶点的路径信息对象
  424.                 PassedPathInfo childPassedPath = bChildVexVisited ? vexPssedPaths[edge.adjvex.data] : null;
  425.                 //当前边的父顶点的路径信息对象
  426.                 PassedPathInfo parentPassedPath = bParentVexVisited ? vexPssedPaths[edge.parentVex.data] : null;
  427.                 //如果当前边的父顶点的路径信息对象不为空则copy一分副本
  428.                 List<T> parentPathListCopy = bParentVexVisited ? new List<T>(parentPassedPath.PassedVertexs) ?? null:null;
  429.                 
  430.                 //如果下一个顶点没有路径信息的话
  431.                 if (!bChildVexVisited)
  432.                 {           
  433.                     //父顶点和子顶点都没有访问(父顶点是源点)
  434.                     if (!bParentVexVisited)
  435.                     {
  436.                         List<T> list = new List<T>() { edge.parentVex.data, edge.adjvex.data };
  437.                         vexPssedPaths.Add(edge.adjvex.data, new PassedPathInfo(edge.Wegit, list));
  438.                     }
  439.                     else
  440.                     {
  441.                         //父顶点与当前路径的权值与路径相加赋给子顶点对象
  442.                         parentPathListCopy.Add(edge.adjvex.data);
  443.                         vexPssedPaths.Add(edge.adjvex.data, new PassedPathInfo(parentPassedPath.Weight + edge.Wegit,parentPathListCopy));
  444.                     }
  445.                 }
  446.                 else //子顶点已经有路径时
  447.                 {
  448.                     if (!bParentVexVisited)
  449.                     {
  450.                         if (edge.Wegit < childPassedPath.Weight)
  451.                         {
  452.                             parentPathListCopy.Add(edge.adjvex.data);
  453.                             childPassedPath.Weight = parentPassedPath.Weight + edge.Wegit;
  454.                             childPassedPath.PassedVertexs = parentPathListCopy;
  455.                         }
  456.                     }
  457.                     else
  458.                     {
  459.                         int temp = parentPassedPath.Weight + edge.Wegit;
  460.                         if (temp < childPassedPath.Weight)
  461.                         {
  462.                             parentPathListCopy.Add(edge.adjvex.data);
  463.                             childPassedPath.Weight = temp;
  464.                             childPassedPath.PassedVertexs = parentPathListCopy;
  465.                         }
  466.                     }
  467.                 }
  468.                 edge = edge.next;
  469.             }
  470.             originVex.visited = true;
  471.             /*在经从源顶点经过的路径中找到最小的路径,找最小只是为了以后算法优化
  472.               不用把所有源点到其它顶点的路径都找出来*/
  473.             Dictionary<T, PassedPathInfo>.Enumerator e = vexPssedPaths.GetEnumerator();
  474.             Vertex<T> vex=null;
  475.             int minWeight = int.MaxValue;
  476.             while (e.MoveNext())
  477.             {
  478.                 Vertex<T> temp = this.Find(e.Current.Key);
  479.                 if (!temp.visited && e.Current.Value.Weight < minWeight)
  480.                 {
  481.                     minWeight = e.Current.Value.Weight;
  482.                     vex = temp;
  483.                 }
  484.             }
  485.             if (vex != null)
  486.                 RecursiveFindMinPath(vexPssedPaths, vex);
  487.         }
  488.         //////////////////////////////// 拓谱排序 /////////////////////////////////////
  489.         public string TopologicalSort()
  490.         {
  491.             if (this.IsCycle)
  492.                 return "此图是一个环";
  493.             List<Vertex<T>> deepCopyVexList = (List<Vertex<T>>)HBDiscover.Utility
  494.                 .CloneHelpers.DeepClone(this.items);
  495.             string strResult = string.Empty;
  496.             List<Vertex<T>> topoVexList = new List<AdjacencyList<T>.Vertex<T>>();
  497.             while (topoVexList.Count < this.items.Count)
  498.             {
  499.                 foreach (Vertex<T> tempVex in deepCopyVexList)
  500.                 {
  501.                     if (!tempVex.visited  && tempVex.InDegree <= 0)
  502.                     {
  503.                         tempVex.ClearEdges();
  504.                         topoVexList.Add(tempVex);
  505.                         strResult += tempVex.data.ToString();
  506.                         tempVex.visited = true;
  507.                     }
  508.                 }
  509.             }
  510.             return strResult;
  511.         }
  512.     }
  513. }