如何仅使用指针(w / o结构)实现链接列表?

时间:2016-12-29 22:15:31

标签: c pointers linked-list

我正在尝试创建一个链接列表而不使用C中的结构。 我希望能够在每个节点上存储int变量,并指向下一个节点,向列表添加无限数量,删除第一个项目,打印所有元素等等。

我在想,int**类型的每个节点都应该有2个类型为int*的指针。 第一个将指向int地址,第二个将指向NULL。 然后,如果我想在列表中添加一个数字,我将使用最后一个指针指向int**类型的新分配节点,依此类推。

我在编写适当的代码时遇到了麻烦,但似乎无法达到实际的int值。见下图: explanation

3 个答案:

答案 0 :(得分:1)

你可以通过每次分配两个uintptr_t来实现这一点:第一个分配的内存空间将负责存储整数的值,第二个将指向下一个内存位置。

uintptr_t nodeFirst = malloc(2 * sizeof(uintptr_t));
...
...
uintptr_t nodeNext = malloc(2 * sizeof(uintptr_t));
....
....
*nodeFirst = someIntValue;
*(nodeFirst + 1) = nodeNext;
...

事实是,我上面的解决方案仍在使用结构类比,但不使用struct关键字。

答案 1 :(得分:0)

以下是作为int **指针管理的LinkedList的完整解决方案。

第1步 - addNode()函数将一个节点添加到int **head

int **addNode(int **head, int ival)
{
    int **node = malloc(2 * sizeof(int *));

    // don't forget to alloc memory to store the int value
    node[0] = malloc(sizeof(int));
    *(node[0]) = ival;
    // next is pointing to NULL
    node[1] = NULL;

    if (head == NULL) {
        // first node to be added
        head = node;
    }
    else {
        int **temp;

        temp = head;
        // temp[1] is the next
        while (temp[1]!=NULL) {
            // cast needed to go to the next node
            temp = (int **)temp[1];
        }
        // cast needed to store the next node
        temp[1] = (int *)node;
    }
    return (head);
}

第2步 - 用于探索当前链接列表的函数display()

void display(int **head)
{
    int **temp;
    int i = 0;

    temp = head;
    printf("display:\n");
    while (temp!=NULL) {
        // temp[0] is pointing to the ivalue
        printf("node[%d]=%d\n",i++,*(temp[0]));
        temp = (int **)temp[1];
    }
    printf("\n");
}

第3步 - 删除第一个节点的popNode()函数。

int **popNode(int **head)
{
    int **temp;

    if (head!=NULL) {
        temp = (int **)head[1];
        // don't forget to free ivalue
        free(head[0]);
        // then free the next pointer
        free(head[1]);
        head = temp;
    }
    return (head);
}

第4步 - 然后使用链接列表的main()函数示例。

int main()
{
    int **head = NULL;

    head = addNode(head,111);
    head = addNode(head,222);
    head = addNode(head,333);

    display(head);
    // display:
    // node[0]=111
    // node[1]=222
    // node[2]=333

    head = popNode(head);

    display(head);
    // display:
    // node[0]=222
    // node[1]=333

    while ((head = popNode(head))!=NULL);

    display(head);
    // display:

    return (0);
}

答案 2 :(得分:-1)

分配两个数组,这两个数组都存储为指针。在C中,它们可以是从calloc()返回的指针。第一个保存节点数据。我们可以称之为nodes。第二个是指针数组(或整数偏移量)。我们可以称之为nexts。每当您更新列表时,请更新nodes,以便每个nexts[i]链接到包含nodes[i]的节点后的下一个节点,或者NULL或{{无效值1}}如果是尾巴。对于双链表,您需要-1或使用XOR技巧。你需要一个头指针和某种指示器来指示你的池中哪些元素是未分配的,这可能是一个简单的东西,比如第一个免费索引,或者像bitfield那样复杂的东西。

您仍然需要将所有这些包装在一个结构中以在程序中获得多个链接列表,但这确实为您提供了一个链接列表,而不使用除指针之外的任何数据结构。

这个挑战很疯狂,但是数组结构不是,你可能会看到一个图形或顶点列表以类似的方式存储。您可以一次性分配或取消分配您的节点池而不是小块,使用32位偏移而不是64位下一个指针可能更有效,连续存储可以获得引用的位置。