【问题标题】:Can we use doubly linked list in C without dynamic memory allocation?我们可以在没有动态内存分配的情况下在 C 中使用双向链表吗?
【发布时间】:2012-10-11 01:26:23
【问题描述】:

我正在尝试使用双向链表数据结构在缓冲区管理器中实现替换策略。

但是我的C程序没有链表库,所以我只是自己定义了数据结构。

问题是:我可以避免做任何 [dynamic?] 内存分配来使用双向链表吗?

使用palloc() 代替malloc() 有什么好处?

【问题讨论】:

  • 由于语法错误,很难破译您要问的内容。双向链表是一种数据结构,这意味着它包含数据并且数据必须驻留在某些分配的内存中,但是可以以任何方式分配内存,因此不需要 malloc。我怀疑这是否能回答你的问题,因为我不知道它是什么......
  • @RavindraBagale 它基于存储池的分配器,而不是标准的(至少我不知道)。
  • 它是链表,所以它应该是动态的.. 但是如果你不动态分配内存,那么你将如何容纳尽可能多的数据?

标签: c memory-management linked-list malloc


【解决方案1】:

您当然可以完全不使用动态内存分配来创建双向链表;这样做只是一种惯例。

#include <stdio.h>
#include <assert.h>
#include <inttypes.h>

enum { NODEBUG = 0, DEBUG = 1 };

static const int debug = NODEBUG;

typedef struct DList DList;
struct DList
{
    int    data;
    DList *next;
    DList *prev;
};

enum { MAX_DLIST = 100 };
struct DList dlist[MAX_DLIST];

static void add_node(DList *head, DList *node)
{
    assert(head != 0 && node != 0);
    if (head->next == 0)
    {
        assert(head->prev == 0);
        head->next = node;
        head->prev = node;
        node->next = head;
        node->prev = head;
    }
    else
    {
        assert(head->prev != 0);
        node->next = head->next;
        node->prev = head;
        head->next->prev = node;
        head->next = node;
    }
}

static void diagnode(DList *node)
{
    if (debug)
        printf(" (T = 0x%.12" PRIXPTR ", N = 0x%.12" PRIXPTR ", P = 0x%.12" PRIXPTR ")\n",
               (uintptr_t)node, (uintptr_t)node->next, (uintptr_t)node->prev);
}

static void print_list(DList *head)
{
    assert(head != 0);
    printf("List:");
    if (head->next != 0)
    {
        DList *node;
        int counter = 0;
        if (debug)
            printf("\nHEAD");
        diagnode(head);
        for (node = head->next; node != head; node = node->next)
        {
            printf(" %3d", node->data);
            diagnode(node);
            assert(counter++ < MAX_DLIST);
        }
    }
    printf(" <EOL>\n");
}

int main(void)
{
    DList head = { 0, 0, 0 };

    for (int i = 0; i < MAX_DLIST; i++)
    {
        dlist[i].data = (i * 13 + 7) % 100;
        add_node(&head, &dlist[i]);
        if (debug)
            print_list(&head);
    }
    print_list(&head);
}

看不到内存分配!当您有类似缓冲区管理器的东西时,您可以使用此变体,其中有固定的数据缓冲区数组,但您需要 LRU(最近最少使用)替换策略。 data 元素将指向缓冲池中的条目,而不是将数据直接放在双向链表结构中。然后,您可以在列表中添加和删除条目,而无需更改列表链接到的主数据结构中的任何内容。


如果palloc() 是一个池内存分配器,使用它比malloc() 的优势是您可以通过一个函数调用释放分配给给定池的所有内存,而不必管理所有单独的释放你自己。有时,池分配器比使用malloc() 的单独内存分配更有效;它可能会分配一个固定大小结构的大数组,然后根据请求分配条目,从而减少分配次数,从而减少开销。

【讨论】:

  • 谢谢你的回答,我不知道为什么其他人给我负分。这是一个愚蠢的问题吗?
  • 这不是一个愚蠢的问题,尽管不使用链表进行动态内存分配相对不寻常。但是,缓冲区管理器是通过分配数组(静态地,如我的回答,或一次动态地分配数组)来避免重复单个项目分配开销的地方之一,并且使用它是完全合理的。我怀疑投反对票的人没有遇到过这种情况,他们之前的“从标准输入读取值列表”的经验并没有向他们展示替代方案,所以他们没有意识到他们在做什么......
  • 您可以通过提及 palloc() 是什么来为自己省去一点悲伤;期望熟悉 C89 标准库是合理的,假设 C99 也是合理的。进入 C2011 的深奥新部分,你应该提到这一点;进入 POSIX 或 Windows API,您至少应该规定这一点。远离这些,你应该指出人们可以在哪里找到关于函数是什么以及它做什么的信息。我之前没有googlepalloc(),但是有很多种版本;我希望他们或多或少做同样的事情。
猜你喜欢
  • 2019-12-26
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
  • 1970-01-01
  • 2020-08-24
  • 2012-03-18
相关资源
最近更新 更多