【问题标题】:adding node to the beginning of double circular linked list in c在c中将节点添加到双循环链表的开头
【发布时间】:2020-02-27 12:35:09
【问题描述】:

我正在尝试将“n”个节点添加到双循环链表的开头 这是添加节点的函数:

//the **head is assigned the address of the original head pointer which is being passed from the main function.

void insert(struct node**head,int n){
 while(n-- >0){
    int num;
    //to input the data for the linked list
    scanf("%d",&num);
    struct node* newnode=(struct node*)malloc(sizeof(struct node));
    newnode->data=num;

    if(*head==NULL){
        newnode->next=newnode;
        newnode->prev=newnode;

        *head=newnode;
    }
    else{

        newnode->next=*head;
        newnode->prev=(*head)->prev;

        //to make the previously first node point to the new first node
        newnode->next->prev=newnode;
        //to make the last node point to the new first node
        (*head)->prev->next=newnode;
        *head=newnode;

    }
 }
}

当我执行它时,它没有显示任何输出但是当我改变时

//to make the last node point to the new first node
            (*head)->prev->next=newnode;

这一行到

newnode->prev->next=newnode;

代码正在运行。 我无法理解这两种说法有什么区别。

【问题讨论】:

  • @virolino *head 非常有意义,因为这意味着 head 的更新值被传递给调用函数
  • @ChrisTurner:头脑风暴——*head 只有在 head 被定义为 struct node** head 之类的东西时才有意义——这太过分了。
  • @virolino 无需猜测 - 传入指向某事物的指针允许您对其进行更新,因为 C 仅通过值传递,并且是编写此类函数的两种方法之一
  • 张贴struct的声明,这一切都是基于。 (真的应该是minimal reproducible example以便更多的理解。)
  • 这并没有解决核心问题,但因为这是C(而不是C++),所以声明:struct node* newnode=(struct node*)malloc(sizeof(struct node)); 将正确地写为struct node* newnode=malloc(sizeof(* newnode));。即it is not necessary or optimal to cast the return of malloc() in C.

标签: c circular-list


【解决方案1】:
(*head)->prev->next=newnode;
...
newnode->prev->next=newnode;

我无法理解这两种说法有什么区别。

newnode->prev 已正确设置为 head 之前的节点。相比之下,此时的(*head)->prev 已经被newnode->next->prev=newnode 更改,因为newnode->next=*head。因此(*head)->prev 不再指向head 之前的节点,而是指向新节点。这就是区别。

【讨论】:

  • 感谢您的帮助,我现在明白问题所在了!
【解决方案2】:

下一个代码假定head 定义为:struct node* head;。我刚刚删除了一些额外的取消引用运算符(*)。

它不能直接测试,因为没有提供最低限度的可重现示例。

 while(n-- >0){
    int num;
    //to input the data for the linked list
    scanf("%d",&num);
    struct node* newnode=(struct node*)malloc(sizeof(struct node));
    newnode->data=num;

    if(head==NULL){              /*   was: if(*head==NULL){   */
        newnode->next=newnode;
        newnode->prev=newnode;

        head=newnode;{              /*   was: *head=newnode;{   */
    }
    else{

        newnode->next=head;              /*   was: newnode->next=*head;   */
        newnode->prev=(*head)->prev;

        //to make the previously first node point to the new first node
        newnode->next->prev=newnode;
        //to make the last node point to the new first node
        (*head)->prev->next=newnode;
        head=newnode;              /*   was: *head=newnode;   */
    }
 }

【讨论】:

  • 我已经编辑了我的问题,因为不清楚 *head 是关于什么的。
  • 无论哪种方式,您的原始代码都是错误的。这两行newnode->next=*head;newnode->prev=(*head)->prev; 不能同时导致想要的结果。
  • 能否请您再次查看并帮助我理解我的问题。
  • 您能详细说明一下吗?
  • 我的直觉是,在处理双链循环列表之前,您需要更好地理解指针和结构(以及指向结构的指针)。我有这种预感是因为要我详细说明。对这些(复杂的)特性有了很好的理解,就没有必要进行详细说明了。所以我最好的建议是:回到你的 C 手册中的早期课程,更好地学习这些主题。也许也使用其他手册。当您无需详细说明就可以自己理解这个答案时,您可以说您实际上(开始)理解事物。
【解决方案3】:

当列表在添加新节点之前包含单个节点时,原始代码会出错。让我们将该节点称为A 以供参考。在插入新节点之前,情况如下:

/* List with single node. */
(*head) = &A;
A.next = &A;
A.prev = &A;

我们调用newnode指向的节点B

newnode = &B;

添加newnode的代码目前如下(添加了cmets//>):

    newnode->next=*head;         //> B.next=&A;
    newnode->prev=(*head)->prev; //> B.prev=&A;

    //to make the previously first node point to the new first node
    newnode->next->prev=newnode; //> A.prev=&B;
    //to make the last node point to the new first node
    (*head)->prev->next=newnode; //> B.next=&B; !!! want A.next = &B;
    *head=newnode;

上述代码序列后的情况:

(*head) = &B;
B.next = &B; // !!! want B.next = &A;
B.prev = &A;
A.next = &A; // !!! want A.next = &B;
A.prev = &B;

列表已损坏,因为更改了错误的链接指针。它可以通过使用临时变量lastnode 设置为(*head)->prev 的旧值来修复。更新后的代码如下:

    struct node *lastnode;
    lastnode=(*head)->prev;      //> lastnode=&A;
    newnode->next=*head;         //> B.next=&A;
    newnode->prev=lastnode;      //> B.prev=&A;

    //to make the previously first node point to the new first node
    newnode->next->prev=newnode; //> A.prev=&B;
    //to make the last node point to the new first node
    lastnode->next=newnode;      //> A.next=&B;
    *head=newnode;

代码序列更新后的情况:

(*head) = &B;
B.next = &A;
B.prev = &A;
A.next = &B;
A.prev = &B;

【讨论】:

  • 感谢您更详细的解释!
猜你喜欢
  • 2021-06-28
  • 1970-01-01
  • 2012-09-22
  • 1970-01-01
  • 1970-01-01
  • 2020-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多