我需要编写一个返回链表大小的函数。这看起来很简单,但是当我试图推进我的指针时,我得到一个例外。 这是代码:
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");
}
答案 0 :(得分:3)
问题在于您没有显示的代码,因为您提供的所有代码都很好(*)。
我可以使用你的结构和函数:
这里是完整的代码:
#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))就足够了。在修复这些错误后,几个错误变得明显:
真正的问题似乎是合并。您应该将列表合并到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);
}