我正在编写一个简单的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);
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;
}
}
答案 0 :(得分:2)
此代码(至少)有两个错误:
该行
if((* p) - > value> value){
意味着如果你以1作为第一个值开始列表,然后尝试插入2,3,4 ......,'if'语句的主体永远不会运行,所以什么都没有插入。
尝试使用插入功能:
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);
}
}
评论:您使用指针的方式可能无助于调试过程。
例如,您的print_list()可以像这样重写:
void print_list(List l){
List aux;
for(aux = l; aux != NULL; aux = aux->next)
printf("Valor: %d\n", aux->value);
}
并且仍然表现相同。通常,不要通过在typedef中包含'*'来“隐藏”指针的类似指针的性质。 例如,如果您按以下方式定义列表:
typedef struct node{
int value;
struct node *next;
} List
并将其传递给这样的函数:
my_func(List *l, ...)
然后它会使这些问题更加明显。希望这会有所帮助。
答案 1 :(得分:1)
您的代码中存在许多问题:
隐藏typedef背后的指针是一个坏主意,它会给程序员和读者带来困惑。
您必须确定初始节点是否为虚拟节点,或者空列表是否只是NULL
指针。后者更易于处理,但您必须将头节点的地址传递给insert
和delete
,以便他们可以更改头节点。
printlist
不需要间接指针,尤其是从作为参数传递的指针的地址开始。通过直接使用Node指针简化。
在insert
中您正确地在下一个更高节点之前插入新节点,但您应该从该函数返回。相反,您将跳出开关并执行附加代码,将具有相同值的新节点替换为插入节点,并使用NULL下一个指针。这是5
插入4
时被移除和丢失的原因。此外,您应该传递头节点的地址,以便可以在第一个节点之前插入节点。
delete
从参数的地址开始。它无法删除头节点,因为调用者空间中的指针不会更新。您应该传递头节点的地址。
你应该避免在C代码中使用new
和delete
之类的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;
}