• 图的创建和遍历(BFS/DFS)


         图的表示方法主要有邻接矩阵和邻接表。其中邻接表最为常用,因此这里便以邻接表为例介绍一下图的创建及遍历方法。

         创建图用到的结构有两种:顶点及弧

    struct ArcNode
        {
            int vertexIndex;        //该弧指向的顶点位置
            struct ArcNode* next;    //指向下一个弧
            InfoType info;            //该弧的相关信息,如权重等
        };
    
        struct Vertex
        {
            VertexType data;    //顶点信息
            ArcNode* firstArc;    //指向第一条依附该节点弧的指针
            ColorType color;    //访问情况
        };

      其中ColorType是一个枚举,遍历的时候才会用到。图的创建比较简单,直接看代码很容易理解,这里不再详细说了。 图的深度和广度遍历直接看算法导论中的两张图就明白了 :

    //结点颜色代表遍历情况
    enum ColorType
    {
        WHITE,    //未访问
        GRAY,    //正在访问,邻接点还没访问完
        BLACK    //访问完毕
    };

     
    代码:
      1 #include <queue>
      2 #include <stack>
      3 #include <iostream>
      4 using namespace std;
      5 
      6 
      7 enum GraphType
      8 {    
      9     UNDIR_UNWEIGHT_GRAPH,        //无向无权图
     10     UNDIR_WEIGHT_GRAPH,            //无向带权图
     11     DIR_UNWEIGHT_GRAPH,            //有向无权图
     12     DIR_WEIGHT_GRAPH            //有向带权图    
     13 };
     14 
     15 //结点颜色代表遍历情况
     16 enum ColorType
     17 {
     18     WHITE,    //未访问
     19     GRAY,    //正在访问,邻接点还没访问完
     20     BLACK    //访问完毕
     21 };
     22 
     23 template<typename VertexType,typename InfoType>
     24 class Graph
     25 {
     26 public:
     27     Graph(int vertexNum, GraphType type) :m_vertexNum(vertexNum), m_type(type), m_arcNum(0)
     28     {
     29         for (int i = 0; i < MAX_VERTEX_NUM; ++i)
     30         {
     31             m_vertices[i].firstArc = nullptr;
     32         }
     33     }
     34 
     35     void Create()
     36     {
     37         switch (m_type)
     38         {
     39         case UNDIR_UNWEIGHT_GRAPH:
     40             CreateUndirUnweightGraph();
     41             break;
     42         case UNDIR_WEIGHT_GRAPH:
     43             CreateUndirWeightGraph();
     44             break;
     45         case DIR_UNWEIGHT_GRAPH:
     46             CreateDirUnweightGraph();
     47             break;
     48         case DIR_WEIGHT_GRAPH:
     49             CreateDirWeightGraph();
     50             break;
     51         default:
     52             break;
     53         }
     54     }
     55 
     56     //输出图的信息
     57     void Display()
     58     {
     59         for (int i = 0; i < m_vertexNum; ++i)
     60         {
     61             cout << "" << i + 1 << "个结点为" << m_vertices[i].data << " 邻接表为:";
     62             ArcNode* node = m_vertices[i].firstArc;
     63             while (node)
     64             {
     65                 cout << "->" << m_vertices[node->vertexIndex].data << "(" << node->info << ")";
     66                 node = node->next;
     67             }
     68             cout << endl;
     69         }
     70     }
     71 
     72     void BFS()
     73     {
     74         for (int i = 0; i < m_vertexNum; ++i)
     75         {
     76             m_vertices[i].color = WHITE;
     77         }
     78         cout << "图的广度优先遍历为:";
     79         BFS(&m_vertices[0]);
     80         cout << endl;
     81     }
     82 
     83     void DFS()
     84     {
     85         for (int i = 0; i < m_vertexNum; ++i)
     86         {
     87             m_vertices[i].color = WHITE;
     88         }
     89         cout << "图的深度优先遍历为:";
     90         DFS(&m_vertices[0]);
     91         cout << endl;
     92     }
     93 private:
     94     struct ArcNode
     95     {
     96         int vertexIndex;        //该弧指向的顶点位置
     97         struct ArcNode* next;    //指向下一个弧
     98         InfoType info;            //该弧的相关信息,如权重等
     99     };
    100 
    101     struct Vertex
    102     {
    103         VertexType data;    //顶点信息
    104         ArcNode* firstArc;    //指向第一条依附该节点弧的指针
    105         ColorType color;    //访问情况
    106     };
    107 
    108     //最大顶点数
    109     static const int MAX_VERTEX_NUM = 20;
    110     Vertex m_vertices[MAX_VERTEX_NUM];    //顶点列表
    111     int m_vertexNum;    //当前顶点数量
    112     int m_arcNum;        //当前弧数量
    113     GraphType m_type;    //图类型:有向无权图、有向带权图、无向无权图、无向无权图
    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 CreateUndirUnweightGraph()
    152     {
    153         InitVertices();
    154         cout << "请分别输入每条边的起始结点:" << endl;
    155         int head, tail;
    156         while (cin >> head >> tail)
    157         {
    158             //无向图head->tail tail->head插入两次
    159             Insert(head, tail, 0);
    160             Insert(tail, head, 0);
    161         }
    162     }
    163     //创建无向有权图
    164     void CreateUndirWeightGraph()
    165     {
    166         InitVertices();
    167         cout << "请分别输入每条边的起始结点和权值:" << endl;
    168         int head, tail;
    169         InfoType weight;
    170         while (cin >> head >> tail >> weight)
    171         {
    172             Insert(head, tail, weight);
    173             Insert(tail, head, weight);
    174         }
    175     }
    176     //创建有向无权图
    177     void CreateDirUnweightGraph()
    178     {
    179         InitVertices();
    180         cout << "请分别输入每条边的起始结点值:" << endl;
    181         int head, tail;
    182         while (cin >> head >> tail)
    183         {
    184             Insert(head, tail,0);
    185         }
    186     }
    187     //创建有向带权图 
    188     void CreateDirWeightGraph()
    189     {
    190         InitVertices();
    191         cout << "请分别输入每条边的起始结点和权值:" << endl;
    192         int head, tail;
    193         InfoType weight;
    194         while (cin >> head >> tail >> weight)
    195         {
    196             Insert(head, tail, weight);
    197         }
    198     }
    199 
    200     void BFS(Vertex* vertex)
    201     {
    202         vertex->color = GRAY;
    203         queue<Vertex*> vertices;
    204         vertices.push(vertex);
    205         while (!vertices.empty())
    206         {
    207             Vertex* curVertex = vertices.front();
    208             vertices.pop();
    209             cout << curVertex->data << "->";
    210             ArcNode* node = curVertex->firstArc;
    211             while (node)
    212             {
    213                 Vertex* tmpVertex = &m_vertices[node->vertexIndex];
    214                 if (tmpVertex->color == WHITE)
    215                 {
    216                     tmpVertex->color = GRAY;
    217                     vertices.push(tmpVertex);
    218                 }
    219                 node = node->next;
    220             }
    221             curVertex->color = BLACK;
    222         }
    223     }
    224 
    225     void DFS(Vertex* vertex)
    226     {
    227         vertex->color = GRAY;
    228         stack<Vertex*> vertices;
    229         vertices.push(vertex);
    230         while (!vertices.empty())
    231         {
    232             Vertex* curVertex = vertices.top();
    233             vertices.pop();
    234             cout << curVertex->data << "->";
    235             ArcNode* node = curVertex->firstArc;
    236             while (node)
    237             {
    238                 Vertex* tmp = &m_vertices[node->vertexIndex];
    239                 if (tmp->color == WHITE)
    240                 {
    241                     tmp->color = GRAY;
    242                     vertices.push(tmp);
    243                 }
    244                 node = node->next;
    245             }
    246             curVertex->color = BLACK;
    247         }                
    248     }
    249 };
    250 
    251 int main()
    252 {
    253     int  vertexNum;
    254     cout << "请输入要创建的图的结点数:";
    255     cin >> vertexNum;
    256     Graph<char, int> g(vertexNum,GraphType::UNDIR_UNWEIGHT_GRAPH);
    257     g.Create();
    258     g.Display();
    259     g.BFS();
    260     g.DFS();
    261 }
     
    运行结果:(创建的树为算法导论BFS说明图片中的树)

     
     
  • 相关阅读:
    Python之socket
    Python之创建low版的线程池
    Python之面向对象及相关
    Python之面向对象(进阶篇)
    Python之面向对象(初级篇)
    Python之线程与进程
    python中执行父类的构造方法
    python之反射
    记一次有趣的米筐经历~
    算法第四章作业
  • 原文地址:https://www.cnblogs.com/zhangbaochong/p/5612410.html
Copyright © 2020-2023  润新知