数据结构-链表(为什么要使用双重指针+详解)-C语言

想要理解为什么在链表中使用双重指针这一知识点,首要我们要明白的一点就是,指针变量作为函数的参数时。

它的作用是将一个变量的地址传送到这个函数中。
但如果我们想要在子函数中改变实参的值需要怎么做呢?

在这里插入图片描述

一般函数

代码示例:

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

打印结果:
在这里插入图片描述

这次我们创建链表使用的方式是:在子函数中建立链表,然后将头指针返回的方式。这也是一种建立链表的方法,在实际应用中我们可以按照自己喜欢的方式编写代码呦。

在这里插入图片描述不足之处,还请批评指正。
在这里插入图片描述

  • 46
    点赞
  • 79
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值