怪事...一定给分!

时间:2022-05-15 11:47:48
在调试下面(A)函数时,当执行p1=p1->Link时,p1的值竟然不变,why?
而在(B)中,p的值就变,两个的传值和定义都一样,为什么执行结果就不一样?

(A)
LinkNode *MergeLink(LinkNode *Head1,LinkNode *Head2)
{
LinkNode *Head3,*p1,*p2,*p3;
//p1=Head1->Link;p2=Head2->Link;
p1=Head1;p2=Head2;
Head3=p3=Head1;
while(p1&&p2)
{
if(p1->nValue<p2->nValue)
{
p3->Link=p1;
p3=p1;
p1=p1->Link;
}
else if(p1->nValue>p2->nValue)
{
p3->Link=p2;
p3=p2;
p2=p2->Link;
}
else
{
p3->Link=p1;
p3=p1;
p1=p1->Link;p2=p2->Link;
}
}
p3->Link=p1?p1:p2;
delete Head2;
return Head3;


}

(B)
void PrintList(LinkNode *Head)
{
LinkNode *p;
#if(HAS_HEADNODE)
p=Head->Link;
#else
p=Head;
#endif
while(p!=NULL)
{
printf("[%d]",p->nValue);
p=p->Link;
}
printf("\n");
}

14 个解决方案

#1


大家帮帮忙吧,这个问题让我苦恼了很长时间了

#2


你没有贴出整个工程,单从现在的来看没有什么问题,应该具体数据的问题,你仔细跟踪一下就应该会明白。

PS,建议使用STL中的list,而不要自己写链表。

#3


c/c++是传值调用的,你如果想改变一个指针的值,那么你应该传指针的指针(二重指针)进来,这样你才能改变一个指针的指向

#4


1)为什么PrintList就可以执行?
2)如果我把p1=Head1;p2=Head2;
改成:p1=Head1->Link;p2=Head2->Link;
p1=p1->link就可以指向它的link了。

why?都把我弄糊涂了,请大家帮帮忙,再给200分都行!

#5


要改变指针用引用把,这个比较方便.

#6


to liu_feng_fly:
p1=head是让p1指向以head为头指针的这个链表,整个过程没改动head链表的值。
即如图:

head
| p1
||
[x|x]--->[x|x]--->....

#7


我还没学c++,只想知道我的程序在c中到底那错了。
我把所有程序都贴出来,大家看看,谢了!
文件mergeLink.cpp

#include "mergeLink.h"
#include "globals.h"

void main()
{
LinkNode *Head,*Head1,*Head2;
Head=Head1=Head2=NULL;
Head1=CreateList(Head1,Data1,MAX1);
Head2=CreateList(Head2,Data2,MAX2);
if(Head1!=NULL&&Head2!=NULL)
{
printf("Input data:\n");
PrintList(Head1);
PrintList(Head2);
Head=MergeLink(Head1,Head2);
printf("After Merged:\n");
PrintList(Head);
FreeList(Head);
}
}

void PrintList(LinkNode *Head)
{
LinkNode *p;
#if(HAS_HEADNODE)
p=Head->Link;
#else
p=Head;
#endif
while(p!=NULL)
{
printf("[%d]",p->nValue);
p=p->Link;
}
printf("\n");
}

void FreeList(LinkNode *Head)
{
LinkNode *p;
while(Head!=NULL)
{
p=Head;
Head=Head->Link;
delete p;
}
}

LinkNode *MergeLink(LinkNode *Head1,LinkNode *Head2)
{
LinkNode *Head3,*p1,*p2,*p3;
//p1=Head1->Link;p2=Head2->Link;
p1=Head1;p2=Head2;
Head3=p3=Head1;
while(p1&&p2)
{
if(p1->nValue<p2->nValue)
{
p3->Link=p1;
p3=p1;
p1=p1->Link;
}
else if(p1->nValue>p2->nValue)
{
p3->Link=p2;
p3=p2;
p2=p2->Link;
}
else
{
p3->Link=p1;
p3=p1;
p1=p1->Link;p2=p2->Link;
}
}
p3->Link=p1?p1:p2;
delete Head2;
return Head3;


}

