嘉明的数据结构学习Day3——单链表的头插法和尾插法

链表

链表的定义

在这里插入图片描述
其中链表的定义有带头结点和不带头结点,带头的结点操作起来更方便容易
头指针的优点
在这里插入图片描述

单链表结点的定义

在这里插入图片描述

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

typedef int ElemType;
//定义链表的结点
typedef struct LNode {
	ElemType data;//数据域
	struct LNode* next;//指针域
}LNode, * LinkList;//别名

其中插入操作中有头插法和尾插法,下面我们一一介绍

头插法

头插法顾名思义就是插在头结点的后面
代码如下:

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

typedef int ElemType;
//定义链表的结点
typedef struct LNode {
	ElemType data;//数据域
	struct LNode* next;//指针域
}LNode, * LinkList;//别名

//头插法,即从头结点后面插入。比如输入的是12345,插入之后可能顺序就是54321
LinkList creatList1(LinkList& L) {
	LNode* s;//定义要插入的指针
	int x;//定义需要插入的数据域
	L = (LinkList)malloc(sizeof(LNode));//头结点,没有数据域(默认值)。用于表明这是指针
	L->next = NULL;//因为头结点的指向下一个结点,但是还没定义所以是NULL
	scanf("%d", &x);
	//使用9999作为中止循环的结束符
	while (x != 9999) {
		s = (LinkList)malloc(sizeof(LNode));
		s->data = x;//把数据赋值给插入结点的数据域
		s->next = L->next;//把指针指向的下一个结点赋给插入的结点的指针(头插法)
		L->next = s;//然后再把指针指向的结点指向插入的结点
		scanf("%d", &x);//再次读取数据知道x等于9999为止
	}
	return L;
}

int main() {
	LinkList L;
	creatList1(L);
}

在这里插入图片描述
可以看到我们输入的顺序是3 4 5 6但是得到的结果确实 6 5 4 3。这就是头插法。
在这里插入图片描述

尾插法

思路添加一个尾结点,这样头结点就可以指向下一个元素之后保持不变了,只需要尾结点移动即可。

//尾插法,即从头结点后面插入。比如输入的是12345,插入之后可能顺序就是12345
LinkList creatList_Tail(LinkList& H) {
	LNode *s,*r;//定义要插入的结点和表尾结点
	int x;//定义需要插入的数据域
	H = (LinkList)malloc(sizeof(LNode));//头结点,没有数据域(默认值)。用于表明这是指针
	r = H;//链表为空尾指针指向头结点
	scanf("%d", &x);
	//使用9999作为中止循环的结束符
	while (x != 9999) {
		s = (LinkList)malloc(sizeof(LNode)); //申请空间创建新的结点
		s->data = x;
		r->next = s;
		r = s;
		scanf("%d", &x);
	}
	r->next = NULL;
	return H;
}

在这里插入图片描述
在这里插入图片描述

脑短路以及解决

问题

一开始做头插法的时候,看到了下面这个函数,想到了引用

LinkList creatList1(LinkList& L)

我就在想,既然LinkList本来就是一个指针

LinkList L

L本来就是一个指针变量存的是地址,引用是实际上是别名(但是理解的太肤浅了),那为什么我不直接这样定义

LinkList creatList1(LinkList L)

把&删掉呢?反正L传的都是地址。我们直接传过去对地址进行操作不是一样吗?
就像这样

LinkList creatList1(LinkList L)//错误的

int main() {
	LinkList L;
	creatList_Head(L);
	}

我以为拿到了指针L把地址传过去,形参里的L是在操作主函数的L了。。。。

解决方法以及总结

然后我就去搜索,直到看到了这篇文章我恍然大悟。
https://blog.csdn.net/HurryRabbit/article/details/105524133
它说道:
地址也只是一个"无符号的整型"数据,其本身也跟普通变量一样是值的传递, 区别在于,我们可以通过这个值来去物理内存中找到的具体地址空间, 然后对这个地址空间进行访问。

形参只得到了传过去的地址。不意为着你就再操作这个形参的指针变量就是操作实参!!!!!
但是你可以通过✳+形参的指针变量来改变实参指针变量所指向的值。

但我们需要的使用p=malloc来申请空间。所以如果这样下去也只是形参得到申请空间,但是使局部变量,函数运行完毕就被系统销毁,所以实参只做了传递地址而没有申请到空间。
其实只是把地址传过去,形参又是系统在栈开辟的一个新的指针变量,你只是把地址传过去而已,没有进行任何操作使主函数的L改变

其实引用不是单纯的起别名,实质原理就是二级指针不过简化了而已。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值