链表中抛出异常

时间:2014-12-27 14:49:51

标签: c

我需要编写一个返回链表大小的函数。这看起来很简单,但是当我试图推进我的指针时,我得到一个例外。 这是代码:

int List_size(List *list)
{
    List_node *p;
    int counter = 0;
    p = list->head;

    while (p != NULL)
    {
        p = p->next;
        counter = counter + 1;
    }
    return counter;
}

这是定义链表的代码:

typedef struct List_node
{
    int data;
    struct List_node *next;
    struct List_node *prev;
}List_node;

typedef struct List
{
    List_node *head;
}List;

这是创建列表的代码:

List *create_list(int n)
{
    List *list = (List*) calloc(n,sizeof(List));
    list->head = NULL;
    return list;
}

最后,我使用这两个函数将数据(数字)插入到列表中:(所以不要认为列表是空的)。

void insert_first(List_node *x, List *list)
{
    x->next = list->head;
    list->head = x;
}

void insert(List_node *x, List_node *y)
{
    x->next = y->next;
    y->next = x;
}

List_node *mk_node(int data, int n) 
{
    List_node *node = (List_node *)calloc(n, sizeof(List_node));
    node->data = data;
    return node;
}

使用断点我发现问题出在p = p->接下来,但我不明白为什么。

非常感谢。

编辑 - 我认为没有必要使用完整的代码,但这里是:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include "List.h"

void merge(List *small_list, List *big_list)
{
    List_node *x, *y;
    y = small_list->head;
    x = big_list->head;
    t = x->prev;

//  while (y < x) //If there are smaller numbers on the small list, insert them first
//  {
//      insert(y,t)
//      t = t->next;
//      y = y->next;
//  }

    while (y != NULL && x->next != NULL)
    {
        if (x <= y && x->next >= y)
        {
            insert(y, x);
            y = y->next;
        }
        else
            x = x->next;
    }
    while (y != NULL)
    {
        insert(y, x);
        y = y->next;
    }
}

void main()
{
    List *L1, *L2, *big_list, *small_list;
    int num1, num2;
    int i;
    int a, b;

    create_list(5,&L1);
    create_list(3,&L2);

    printf("Insert first number into L1\n");
    scanf("%d", &num1);
    node = mk_node(0,5);
    insert_first(node, &L1);
    for (i = 0; i<5; i++) 
    {
        printf("Now insert the rest of the numbers\n");
        scanf("%d", &num1);
        next = mk_node(&num1,5);
        insert(next, node);
        node = next;
    }

    printf("Insert first number into L2\n");
    scanf("%d", &num2);
    node = mk_node(0,3);
    insert_first(node, &L2);
    for (i = 0; i<3; i++)
    {
        printf("Now insert the rest of the numbers\n");
        scanf("%d", &num2);
        next = mk_node(&num2,3);
        insert(next, node);
        node = next;
    }

//If lists are in descending order, reverse them to ascending order
        //if (L1->head > L1->head->next)
   //       reverse(L1);
    //  if (L2->head > L2->head->next)
        //  reverse(L2);

    int size_L1 = List_size(L1);
    int size_L2 = List_size(L2);

    if (size_L1 <= size_L2)
    {
        big_list = L2;
        small_list = L1;
    }
    else
    {
        big_list = L1;
        small_list = L2;
    }

    merge(small_list, big_list);

    print_list(L3);
    getchar(); getchar();
}

如您所见,我使用函数insert()插入数字。我希望没关系。

反向函数是:(我真的希望它有效,我从伪代码翻译它)

List reverse(List *list)
{
    List_node *x, *y, *z;
    if (list->head == NULL || list->head->next == NULL)
    {
        return *list;
    }
    x = list->head;
    y = list->head->next;
    z = list->head->next->next;
    x->next = NULL;
    while (z != NULL)
    {
        y->next = x;
        x = y;
        y = z;
        z = z->next;
    }
    y->next = x;
    list->head = y;
}

基本上,这是一个分配,说我有两个双向排序链接列表,我应该将它们合并到一个大的排序链表中。

异常 - Lists.exe中0x00E21766处的未处理异常:0xC0000005:访问冲突读取位置0xCCCCCCD0。

编辑 - print_list函数:

