【问题标题】:Proper Implementation of graph through adjacency list in c++ stl通过 c++ stl 中的邻接表正确实现图
【发布时间】:2015-01-18 08:34:51
【问题描述】:

我试图通过 C++ 的 STL 中的邻接表来表示基本的无向图。这是我的代码:

#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int main()
   {
       int no_vertices,no_edges;

       printf("Enter the no. of vertices and Edges : ");
       scanf("%d%d",&no_vertices,&no_edges);

       vector<pair<int,int> > graph[no_vertices];
       //Pair because we edge along with its weight!!

       printf("\nEnter the Edges along with their weight :");

       int s,d,weight;

       for(int i=0;i<no_edges;i++)
         {

           scanf("%d%d%d",&s,&d,&weight);
           graph[s].push_back(pair<int,int>(d,weight));

         }

       for(int i=0;i<no_vertices;i++)
          {
            vector<pair<int,int> >::iterator it = graph[i].begin();

            cout<<endl;

            while(it+1!= graph[i].end())
               {
                 printf("%d->",*it);
                 it++;
               }

            printf("%d",*it);

          }

     return 0;
 }

在上面的代码中,我试图打印每个顶点及其每条边,编译器打印一些东西,然后进入一些内存错误或无限循环。例如。在上面的程序中输入 V=4 E=4 和边缘以及权重是

0 1 4
1 2 5
1 5 2
3 1 3

预期输出-

0->1
1->2->5
2
3->1

但输出是

1
2->5

然后是内存错误或无限循环。请建议对我的代码进行改进??

——

谢谢!

【问题讨论】:

    标签: c++ graph stl adjacency-list


    【解决方案1】:

    printf("%d-&gt;",*it)

    此语句无效,因为 it 的类型为 vector&lt;pair&lt;int,int&gt; &gt;::iterator。所以*it 的类型为pair&lt;int,int&gt;,你不能使用%d 打印它,它需要int

    试试这样的printf("%d %d",it-&gt;first, it-&gt;second);

    【讨论】:

    • 我认为 Sameer 将目标和重量存储在对中,而不是源和目标
    【解决方案2】:

    主要问题是您没有打印原点的编号(它不包含在graph[i] 中,但它是i 本身)。 第二个错误是打印 *itstd::pair)而不是 it-&gt;first(实际的 int),正如 Ashot 解释的那样。
    一种可能性是像这样编写最后一个循环:

        cout << endl;
        for (int i = 0; i<no_vertices; i++)
        {
            printf("%d", i);
            for (auto& e: graph[i]) {
                printf("->%d", e.first);
            }
            cout << endl;
        }    
    

    显式使用迭代器:

    cout << endl;
    for (int i = 0; i<no_vertices; i++)
    {
        printf("%d", i);
        vector<pair<int, int> >::iterator it = graph[i].begin();
        vector<pair<int, int> >::iterator it_end = graph[i].end();
        for (; it != it_end; it++) {
            printf("->%d", it->first);
        }
        cout << endl;
    }
    

    虽然上面的代码可以解决您的问题,但我可能没有正确解释为什么您当前的代码会产生错误: 由于源节点不是向量的一部分,graph[2] 是一个空向量。所以你用等于graph[2].end()graph[2].begin()初始化迭代器ìt。 结果,

    1. 检查while(it+1!= graph[2].end()) 将始终返回true(it+1 将在graph[2].end() 后面开始一个位置)。
    2. printf("%d-&gt;",*it); 取消引用指向无效内存位置的插入器。

    【讨论】:

    • @Sameer:基于范围的 for 循环 (en.cppreference.com/w/cpp/language/range-for) 隐藏了迭代器机制并使代码(在我看来)更具可读性,但如果你愿意,我可以给你一个版本显式迭代器。
    • 另外,如果你可以请我参考一些关于迭代器的好教程。我无法理解迭代器究竟是如何使用的以及它是如何工作的......
    • 另外,如果我使用以下循环而不是您的循环,即 for (int i = 0; i >::iterator it = graph[i].begin(); while(it != graph[i].end()) { cout"
    • @Sameer:完成。不幸的是,我无法专门为您指出迭代器的良好来源。如果你是一个普通的 c++ 初学者,我可以推荐 Bjarne Stroustrup 的“A Tour of C++ (C++ In-Depth)”。
    • 感谢@MikeMB。还有为什么我不能直接将它与 graph[i].end() 进行比较,而是明确定义 iterator_end??
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-08
    相关资源
    最近更新 更多