LinkNode *CreateList(LinkNode *Head,int *Data,int nMax)
{
LinkNode *pNew;
LinkNode *p;
int i;
Head=new LinkNode;
if(Head==NULL) printf("Memory allocate failure!\n");
else
{
Head->nValue=Data[0];
Head->Link=NULL;
p=Head;
for(i=1;i<nMax;i++)
{
pNew=new LinkNode;
pNew->nValue=Data[i];
pNew->Link=NULL;
p->Link=pNew;
p=pNew;
}
}
return Head;
}


/*
LinkNode *CreateList(LinkNode *Head,int *Data,int nMax)
{
int i;LinkNode *p;
Head=new LinkNode;
Head->Link=NULL;
for(i=nMax-1;i>=0;i--)
{
p=new LinkNode;
p->nValue=Data[i];
p->Link=Head->Link;
Head->Link=p;
}
return Head;
}
*/

mergeLink.h
#include <stdio.h>
#include <stdlib.h>

#define HAS_HEADNODE 0
#define MAX1 3
#define MAX2 5

typedef struct LINK_NODE{
int nValue;
struct LINK_NODE *Link;
}LinkNode;

int Data1[MAX1]={1,3,5};
int Data2[MAX2]={2,3,4,6,8};

只要把/*...*/和//里的换上程序运行就正确了,但我不明白这样到底错在哪?麻烦各位大虾了!

#8


delete head2有内存泄露的。
如果你把这个链表指针定为全局变量我觉得这样传指针没错。

p3->Link=p1?p1:p2;//这句是什么意思?
如果是连接余下的链表,应该是
p3->Link==p1?p3->Link=p1:p3->Link=p2;

#9


有内存泄露,我改过之后问题依旧。
p3->Link=p1?p1:p2没错,你错了。

这个程序是死循环,因为p1和p2的值不改变,尽管有p1=p1->link,p2=p2->link,我想知道为什么p1和p2的值不改变!

#10


up一下
我在线等待,请大家帮帮忙了!
有需要源程序的给我email,我发给你。麻烦了!

#11


c/c++是传值调用的,你如果想改变一个指针的值,那么你应该传指针的指针

#12


我不同意以上的看法,我认为其错误只是一个逻辑错误,发生在:

p1=Head1;p2=Head2;
Head3=p3=Head1;
while(p1&&p2)
{
if(p1->nValue<p2->nValue)
{
p3->Link=p1;
p3=p1;
p1=p1->Link;
}

此时有两个list,p1和p3都指向第一个list的头部,而p2指向第二个list的头部.

假设list2的头结点的值大于list1的头结点中的值.
那么:
 p3->Link=p1; 也就是说将list1的头结点的Link指针指向list1的头部,实际就是指向自已, 即p1->Link=p1;
然后
  p3=p1;   实际是多余, p3和p1本来就都指向list1的头部.
p1=p1->Link; 现在我们又指回来的,p1->Link已被作者指向了p1,他现在倒又来抱怨为什么p1不变了, 多么没有公理啊!

#13


p1=Head1;
p3=Head1;
//设Head1->nValue<Head2->nValue,即p1->nValue<p2->nValue,则
p3->Link=p1;
p1=p1->Link;
//以上两句变成:
//Head1->Link=Head1;
//Head1=Head1->Link;
故实际上是一直在使Head1->Link指向自己。

因为你可能想出成另一个链,因此在定义Head3和p3时可定义成LinkNode **Head3和LinkNode **p3.

#14


我当天就明白了,不过登陆不上,只好作罢。  
下面是改动的程序:  
LinkNode  *MergeLink(LinkNode  *Head1,LinkNode  *Head2)  
{//通过直接把head2中的结点插入到head1中来完成合并  
           LinkNode  *p1,*p2,*p;  
           p1=Head1;p2=Head2;  
           //因为插入结点可能引起head1表头的变化,需插入一首结点  
           p=new  LinkNode;  
           p-  >Link=p1;  
           Head1=p1=p;  
           while(p1-  >Link&&p2)  
           {  
                       if(p1-  >Link-  >nValue  <=p2-  >nValue)  
                                   p1=p1-  >Link;  
                       else{  
                                   //取下p2要插入的结点  
                                   p=p2;p2=p2-  >Link;  
                                   //把取下的结点插入到p1中  
                                   p-  >Link=p1-  >Link;  
                                   p1-  >Link=p;  
                       }  
           }  
           if(p2)  p1-  >Link=p2;  
           return  Head1=Head1-  >Link;  
}  
 
分还是要给的,毕竟是帮忙了。  
从这件事得出的经验是:少问多想。有些事情自己想想就可以解决的。

#1


大家帮帮忙吧,这个问题让我苦恼了很长时间了

#2


你没有贴出整个工程,单从现在的来看没有什么问题,应该具体数据的问题,你仔细跟踪一下就应该会明白。

PS,建议使用STL中的list,而不要自己写链表。

#3


c/c++是传值调用的,你如果想改变一个指针的值,那么你应该传指针的指针(二重指针)进来,这样你才能改变一个指针的指向

#4


1)为什么PrintList就可以执行?
2)如果我把p1=Head1;p2=Head2;
改成:p1=Head1->Link;p2=Head2->Link;
p1=p1->link就可以指向它的link了。

