在C中的链表实现中打印额外的0而不删除前面的节点
我的代码有两个独立的(尽管可能是连接的)问题,其中一个问题是,当我打印出链表时(无论我是将节点推到前面还是推到后面),它会在链表的开头额外打印一个0。我看到了一篇类似的文章,但是push方法的实现是不同的,因为它没有将head作为参数,所以我在main()方法中定义了head:在C中的链表实现中打印额外的0而不删除前面的节点,c,linked-list,singly-linked-list,C,Linked List,Singly Linked List,我的代码有两个独立的(尽管可能是连接的)问题,其中一个问题是,当我打印出链表时(无论我是将节点推到前面还是推到后面),它会在链表的开头额外打印一个0。我看到了一篇类似的文章,但是push方法的实现是不同的,因为它没有将head作为参数,所以我在main()方法中定义了head: struct node *head = NULL; 我的链表实例化如下所示 struct node *temp, *ptr; temp=(struct node*)malloc(sizeof(struct node))
struct node *head = NULL;
我的链表实例化如下所示
struct node *temp, *ptr;
temp=(struct node*)malloc(sizeof(struct node));
if(temp==NULL) {
exit(0);
}
temp->next=NULL;
if(head==NULL) {
head=temp;
} else {
ptr=head;
while(ptr->next!=NULL) {
ptr=ptr->next;
}
ptr->next=temp;
ptr->data=NULL;
}
我遇到的问题是,我不确定这个问题是在print方法、pushfront方法还是链表实例化中
有关守则如下:
case PUSH_FRONT: ; // push onto front of list
struct node *temp1;
temp1=(struct node*)malloc(sizeof(struct node));
if(temp1==NULL) {
break;
}
temp1->next=NULL;
temp1->data=val;
if(head==NULL) {
head=temp1;
} else {
temp1->next=head;
head=temp1;
}
break;
case POP_FRONT: ; // remove from front of list
// If list is empty, do nothing.
struct node *ptr2;
ptr2=(struct node *)malloc(sizeof(struct node));
if(ptr2==NULL) {
break;
}
if(head==NULL) {
break;
} else if(head->next==NULL) {
ptr2=head;
head=head->next;
free(ptr2);
}
break;
我的另一个问题(尽管我仍然相信这个问题在别处)是我的pop-front方法完全不起作用,我猜这与链表的初始实例化有关。有关守则如下:
case PUSH_FRONT: ; // push onto front of list
struct node *temp1;
temp1=(struct node*)malloc(sizeof(struct node));
if(temp1==NULL) {
break;
}
temp1->next=NULL;
temp1->data=val;
if(head==NULL) {
head=temp1;
} else {
temp1->next=head;
head=temp1;
}
break;
case POP_FRONT: ; // remove from front of list
// If list is empty, do nothing.
struct node *ptr2;
ptr2=(struct node *)malloc(sizeof(struct node));
if(ptr2==NULL) {
break;
}
if(head==NULL) {
break;
} else if(head->next==NULL) {
ptr2=head;
head=head->next;
free(ptr2);
}
break;
你应该发布有人可以下载和编译的代码。什么时候
需要数据文件或问题说明。代码片段是
不太好
通过查看标签PRINT\u list
我的想法是这样的
- 列表是节点的集合。在java中,列表甚至被称为集合。在C++列表中称为容器。当您为链表编写代码时,就像它是一个
节点一样,您将得到更多的工作和更少的结果
- 作为将节点用作列表的直接结果,在实例化代码中,这里有3个指针来管理列表:
、head
和temp
,这太多了。想象一下,如果有3个列表ptr
- 只指向一个方向的指针的列表更难编程,而且比指向下一个和上一个节点的指针的列表用处要小得多。如果是你的决定,你应该重新考虑。如果额外指针的空间不是问题,则很难证明不使用2个指针是合理的。想象一下一个库的列表,一条路径,一个播放列表,所有经典的例子:能够在两个方向上导航是非常困难的
- 使用switch()是不常见的。为什么不直接使用函数呢
ptr->data=NULL
我们可能认为数据
是一个指针,但在您编写的列表标签中
ptr4=head;
while(ptr4) {
printf("%d",ptr4->data);
printf(" ");
ptr4=ptr4->next;
}
printf("\n");
free(ptr4);
当您在printf()
中使用%d
时,数据只是一个int
。嗯,实例化中的NULL
是,嗯,一个零
而NULL就是您正在抱怨的0
这段代码似乎比它需要的要复杂得多,也很难阅读
让我展示另一种选择
关于宣言
您可以像这样编写节点结构
typedef struct _nd
{
int data;
struct _nd* next;
} node;
因此,您可以在声明中使用节点
,而不必一直重复struct
。另外,为typedef
设置约定也很有用,比如使用大写字母帮助提高可读性
正如我之前所说,列表是一组节点,它不是一个节点,而是一个节点,里面有一个指针,每个节点都有一个有效负载,一些数据,通常是一个指针。例如,考虑
列表结构的另一个示例
这里的列表是,list
。每个列表都有头
,尾
,大小
,限制
,甚至还有一个名称
。我将数据保存为int
,但不好:您真的希望它作为指针,可能是(void*)
为什么?因为通过这种方式,您可以在任何地方重用代码,而无需进行任何更改 如何使用这样的列表? 使用类似于这些可能的原型的函数
List* _create(const char*);
int _define_max(List* l, const unsigned);
List* _delete(List*);
int _empty(List*);
int _get_max(List*);
List* _insert_begin(int, List*);
List* _insert_end(int, List*);
int _insert_your_way(List*, int(*)(int,int));
int _print(List*);
int _print_your_way(List*, int(*)(int,int));
List* _remove(int, List*);
int _size(List*);
我将在下面发布一个运行示例,以便您可以测试或询问您需要的案例。但这是正常的。只有这两个功能不太常见,但更有用:
int _insert_your_way(List*, int(*F)(int,int));
int _print_your_way(List*, int(*F)(int,int));
这里您可以传递一个函数,如qsort()
函数中的函数,然后在该位置插入节点,使用函数F()比较节点。其效果是,只需为“打印”或“插入”函数提供不同的函数,就可以按任意顺序插入(或列出)节点,而不改变列表代码。C,那么,C++,每个人都这样做,所以我们也可以:< /P>
用于实例化此类列表的代码
您可能会发现,以这种方式编写代码更容易维护或阅读代码。而列表
作为一个容器更具表现力:关于列表的元数据包含在列表中。无需使用ptr
、head
、temp
、size
或悬挂在main()中的其他控件
要创建一个列表,您只需编写,如示例中所示
List* first = _create("The First List");
在节点处插入节点
正如我告诉你的,这只是一个玩具,一个例子。实际上,为了得到一个通用代码,您将使用void*。我在这里使用int
作为数据,正如您所做的那样。要在上面创建的列表中插入几个节点,只需编写
// insert 6,7,8,9,10 at the end
for(int i = 6; i<11; i+=1 ) _insert_end(i, first);
代码(几乎没有测试)
这不是问题,但是打印列表的代码不应该分配内存。删除调用malloc
的行和调用free
的行。内存分配没有做任何有用的事情,如果head
为空,它将泄漏内存。在POP\u FRONT
中,您泄漏内存。您要么不使用ptr2
,要么通过将head
分配给该指针来覆盖分配块的地址。在C语言中,不需要强制转换malloc的返回,这是不必要的。请参阅:虽然没有错误,但不鼓励使用全局变量(特别是使用通用名称行temp
和ptr
),请看一看,然后请不要发布代码片段,因为它们尚未经过测试,这表明您观察到的问题存在。f后
List* first = _create("The First List");
List* _insert_begin(int value, List* l)
{
if (l == NULL) return l; //no list
if ((l->limit > 0) && (l->size == l->limit)) return l; // full
// ok: create a node and stuff data in
Node* nd = (Node*)malloc(sizeof(Node));
nd->data = value; // data comes in
nd->next = l->head; // depois vem o que estava na frente
l->head = nd; // nd fim
l->size = l->size + 1;
// if it is the first node
if (l->size == 1)l->tail = nd;
return l;
};
// insert 6,7,8,9,10 at the end
for(int i = 6; i<11; i+=1 ) _insert_end(i, first);
int main(void)
{
List* first = _create("The First List");
_print(first);
_define_max(first,300);
_print(first);
// insert 5,4,3,2,1 at the beggining
for(int i = 5; i>0; i-=1 ) _insert_begin(i, first);
// list again
_print(first);
// insert 6,7,8,9,10 at the end
for(int i = 6; i<11; i+=1 ) _insert_end(i, first);
// list again
_print(first);
printf("empty(): %d size()= %d\n",
_empty(first),
_size(first) );
first = _delete(first);
_print(first);
return 0;
}
List 'The First List' with 0 elements [MAX not defined yet]
List 'The First List' with 0 of 300 MAX elements
List 'The First List' with 5 of 300 MAX elements
First: 1
Last: 5
Elements
1
2
3
4
5
End of list
List 'The First List' with 10 of 300 MAX elements
First: 1
Last: 10
Elements
1
2
3
4
5
6
7
8
9
10
End of list
empty(): 0 size()= 10
Deleting 'The First List'
List not created!
#include <memory.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct _nda
{
int data;
struct _nda* next;
} Node;
struct _the_list
{
char* name;
unsigned size;
unsigned limit;
Node* head;
Node* tail;
};
typedef struct _the_list List;
List* _create(const char*);
int _define_max(List* l, const unsigned);
List* _delete(List*);
int _empty(List*);
int _get_max(List*);
List* _insert_begin(int, List*);
List* _insert_end(int, List*);
int _insert_your_way(List*, int(*)(void*));
int _print(List*);
int _print_your_way(List*, int(*)(void*));
List* _remove(int, List*);
int _size(List*);
int main(void)
{
List* first = _create("The First List");
_print(first);
_define_max(first,300);
_print(first);
// insert 5,4,3,2,1 at the beggining
for(int i = 5; i>0; i-=1 ) _insert_begin(i, first);
// list again
_print(first);
// insert 6,7,8,9,10 at the end
for(int i = 6; i<11; i+=1 ) _insert_end(i, first);
// list again
_print(first);
printf("empty(): %d size()= %d\n",
_empty(first),
_size(first) );
first = _delete(first);
_print(first);
return 0;
}
List* _create(const char* name)
{
List* one = (List*)malloc(sizeof(List));
one->name = (char*)malloc(1 + strlen(name));
strcpy(one->name, name);
one->size = 0;
one->limit = 0;
one->head = NULL;
one->tail = NULL;
return one;
}; // criar()
int _define_max(List* l, const unsigned m)
{
if (l == NULL) return -1;
// new value can not be less than present size
if (l->size > m) return -2;
l->limit = m;
return m;
};
List* _delete(List* l)
{
if (l == NULL) return NULL;
printf("Deleting '%s'\n", l->name);
free(l->name);
if (l->size == 0)
{
free(l);
return NULL; // empty
}; // if()
Node* node = l->head;
do
{
Node* p = node->next;
free(node);
node = p;
} while (node != NULL);
return NULL;
};
int _empty(List* L)
{
if (L == NULL) return -1;
return (L->size == 0);
};
int _get_max(List* L)
{
if (L == NULL) return -1;
return (int)L->limit;
};
List* _insert_begin(int value, List* l)
{
if (l == NULL) return l; //no list
if ((l->limit > 0) && (l->size == l->limit)) return l; // full
// ok: create a node and stuff data in
Node* nd = (Node*)malloc(sizeof(Node));
nd->data = value; // data comes in
nd->next = l->head; // depois vem o que estava na frente
l->head = nd; // nd fim
l->size = l->size + 1;
// if it is the first node
if (l->size == 1)l->tail = nd;
return l;
};
List* _insert_end(int value, List* l)
{
if (l == NULL) return l;
if ((l->limit > 0) && (l->size == l->limit)) return l; // full
// ok: create a node and insert at the end
Node* nd = (Node*)malloc(sizeof(Node));
nd->data = value;
// first one?
if (l->size == 0)
{
l->head = nd;
nd->next = NULL;
}
else
{
nd->next = NULL; // no one after this
(l->tail)->next = nd;
}; // if()
l->tail = nd; // nd is tail now
l->size = l->size + 1;
// of this is the first node
if (l->size == 1)l->head = nd;
return l;
};
int _insert_your_way(List* L, int(*F)(void*))
{
return 0;
};
int _print(List* l)
{
if (l == NULL)
{
printf("List not created!\n");
return -1;
};
if (l->limit > 0)
{
printf("\nList '%s' with %d of %d MAX elements\n",
l->name,
l->size,
l->limit
);
}
else
{
printf("\nList '%s' with %d elements [MAX not defined yet]\n",
l->name,
l->size
);
}
if (l->size < 1) return 0;
// assume data as just an int
Node* p = l->head;
printf("\n First:%10d\n", l->head->data);
printf(" Last:%10d\n", l->tail->data);
printf("\nElements\n\n");
do
{
printf("%10d \n", p->data);
p = p->next;
} while (p != NULL);
printf("\nEnd of list\n\n");
return 0;
}; // _print()
int _print_your_way(List* L, int(*F)(void*))
{
return 0;
};
List* _remove(int value, List* L)
{
return NULL;
};
int _size(List* L)
{
if (L == NULL) return -1;
return (int)L->size;
};