void print_list(List *list)
{
    List_node *p;
    p = list->head;
    printf("The linked list consists of: ");
    while (p != NULL)
    {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

3 个答案:

答案 0 :(得分:3)

问题在于您没有显示的代码,因为您提供的所有代码都很好(*)。

我可以使用你的结构和函数:

  • 创建一个列表
  • 添加第一个节点(使用insert_first)
  • 添加其他节点(带插入)
  • 获取大小(使用List_size)
  • 显示每个节点的数据值
  • 释放节点和列表

这里是完整的代码:

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

typedef struct List_node
{
    int data;
    struct List_node *next;
    struct List_node *prev;
}List_node;

typedef struct List
{
    List_node *head;
}List;

List *create_list()
{
    List *list = (List*) malloc(sizeof(List));
    list->head = NULL;
    return list;
}

int List_size(List *list)
{
    List_node *p;
    int counter = 0;
    p = list->head;

    while (p != NULL)
    {
        p = p->next;
        counter = counter + 1;
    }
    return counter;
}

void insert_first(List_node *x, List *list)
{
    x->next = list->head;
    list->head = x;
}

void insert(List_node *x, List_node *y)
{
    x->next = y->next;
    y->next = x;
}

/* my own additions */
List_node *mk_node(int data) {
    List_node *node = (List_node *) malloc(sizeof(List_node));
    node->data = data;
    return node;
}

void delete_list(List *list) {
    List_node *node = list->head;
    while (node != NULL) {
        List_node *next = node ->next;
        free(node);
        node = next;
    }
    free(list);
}

int main() {
    List* list = create_list();
    List_node *node, *next;
    int i;

    node = mk_node(0);
    insert_first(node, list);
    for (i=1; i<5; i++) {
        next = mk_node(i);
        insert(next, node);
        node = next;
    }

    int n = List_size(list);
    printf("size : %d\n", n);

    node = list->head;
    while (node != NULL) {
        printf("node val : %d\n", node->data);
        node = node->next;
    }
    delete_list(list);
    return 0;
}

(*)您的代码并不完美,因为List_node struct包含一个从未使用的指针prev,因此您以单链表结束,每三个值都未使用。

答案 1 :(得分:1)

所以问题是你分配列表头,但从不为列表元素分配内存。 Serge添加了mk_node进行分配(所以Serge解决了它。)

答案 2 :(得分:1)

我在上面添加了一条注释,我将您的代码复制到我的编译器中并且它没有编译,因此它不会运行:对create_list的调用不会编译:它们返回一个值作为函数返回,而不是参数;有未声明的变量。此外,给create_list和mk_node一个参数是没用的:它们将分配一个数组,而不是创建一个列表元素。调用calloc(1,sizeof(your_thing))就足够了。在修复这些错误后,几个错误变得明显:

  • in insert_first(node,&amp; L2);你给它列表的地址,这已经是一个指针。删除&#39;&amp;&#39; (编译器应该抱怨!)。
  • 与List_size(&amp; L1)相同; L1已经是一个指针。删除&#39;&amp;&#39;。
  • in:if(x&lt; = y ...)比较内存地址。更改为:if(x-&gt; data&lt; = y-&gt; data ...)
  • 在该陈述中,部分&#34; x-&gt; next&gt; = y&#34;还比较了内存​​地址,我不知道为什么需要它。我删除了它。

真正的问题似乎是合并。您应该将列表合并到L1或L2中,最好是创建结果列表。但你随机地&#34;将一个元素插入L1,然后插入L2,然后再插入L1,等等。在我的测试中它无限期地运行。以下合并工作正常:

List *merge(List *small_list, List *big_list)
{
    List_node *x, *y, *r;
    List *result= create_list();
    y = small_list->head;
    x = big_list->head;

    if (x->data < y->data)
         {result->head= x; x= x->next;}
    else {result->head= y; y= y->next;}
    r= result->head;

    while (y != NULL && x != NULL)
    {
        if (x->data < y->data)
        {
            r->next= x;
            x = x->next;
        }
        else {
            r->next= y;
            y = y->next;
        }
        r= r->next;
    }
    while (y != NULL)
    {
        r->next= y;
        y = y->next;
        r= r->next;
    }
    while (x != NULL)
    {
        r->next= x;
        x = x->next;
        r= r->next;
    }
    r->next= 0;
    return (result);
}