这是高程书上一道完整的例题,我抄下来在下面,有些地方不理解,请求高手详细的解说。
可能是对指针的部分还没理解吧,我有点纳闷了。
1.first函数那里参数用指向指针的指针——main函数里调用用的是指针的地址,类型是匹配了,可是创建这个链表一定要用二级指针来实现吗?
2.接一问。在main函数里的first_insert(&link1,i);语句可以通过first_insert(link1,i);这种方式来实现吗?如果可以main和first的函数部分需要如何相应的改动?
3.在first函数里我始终没有看到有头指针head的概念出现啊?为什么书上说p是头指针?
4.接上问。在main中for(i=1;i<10;i++)first_insert(&link1,i);这句到底是如何运作的?头指针的移动在程序中哪句得以体现?
5.为何在main中for(i=1;i<10;i++)first_insert(&link1,i);这句链表始终在增加,当到了reverse函数里再次调用first函数时,这时链表不是在继续增加而是变成了创建出了一个新链表了?
6.接一问。为何reverse函数中的参数只需要用到*p这样的一级指针,而first函数中却用到二级指针??是什么原因?
完毕。
===================
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int val;
struct node *next;
}NODE;
void first_insert(NODE **p,int v)/*在已知链表的首表元之前插入一个指定值的表元*/
{
NODE *q=(NODE *)malloc(sizeof(NODE));
q->val=v;
q->next=*p;/*使q成为表首单元*/
*p=q;/*头指针*p指向q*/
}
NODE *reverse_copy(NODE *p)/*按已知链表复制出一个新链表,但新链表的表元链按顺序与已知链表的表元链接顺序相反*/
{
NODE *u;
for(u=NULL;p;p=p->next)first_insert(&u,p->val);/*这里u是指向新链表的表首指针*/
return u;
}
void print_link(NODE *p)/*用来输出链表中各表元的值*/
{
for(;p;p=p->next)/*从表首p开始直到表尾*/
printf("%d\t",p->val);
printf("\n");
}
void free_link(NODE *p)/*用来释放链表全部表元空间*/
{
NODE *u;
while(p!=NULL)
{
u=p->next;free(p);
p=u;/*这里u是临时指针,总在释放当前表元p前,记下它的下个表元,因此在p释放后,让p指向u为下次循环做好准备*/
}
}
void main()
{
NODE *link1,*link2;int i;
link1=NULL;
for(i=1;i<10;i++)first_insert(&link1,i);
link2=reverse_copy(link1);
print_link(link1);free_link(link1);
print_link(link2);free_link(link2);
}
1.first函数那里参数用指向指针的指针——main函数里调用用的是指针的地址,类型是匹配了,可是创建这个链表一定要用二级指针来实现吗?
在这道题里,他显然是要减少一次指针的复制来返回你现在的头指针了,
因为NODE** p 就已经帮你将这些做好,可能这样说你不会理解,这些东西很基础,
你应该重新将指针部分好好看看;指针传递返回值是C语言的一大特色。
2.接一问。在main函数里的first_insert(&link1,i);语句可以通过first_insert(link1,i);这种方式来实现吗?如果可以main和first的函数部分需要如何相应的改动?
可以
解答
NODE first_insert(NODE* p,int v)/*在已知链表的首表元之前插入一个指定值的表元*/
{
NODE* q=(NODE *)malloc(sizeof(NODE));
q->val=v;
q->next=p;/*使q成为表首单元*/
p=q;/*头指针*p指向q*/
return p;
}
void main()
{
NODE *link1,*link2;int i;
link1=NULL;
for(i=1;i<10;i++)
link1 = first_insert(link1,i);
link2=reverse_copy(link1);
print_link(link1);free_link(link1);
print_link(link2);free_link(link2);
}
3.在first函数里我始终没有看到有头指针head的概念出现啊?为什么书上说p是头指针?
强烈建议你区看源码,这个注释还不明白?哪里不懂再问;
void first_insert(NODE **p/*这个是头指针*/,int v)/*在已知链表的首表元之前插入一个指定值的表元*/
{
NODE *q=(NODE *)malloc(sizeof(NODE));
q->val=v;
q->next=*p;/*使q成为表首单元*/
*p=q;/*头指针*p指向q*/
}
4.接上问。在main中for(i=1;i<10;i++)first_insert(&link1,i);这句到底是如何运作的?头指针的移动在程序中哪句得以体现?
q->next=*p;/*使q成为表首单元*/
*p=q;/*头指针*p指向q*/
关键是这两句了q->next = p;就是q链接在p的前面;
*p=q; 然后p再挪到q的地方就是原来p的前面,使p永远走在世界的前列
5.为何在main中for(i=1;i<10;i++)first_insert(&link1,i);这句链表始终在增加,当到了reverse函数里再次调用first函数时,这时链表不是在继续增加而是变成了创建出了一个新链表了?
NODE *reverse_copy(NODE *p)/*按已知链表复制出一个新链表,但新链表的表元链按顺序与已知链表的表元链接顺序相反*/
{
NODE *u;
for(u=NULL;p;p=p->next)first_insert(&u,p->val);/*这里u是指向新链表的表首指针*/
return u;
}
我不知道你是否看到它传入的不是二级指针,它返回的是一个新的节点u,看来你真的
应该好好的看看指针了
都说完了。
实际上就是一句话
int fun()
{
int i = 10;
return i;
}
void fun(int* i)
{
*i = 10;
}
这两个函数实现的功能是一样的,但是后者效率要高一些
你用这个去解释那个程序就很简单了
tjjmmtds (看我72变) :
请注意这里的函数原型声明,
void first_insert(NODE **p,int v);
NODE *reverse_copy(NODE *p);
void print_link(NODE *p);
void free_link(NODE *p);
只有第一个插入链表函数first_insert使用了二级指针,其他的都是使用了一级指针!
》》3.在first_insert函数里我始终没有看到有头指针head的概念出现啊?为什么书上说p是头指针?
答:在main函数里说明了如下内容
NODE *link1;
link1 = NULL;
for(i=1;i<10;i++) first_insert (&link1,i);
再看first_insert函数原型:
void first_insert(NODE **p,int v);
这里的函数参数NODE **p赋值是通过传地址实现的!!!