C 跟踪链表的初始值
对我来说,遍历链表有时似乎很棘手(我正在学习) 我一直在递归地做事情,但我想迭代地做这个 下一个函数将列表C 跟踪链表的初始值,c,linked-list,C,Linked List,对我来说,遍历链表有时似乎很棘手(我正在学习) 我一直在递归地做事情,但我想迭代地做这个 下一个函数将列表l中的值添加到列表mx,如果其值大于x: typedef struct slist *Lint; typedef struct slist { int value; Lint next; } Nodo; void split(Lint l, int x, Lint *mx){ Lint mxtmp=NULL; while (l!=NULL){
l
中的值添加到列表mx
,如果其值大于x
:
typedef struct slist *Lint;
typedef struct slist {
int value;
Lint next;
} Nodo;
void split(Lint l, int x, Lint *mx){
Lint mxtmp=NULL;
while (l!=NULL){
if(l->value > x){
*mx = (Lint) calloc(1,sizeof(Nodo));
(*mx)->value = l->value;
(*mx)->next = NULL;
mxtmp = *mx;
*mx = (*mx)->next;
}
l = l->next;
}
*mx = mxtmp;
}
打印*mx
而不是列表会给我一个值(使用适当的循环遍历列表)
问题是,我似乎忘记了列表的开头;在这种情况下,我似乎无法跟踪指向列表开头的指针*mx
,这是我正在更改的列表
我该怎么办
我对这个函数的另一个疑问是,我怎么能不将这些值赋给一个新的列表,而是创建一个新的mx
列表,只指向主列表l
中的结构
typedef struct slist *Lint;
typedef struct slist {
int value;
Lint next;
} Nodo;
void split(Lint l, int x, Lint *mx){
Lint mxtmp=NULL;
int i = 0;
while (l!=NULL){
if(l->value > x){
*mx = (Lint) calloc(1,sizeof(Nodo));
(*mx)->value = l->value;
(*mx)->next = NULL;
if(!i) //mxtmp will keep track of the first allocated Nodo item
{
mxtmp = *mx;
i++;
}
mx = &((*mx)->next); // with this, next( so *mx) will be initialized to point to a new Nodo item in the next loop
}
l = l->next;
}
mx = &mxtmp; //finally we make mx point to the first allocated Nodo item
}
我执行了以下代码来测试它:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
typedef struct slist *Lint;
typedef struct slist {
int value;
Lint next;
} Nodo;
void recurs_free(Lint f)
{
if(!f)return;
if(f->next)recurs_free(f->next);
free(f);
}
void recurs_printf(Lint f)
{
if(!f)return;
printf("%d\n", f->value);
if(f->next)recurs_printf(f->next);
}
void split(Lint l, int x, Lint *mx){
Lint mxtmp=NULL;
int i = 0;
while (l!=NULL){
if(l->value > x){
*mx = (Lint) calloc(1,sizeof(Nodo));
(*mx)->value = l->value;
(*mx)->next = NULL;
if(!i) //mxtmp will keep track of the first allocated Nodo item
{
mxtmp = *mx;
i++;
}
mx = &((*mx)->next); // with this, next( so *mx) will be initialized to point to a new Nodo item in the next loop
}
l = l->next;
}
mx = &mxtmp; //finally we make mx point to the first allocated Nodo item
}
int main()
{
void recurs_printf(Lint f);
void recurs_free(Lint f);
void split(Lint l, int x, Lint *mx);
Lint t = NULL;
Nodo a = {1, NULL}, b = {2, &a}, c = {3, &b}, d = {4, &c}, e = {5, &d};
split(&e, 3, &t);
recurs_printf(t);
recurs_free(t);
return 0;
}
#包括
#包括
#包括
#包括
typedef结构列表*Lint;
类型定义结构列表{
int值;
其次是皮棉;
}野藤;
无效无递归(林特f)
{
如果(!f)返回;
如果(f->next)无递归(f->next);
免费(f);
}
无效递归打印f(Lint f)
{
如果(!f)返回;
printf(“%d\n”,f->value);
如果(f->next)递归\u printf(f->next);
}
空隙分割(衣料l、衣料x、衣料*mx){
Lint mxtmp=NULL;
int i=0;
while(l!=NULL){
如果(l->值>x){
*mx=(Lint)calloc(1,sizeof(Nodo));
(*mx)->value=l->value;
(*mx)->next=NULL;
if(!i)//mxtmp将跟踪第一个分配的Nodo项
{
mxtmp=*mx;
i++;
}
mx=&(*mx)->next);//这样,next(so*mx)将被初始化为指向下一个循环中的新Nodo项
}
l=l->next;
}
mx=&mxtmp;//最后我们让mx指向第一个分配的Nodo项
}
int main()
{
无效递归打印f(Lint f);
无效无复发(林特f);
空隙分割(衣料l、衣料x、衣料*mx);
Lint=NULL;
nodoa={1,NULL},b={2,&a},c={3,&b},d={4,&c},e={5,&d};
拆分(e、3和t);
递归打印f(t);
无递归(t);
返回0;
}
诊断
您的问题在以下代码中:
void split(Lint l, int x, Lint *mx){
Lint mxtmp=NULL;
while (l!=NULL){
if(l->value > x){
*mx = (Lint) calloc(1,sizeof(Nodo));
分配给*mx
意味着您丢失了原始指针,无法正确更新列表。很少有平台使用calloc()
不会将指针设置为null,但是当代码显式设置结构的内容时,使用calloc()
是没有意义的
您可能需要一些更像:
void split(Lint l, int x, Lint *mx)
{
Lint mxtmp = NULL;
while (l != NULL)
{
if (l->value > x)
{
mxtmp = (Lint) malloc(sizeof(*mxtmp));
if (mxtmp == 0)
…report error and do not continue…
mxtmp->value = l->value;
mxtmp->next = *mx;
*mx = mxtmp;
}
l = l->next;
}
}
这将按照项目在*mx
中出现的顺序的相反顺序插入项目,因为它总是插入列表的前面。如果愿意,您可以安排附加到*mx
的末尾
如果需要从源列表中删除条目,l
,并将其传输到*mx
,则需要将Lint*l
传递到函数,以便在需要将l
中的第一项(或带有修订签名的*l
中的第一项)传输到*mx
时,可以更新列表的标题
解释
这项工作做得很好。您介意解释一下
*mx
会发生什么吗?因为我似乎不明白*mx
是如何“增加”的;似乎*mx
始终处于相同的指针值中
我松了一口气,因为在这次更新之前我没有机会测试它
假设我们接到这样的电话:
Lint list1 = 0;
…populate list1…
Lint list2 = 0;
split(list1, 10, &list2);
指针list2
有自己的地址。它保存一个值,最初是空指针。list2
指针的地址被传递到split()
,这意味着split()
可以修改指针内容(就像如果您有int i=0;some_func(&i);
,那么some_func()
可以修改i
中的值一样)
当split()
遍历列表l
时,当它找到需要复制的值时,它会创建一个由mxtmp
指向的新节点,并填充该值。它使新节点的next
指针指向当前位于列表顶部的内容(mxtmp->next=*mx;
),然后它修改*mx
-的地址,该地址实际上是示例调用中的调用函数中的list1
,以便它包含新节点的地址(*mx=mxtmp;
)
测试
这是我提出的测试代码,它可以在以下条件下正常运行:
我认为这是最基本的要求;我通常甚至不运行代码,直到它安静地编译
示例输出:
打印list1
两次是妄想症,检查它在split
操作期间是否损坏。请注意,应编写split()
函数以使用insert()
函数
调试打印还将打印节点和下一个指针的地址:
static void print_list(const char *tag, Lint list)
{
printf("%s:\n", tag);
while (list != NULL)
{
printf("--> %3d (%p, next %p)\n", list->value, (void *)list, (void *)list->next);
list = list->next;
}
putchar('\n');
}
例如:
List 1:
--> 23 (0x10081f410, next 0x10081f3c0)
--> 11 (0x10081f3c0, next 0x10081f370)
--> 10 (0x10081f370, next 0x10081f320)
--> 2 (0x10081f320, next 0x0)
List 1:
--> 23 (0x10081f410, next 0x10081f3c0)
--> 11 (0x10081f3c0, next 0x10081f370)
--> 10 (0x10081f370, next 0x10081f320)
--> 2 (0x10081f320, next 0x0)
List 2:
--> 11 (0x10081f4b0, next 0x10081f460)
--> 23 (0x10081f460, next 0x0)
临别赠言
我没有重新组织数据类型,但如果让我自己的设备使用,我可能会使用类似于:
typedef struct List List;
struct List
{
int value;
List *next;
};
然后通过<代码>列表*和列表**/Code >。这是一个C++的自动调用,没有显式<代码> TyPulfF
。< /P>有两个参数,即代码> Lt**MX和 Ltt*Mx/Code >,这是类似的名称,是自找麻烦。oesn没有引用
,这让我对Mx
可能的用途感到困惑。您想做什么还不完全清楚。如果您想保持列表Mx
不变,但要从l
复制值大于阈值的任何节点,那么您可以用一种方法来做
l
static void print_list(const char *tag, Lint list)
{
printf("%s:\n", tag);
while (list != NULL)
{
printf("--> %3d (%p, next %p)\n", list->value, (void *)list, (void *)list->next);
list = list->next;
}
putchar('\n');
}
List 1:
--> 23 (0x10081f410, next 0x10081f3c0)
--> 11 (0x10081f3c0, next 0x10081f370)
--> 10 (0x10081f370, next 0x10081f320)
--> 2 (0x10081f320, next 0x0)
List 1:
--> 23 (0x10081f410, next 0x10081f3c0)
--> 11 (0x10081f3c0, next 0x10081f370)
--> 10 (0x10081f370, next 0x10081f320)
--> 2 (0x10081f320, next 0x0)
List 2:
--> 11 (0x10081f4b0, next 0x10081f460)
--> 23 (0x10081f460, next 0x0)
typedef struct List List;
struct List
{
int value;
List *next;
};