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;
};