我的项目遇到了一个问题,起初我制作了一个链表,它工作正常,但后来我不得不编辑它,使其成为一个链表数组,但它只是以错误的方式存储,我想,这是我的代码,它出了什么问题?
#include <stdio.h>
#include <stdlib.h>
struct node
{
int coeff;
int power;
struct node* Next;
};
void Insert(int X,int Y, struct node* L, struct node* P)
{
struct node* temp;
temp = (struct node*)malloc(sizeof(struct node));
temp->coeff = X;
temp->power = Y;
temp->Next = P->Next;
P->Next = temp;
}
void PrintList(struct node* L)
{
struct node* P = L;
printf("%d %d ",P->coeff,P->power);
printf("n");
P=P->Next;
}
int main()
{
struct node* head[3] ;
for(int q =0 ; q!= 3 ; q++)
{
head[q] = malloc(sizeof(struct node));
}
Insert(1,2,head[0],&head[0]);
Insert(2,3,head[0],&head[0]);
Insert(1,2,head[1],&head[1]);
Insert(2,2,head[1],&head[1]);
for(int i=0 ;i!=3;i++){
PrintList(head[i]);
}
return 0;
}
在LinkedList中只有一个头。您已经分配了3个不同的头,并且正在尝试向这些头添加节点。因此,下面的答案假设您打算有3个不同的LinkedLists,每个列表的头都在一个数组中。
此行中来自malloc()
的内存
head[q] = malloc(sizeof(struct node));
未初始化。在这里,使用calloc()
显得更加谨慎。所以,
head[q] = calloc(sizeof(struct node), 1); //Initialize everything to 0
接下来,Insert()
中的一个参数是多余的,并且也不符合调用代码。它是的标志
void Insert(int ,int , struct node* , struct node*)
但是你用调用它
void Insert(int ,int , struct node* , struct node**)
我想,在这种情况下,删除最后一个参数应该是可以的,因为您不是在修改传入的struct node*
指针,而是在修改其内容。如果您将struct node*
更改为指向Insert()
函数中的其他内容(例如P = temp;
等(,那么传入struct node**
将更有意义。因此,将您的代码更改为
void Insert(int X,int Y, struct node* P)
{
struct node* temp;
temp = (struct node*)malloc(sizeof(struct node));
temp->coeff = X;
temp->power = Y;
temp->Next = P->Next;
P->Next = temp;
}
以及的调用代码
Insert(2,3,head[0]);
Insert(1,2,head[0]);
Insert(1,2,head[1]);
Insert(2,2,head[1]);
接下来,将PrintList
更改为实际遍历LinkedList:
void PrintList(struct node* L)
{
struct node* P = L;
while(P) {
printf("%d %dn",P->coeff,P->power);
P=P->Next;
}
}
除此之外,我只是添加了一些日志记录,以更好地澄清正在打印的LinkedList。
for(int i=0 ;i!=3;i++){
printf("Printing list %d:n", i);
PrintList(head[i]);
printf("*****n");
}
这给出了输出:
Printing list 0:
0 0
1 2
2 3
*****
Printing list 1:
0 0
2 2
1 2
*****
Printing list 2:
0 0
*****
显然,LinkedLists的所有head
都是0初始化的,因此显示为0 0
。根据程序的期望,它们可以被初始化为合适的,也可以完全从PrintList()
函数中删除。
在处理C项目时,应始终启用编译器警告。如果你这样做,编译器将发出类似的警告
warning: passing argument 4 of ‘Insert’ from incompatible pointer type [-Wincompatible-pointer-types]
这只是代码中的第一个问题。在主函数中分配的节点中也有未初始化的字段。
与其有一个修改列表的函数,不如定义一个向列表添加新节点并返回新列表的函数。下面是另一种方法,它还使用方便的宏函数来分配内存和计算数组的长度。该代码还将指针隐藏在类型定义后面,并定义一个释放列表的函数。
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN(array) ((int) (sizeof (array) / sizeof (array)[0]))
#define NEW_ARRAY(pointer, length)
{
(pointer) = malloc(((size_t) length) * sizeof (pointer)[0]);
if ((pointer) == NULL) {
fprintf(stderr, "Allocating memory with malloc failed: %sn", strerror(errno));
exit(EXIT_FAILURE);
}
}
#define NEW(pointer) NEW_ARRAY((pointer), 1)
typedef struct node *List;
struct node {
int coeff;
int power;
struct node *next;
};
List NewList(int coeff, int power, List next)
{
List node;
NEW(node);
node->coeff = coeff;
node->power = power;
node->next = next;
return node;
}
void FreeList(List list)
{
if (list != NULL) {
FreeList(list->next);
free(list);
}
}
void PrintList(List list)
{
while (list != NULL) {
printf("%d %dn", list->coeff, list->power);
list = list->next;
}
}
int main(void)
{
List head[3] ;
head[0] = NewList(1, 2, NewList(2, 3, NULL));
head[1] = NewList(1, 2, NewList(2, 2, NULL));
head[2] = NULL;
for (int i = 0; i < LEN(head); i++) {
PrintList(head[i]);
FreeList(head[i]);
}
return 0;
}