[英]Inserting an element to the end of the doubly-linked list
我正在编写一个程序,该程序可以将元素插入列表的末尾,并显示其中之一。 它可以正确插入,但是我可以显示指定的一个。
typedef struct Node
{
int data;
struct Node *next;
struct Node *prev;
} node;
void insert(node *head, int data)
{
node *newNode = (node*) malloc(sizeof(node));
newNode->data = data;
newNode->next = NULL;
if(head == NULL)
{
head = newNode;
}
else
{
while(head != NULL)
head = head->next;
head->next = newNode;
(head->next)->prev = head;
}
}
void print(node *head, int element)
{
node *temp = head;
int count = 0, i = 1;
while(i < element)
{
temp = temp->next;
i++;
}
printf("%d", temp->data);
}
int main()
{
node *start = (node*) malloc(sizeof(node));
start = NULL;
int data1 = 4, data2 = 5;
insert(start,data1);
insert(start,data2);
print(start, 1);
}
为什么不起作用? 另外,您能告诉我我是否做得正确吗?
这是因为您通过value传递了start
指针。 这意味着insert
函数内部对其所做的任何更改都将在该函数返回后丢失。
您可以通过引用传递指针:
void insert(node **head, int data)
{
/* ... */
if (*head == NULL)
*head = newNode;
else
{
/* ... */
}
}
int main(void)
{
node *start = NULL;
insert(&start, 1);
/* ... */
}
或从函数返回指针:
node *insert(node *head, int data)
{
/* ... */
return head;
}
int main(void)
{
node *start = NULL;
start = insert(start, 1);
insert(start, 2); /* Do not get the returned pointer, as the returned pointer no longer points to the start of the list */
/* ... */
}
这两个解决方案的问题在于,如果head
NULL
不是NULL
,则将其更改为指向最后一个节点之前的节点。 在insert
循环中,您应该使用临时指针。
为安全起见,应检查print
功能循环中是否没有NULL
节点。 考虑如果传递的数字大于列表中节点的数目,将会发生什么情况。
编辑:我跳过了几行。
请在与您的main()
代码段内联的地方查看我的修订注释:
node *start = (node*) malloc(sizeof(node));//You allocate memory here. Good.
start = NULL;//Memory leak.
//Instead of the above two lines use this
node* start=NULL;
int data1 = 4, data2 = 5;
start=insert(start,data1);//If you want to do it statically, why not write insert(start,4)?
insert(start,data2);
....
我建议在print()
函数中添加一个NULL检查。
void print(node *head, int element)
{
//Null check for the start pointer.
//If you would have had this here, you'd have never faced such problem.
if(head == NULL)
{
//Handle null
}
node *temp = head;
int count = 0, i = 1;
....
}
加上您的insert()
我建议:
node* insert(node *head, int data)
{
node *newNode = (node*) malloc(sizeof(node));
newNode->data = data;
newNode->next = NULL;
if(head == NULL)
{
head = newNode;
return head;
}
else
{
while(head != NULL)
head = head->next;
head->next = newNode;
(head->next)->prev = head;
return NULL;
}
}
希望能帮助到你。
有一个技巧可以使事情变得简单得多,并使您的代码更高效!
诀窍是使用循环列表,并使“ head”节点成为前哨值。 空列表是由既具有单个节点表示prev
和next
指向其自身。 您永远不需要NULL,并且这种样式大大减少了所需的特殊外壳。 它还使您可以O(1)访问列表的开头和结尾。 磁头的data
字段从不使用。 在Knuth的“计算机编程艺术”中对此进行了描述。
通过这种样式,您会得到如下所示:[unested]
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node *next, *prev;
} node;
void insert_list(node *head, int data) {
node d = {data, head, head->prev};
node *new_node = malloc(sizeof(node));
/* TODO: handle malloc failure */
*new_node = d;
head->prev->next = new_node;
head->prev = new_node;
}
node *get_list(node *head, int n) {
node *node = head;
int i;
for (i = 0; i <= n; i++) {
node = node->next;
if (node == head) {
/* TODO: handle out-of-bounds index */
}
}
return node;
}
void print_list(node *head, int i) {
printf("%d\n", get_list(head, i)->data);
}
node *new_list(void) {
node *head = malloc(sizeof(node));
/* TODO: handle malloc failure */
head->next = head->prev = head;
return head;
}
int main(int argc, char**argv) {
node *list = new_list();
insert_list(list, 10);
insert_list(list, 20);
print_list(list, 0);
print_list(list, 1);
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.