3.7.2 按位查找
3.8 插入
3.9 删除
4、建立单链表
4.1 头插法——每次插在头结点的后头
4.2 尾插法——元素插入在链表的尾部
1、链表的概念
=======
1.1 链表的定义
线性表的链式存储又称单链表,它是指通过一组任意的存储单元来存储线性表中的数据元素。为了建立数据元素之间的线性关系,对每个链表结点,除存放元素自身的信息外,还需要存放一个指向其后继的指针
1.2 头指针、头结点和首元结点
头指针:是指向链表中第一结点的指针;
首元结点:是指链表中存储第一个数据元素a1的结点;
头节点:是在链表的首元结点之前附设的一个结点;
1.3 空表的表示
1)无头结点的链表:头指针为空时表示空表
2)有头结点的链表:当头结点的指针域为空时表示空表
1.4 头结点的好处
-
由于第一个数据结点的位置被存放在头结点的指针域中,因此在链表的第一个位置上的操作和在表上的其他位置上的操作一致,无须进行特殊处理。
-
无论链表是否为空,其头指针都指向头结点的非空指针(空表中头结点的指针域为空),因此空表和非空表的处理也就得到了统一。
1.5 头结点的数据域
头结点的数据域可以为空,也可以存放线性表长度等附加信息,但此结点不能计入链表长度值
1.6 链表(链式存储结构)的特点
1)结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上还不相邻
2)访问时只能通过头指针进入链表,并通过每个结点的指针域依次向后顺序扫描其他结点,所以寻找的第一个结点和最后一个结点所花的时间不等**(顺序存取法)**
注意:顺序表是随机存取,顺序存储
链表是顺序存取,非顺序存储
2、单链表的定义
========
单链表是由表头唯一确定,因此单链表可以用头指针的名字来命名,若头指针的名是:L,则把链表称为表L
不带头结点的单链表
定义链表头指针L:LinkList L;
定义结点指针P:LNode *p;
typedef struct LNode{ //定义单链表结点类型
ElemType data; //每个结点存放一个数据元素
struct LNode *next; //指针指向下一个结点
}LNode,*LinkList; //LinkList为指向结构体Lnode的指针类型
3、单链表的基本操作
==========
3.1 初始化
//初始化一个空的单链表
bool InitList(LinkList &L){
L=new LNode;//或L=(LinkList)malloc(sizeof(LNode));
L->next=NULL; //空表,暂时还没有任何结点。防止脏数据
return OK;
}
3.2 判断空表
int LIstEmpty(LinkList L){//若L为空表,贼返回1,否则返回0
if(L—>next)//非空
return 0;
else
return 1;
}
3.3 销毁
L指向头结点的指针域,这样就指向了下一个结点,然后再指向下一个结点的指针域,不断操作,销毁单链表
Status DestroyList_L(LinkLIst &L){
Lnode *p;//LinkList p;
while(L){
p=L;//将头结点的指针赋值给p,从头结点开始
L=L->next;
delete p;
}
}
3.4 清空
链表仍存在,但链表中无元素,成为空链表(头指针和头结点仍然在)
算法思路:依次释放所有结点,并将头结点指针域设置为空
Status ClearList(LinkList & L){
Lnode *p,*q;//或者LinkList p,q;
p=L->next;
while§{ //没到表尾
q=p->next;
delete p;
p=q;
}
L->next=NULL; //头结点指针为空
return OK;
}
3.5 求单链表的表长
int ListLength_L(LinkList L){
LinkList p;
p=L->next;
i=0;
while§{
i++;
p=p->next;
}
return i;
}
3.6 取第i个元素值
Status GetElem_L(LinkList L,int i,ElemType &e){
p=L->next; //初始化
j=1; //初始化
while(p&&j<i){ //向后扫描,直到p指向第i个元素或p为空
p=p->next;
j++;
}
if(!p\j>i) return ERROR; //第i个元素不存在
e=p->data; //取第i个元素
return OK;
}//GetElem_L
3.7 查找
3.7.1 按值查找
//按值查找,找到数据域==e的结点(带头结点)
LNode LocateElem(LinkList L,ElemType e){
LNode p=L->next;
//从第1个结点开始查找数据为e的结点
while(p&&p->data!=e)
p=p->next;
return p; //找到后返回该结点的指针,否则返回NULL
}
3.7.2 按位查找
//按位查找,返回第i个元素(带头结点)
LNode GetElem(LinkList L,int i){
if(i<0)
return NULL;
LNode *p; //指针p指向当前扫描到的结点
int j=0; //当前p指向的是第几个结点
p=L; //L指向头结点,头结点是第0个结点(不存数据)
while(p!=NULL&&j<i){ //循环找到第i个结点
p=p->next;
j++;
}
return p;
}
3.8 插入
1)首先找到ai-1的存储位置p
2)生成一个数据域为e的新结点s
3)插入新结点:
-
新结点的指针域指向结点ai
-
结点ai-1的指针域指向新结点
第一步、将p指向的结点的指针域(原本下个结点的地址)赋值给s的指针域 s->next = p->next;
第二步、将s的指针域赋值给将p指向的结点的指针域(原本下个结点的地址)p->next = s
Status ListInsert_L(LinkLIst &L,int i,ElemType e){
p=L;
j=0;
while(p&&j<i-1){//寻找第i-1结点,p指向i-1结点
p=p->next;
j++;
}
if(!p||j>i-1)//大于表长+1或者小于1,插入位置非法
return ERROR;
s=new LNode;//生成新结点s,将结点s的数据域置为e
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}//ListInsert_L
3.9 删除
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
前端面试题汇总
JavaScript
性能
linux
前端资料汇总
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
228aa41f0d.png)
JavaScript
性能
linux
前端资料汇总
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-UtwG6DFn-1712837962212)]