0

我正在编写一个程序,它可以将元素插入到列表的末尾,然后显示其中一个。它插入正确,但我可以显示指定的。

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);
}

为什么它不起作用?另外,你能告诉我我这样做是否正确吗?

4

3 回答 3

1

这是因为您通过valuestart传递指针。这意味着一旦函数返回,函数内部对其进行的任何更改都将丢失。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,则更改为指向最后一个节点之前的节点。在里面的循环中,insert您应该使用临时指针。


作为安全预防措施,您应该检查在函数NULL的循环中没有节点。print考虑一下如果传递的数字大于列表中的节点数会发生什么。

于 2013-01-19T17:08:55.037 回答
0

编辑:我跳过了几行。

请在您的代码片段中查看我修改后的评论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;
        }
}

希望能帮助到你。

于 2013-01-19T17:15:55.347 回答
0

有一个技巧可以让事情变得更容易,也让你的代码更有效率!

诀窍是使用循环列表,并让“头”节点成为哨兵值。一个空列表由一个节点表示,该节点既具有prevnext指向自身。你永远不需要 NULL,这种风格大大减少了你需要的特殊情况。它还使您可以 O(1) 访问列表的头部和尾部。头部data区域从未使用过。它在 Knuth 的“计算机编程艺术”中有所描述。

在这种风格中,你会得到这样的东西:[未经测试]

#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;
}
于 2013-01-19T18:38:33.077 回答