回来了,今天心情好再更新一个。
链表分为单链表,双链表,循环链表。
前文我们说到,线性表他是一个连续的空间,但是 我们如果 a1 然后后面都没有 一直到a2000 那中间的话你如果用线性表的话是不是会造成资源空间浪费?所以说。这时候采取线性表是不好的。那我们该怎么办?这里就引入了单链表。
链表是一种物理存储单元上非连续、非顺序的数据结构,
那我们怎么想呢?链表他是不是一个线?是不是每个元素之间都有关系?哦,当然是,那我们怎么表示?他是不是要具备元素信息和元素序号。信息是不是data 序号是不是指针?
那链表我们就可以用指针+data来构造 这就是我们一开始所想的。
链表由一系列结点(链表中每一个元素称为结点)组成,每一次为一个结构体 动态分配的内存空间,可称之为一个结点,每个结点之间可以是不连续的,但结点内是连续的。结点个数是不受限定的,可以随时删改,这是与数组相比的优点。
结点由指针域和数据域构成。结点之间的联系可以用指针实现,即在结点结构体中定义一个成员项来存放下一结点的首地址,该成员被称为指针域。第n个结点的指针域内存入第n+1个结点的首地址,如此串联下去直到最后一个结点(尾结点),其指针域为NULL,被称为空指针,表示该链表结束。(这是官方定义的)
单链表分为带头单链表和不带头单链表
使用不使用头这个null的 他的关键是看你的操作会不会操作到a1 个人观点,尽可能情况下都使用带头结点,代码方便,可操行强!
这里介绍两个函数 malloc 和free 函数
malloc函数:malloc的全称是memory allocation,中文叫动态内存分配,用于申请一块连续的指定大小的内存块区域以void*类型返回分配的内存区域地址,当无法知道内存具体位置的时候,想要绑定真正的内存空间,就需要用到动态的分配内存,且分配的大小就是程序要求的大小。
这个和c++中的new有着异曲同工之妙 大家可以看看c++中的new
free() 就是释放内存。
这里我们都需要用到
首先 我们要建立单链表;
需要什么? 一个工作指针 一个头结点
int CreateListTail(Linklist &L,int n){
LNode *s,*p;
L=(Linklist *)malloc(sizeof(LNode));//创建头结点
L->next = NULL; //将头结点next域置空
s=L;//s,l同时指向头结点,开始时头结点和尾结点是同一个
for(int i=0;i<n;i++){
p=(LNode *)malloc(sizeof(LNode));//创建数据结点,函数malloc分配了一个LNode类型的结点空间,并将其首地址存入指针变量p中
scanf("%d",&p->data);
s->next=p;//新结点插入到当前链表的表尾
s=p;//使s指向尾结点
}
}
这些创建的代码的名字,虽然理论上你咋定义都可以。但是你要为监考老师,为工作,更是为了以后提桶跑路后你的代码接手的新人。还是这种官方统一的比较合适。
s是尾指针 p是工作指针;L(linklistl)是头指针。那个Lnode还需要自己再定义 就是之前我们说的那个数据域和指针域。c的话需要typedef struct 记住了 不是c++直接struct
这样就可以创建好一个单链表了。
那创建好了我们就要增删查了
那就先查找吧 查找的话不需要对链表进行改变 不需要用*;
这个就像key-value一样 我们现在要查东西,肯定不给你指针,因为给了就给出了他的位置
所以她肯定是让你用value(值)来查找到
int getelem2(Linklist L, ElemType e)
{
int i=0;
Lnode *p = L->next;
while (p!=NULL&&p->data!=e)当p指向的不是空值域然后p这个数据指向的结果不是e的时候
{
p = p->next;
i++;
}
if(p!=NULL)return(i);
else return p,i;
}
那接下来就是插入的操作了
怎么插入呢?是不是先建立一个这个,上图
咱们先创建一个和ai那个一样的 让他也指向ai+1;然后可以改变了让ai那个指针指向e,改变一下意思就是3这条路被1和2给段了
int ListInsert(LinkList &L,int i ,ElemType e)
{
LNode *p,*s;
p = L;
int j = 0;
while (p && j<i-1) /*寻找第i-1个结点*/
{
p = p->next;
++j;
}
if (!p || j >i)
return ERROR; /*第i个元素不存在*/
s = (LNode)malloc(sizeof(Node)); /*生成新的结点*/
s->data = e;
s->next = p->next; /*将p的后继结点赋值给s的后继*/
p->next = s; /*将s赋值给p的后继*/
return OK;
}
那么删除是不是也是同一个道理?只要我们把旁边的两个指针给相连 不和中间的ai连,是不是就把ai给他断了,就可以删除了,当然,记得free()一下,清理内存
int ListInsert(LinkList &L,int i ,ElemType e)
{
LNode *p,*s;
p = L;
int j = 0;
while (p && j<i-1) /*寻找第i-1个结点*/
{
p = p->next;
++j;
}
if (!p || j >i)
return ERROR; /*第i个元素不存在*/
s = (LNode)malloc(sizeof(Node)); /*生成新的结点*/
s->data = e;
s->next = p->next; /*将p的后继结点赋值给s的后继*/
p->next = s; /*将s赋值给p的后继*/
return OK;
}
好了,我要去打cf了