链表
链表的定义
其中链表的定义有带头结点和不带头结点,带头的结点操作起来更方便容易
头指针的优点
单链表结点的定义
#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改变
其实引用不是单纯的起别名,实质原理就是二级指针不过简化了而已。