想要理解为什么在链表中使用双重指针这一知识点,首要我们要明白的一点就是,指针变量作为函数的参数时。
它的作用是将一个变量的地址传送到这个函数中。
但如果我们想要在子函数中改变实参的值需要怎么做呢?
一般函数
代码示例:
#include <stdio.h>
int main()
{
//比较两个数a,b的大小并将最大值赋给max_num
void max_a(int *x,int *y,int *max_num);
void max_b(int x,int y,int max_num);
int a,b,max=0;
int *pointer_1,*pointer_2,*pointer_3;
printf("Input 'a' and 'b':\n");
scanf("%d,%d",&a,&b);
pointer_1=&a;
pointer_2=&b;
pointer_3=&max;
max_b(a,b,max);
printf("使用整形变量作为参数 Max=%d\n",max);
max_a(pointer_1,pointer_2,pointer_3);
printf("使用指针变量作为参数 Max=%d\n",max);
}
//x=&a,y=&b,max_num=&max
void max_a(int *x,int *y,int *max_num)
{
*max_num=(*x>*y)?*x:*y;
}
void max_b(int x,int y,int max_num)
{
max_num=(x>y)?x:y;
}
打印结果:
这里我们对两个函数进行分析:max_b这个函数在调用时,a的值传给x,b的值传给y,max_num的值传给max_num。在执行完成max_b函数后,x与y的值进行比较并赋值给函数中的max_num,但并没有影响到a和b的值。函数结束后,x、y、max_num被释放,main函数中的max并没有接收到x、y比较后的最大值。这是因为由于“单向传送”的“值传递”方式,形参不能改变实参的值。
max_a这个函数使用指针变量作为函数的形参,x指向变量a,y指向变量b,max_num指向变量max,在函数执行的过程中使用指针变量所指向的值发生变化,但max_num指向的地址没变,故函数调用结束后,这些值得变化被保留下来。
链表函数(双重指针)
从上面的分析我们可以得出的结论是:
如果要在子函数中使用形参改变实参的值,需要用到指针变量做形参的方式。
那么在链式存储结构的线性表中该怎么实现呢?
代码示例:
#include "stdio.h"
#include "stdlib.h"
typedef char datatype;
typedef struct Node
{
datatype data;
struct Node *next;
}Node;
int main()
{
void CreateList(Node **L);
void print_list(Node *node);
Node *node;
printf("Input data:(End with '@')\n");
CreateList(&node);
printf("OutPut data:\n");
print_list(node);
printf("\n");
return 0;
}
//建立带表头结点的单链线性表L(尾插法)
void CreateList(Node **L)
{
Node *p,*r;
datatype ch;
ch=getchar();
*L = (Node *)malloc(sizeof(Node));
r=*L; /* r为指向尾部的结点 */
while(ch!='@')
{
p = (Node *)malloc(sizeof(Node)); /* 生成新结点 */
p->data = ch;
r->next=p; /* 将表尾终端结点的指针指向新结点 */
r = p; /* 将当前的新结点定义为表尾终端结点 */
ch=getchar();
}
r->next = NULL; /* 表示当前链表结束 */
}
//输出函数
void print_list(Node *node)
{
do
{
node=node->next;
if(node==NULL)break;
printf("%c",node->data);
}while(node!=NULL);
}
打印结果:
这里我们对创建函数进行分析:我们的返回类型依然是void,说明在函数内部已经建立好了链表,而且实参发生了改变。在上面的代码中我们需要改变的是node的值,但是node是一个指针。我们类比前面的一般函数,要改变指针变量的值就要传指针变量node的地址进去,由于双重指针代表的是指针的指针(地址的地址),故我们这里使用双重指针用**L指向*node的地址。
当然在函数调用时也要传入指针变量node的地址–> &node 啦。
链表函数(返回地址)
当然啦,不使用双重指针可不可以啊?
答案是:当然可以了
示例代码:
#include "stdio.h"
#include "stdlib.h"
typedef char datatype;
typedef struct Node
{
datatype data;
struct Node *next;
}Node;
int main()
{
Node *Create_end(void);
void print_list(Node *node);
Node *l;
printf("Input data:(End with '@')\n");
l=Create_end();
printf("OutPut data:\n");
print_list(l);
printf("\n");
return 0;
}
//尾插法
Node *Create_end(void)
{
char ch;
Node *head,*a,*b;
head=(Node *)malloc(sizeof(Node));
a=head;
ch=getchar();
while(ch!='@')
{
b=(Node *)malloc(sizeof(Node));
b->data=ch;
a->next=b;
a=b;
ch=getchar();
}
a->next=NULL;
return head;
}
void print_list(Node *node)
{
do
{
node=node->next;
if(node==NULL)break;
printf("%c",node->data);
}while(node!=NULL);
}
打印结果:
这次我们创建链表使用的方式是:在子函数中建立链表,然后将头指针返回的方式。这也是一种建立链表的方法,在实际应用中我们可以按照自己喜欢的方式编写代码呦。
不足之处,还请批评指正。