链接列表遍历跳过第一个元素

时间:2016-12-31 02:48:46

标签: c data-structures linked-list singly-linked-list

我有一个C程序在链表的开头插入元素,但是当我尝试打印元素时,它总是跳过第一个元素。有人可以指出我在我的计划中做错了什么。

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>


void PrintElements();
void InsertElement(int x);

struct node
{
    int data;
    struct node* next;
};

struct node* HEAD;
struct node* temp;
struct node* temp1;


void PrintElements()
{
    temp1=HEAD;
    while(temp1->next!=NULL)
    {
        printf("\n\r Data %d\n\r",temp1->data);
        printf("\n\r Address %x\n\r",temp1->next);
        temp1=temp1->next;
    }
}

void InsertElement(int x)
{
    struct node* temp=(struct node*)malloc(sizeof(struct node));
    temp->data=x;
    temp->next=HEAD;
    HEAD=temp;

}

int main()
{

    int i, x;
    int n;   //n stores the number of elements to be added to the linked list
    HEAD=NULL; //Assigning HEAD to null when there are no elements in the list
    printf("Enter the number of elements\n");
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        printf("\n\rEnter the number");
        scanf("%d",&x);
        InsertElement(x);
        PrintElements();
    }

    return 0;
}

当我更改以下行

while(temp1->next!=NULL)

while(temp1!=NULL)

程序正常运行但我仍然无法理解原因。

2 个答案:

答案 0 :(得分:3)

while(temp1->next!=NULL)

将此更改为

while(temp1 != NULL)

它应该可以正常工作。

原因:我认为它不会打印您输入的第一个元素。

示例:输入:1 2 3

链接列表形成为:3 -> 2 -> 1 -> NULL 使用的表示法:每个数字都是data,箭头显示指针next

然后当你开始循环时,对于每次迭代:

  • temp1指向3

  • 的地址
  • temp1 -> next != NULL(正如temp1 -> next指向2的地址)

  • 打印3temp1现在指向2的地址

  • temp1 -> next != NULL(正如temp1 -> next指向1的地址)

  • 打印2temp1现在指向1的地址

  • temp1 -> next != NULL由于temp1指向1的地址且temp1 -> next为NULL,因此变为错误

所以我们永远不会进入循环来打印1

所以正确的方法是使用temp1 != NULL,因为这将消除上述错误。

答案 1 :(得分:1)

您可以通过将PrintElements()功能中的控制表达式更改为temp1 != NULL来解决您描述的问题。这样,如果temp1指向某个节点,则会打印datanext字段,并且循环将继续,直到没有更多节点为止。当迭代链表时,当您查看下一个节点以决定对当前节点执行的操作时,通常会出现混淆。但是这个代码还有其他问题。

首先,在struct中声明main()指针并将它们传递给函数会更好,而不是将它们声明为全局变量。您应该检查尽可能调用的函数的返回值。您应该检查scanf()以确保输入符合预期;这也提供了一种控制输入循环的方法,消除了用户在输入数据之前显式输入计数的需要。您还应检查调用malloc()返回的值以捕获分配错误。如果在下一行中取消引用temp,代码中的这种分配错误将导致未定义的行为。

对于free的每次调用,您应该free()所有内存分配,一个malloc()。当您在函数next中的列表中打印PrintElements()节点的地址时,将调用未定义的行为。要打印指针的值,您应该使用%p格式说明符,并且必须将指针强制转换为(void *)。最后,没有必要#include <malloc.h>; stdlib.h会照顾您的需求。

以下是修改后的代码版本,用于实现建议的更改。请注意,如果出现分配错误,会向stderr和程序exit打印一条消息。对malloc()的调用已经简化:没有理由在C中转换malloc()的结果,最好使用指定内存的指针的名称来代替给malloc()的参数中的显式类型。 new_node返回到调用函数,其中指向列表head的指针被重新分配以指向new_node

#include <stdio.h>
#include <stdlib.h>

struct node
{
    int data;
    struct node* next;
};

void print_elements(struct node *start);
struct node * insert_element(int x, struct node *head);


int main(void)
{
    struct node* head = NULL;
    struct node* curr = NULL;
    int x;

    /* Read data into linked list */
    printf("Enter the first integer (q to quit): ");
    while (scanf("%d", &x) == 1) {
        head = insert_element(x, head);
        print_elements(head);
        printf("Enter another integer (q to quit): ");
    }

    /* Free allocated memory */
    while (head) {
        curr = head;
        head = curr->next;
        free(curr);
    }

    return 0;
}

void print_elements(struct node *curr)
{
    while(curr) {
        printf("   Data: %d\n",curr->data);
        printf("Address: %p\n\n",(void *) curr->next);
        curr = curr->next;
    }
}

struct node * insert_element(int x, struct node *head)
{
    struct node *new_node = malloc(sizeof(*new_node));

    if (new_node == NULL) {
        fprintf(stderr, "Allocation error in function insert_element()\n");
        exit(EXIT_FAILURE);
    }

    new_node->data = x;
    new_node->next = head;

    return new_node;
}