zoukankan      html  css  js  c++  java
  • 基于邻接表的拓扑排序实现

      上一篇博客实现了图的基本操作(使用邻接表),包括图的创建、输出、遍历等,这次来实现一下拓扑排序。拓扑排序基本原理可以参考以前转载的一篇博客

    http://www.cnblogs.com/zhangbaochong/p/5406159.html

      由于代码比较简单,就直接贴出来了

      1 #include <queue>
      2 #include <vector>
      3 #include <stack>
      4 #include <iostream>
      5 using namespace std;
      6 
      7 
      8 enum GraphType
      9 {
     10     UNDIR_UNWEIGHT_GRAPH,        //无向无权图
     11     UNDIR_WEIGHT_GRAPH,            //无向带权图
     12     DIR_UNWEIGHT_GRAPH,            //有向无权图
     13     DIR_WEIGHT_GRAPH            //有向带权图    
     14 };
     15 
     16 //结点颜色代表遍历情况
     17 enum ColorType
     18 {
     19     WHITE,    //未访问
     20     GRAY,    //正在访问,邻接点还没访问完
     21     BLACK    //访问完毕
     22 };
     23 
     24 template<typename VertexType, typename InfoType>
     25 class Graph
     26 {
     27 public:
     28     Graph(int vertexNum, GraphType type) :m_vertexNum(vertexNum), m_type(type), m_arcNum(0)
     29     {
     30         for (int i = 0; i < MAX_VERTEX_NUM; ++i)
     31         {
     32             m_vertices[i].firstArc = nullptr;
     33         }
     34     }
     35 
     36     void Create()
     37     {
     38         CreateDirUnweightGraph();
     39     }
     40 
     41 
     42     //输出图的信息
     43     void Display()
     44     {
     45         for (int i = 0; i < m_vertexNum; ++i)
     46         {
     47             cout << "" << i + 1 << "个结点为" << m_vertices[i].data << " 邻接表为:";
     48             ArcNode* node = m_vertices[i].firstArc;
     49             while (node)
     50             {
     51                 cout << "->" << m_vertices[node->vertexIndex].data << "(" << node->info << ")";
     52                 node = node->next;
     53             }
     54             cout << endl;
     55         }
     56     }
     57 
     58     //拓扑排序
     59     void TopologicalSort()
     60     {
     61         cout << "拓扑排序为:";
     62         CountInDegree();
     63         stack<Vertex> s;
     64         //把所有入度为0的结点入栈
     65         for (int i = 0; i < m_vertexNum; ++i)
     66         {
     67             if (m_inDegreeArray[i] == 0)
     68                 s.push(m_vertices[i]);
     69         }
     70         int count = 0;//输出结点计数,用于判断有没有环
     71         while (!s.empty())
     72         {
     73             Vertex v = s.top();
     74             s.pop();
     75             cout << v.data << "->";
     76             ++count;
     77             ArcNode* node = v.firstArc;
     78             while (node)
     79             {
     80                 //从图中删除结点v,v指向的结点入度-1
     81                 //结点 入度为0加入栈中
     82                 if (--m_inDegreeArray[node->vertexIndex] == 0)
     83                     s.push(m_vertices[node->vertexIndex]);
     84                 node = node->next;
     85             }
     86         }
     87         if (count < m_vertexNum)
     88             cout << "图中存在环!" << endl;
     89     }
     90 private:
     91     struct ArcNode
     92     {
     93         int vertexIndex;        //该弧指向的顶点位置
     94         struct ArcNode* next;    //指向下一个弧
     95         InfoType info;            //该弧的相关信息,如权重等
     96     };
     97 
     98     struct Vertex
     99     {
    100         VertexType data;    //顶点信息
    101         ArcNode* firstArc;    //指向第一条依附该节点弧的指针
    102         ColorType color;    //访问情况
    103     };
    104 
    105     //最大顶点数
    106     static const int MAX_VERTEX_NUM = 20;
    107     Vertex m_vertices[MAX_VERTEX_NUM];    //顶点列表
    108     int m_vertexNum;    //当前顶点数量
    109     int m_arcNum;        //当前弧数量
    110     GraphType m_type;    //图类型:有向无权图、有向带权图、无向无权图、无向无权图
    111 
    112     //结点入度数组
    113     int m_inDegreeArray[MAX_VERTEX_NUM];
    114 private:
    115     //初始化顶点列表
    116     void InitVertices()
    117     {
    118         cout << "请输入每个顶点的关键字" << endl;
    119         VertexType data;
    120         for (int i = 0; i < m_vertexNum; ++i)
    121         {
    122             cin >> data;
    123             m_vertices[i].data = data;
    124         }
    125     }
    126     //插入一个表结点
    127     void Insert(int headVertex, int tailVertex, InfoType info)
    128     {
    129         //构造一个邻接表结点,即创建一条弧
    130         ArcNode* newNode = new ArcNode;
    131         newNode->info = info;
    132         newNode->next = nullptr;
    133         newNode->vertexIndex = tailVertex;
    134 
    135         //找到邻接表的最后一个节点
    136         ArcNode* lastNode = m_vertices[headVertex].firstArc;
    137         if (lastNode == nullptr)
    138             m_vertices[headVertex].firstArc = newNode;
    139         else
    140         {
    141             while (lastNode->next)
    142             {
    143                 lastNode = lastNode->next;
    144             }
    145             lastNode->next = newNode;
    146         }
    147         ++m_arcNum;
    148     }
    149 
    150     //创建有向无权图
    151     void CreateDirUnweightGraph()
    152     {
    153         InitVertices();
    154         cout << "请分别输入每条边的起始结点值:" << endl;
    155         int head, tail;
    156         while (cin >> head >> tail)
    157         {
    158             Insert(head, tail, 0);
    159         }
    160     }
    161     
    162     void CountInDegree()
    163     {
    164         for (int i = 0; i < m_vertexNum; ++i)
    165         {
    166             m_inDegreeArray[i] = 0;
    167             for (int j = 0; j < m_vertexNum; ++j)
    168             {
    169                 ArcNode* node = m_vertices[j].firstArc;
    170                 while (node)
    171                 {
    172                     if (node->vertexIndex == i)
    173                     {
    174                         ++m_inDegreeArray[i];
    175                     }
    176                     node = node->next;
    177                 }
    178             }
    179         }
    180     }
    181 };
    182 
    183 int main()
    184 {
    185     Graph<char, int> g(6, DIR_UNWEIGHT_GRAPH);
    186     g.Create();
    187     g.Display();
    188     g.TopologicalSort();
    189 }

      测试用的有向图:

      输出结果:

  • 相关阅读:
    ubuntu12.04 死机 卡屏 画面冻结解决方案
    Install Firefox 20 in Ubuntu 13.04, Ubuntu 12.10, Ubuntu 12.04, Linux Mint 14 and Linux Mint 13 by PPA
    ListView1.SelectedItems.Clear()
    android studio 下载地址
    jquery.slider.js jquery幻灯片测试
    jquery.hovermenu.js
    jquery.tab.js选项卡效果
    适配 placeholder,jquery版
    jquery.autoscroll.js jquery自动滚动效果
    将 Google Earth 地图集成到自己的窗体上的 简单控件
  • 原文地址:https://www.cnblogs.com/zhangbaochong/p/5631250.html
Copyright © 2011-2022 走看看