理解c中类似链表的结构



我很难理解一段表示链表结构的C代码。结构的骨架如下所示:

struct r{
   r *next;
   r **prev; 
   data *d;
}
struct r *rlist;

rlist可以通过调用以下函数来填充:(仅限骨架)

r* rcreate(data *d){
     struct r *a = xmalloc(sizeof(*r))
     a->d = d;
     a->next = rlist;
     a->prev = &rlist;
     if (rlist)
         rlist->prev = &a->next;
     rlist = a;
     return a;
}

如何使用此数据结构?例如,如何遍历rlist?

编辑:这是删除链接列表中节点的功能

void rdestroy(struct r *a){
     if (a->next){
         a->next->prev = a->prev;
     }
     *a->prev = a->next;
      destroy(a->d); /* destroy is defined elsewhere */
}

prev指针似乎只允许在一个方向上遍历列表,同时允许轻松删除(因为即使不能(轻松)访问上一个元素,也可以访问上一元素的next指针,并在删除节点时将其设置为新的正确值。

如果没有看到其他相关的功能,很难理解为什么要这样做。我还没有看到这样做,也无法立即想到任何真正有用的好处。

我认为这允许使用更简单的节点删除代码,因为节点不需要关心是否首先删除,因为节点的prev指针在删除自己时总是具有非NULL值,指向需要修改的指针。在当前节点之前插入也同样简单。如果这些操作主导了使用模式,那么我想这可以被视为小的优化,尤其是在分支可能更昂贵的旧CPU中。

如何遍历列表

这就是问题所在,对吧?您只能以一种非常简单的方式向前遍历它,这里有一个for循环来遍历整个列表:

struct r *node;
for (node = rlist ; node ; node = node->next) {
    // assert that prev points to pointer, which should point to this node
    assert(*(node->prev) == node); 
    // use node
    printf("node at %p with data at %pn", node, node->d);
}

插入函数示例

这个示例插入函数演示了在节点之前的插入如何不需要分支(未测试):

struct r *rinsert(struct r *nextnode, data *d) {
     // create and initialize new node
     struct r *newnode = xmalloc(sizeof(struct r));
     newnode->d = d;
     newnode->next = nextnode;
     newnode->prev = nextnode->prev;
     // set next pointer of preceding node (or rlist) to point to newnode
     *(newnode->prev) = newnode;
     // set prev pointer of nextnode to point to next pointer of newnode
     nextnode->prev = &(newnode->next);
     return newnode;
}

没有充分的理由在该结构中使用r**。这是一个双链接列表。所以,如果这个东西被创建了,你就给它分配了

thisList=r创建("我的数据")

现在您可以开始遍历它while(thisList->next)thisList=thisList->next。…

您的代码中有许多语法错误,可能是因为(正如您所说)它是一个"骨架",所以很难解析作者(无论是您还是其他人)实际想要做什么。

一个简单的(双)链表结构如下:

struct node {
  struct node *next, *prev; // pointers to the adjacent list entries
  int data; // use whatever datatype you want
};
struct node *list = NULL; // the list starts empty
void add_entry(int new_data) {
  struct node *new_entry = malloc(sizeof(struct node));
  // note that in the above line you need sizeof the whole struct, not a pointer
  new_entry->data = new_data;
  new_entry->next = list; // will be added to the beginning of the list
  new_entry->prev = NULL; // no entries currently front of this one
  // in general a NULL pointer denotes an end (front or back) of the list
  list->prev = new_entry;
  list = new_entry; // now list points to this entry
  // also, this entry's "next" pointer points to what used to
  // be the start of the list
}

编辑:我想说的是,如果你想让我们帮助你理解一些你没有写也不能修改的大型程序中的代码,那么请以至少语法的格式发布相关代码。例如,正如其他人所说,在你发布的代码中使用prev是不可破译的,也不清楚(因为还有其他类似的令人困惑的语法问题)这是在原始代码中还是在转录中引入的错误。

Yang,我不确定你对指针的总体感觉有多舒服。我建议看看其他一些链表实现,它可能会起到作用。

看看这个通用链表实现。

相关内容

  • 没有找到相关文章

最新更新