(悬赏贴)求个大佬求助,帮我解答一下本题
本题要求实现一个函数,将两个链表表示的递增整数序列合并为一个非递减的整数序列。函数接口定义:
List Merge( List L1, List L2 );
其中List结构定义如下:
typedef struct Node *PtrToNode;
struct Node {
ElementType Data; /* 存储结点数据 */
PtrToNode Next; /* 指向下一个结点的指针 */
};
typedef PtrToNode List; /* 定义单链表类型 */
L1和L2是给定的带头结点的单链表,其结点存储的数据是递增有序的;函数Merge要将L1和L2合并为一个非递减的整数序列。应直接使用原序列中的结点,返回归并后的带头结点的链表头指针。
裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
ElementType Data;
PtrToNode Next;
};
typedef PtrToNode List;
List Read(); /* 细节在此不表 */
void Print( List L ); /* 细节在此不表;空链表将输出NULL */
List Merge( List L1, List L2 );
int main()
{
List L1, L2, L;
L1 = Read();
L2 = Read();
L = Merge(L1, L2);
Print(L);
Print(L1);
Print(L2);
return 0;
}
/* 你的代码将被嵌在这里 */
我的代码:
List Merge( List L1, List L2 )
{
List head,temp;
head = temp = (List)malloc(sizeof(struct Node));
L1 = L1->Next;
L2 = L2->Next;
while(L1 && L2)
{
if(L1->Data <= L2->Data)
{
temp->Next = L1;
L1 = L1->Next;
}
else
{
temp->Next = L2;
L2 = L2->Next;
}
temp = temp->Next;
}
if(L1)
{
while(L1)
{
temp->Next = L1;
L1 = L1->Next;
temp = temp->Next;
}
temp->Next = NULL;
}
else if(L2)
{
while(L2)
{
temp->Next = L2;
L2 = L2->Next;
temp = temp->Next;
}
temp->Next = NULL;
}
else
temp->Next = NULL;
//到这里L1 L2为NULL 运行到后面在main函数里打印出L1 L2为原始头节点。。
return head;
}
实例测试:
结果图片:
我在函数里通过传进去结构体指针L1 L2修改L1 L2的节点位置 最后返回head最后在main函数里打印出来的链表却是原始节点 按照正常情况下在Merge函数里 L1 L2都为NULL。
函数是传值操作,但是传入的L1 L2是结构体指针所以传入的L1 L2应该是地址吧?那为什么在Merge函数里做的修改都没有用那如果需要修改 要怎样才行呢?
比如在main函数里 a = 4;int *p = a;我把p传进一个函数里做修改,最后回到main函数里打印a的值 能够做修改这里传递指针p和结构体指针有什么区别呢? 为什么结构体指针传进去不能做修改呢? 求解答 十分感谢! 我确实没认真看题,^_^
我是先直接看的代码
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
ElementType Data;
PtrToNode Next;
};
typedef PtrToNode List;
List Read(); /* 细节在此不表 (也就是说提交的时候可以不考虑,不过还是要写的!) */
void Print(List L); /* 细节在此不表;空链表将输出NULL (同上)*/
List Merge(List L1, List L2);
// 你是不是忘了写这个函数了?
void list_free(List L) {
if(L) list_free(L->Next);
free(L);
}
int main(void) {
List L1, L2, L;
L1 = Read();
L2 = Read();
L = Merge(L1, L2);
Print(L);
Print(L1);
Print(L2);
list_free(L);
// 现在就可以free了
list_free(L1);
list_free(L2);
// 要共用节点的话,这两个就只能单独释放了
//free(L1);
//free(L2);
return 0;
}
/* 你的代码将被嵌在这里 */
List Read() {
int n, i;
scanf("%d", &n);
//List L = (List)malloc(sizeof(PtrToNode)); /// 申请一个头结点
//List L = malloc(sizeof(PtrToNode)); // 这是C语言,没必要强制转换
//List L = malloc(sizeof(struct Node)); // 是PtrToNode还是struct Node?
List L = malloc(sizeof(*L)); // 对吧?管他什么类型了
L->Next = NULL; // 头指针为空
if(n) // 当n不是0时
{
List r = L; /// r是一个中间变量的节点
for(i = 0; i < n; i++) {
//List p = (List)malloc(sizeof(struct Node));
List p = malloc(sizeof(*p));
//scanf("%d", &(p->Data)); // 尾插法
scanf("%d", &p->Data);// 尾插法
r->Next = p;
r = p;
}
r->Next = NULL;
}
return L;
}
void Print(List L) {
List p = L->Next;
if(p) {
List r;
r = L;
while(r->Next) {
r = r->Next;
printf("%d ", r->Data);
}
} else {
printf("NULL");
}
printf("\n");
}
#if 0
// 好了,知道定义了
List Merge(List L1, List L2) {
List L = malloc(sizeof(*L));
L->Next = NULL;
List *px = &L->Next;
List p1 = L1->Next;
List p2 = L2->Next;
while(p1 && p2) {
ElementType v;
ElementType a = p1->Data;
ElementType b = p2->Data;
if(a < b) {
v = a; p1 = p1->Next;
} else {
v = b; p2 = p2->Next;
}
*px = malloc(sizeof(**px));
(*px)->Data = v;
(*px)->Next = NULL;
px = &(*px)->Next;
}
while(p1) {
*px = malloc(sizeof(**px));
(*px)->Data = p1->Data;
(*px)->Next = NULL;
p1 = p1->Next;
px = &(*px)->Next;
}
while(p2) {
*px = malloc(sizeof(**px));
(*px)->Data = p2->Data;
(*px)->Next = NULL;
p2 = p2->Next;
px = &(*px)->Next;
}
return L;
}
#else
List Merge(List L1, List L2) {
List head, temp;
//head = temp = (List)malloc(sizeof(struct Node));
head = temp = malloc(sizeof(*head));
List L1_bak = L1;
List L2_bak = L2;
L1 = L1->Next;
L2 = L2->Next;
while(L1 && L2) {
if(L1->Data <= L2->Data) {
temp->Next = L1;
L1 = L1->Next;
} else {
temp->Next = L2;
L2 = L2->Next;
}
temp = temp->Next;
}
if(L1) {
while(L1) {
temp->Next = L1;
L1 = L1->Next;
temp = temp->Next;
}
temp->Next = NULL;
}
else if(L2) {
while(L2) {
temp->Next = L2;
L2 = L2->Next;
temp = temp->Next;
}
temp->Next = NULL;
} else
temp->Next = NULL;
// 到这里L1 L2为NULL 运行到后面在main函数里打印出L1 L2为原始头节点。。
L1_bak->Next = NULL;
L2_bak->Next = NULL;
return head;
}
#endif
函数参数传递分为值传递和指针传递。对于基本类型的值传递,传入的是该值的副本,修改该副本不会对原始值造成影响;而对于指针类型的值传递,传入的是指针所指向地址的副本,这个副本指向同一个地址,因此可以通过该指针修改原始值。结构体指针也是指针类型,如果传入 Merge 函数的是 L1 和 L2 的指针,那么在函数内部修改 L1 和 L2 就可以作用到原始链表的头结点上了。可能你的问题出在 L1 和 L2 是值传递而非指针传递,导致在 Merge 函数中做的修改不能反映到 main 函数里。 在C语言中,函数参数的传递方式可以是值传递或地址传递。对于基本数据类型(如int、float等),采用值传递的方式,即将变量的值复制给形式参数,在函数内部对形参的修改不会影响到实参的值。而对于指针类型,采用地址传递的方式,即将实参的地址传递给形式参数,函数内部通过操作该地址所指向的内存,可以修改实参所指向的数据。
在你的代码中,`List`类型是指向结构体 `Node` 的指针类型,当你将 `L1` 和 `L2` 作为函数参数进行传递时,实际上是将它们的值(即结构体指针的地址)复制给了函数内部的形参 `L1` 和 `L2`。因此,在函数内部修改 `L1` 和 `L2` 的指向并不会影响原始的链表头节点。
要解决这个问题,可以考虑使用指向指针的指针(双重指针)来实现地址传递,以达到在函数内部修改链表头节点的目的。函数声明和定义需要做以下修改:
List Merge(List* L1, List* L2);
在函数内部,通过对指针的间接引用,修改指针指向的值即可:
List Merge(List* L1, List* L2) {
List head, temp;
head = temp = (List)malloc(sizeof(struct Node));
*L1 = (*L1)->Next;// 修改L1指针指向的值,使其指向下一个节点
*L2 = (*L2)->Next;// 修改L2指针指向的值,使其指向下一个节点
// 其他代码不变...
return head;
}
在函数调用时,传入 `&L1` 和 `&L2`,以传递它们的地址(即指向指针的指针):
L = Merge(&L1, &L2);
这样,在函数内部对 `L1` 和 `L2` 的操作就能够影响到原始的链表头节点了。
求最佳答案{:10_254:} sfqxx 发表于 2023-6-18 18:21
在C语言中,函数参数的传递方式可以是值传递或地址传递。对于基本数据类型(如int、float等),采用值传递 ...
我只能在Merge函数里做修改,参数只能是这样List Merge( List L1, List L2 ),我该如何解决呢? sfqxx 发表于 2023-6-18 18:21
在C语言中,函数参数的传递方式可以是值传递或地址传递。对于基本数据类型(如int、float等),采用值传递 ...
将 `L1` 和 `L2` 作为函数参数进行传递时,实际上是将它们的值(即结构体指针的地址)复制给了函数内部的形参 `L1` 和 `L2`。 那么传递&L1和&L2 实际上是传递的什么呢? 有人吗? List Merge( List L1, List L2 )
{
List head,temp,TL1,TL2;
head = temp = (List)malloc(sizeof(struct Node));
TL1 = L1->Next;
TL2 = L2->Next;
while(TL1 && TL2)
{
if(TL1->Data <= TL2->Data)
{
temp->Next = TL1;
TL1 = TL1->Next;
}
else
{
temp->Next = TL2;
TL2 = TL2->Next;
}
temp = temp->Next;
}
if(TL1)
{
while(TL1)
{
temp->Next = TL1;
TL1 = TL1->Next;
temp = temp->Next;
}
temp->Next = NULL;
}
else if(TL2)
{
while(TL2)
{
temp->Next = TL2;
TL2 = TL2->Next;
temp = temp->Next;
}
temp->Next = NULL;
}
else
temp->Next = NULL;
//到这里L1 L2为NULL 运行到后面在main函数里打印出L1 L2为原始头节点。。
L1->Next = NULL;
L2->Next = NULL;
return head;
}
代码修改一下就可以了 真的希望有大佬出来解释一下 @isdkz 能帮我看看吗? 在C语言中,函数参数传递有两种方式:传值和传址。传值是将参数的值拷贝一份传入函数内部,对参数的修改不会影响原始值;而传址是将参数的内存地址传入函数内部,因此对参数的修改会直接反映到原始值上。
对于指针类型的参数,传递时一般是传递指针的值,即指针变量所指向的内存地址。这样做相当于传址,因为函数内部可以通过指针来访问原始值的内存地址,并对其值进行修改。
回到你的问题,你在Merge函数中对L1和L2指针的修改并不能影响main函数中的L1和L2的值,因为你修改的是指针变量本身的值,而非其指向的内存地址的值。要想在Merge函数中修改L1和L2的值,可以使用指向指针的指针或者指针的引用作为函数参数,这样可以实现对指针变量本身的修改,从而使得修改在函数外部可见。
以下是使用指针的指针实现对L1和L2的修改的示例代码:
List Merge( List* pL1, List* pL2 )
{
List head,temp;
head = temp = (List)malloc(sizeof(struct Node));
List L1 = (*pL1)->Next;
List L2 = (*pL2)->Next;
while(L1 && L2)
{
if(L1->Data <= L2->Data)
{
temp->Next = L1;
L1 = L1->Next;
}
else
{
temp->Next = L2;
L2 = L2->Next;
}
temp = temp->Next;
}
if(L1)
{
while(L1)
{
temp->Next = L1;
L1 = L1->Next;
temp = temp->Next;
}
temp->Next = NULL;
}
else if(L2)
{
while(L2)
{
temp->Next = L2;
L2 = L2->Next;
temp = temp->Next;
}
temp->Next = NULL;
}
else
temp->Next = NULL;
*pL1 = head; // 修改 L1 指针的值,使其指向合并后的链表头
(*pL2)->Next = NULL; // 将 L2 头节点的 Next 指针置为 NULL,防止出现错误
return head;
}
在main函数中,可以这样调用Merge函数:
L = Merge(&L1, &L2);
注意,由于L1和L2都是带头结点的链表,所以在Merge函数返回之前要将它们的头节点的Next指针置为NULL,以免出现链接关系错乱的情况。
如果只能在Merge函数里做修改,那么最简单的方式是使用一个新的指针变量p指向head,然后在函数中修改p的值即可,这样就不会修改原始的L1和L2指针了。具体实现如下:
List Merge( List L1, List L2 )
{
List head,temp,p;
head = temp = (List)malloc(sizeof(struct Node));
p = head; // 新增一个指针p,指向head
L1 = L1->Next;
L2 = L2->Next;
while(L1 && L2)
{
if(L1->Data <= L2->Data)
{
p->Next = L1; // 使用p指针更新链表
L1 = L1->Next;
}
else
{
p->Next = L2; // 使用p指针更新链表
L2 = L2->Next;
}
p = p->Next;
}
if(L1)
{
while(L1)
{
p->Next = L1;
L1 = L1->Next;
p = p->Next;
}
p->Next = NULL;
}
else if(L2)
{
while(L2)
{
p->Next = L2;
L2 = L2->Next;
p = p->Next;
}
p->Next = NULL;
}
else
p->Next = NULL;
return head;
}
调用方式与之前相同:
L = Merge(L1, L2);
需要注意的是,在Merge函数中只要涉及到链表的插入、删除、移动等操作,都需要使用p指针来修改链表结构,以免影响原始的L1和L2指针。 有没有一个不是人工智能回答的呀,有没有真人回答一下
本题我已测试过L1 L2是一个结构体指针 传进Merge函数里做修改 main函数打印也会改变如图:
@小甲鱼 他们的回答都是通过L1 L2在Merge函数修改节点位置在main函数里是无法修改的而在Merge函数里通过L1 L2头节点下一个指NULL时在main函数里打印的NULL 能够被修改 完整的测试代码
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
ElementType Data;
PtrToNode Next;
};
typedef PtrToNode List;
List Read(); /* 细节在此不表 (也就是说提交的时候可以不考虑,不过还是要写的!) */
void Print( List L ); /* 细节在此不表;空链表将输出NULL (同上)*/
List Merge( List L1, List L2 );
int main()
{
List L1, L2, L;
L1 = Read();
L2 = Read();
L = Merge(L1, L2);
Print(L);
Print(L1);
Print(L2);
return 0;
}
/* 你的代码将被嵌在这里 */
List Read()
{
int n,i;
scanf("%d",&n);
List L=(List)malloc(sizeof(PtrToNode)); ///申请一个头结点
L->Next = NULL; ///头指针为空
if(n) ///当n不是0时
{
List r=L; ///r是一个中间变量的节点
for(i=0;i<n;i++)
{
List p=(List)malloc(sizeof(struct Node));
scanf("%d",&(p->Data)); ///尾插法
r->Next = p;
r = p;
}
r->Next = NULL;
}
return L;
}
void Print( List L )
{
List p=L->Next;
if(p)
{
List r;
r = L;
while(r->Next)
{
r = r->Next;
printf("%d ",r->Data);
}
}
else
{
printf("NULL");
}
printf("\n");
}
a905448839 发表于 2023-6-18 21:03
有没有一个不是人工智能回答的呀,有没有真人回答一下
本题我已测试过L1 L2是一个结构体指针 传进Merge ...
那就来个不是ai的回答
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
ElementType Data;
PtrToNode Next;
};
typedef PtrToNode List;
List Read(); /* 细节在此不表 (也就是说提交的时候可以不考虑,不过还是要写的!) */
void Print(List L); /* 细节在此不表;空链表将输出NULL (同上)*/
List Merge(List L1, List L2);
// 你是不是忘了写这个函数了?
void list_free(List L) {
if(L) list_free(L->Next);
free(L);
}
int main(void) {
List L1, L2, L;
L1 = Read();
L2 = Read();
L = Merge(L1, L2);
Print(L);
Print(L1);
Print(L2);
list_free(L);
list_free(L1);
list_free(L2);
return 0;
}
/* 你的代码将被嵌在这里 */
List Read() {
int n, i;
scanf("%d", &n);
//List L = (List)malloc(sizeof(PtrToNode)); /// 申请一个头结点
//List L = malloc(sizeof(PtrToNode)); // 这是C语言,没必要强制转换
//List L = malloc(sizeof(struct Node)); // 是PtrToNode还是struct Node?
List L = malloc(sizeof(*L)); // 对吧?管他什么类型了
L->Next = NULL; // 头指针为空
if(n) // 当n不是0时
{
List r = L; /// r是一个中间变量的节点
for(i = 0; i < n; i++) {
//List p = (List)malloc(sizeof(struct Node));
List p = malloc(sizeof(*p));
//scanf("%d", &(p->Data)); // 尾插法
scanf("%d", &p->Data);// 尾插法
r->Next = p;
r = p;
}
r->Next = NULL;
}
return L;
}
void Print(List L) {
List p = L->Next;
if(p) {
List r;
r = L;
while(r->Next) {
r = r->Next;
printf("%d ", r->Data);
}
} else {
printf("NULL");
}
printf("\n");
}
// 定义是什么?
List Merge(List L1, List L2) {
List L = malloc(sizeof(*L));
L->Next = NULL;
List *px = &L->Next;
List p1 = L1->Next;
while(p1) {
*px = malloc(sizeof(**px));
(*px)->Data = p1->Data;
(*px)->Next = NULL;
p1 = p1->Next;
px = &(*px)->Next;
}
List p2 = L2->Next;
while(p2) {
*px = malloc(sizeof(**px));
(*px)->Data = p2->Data;
(*px)->Next = NULL;
p2 = p2->Next;
px = &(*px)->Next;
}
return L;
}
稍微改一改
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
ElementType Data;
PtrToNode Next;
};
typedef PtrToNode List;
List Read(); /* 细节在此不表 (也就是说提交的时候可以不考虑,不过还是要写的!) */
void Print(List L); /* 细节在此不表;空链表将输出NULL (同上)*/
List Merge(List L1, List L2);
// 你是不是忘了写这个函数了?
void list_free(List L) {
if(L) list_free(L->Next);
free(L);
}
int main(void) {
List L1, L2, L;
L1 = Read();
L2 = Read();
L = Merge(L1, L2);
Print(L);
Print(L1);
Print(L2);
list_free(L);
list_free(L1);
list_free(L2);
return 0;
}
/* 你的代码将被嵌在这里 */
List Read() {
int n, i;
scanf("%d", &n);
//List L = (List)malloc(sizeof(PtrToNode)); /// 申请一个头结点
//List L = malloc(sizeof(PtrToNode)); // 这是C语言,没必要强制转换
//List L = malloc(sizeof(struct Node)); // 是PtrToNode还是struct Node?
List L = malloc(sizeof(*L)); // 对吧?管他什么类型了
L->Next = NULL; // 头指针为空
if(n) // 当n不是0时
{
List r = L; /// r是一个中间变量的节点
for(i = 0; i < n; i++) {
//List p = (List)malloc(sizeof(struct Node));
List p = malloc(sizeof(*p));
//scanf("%d", &(p->Data)); // 尾插法
scanf("%d", &p->Data);// 尾插法
r->Next = p;
r = p;
}
r->Next = NULL;
}
return L;
}
void Print(List L) {
List p = L->Next;
if(p) {
List r;
r = L;
while(r->Next) {
r = r->Next;
printf("%d ", r->Data);
}
} else {
printf("NULL");
}
printf("\n");
}
// 好了,知道定义了
List Merge(List L1, List L2) {
List L = malloc(sizeof(*L));
L->Next = NULL;
List *px = &L->Next;
List p1 = L1->Next;
List p2 = L2->Next;
while(p1 && p2) {
ElementType v;
ElementType a = p1->Data;
ElementType b = p2->Data;
if(a < b) {
v = a; p1 = p1->Next;
} else {
v = b; p2 = p2->Next;
}
*px = malloc(sizeof(**px));
(*px)->Data = v;
(*px)->Next = NULL;
px = &(*px)->Next;
}
while(p1) {
*px = malloc(sizeof(**px));
(*px)->Data = p1->Data;
(*px)->Next = NULL;
p1 = p1->Next;
px = &(*px)->Next;
}
while(p2) {
*px = malloc(sizeof(**px));
(*px)->Data = p2->Data;
(*px)->Next = NULL;
p2 = p2->Next;
px = &(*px)->Next;
}
return L;
}
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
ElementType Data;
PtrToNode Next;
};
typedef PtrToNode List;
List Read(); /* 细节在此不表 (也就是说提交的时候可以不考虑,不过还是要写的!) */
void Print(List L); /* 细节在此不表;空链表将输出NULL (同上)*/
List Merge(List L1, List L2);
// 你是不是忘了写这个函数了?
void list_free(List L) {
if(L) list_free(L->Next);
free(L);
}
int main(void) {
List L1, L2, L;
L1 = Read();
L2 = Read();
L = Merge(L1, L2);
Print(L);
Print(L1);
Print(L2);
list_free(L);
//list_free(L1);
//list_free(L2);
// 要共用节点的话,这两个就只能单独释放了
free(L1);
free(L2);
return 0;
}
/* 你的代码将被嵌在这里 */
List Read() {
int n, i;
scanf("%d", &n);
//List L = (List)malloc(sizeof(PtrToNode)); /// 申请一个头结点
//List L = malloc(sizeof(PtrToNode)); // 这是C语言,没必要强制转换
//List L = malloc(sizeof(struct Node)); // 是PtrToNode还是struct Node?
List L = malloc(sizeof(*L)); // 对吧?管他什么类型了
L->Next = NULL; // 头指针为空
if(n) // 当n不是0时
{
List r = L; /// r是一个中间变量的节点
for(i = 0; i < n; i++) {
//List p = (List)malloc(sizeof(struct Node));
List p = malloc(sizeof(*p));
//scanf("%d", &(p->Data)); // 尾插法
scanf("%d", &p->Data);// 尾插法
r->Next = p;
r = p;
}
r->Next = NULL;
}
return L;
}
void Print(List L) {
List p = L->Next;
if(p) {
List r;
r = L;
while(r->Next) {
r = r->Next;
printf("%d ", r->Data);
}
} else {
printf("NULL");
}
printf("\n");
}
#if 0
// 好了,知道定义了
List Merge(List L1, List L2) {
List L = malloc(sizeof(*L));
L->Next = NULL;
List *px = &L->Next;
List p1 = L1->Next;
List p2 = L2->Next;
while(p1 && p2) {
ElementType v;
ElementType a = p1->Data;
ElementType b = p2->Data;
if(a < b) {
v = a; p1 = p1->Next;
} else {
v = b; p2 = p2->Next;
}
*px = malloc(sizeof(**px));
(*px)->Data = v;
(*px)->Next = NULL;
px = &(*px)->Next;
}
while(p1) {
*px = malloc(sizeof(**px));
(*px)->Data = p1->Data;
(*px)->Next = NULL;
p1 = p1->Next;
px = &(*px)->Next;
}
while(p2) {
*px = malloc(sizeof(**px));
(*px)->Data = p2->Data;
(*px)->Next = NULL;
p2 = p2->Next;
px = &(*px)->Next;
}
return L;
}
#else
List Merge(List L1, List L2) {
List head, temp;
//head = temp = (List)malloc(sizeof(struct Node));
head = temp = malloc(sizeof(*head));
L1 = L1->Next;
L2 = L2->Next;
while(L1 && L2) {
if(L1->Data <= L2->Data) {
temp->Next = L1;
L1 = L1->Next;
} else {
temp->Next = L2;
L2 = L2->Next;
}
temp = temp->Next;
}
if(L1) {
while(L1) {
temp->Next = L1;
L1 = L1->Next;
temp = temp->Next;
}
temp->Next = NULL;
}
else if(L2) {
while(L2) {
temp->Next = L2;
L2 = L2->Next;
temp = temp->Next;
}
temp->Next = NULL;
} else
temp->Next = NULL;
// 到这里L1 L2为NULL 运行到后面在main函数里打印出L1 L2为原始头节点。。
return head;
}
#endif
人造人 发表于 2023-6-18 23:08
稍微改一改
感谢你的回复,真的很牛,不过这二级指针我越看越迷糊,我也free不了内存空间,我只能对Merge函数内容做出修改,参数也不能更改。main函数也不能动。我把你的代码copy过去测试了,我把测试结果发出来。
你的第一次回复 Merge函数代码 测试:
List Merge(List L1, List L2) {
List L = malloc(sizeof(*L));
L->Next = NULL;
List *px = &L->Next;
List p1 = L1->Next;
while(p1) {
*px = malloc(sizeof(**px));
(*px)->Data = p1->Data;
(*px)->Next = NULL;
p1 = p1->Next;
px = &(*px)->Next;
}
List p2 = L2->Next;
while(p2) {
*px = malloc(sizeof(**px));
(*px)->Data = p2->Data;
(*px)->Next = NULL;
p2 = p2->Next;
px = &(*px)->Next;
}
return L;
}
你的第二次回复 Merge函数代码 测试:
List Merge(List L1, List L2) {
List L = malloc(sizeof(*L));
L->Next = NULL;
List *px = &L->Next;
List p1 = L1->Next;
List p2 = L2->Next;
while(p1 && p2) {
ElementType v;
ElementType a = p1->Data;
ElementType b = p2->Data;
if(a < b) {
v = a; p1 = p1->Next;
} else {
v = b; p2 = p2->Next;
}
*px = malloc(sizeof(**px));
(*px)->Data = v;
(*px)->Next = NULL;
px = &(*px)->Next;
}
while(p1) {
*px = malloc(sizeof(**px));
(*px)->Data = p1->Data;
(*px)->Next = NULL;
p1 = p1->Next;
px = &(*px)->Next;
}
while(p2) {
*px = malloc(sizeof(**px));
(*px)->Data = p2->Data;
(*px)->Next = NULL;
p2 = p2->Next;
px = &(*px)->Next;
}
return L;
}
也许大佬你没有仔细看题实现这个题目最后L1 L2指向的下一个节点是NULL由于我的代码是通过传递进去的L1 L2指针来进行改动移动节点 导致回到主函数中去的时候好像没有改动到L1 L2节点位置 还依然是头节点 我看过一些题解是用两个局部变量的指针指向L1 L2 再来做这两个局部变量的指针移动节点 最后把L1 L2指向的下一个节点为NULL 有这样一段代码实现 我不明白的是 为什么用完局部变量的节点之后最后L1->Next = NULL和L2->Next = NULL 是能够影响到外面main函数的L1 L2。而直接对L1 L2修改 直到L1 L2都为NULL时返回到main函数,main函数里的L1 L2依然为最开始头节点。
能够实现的代码 使用两个局部变量来移动节点用temp来指向产生一个新的链表最后让始终是L1 L2头结点下一个指向NULL成功影响外面的main函数里的L1 L2:
List Merge( List L1, List L2 )
{
List head,temp,TL1,TL2;
head = temp = (List)malloc(sizeof(struct Node));
TL1 = L1->Next;
TL2 = L2->Next;
while(TL1 && TL2)
{
if(TL1->Data <= TL2->Data)
{
temp->Next = TL1;
TL1 = TL1->Next;
}
else
{
temp->Next = TL2;
TL2 = TL2->Next;
}
temp = temp->Next;
}
if(TL1)
{
while(TL1)
{
temp->Next = TL1;
TL1 = TL1->Next;
temp = temp->Next;
}
temp->Next = NULL;
}
else if(TL2)
{
while(TL2)
{
temp->Next = TL2;
TL2 = TL2->Next;
temp = temp->Next;
}
temp->Next = NULL;
}
else
temp->Next = NULL;
L1->Next = NULL;
L2->Next = NULL;
return head;
}
不能够实现的代码对传进来L1 L2结构体指针操作能够实现让两个链表合并成一个递增的顺序链表 但是L1 L2在Merge函数结束时为NULL 回到main函数却变成了最开始L1 L2的头指针:
List Merge( List L1, List L2 )
{
List head,temp;
head = temp = (List)malloc(sizeof(struct Node));
L1 = L1->Next;
L2 = L2->Next;
while(L1 && L2)
{
if(L1->Data <= L2->Data)
{
temp->Next = L1;
L1 = L1->Next;
}
else
{
temp->Next = L2;
L2 = L2->Next;
}
temp = temp->Next;
}
if(L1)
{
while(L1)
{
temp->Next = L1;
L1 = L1->Next;
temp = temp->Next;
}
temp->Next = NULL;
}
else if(L2)
{
while(L2)
{
temp->Next = L2;
L2 = L2->Next;
temp = temp->Next;
}
temp->Next = NULL;
}
else
temp->Next = NULL;
//到这里L1 L2为NULL 运行到后面在main函数里打印出L1 L2为原始头节点。。
return head;
}
a905448839 发表于 2023-6-18 23:42
感谢你的回复,真的很牛,不过这二级指针我越看越迷糊,我也free不了内存空间,我只能对Merge函数内容做 ...
这里需要修改的是L->Next
L1 = L1->Next;
L1->Next = NULL;
这个修改的就是 L->Next->Next 了
L1 = L1->Next;
L1->Next = NULL;
L->Next->Next = NULL;
他俩一个意思 #include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
ElementType Data;
PtrToNode Next;
};
typedef PtrToNode List;
void Print(List L); /* 细节在此不表;空链表将输出NULL (同上)*/
void list_free(List L) {
if(L) list_free(L->Next);
free(L);
}
void set_null(List a, List b) {
a->Next->Next = NULL;
b = b->Next;
b->Next = NULL;
}
int main(void) {
List L1, L2;
L1 = malloc(sizeof(*L1));
L1->Next = malloc(sizeof(*L1->Next));
L1->Next->Data = 123;
L2 = malloc(sizeof(*L2));
L2->Next = malloc(sizeof(*L2->Next));
L2->Next->Data = 456;
set_null(L1, L2);
Print(L1);
Print(L2);
list_free(L1);
list_free(L2);
return 0;
}
void Print(List L) {
List p = L->Next;
if(p) {
List r;
r = L;
while(r->Next) {
r = r->Next;
printf("%d ", r->Data);
}
} else {
printf("NULL");
}
printf("\n");
}
人造人 发表于 2023-6-18 18:13
我确实没认真看题,^_^
我是先直接看的代码
感谢你的回答 两种方式我都看了! 最后还有一个小问题 在第二个Merge函数里最后L1_bak->Next = NULL;
L2_bak->Next = NULL; 这里的L1_bak和L2_bak原本是L1 L2头结点位置这里指向NULL 让main函数L1 L2的下一节点指向NULL了 的的确确影响到了 但是如果在Merge函数里移动L1 L2节点 或者移动L1_bak L2_bak节点 最后在移动的中途节点 或者在最后节点再把下一个节点指向NULL 就不会导致main函数里的L1 L2节点下一个指向为NULL 是原始的情况 是否在Merge函数里移动这些节点 不会导致main函数里的L1 L2节点位置改变 但是如果在Merge函数里直接做指向节点修改 不移动节点就会影响到main函数里的L1 L2指向吗? a905448839 发表于 2023-6-19 10:12
感谢你的回答 两种方式我都看了! 最后还有一个小问题 在第二个Merge函数里最后L1_bak->Next = NULL;
...
没看懂,用代码说明你的问题吧
页:
[1]
2