why?都把我弄糊涂了,请大家帮帮忙,再给200分都行!

#5


要改变指针用引用把,这个比较方便.

#6


to liu_feng_fly:
p1=head是让p1指向以head为头指针的这个链表,整个过程没改动head链表的值。
即如图:

head
| p1
||
[x|x]--->[x|x]--->....

#7


我还没学c++,只想知道我的程序在c中到底那错了。
我把所有程序都贴出来,大家看看,谢了!
文件mergeLink.cpp

#include "mergeLink.h"
#include "globals.h"

void main()
{
LinkNode *Head,*Head1,*Head2;
Head=Head1=Head2=NULL;
Head1=CreateList(Head1,Data1,MAX1);
Head2=CreateList(Head2,Data2,MAX2);
if(Head1!=NULL&&Head2!=NULL)
{
printf("Input data:\n");
PrintList(Head1);
PrintList(Head2);
Head=MergeLink(Head1,Head2);
printf("After Merged:\n");
PrintList(Head);
FreeList(Head);
}
}

void PrintList(LinkNode *Head)
{
LinkNode *p;
#if(HAS_HEADNODE)
p=Head->Link;
#else
p=Head;
#endif
while(p!=NULL)
{
printf("[%d]",p->nValue);
p=p->Link;
}
printf("\n");
}

void FreeList(LinkNode *Head)
{
LinkNode *p;
while(Head!=NULL)
{
p=Head;
Head=Head->Link;
delete p;
}
}

LinkNode *MergeLink(LinkNode *Head1,LinkNode *Head2)
{
LinkNode *Head3,*p1,*p2,*p3;
//p1=Head1->Link;p2=Head2->Link;
p1=Head1;p2=Head2;
Head3=p3=Head1;
while(p1&&p2)
{
if(p1->nValue<p2->nValue)
{
p3->Link=p1;
p3=p1;
p1=p1->Link;
}
else if(p1->nValue>p2->nValue)
{
p3->Link=p2;
p3=p2;
p2=p2->Link;
}
else
{
p3->Link=p1;
p3=p1;
p1=p1->Link;p2=p2->Link;
}
}
p3->Link=p1?p1:p2;
delete Head2;
return Head3;


}

LinkNode *CreateList(LinkNode *Head,int *Data,int nMax)
{
LinkNode *pNew;
LinkNode *p;
int i;
Head=new LinkNode;
if(Head==NULL) printf("Memory allocate failure!\n");
else
{
Head->nValue=Data[0];
Head->Link=NULL;
p=Head;
for(i=1;i<nMax;i++)
{
pNew=new LinkNode;
pNew->nValue=Data[i];
pNew->Link=NULL;
p->Link=pNew;
p=pNew;
}
}
return Head;
}


