C 指向指针的指针-链表混乱
我正在编写一个简单的C程序来管理一个链表,定义如下:C 指向指针的指针-链表混乱,c,pointers,linked-list,C,Pointers,Linked List,我正在编写一个简单的C程序来管理一个链表,定义如下: typedef struct node { int value; struct node *next; } *List; 我检查了代码,看起来还可以,但是当打印结果时,有些地方工作不好 我的主要观点是,在评论方面存在问题: int main(void) { List n = list_create(1); insert(n, 2); insert(n, 3); insert(n, 5);
typedef struct node {
int value;
struct node *next;
} *List;
我检查了代码,看起来还可以,但是当打印结果时,有些地方工作不好
我的主要观点是,在评论方面存在问题:
int main(void) {
List n = list_create(1);
insert(n, 2);
insert(n, 3);
insert(n, 5);
insert(n, 4);
//something here does not work properly. It produces the following output:
//Value: 1
//Value: 2
//Value: 3
//Value: 4
//where is value 5?
print_list(n);
delete(n, 3);
print_list(n);
return 0;
}
我不知道我在哪里破坏列表结构。如果你太客气的话,这些是我要调试的函数
List list_create(int value) {
List new = malloc(sizeof(struct node));
new->value = value;
new->next = NULL;
return new;
}
List new_node(int value, List next_node) {
List new = malloc(sizeof(struct node));
new->value = value;
new->next = next_node;
return new;
}
void print_list(List l) {
List *aux;
for (aux = &l; (*aux) != NULL; aux = &((*aux)->next))
printf("Valor: %d\n", (*aux)->value);
}
void insert(List l, int value) {
List *p;
for (p = &l; (*p) != NULL; p = &((*p)->next))
if ((*p)->value > value) {
List tmp = *p;
List new = new_node(value, tmp);
*p = new;
break;
}
*p = new_node(value, NULL);
}
void delete(List l, int value) {
List *p;
for (p = &l; (*p) != NULL; p = &((*p)->next))
if ((*p)->value == value) {
List del = (*p);
(*p) = ((*p)->next);
free(del);
break;
}
}
此代码(至少)有两个错误:
void insert(List l, int value)
{
List p;
// Find end of list or highest item less than value
for(p = l; p->next != NULL && p->next->value < value; p = p->next);
if (p->value >= value) {
// Over-write p with new value, and insert p as a new one after.
// This saves having to modify l itself.
int tmpval = p->value;
p->value = value;
p->next = new_node(tmpval, p->next);
} else {
// Insert new item after p
p->next = new_node(value, p->next);
}
}
通常,最好不要通过在typedef中包含“*”来“隐藏”指针类似指针的性质。
例如,如果您这样定义列表:
void print_list(List l){
List aux;
for(aux = l; aux != NULL; aux = aux->next)
printf("Valor: %d\n", aux->value);
}
typedef struct node{
int value;
struct node *next;
} List
my_func(List *l, ...)
并将其传递给如下函数:
void print_list(List l){
List aux;
for(aux = l; aux != NULL; aux = aux->next)
printf("Valor: %d\n", aux->value);
}
typedef struct node{
int value;
struct node *next;
} List
my_func(List *l, ...)
然后,它会使其中一些问题变得更加明显。希望这能有所帮助。您的代码中有许多问题:
- 在typedef后面隐藏指针是一个坏主意,它会导致程序员和读者的混淆
- 您必须确定初始节点是虚拟节点,还是空列表只是一个
指针。后者更易于处理,但必须将头节点的地址传递给NULL
和insert
,以便它们可以更改头节点delete
不需要间接指针,尤其是从作为参数传递的指针的地址开始。直接使用节点指针可以简化printlist
- 在
中,您可以在下一个更高的节点之前正确插入新节点,但随后应该从函数返回。相反,您中断开关并执行追加代码,将插入的节点替换为具有相同值和空下一个指针的新节点。这就是insert
获取remove的原因插入5
时会丢失和丢失。此外,应传递头节点的地址,以便在第一个节点之前插入节点4
从参数的地址开始。它无法删除头节点,因为调用方空间中的指针没有更新。您应该传递头节点的地址delete
<> L> > P>避免C代码中使用C++代码,如<代码>新< /C> >代码>删除>代码:虽然不违法,但它混淆了C++中的读者,混淆了语法高亮,阻止了C++编译器的编译。
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int value;
struct Node *next;
} Node;
Node *new_node(int value, Node *next_node) {
Node *node = malloc(sizeof(*node));
if (node != NULL) {
node->value = value;
node->next = next_node;
}
return node;
}
void print_list(Node *list) {
for (; list != NULL; list = list->next)
printf("Valor: %d\n", list->value);
}
void insert_node(Node **p, int value) {
while ((*p) != NULL && (*p)->value < value)
p = &(*p)->next;
*p = new_node(value, *p);
}
void delete_node(Node **p, int value) {
while (*p != NULL) {
if ((*p)->value == value) {
Node *found = *p;
*p = (*p)->next;
free(found);
// return unless delete() is supposed to remove all occurrences
return;
} else {
p = &(*p)->next;
}
}
}
int main(void) {
Node *n = NULL;
insert_node(&n, 2);
insert_node(&n, 3);
insert_node(&n, 5);
insert_node(&n, 4);
insert_node(&n, 1);
print_list(n);
delete_node(&n, 3);
print_list(n);
delete_node(&n, 1);
print_list(n);
return 0;
}
#包括
#包括
类型定义结构节点{
int值;
结构节点*下一步;
}节点;
节点*新节点(int值,节点*下一个节点){
Node*Node=malloc(sizeof(*Node));
如果(节点!=NULL){
节点->值=值;
节点->下一个=下一个节点;
}
返回节点;
}
作废打印列表(节点*列表){
对于(;list!=NULL;list=list->next)
printf(“值:%d\n”,列表->值);
}
void insert_节点(节点**p,int值){
而((*p)!=NULL&(*p)->value下一步;
*p=新节点(值,*p);
}
void delete_节点(节点**p,int值){
while(*p!=NULL){
如果((*p)->value==value){
Node*found=*p;
*p=(*p)->下一步;
自由(找到);
//除非delete()应该删除所有出现的内容,否则返回
返回;
}否则{
p=&(*p)->下一步;
}
}
}
内部主(空){
Node*n=NULL;
插入_节点(&n,2);
插入_节点(&n,3);
插入_节点(&n,5);
插入_节点(&n,4);
插入_节点(&n,1);
打印列表(n);
删除_节点(&n,3);
打印列表(n);
删除_节点(&n,1);
打印列表(n);
返回0;
}
孩子们,这就是为什么你不使用typedef
指针来隐藏指针的原因。你是否尝试过使用调试器?注意,你的列表界面不能捕获所有用例。我建议重写你的程序,使其支持空列表用例。它应该创建一个空列表,而不是一个单元素列表,并且应该能够要处理插入到空列表中的操作,请将元素作为列表的第一个元素插入,并删除列表的第一个/唯一元素。insert
和delete
的签名必须更改才能完成此操作。在insert
函数中,您可以将新元素与下一个元素正确链接,但是忘记在链中插入新元素。实际上我认为*p=new;
应该是类似(*p)的东西->next=new;
@EOFtypedef
ing指针没有什么特别的错误。此代码中存在的错误与此无关。假设您从typedef
中删除星号,并将List
替换为List*
无处不在。现在呢?有什么实现了吗?对于您的删除问题,yo不将下一个元素与上一个元素链接:将其与当前元素重新链接。因此,当删除当前元素时,您只会丢失列表的结尾。如果在插入()
中(p->value>=value),为什么要对进行特殊处理