如何在数组中实现链表?

时间:2011-10-05 18:03:18

标签: data-structures

This question提到可以在数组中实现链表。

虽然我可以想象如何使用多个数组执行此操作,但如何使用单个数组?

编辑:这样做是否可以有效地考虑需要删除项目&从列表中插入 - 可能需要识别数组中的自由元素?

5 个答案:

答案 0 :(得分:5)

如果它是一个对象数组,那么每个对象都会存储一个值和一个指向下一个对象的指针。

[0] -> {"a",1}
[1] -> {"b",2}
[2] -> {"c",4}
[3] -> {"1",5}
[4] -> {"d",7}
[5] -> {"2",6}
[6] -> {"3",8}
[7] -> {"e",-1}
[8] -> {"4",-1}

所以这里有2个链表,第一个:

“a” - > “b” - > “c” - > “d” - > “e” 的

和第二个:

“1” - > “2” - > “3” - > “4”

使用索引-1作为列表的结尾。

然后你需要多个指针(每个列表一个)来确定你在列表中的位置。

老实说,我甚至不确定我是否理解这个问题,但无论如何都想抛弃想法。

答案 1 :(得分:1)

你可以(例如)通过将第一个数据项放在数组的元素中,以及第二个元素中下一个项的索引来拥有整数的链接列表。这会限制您存储与/ convertible兼容的类型。

答案 2 :(得分:0)

在C ++中,我很快写了这个并且它有效。数组中的每个索引都包含一个双向链表。

#include <list>
#include <iostream>
using namespace std;

int main(int argc, char** argv)
{
  list<int> ll[10];
  for (int i = 0; i < 10; i++)
    for (int j = 100; j > 0; j-=10)
      ll[i].push_back(j);

  list<int>::iterator it;
  for (int i = 0; i < 10; i++)
  {
    for (it = ll[i].begin(); it != ll[i].end(); it++)
    {
      cout << " " << *it;
    }
    cout << endl;
  }
  return 0;
}

输出:

$ g++ ll-in-array.cpp && ./a.out
 100 90 80 70 60 50 40 30 20 10
 100 90 80 70 60 50 40 30 20 10
 100 90 80 70 60 50 40 30 20 10
 100 90 80 70 60 50 40 30 20 10
 100 90 80 70 60 50 40 30 20 10
 100 90 80 70 60 50 40 30 20 10
 100 90 80 70 60 50 40 30 20 10
 100 90 80 70 60 50 40 30 20 10
 100 90 80 70 60 50 40 30 20 10
 100 90 80 70 60 50 40 30 20 10

答案 3 :(得分:0)

您可以使用固定大小的内存块分配器,其中每个块都有一个指向链接列表中下一个元素的下一个指针。

一个简单的实现来自Contiki操作系统(BSD许可证),请参阅memblist的实现。

你像这样使用它们:

struct connection {
    struct connection *next;
    /* ... */
};

/* This allocates a fixed size array of 16 'struct connection' */
MEMB(connection_mem, struct connection, 16);

/* This is just a void ** keeping track of list elements in a linked list */
LIST(connection_list);

void main()
{
    /* Initialize the memory block */
    memb_init(&connection_mem);

    /* Allocate a new chunk */
    struct connection *c = memb_alloc(&connection_mem);
    if(c != NULL) {
        /* Add to list */
        list_add(connection_list, c);
    }

    for(c = list_head(connection_list); c != NULL; c = c->next) {
        /* ... */
    }
}

编辑:抱歉,您没有提及任何特定的编程语言,而且我最熟悉C和C ++。如果你可以解释如何实现memblist那么基本理论应该是相同的:一个简单的块分配器跟踪空闲/使用的块,以及一个可以引用这些个体的链表实现块。

答案 4 :(得分:0)

  

如何在数组中实现链表?

这是一种可能的方法(使用C ++):您的节点将由列表中的下一个和前一个元素的索引组成:

struct Link
{
    // additional data
    int next;
    int prev;
};

其中nextprev将保存存储Link s的数组的索引。

Link** head; // = new Link*[initial_size];
int first;  // -1 initially (analogue of nullptr)
int last;   // index of the last element in the array: head

另外,应该有一个机制来计算数组中的可用元素,实现的可能性越大:

bool* available; // = new bool[initial_size]; // all initialized to true

您需要函数来从bool available获取索引(指示ihead处没有索引节点available,其中true的元素具有值{ {1}})。例如:

int get_available_index()
{
    for (int i = 0; i < initial_size; ++i)
    {
        if (available[i] == true)
        {
            available[i] == false;
            return i;
        }
    }
    // indicate / throw list full / resize???
}

以下是puch_back()的样子:

void push_back(Link** head, Link* new_link)
{
    // chech pointer validity

    int index = get_available_index();

    // probably using: placement new(), to construct a node in that location
    // new(head + index) new_link;? or just
    head[index] = new_link;

    if (last != -1) // list not empty
    {
        head[last]->next = index;
        head[index]->prev = (last - head[0]); // gives you the index of the last node
    }
    else
    {
        first = index;
        head[index]->prev = -1;
    }

    last = index;
    head[index]->next = -1;
}

此外,应该有一个与get_available_index()元素设置为available[i]的{​​{1}}相反的函数(对象被销毁true?)

  

这样做是否可以有效地考虑需要删除项目&amp;从列表中插入 - 可能需要识别数组中的自由元素?

据我所知,会有碎片,反映在(head + i)->~Link();数组中存储的值中,这只会影响存储新节点所需的时间。