/*
LinkNode *CreateList(LinkNode *Head,int *Data,int nMax)
{
int i;LinkNode *p;
Head=new LinkNode;
Head->Link=NULL;
for(i=nMax-1;i>=0;i--)
{
p=new LinkNode;
p->nValue=Data[i];
p->Link=Head->Link;
Head->Link=p;
}
return Head;
}
*/

mergeLink.h
#include <stdio.h>
#include <stdlib.h>

#define HAS_HEADNODE 0
#define MAX1 3
#define MAX2 5

typedef struct LINK_NODE{
int nValue;
struct LINK_NODE *Link;
}LinkNode;

int Data1[MAX1]={1,3,5};
int Data2[MAX2]={2,3,4,6,8};

只要把/*...*/和//里的换上程序运行就正确了,但我不明白这样到底错在哪?麻烦各位大虾了!

#8


delete head2有内存泄露的。
如果你把这个链表指针定为全局变量我觉得这样传指针没错。

p3->Link=p1?p1:p2;//这句是什么意思?
如果是连接余下的链表,应该是
p3->Link==p1?p3->Link=p1:p3->Link=p2;

#9


有内存泄露,我改过之后问题依旧。
p3->Link=p1?p1:p2没错,你错了。

这个程序是死循环,因为p1和p2的值不改变,尽管有p1=p1->link,p2=p2->link,我想知道为什么p1和p2的值不改变!

#10


up一下
我在线等待,请大家帮帮忙了!
有需要源程序的给我email,我发给你。麻烦了!

#11


c/c++是传值调用的,你如果想改变一个指针的值,那么你应该传指针的指针

#12


我不同意以上的看法,我认为其错误只是一个逻辑错误,发生在:

p1=Head1;p2=Head2;
Head3=p3=Head1;
while(p1&&p2)
{
if(p1->nValue<p2->nValue)
{
p3->Link=p1;
p3=p1;
p1=p1->Link;
}

此时有两个list,p1和p3都指向第一个list的头部,而p2指向第二个list的头部.

假设list2的头结点的值大于list1的头结点中的值.
那么:
 p3->Link=p1; 也就是说将list1的头结点的Link指针指向list1的头部,实际就是指向自已, 即p1->Link=p1;
然后
  p3=p1;   实际是多余, p3和p1本来就都指向list1的头部.
p1=p1->Link; 现在我们又指回来的,p1->Link已被作者指向了p1,他现在倒又来抱怨为什么p1不变了, 多么没有公理啊!

#13


p1=Head1;
p3=Head1;
//设Head1->nValue<Head2->nValue,即p1->nValue<p2->nValue,则
p3->Link=p1;
p1=p1->Link;
//以上两句变成:
//Head1->Link=Head1;
//Head1=Head1->Link;
故实际上是一直在使Head1->Link指向自己。

因为你可能想出成另一个链,因此在定义Head3和p3时可定义成LinkNode **Head3和LinkNode **p3.

#14


我当天就明白了,不过登陆不上,只好作罢。  
下面是改动的程序:  
LinkNode  *MergeLink(LinkNode  *Head1,LinkNode  *Head2)  
{//通过直接把head2中的结点插入到head1中来完成合并  
           LinkNode  *p1,*p2,*p;  
           p1=Head1;p2=Head2;  
           //因为插入结点可能引起head1表头的变化,需插入一首结点  
           p=new  LinkNode;  
           p-  >Link=p1;  
           Head1=p1=p;  
           while(p1-  >Link&&p2)  
           {  
                       if(p1-  >Link-  >nValue  <=p2-  >nValue)  
                                   p1=p1-  >Link;  
                       else{  
                                   //取下p2要插入的结点  
                                   p=p2;p2=p2-  >Link;  
                                   //把取下的结点插入到p1中  
                                   p-  >Link=p1-  >Link;  
                                   p1-  >Link=p;  
                       }  
           }  
           if(p2)  p1-  >Link=p2;  
           return  Head1=Head1-  >Link;  
}  
 
分还是要给的,毕竟是帮忙了。  
从这件事得出的经验是:少问多想。有些事情自己想想就可以解决的。