无法通过一个单链表列表创建邻接列表

时间:2016-06-14 15:58:53

标签: c++ arrays singly-linked-list adjacency-list

我正在尝试通过一个单链表列表创建邻接列表

看我的代码。

 #include<iostream>
 #include<cstdlib>

 using namespace std;

 typedef struct city
 {
      int id;
      struct city *next;
 }city;

 int main()
 {
     int num_city, index = 0, length;
     cin >> num_city;   

     length = num_city;

     city **adj_list = new city*[num_city]; // here it's the header node
     for(int index = 0 ; index < length ; index++)
             adj_list[index] = new city;
     city **temp = adj_list;

     while( num_city -- )
     {
             int a,b;
             cin >> a;
             cin >> b;

             a--;
             b--;       

             city *t1 = new city;
             t1 -> id = a;
             t1 -> next = NULL;

             city *t2 = new city;
             t2 -> id = b;
             t2 -> next = NULL;

             temp[a] -> next = t2;
             temp[b] -> next = t1;  

             temp[a] = temp[a] -> next;
             temp[b] = temp[b] -> next;
      } 
      for ( int index = 0; index < length ; index ++)
             delete []  adj_list[index];
      delete [] adj_list;

    adj_list = NULL;
    exit(0);
  }

当我尝试逐个浏览单链表时,其输出为NULL

GDB此代码之后,我发现:启动循环,city已成功创建,adj_list[index]也可以指向正确的内存位置。进入下一个循环后,adj_list[index]意外地等于NULL

有什么问题?

1 个答案:

答案 0 :(得分:0)

有两个问题。您正在使用temp来跟踪每个列表中的最后一项。但是temp指向原始adj_list adj_list而不是副本(如果是)),结果就是adj_list本身仅保留您在每个列表中添加的最后一项。如果您将初始adj_list复制到temp,则更新temp不会影响adj_list中的现有项目。

第二个问题是,可能会有比城市更多的邻居对。 5个城市的例子:(2,3),(2,4),(2,5),(2,1),(1,5),(4,5),(3,4)。因此,您无法循环num_city。而是保持循环,直到用户输入城市的-1

我添加了一个构造函数city( int id, city* next ),以便更容易初始化每个新城市。 temp已重命名为tail,以便更清楚其目的是什么。该功能分为3个部分,即构建,打印和删除。

typedef struct city
{
    int id;
    struct city *next;
    city(int id, city *next) { this->id = id; this->next = next; }
} city;

// pass `adj_list` in as a reference (city **&) so you keep the changes to it when you return
int adj_list_build(city **& adj_list)
{
    int num_city, index = 0;
    cin >> num_city;

    // you need to keep track of the "tail" (end) of each list so you know where to add next item
    city **tail = new city*[num_city];

    adj_list = new city*[num_city];
    for (int index = 0; index < num_city; index++)
    {
        adj_list[index] = new city( index, NULL );
        tail[index] = adj_list[index]; // the tail starts off pointing to the first item in each list
    }

    while (true)
    {
        int a, b;
        cin >> a;               // enter `-1` to stop
        if (a == -1 ) break;
        cin >> b;

        a--;                    // convert to 0-index
        b--;

        city *t1 = new city( a, NULL );
        city *t2 = new city( b, NULL );

        tail[a]->next = t2;
        tail[b]->next = t1;

        tail[a] = t2; // or `tail[a] = tail[a]->next;` - they have same effect 
        tail[b] = t1;
    }
    return num_city;
}

void adj_list_print(city ** adj_list, int length)
{
    for (int index = 0; index < length; index++)
    {
        cout << index << ": ";
        city * item = adj_list[index];
        while (item)
        {
            cout << item->id << " " << item->next << " ";
            item = item->next;
        }
        cout << endl;
    }
}

void adj_list_delete(city ** adj_list, int length)
{
    for (int index = 0; index < length; index++)
        delete[]  adj_list[index];
    delete[] adj_list;

    adj_list = NULL;
}

void main()
{
    city ** adj_list;
    int len = adj_list_build( adj_list );
    adj_list_print(adj_list, len);
    adj_list_delete(adj_list, len);
}