目录

一、链表(链式存储结构)的特点

二、单链表的定义和表示

1.带头结点的单链表

2.单链表的存储结构

三、单链表基本操作的实现

1.单链表的初始化(带头结点的单链表)

2.补充单链表的几个常用简单算法

判断链表是否为空:

销毁单链表L:

清空链表:

求链表的表长:

取值——取单链表中第i个元素的内容:

查找:

①按值查找:根据指定数据获取该数据所在的位置(该数据的地址)

②按值查找——根据指定数据获取该数据位置序号

插入——在第i个结点前插入值为e的新结点

删除——删除第i个结点

建立单链表:头插法——元素插入在链表头部,也叫前插

建立单链表:尾插法——元素插入在链表尾部,也叫后插法


一、链表(链式存储结构)的特点

(1)结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻;

(2)访问时只能通过头指针进入链表,并通过每个结点的指针域依次向后顺序扫描其余结点,所以寻找第一个结点和最后一个结点所花费的时间不等。

这种存取元素的方法被称为顺序存取法。

顺序表:随机存取;

链表:顺序存取。

二、单链表的定义和表示

1.带头结点的单链表

单链表是由表头唯一确定,因此单链表可以用头指针的名字来命名,若头指针名是L,则把链表称为表L。

2.单链表的存储结构

数据域 指针域
data next
typedef struct Lnode{    //声明结点的类型和指向结点的指针类型ElemType data;       //结点的数据域struct Lnode *next;  //结点的指针域
}Lnode,*LinkList;        //LinkList为指向结构体Lnode的指针类型

三、单链表基本操作的实现

1.单链表的初始化(带头结点的单链表)

即构造一个空表

算法步骤:

(1)生成新结点作头结点,用头指针L指向头结点;

(2)将头结点的指针域置空。

算法描述:

Status InitList_L(LinkList &L){L=new LNode;    //或L=(LinkList)malloc(sizeof(LNode));L->next=NULL;return OK;
}

2.补充单链表的几个常用简单算法

判断链表是否为空:

空表:链表中无元素,称为空链表(头指针和头结点仍然在)

算法思路:判断头结点指针域是否为空

int ListEmpty(LinkList L){ //若L为空表,则返回1,否则返回0if(L->next)            //非空return 0;elsereturn 1;
}

销毁单链表L:

Status DestroyList_L(LinkList &L){Lnode *p;while(L){p=L;L=L->next;delete p;}return OK;
}

清空链表:

链表仍存在,但链表中无元素,成为空链表(头指针和头结点仍然在)

【算法思路】依次释放所有结点,并将头结点指针域设置为空。

Status ClearList(LinkList &L){      //将L重置为空表Lnode *p,*q;                    //或LinkList p,q;p=L->next;while(p){                       //没到表尾q=p->next;delete p;p=q;}L->next=NULL;                   //头结点指针域为空return OK;
}

求链表的表长:

【算法思路】从首元结点开始,依次计数所有结点

int ListLength_L(LinkList L){    //返回L中数据元素个数LinkList p;p=L->next;                   //p指向第一个结点i=0;while(p){                    //遍历单链表,统计结点数i++;p=p->next;}return i;
}

知识回顾:

带头结点的单链表:

类型定义:

typedef struct LNode{

    ElemType data;

    struct LNode *next;

}LNode,*LinkList;

变量定义:

LinkList L;

LNode *P,*s;

重要操作:

p=L;        //p指向头结点

s=L->next;     //s指向首元结点

p=p->next;     //p指向下一结点

取值——取单链表中第i个元素的内容:

【算法思路】从链表的头指针出发,顺着链域next逐个结点往下搜索,直至搜索到第i个结点为止。因此,链表不是随机存取结构。

【算法步骤】

  1. 从第1 个结点(L->next)顺链扫描,用指针p指向当前扫描到的结点,p初值p=L->next。
  2. j做计数器,累计当前扫描过的结点数,j初值为1。
  3. 当p指向扫描到的下一结点时,计数器j加1。
  4. 当j==i时,p所指的结点就是要找的第i个结点。

【算法描述】

Status GetElem_L(LInkList L,int i,ElemType &e){  //获取线性表L中的某个数据元素的内容,通过变量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

查找:

①按值查找:根据指定数据获取该数据所在的位置(该数据的地址)

【算法步骤】

  1. 从第一个结点起,依次和e相比较。
  2. 如果找到一个其值与e相等的数据元素,则返回其在链表中的“位置”或地址;
  3. 如果查遍整个链表都没有找到其值和e相等的元素,则返回0或“NULL”。

【算法描述】

Lnode *LocateElem_L(LinkList L,Elemtype e){
//在线性表L中查找值为e的数据元素
//找到,则返回L中值为e的数据元素的地址,查找失败返回NULLp=L->next;while(p&&p->data!=e)p=p->next;return p;
}

②按值查找——根据指定数据获取该数据位置序号

【算法描述】

//在线性表L中查找值为e的数据元素的位置序号
int LocateElem_L(LinkList L,Elemtype e){
//返回L中值为e的数据元素的位置序号,查找失败返回0p=L->next;j=1;while(p&&p->data!=e){p=p->next;j++;}if(p)return j;else return 0;
}

插入——在第i个结点前插入值为e的新结点

【算法步骤】

  1. 首先找到a(i-1)的存储位置p。
  2. 生成一个数据域为e的新结点s
  3. 插入新结点:①新结点的指针域指向结点a(i);②结点a(i-1)的指针域指向新结点

①s->next=p->next;②p->next=s;

思考:步骤①和②能互换吗?先执行②,后执行①,可以么?

不可以!会丢失ai的地址

【算法描述】

//在L中第i个元素之前插入数据元素e
Status ListInsert_L(LinkList &L,int i,ElemType e){p=L;j=0;while(p&&j<i-1){p=p->next;++j;}  //寻找第i-1个结点,p指向i-1结点if(!p||j>i-1)return ERROR;       //i大于表长+1或者小于1,插入位置非法s=new LNode;   s->data=e;        //生成新结点s,将结点s的数据域置为es->next=p->next;                 //将结点s插入L中p->next=s;return OK;
}ListInsert_L

删除——删除第i个结点

【算法步骤】

  1. 首先找到a(i-1)的存储位置p,保存要删除的a(i)的值。
  2. 令p->next指向a(i+1)。

p->next=p->next->next;

//将线性表L中第i个数据元素删除
Status ListDelete_L(LinkList &L,int i,ElemType &e){p=L;j=0;while(p->next&&j<i-1){p=p->next;++j;} //寻找第i个结点,并令p指向其前驱if(!(p->next)||j>i-1)return ERROR;    //删除位置不合理q=p->next;                            //临时保存被删除结点的地址以备释放p->next=q->next;                      //改变删除结点前驱结点的指针域e=q->data;                            //保存删除结点的数据域delete q;                             //释放删除结点的空间return OK;
}ListDelete_L

单链表的查找、插入、删除算法时间效率分析

1.查找:

因线性链表只能顺序存取,即在查找时要从头指针找起,查找的时间复杂度为O(n)。

2.插入和删除:

因线性链表不需要移动元素,只要修改指针,一般情况下时间复杂度为O(1)。

但是,如果要在单链表中进行前插或删除操作,由于从头查找前驱结点,所耗时间复杂度为O(n)。

建立单链表:头插法——元素插入在链表头部,也叫前插

  1. 从一个空表开始,重复读入数据;
  2. 生成新结点,将读入数据存放在新结点的数据域中;
  3. 从最后一个结点开始,依次将各结点插入到链表的前端。

【算法描述】

void CreatList_H(LinkList &L,int n){L=new LNode;L->next=NULL;         //先建立一个带头结点的单链表for(i=n;i>0;--i){p=new LNode;      //生成新结点p=(LNode*)malloc(sizeof(LNode));cin>>p->data;     //输入元素值scanf(&p->data);p->next=L->next;  //插入到表头L->next=p;}
}CreatList_H

建立单链表:尾插法——元素插入在链表尾部,也叫后插法

  1. 从一个空表L开始,将新结点逐个插入到链表的尾部,尾指针r指向链表的尾结点。
  2. 初始时,r同L均指向头结点。每读入一个数据元素则申请一个新结点,将新结点插入到尾结点后,r指向新结点。

【算法描述】

//正位序输入n个元素的值,建立带表头结点的单链表L
void CreateList_R(LinkList&L,int n){    L=new LNode;   L->next=NULL;r=L;            //尾指针r指向头结点for(i=0;i<n;++i){p=new LNode;cin>>p->data;   //生成新结点,输入元素值p->next=NULL;r->next=p;        //插到表尾r=p;     //r指向新的尾结点}
}CreateList_R

算法的时间复杂度是:O(n)

链表的特点,单链表的定义、存储结构,单链表的基本操作(判断链表是否为空、销毁链表、清空链表、求链表表长、查找、插入、删除,建立单链表)相关推荐

  1. PTA 6-8 求单链表表长 (10 分)本题要求实现一个函数,Length_LinkList(LinkList L)函数是求出带头结点单链表的长度。

    6-8 求单链表表长 (10 分) 本题要求实现一个函数,Length_LinkList(LinkList L)函数是求出带头结点单链表的长度. 函数接口定义: int Length_LinkList ...

  2. 链表(线性表的一种存储结构)

    链表 一.单链表 1.代码定义单链表 2.两种实现 带头结点 不带头结点 3.单链表的操作 插入 按位序插入 指定结点的后插操作 指定结点的前插操作 删除 按位序删除 指定结点的删除 查找 按位查找 ...

  3. 链表list(链式存储结构实现)_数据结构知否知否系列之 — 线性表的顺序与链式存储篇(8000 多字长文)...

    从不浪费时间的人,没有工夫抱怨时间不够. -- 杰弗逊 线性表是由 n 个数据元素组成的有限序列,也是最基本.最简单.最常用的一种数据结构. 作者简介:五月君,Nodejs Developer,热爱技 ...

  4. c语言判断顺序链表是否为空,数据结构之线性表(五)——单链表(2 初始化,判断空表,销毁,清空,求表长)...

    1.单链表(带头结点)的初始化 即,构造一个空表,如下图, 算法步骤: 1.生成新结点作头结点,用头指针L指向头结点. 2.将头指针的指针域置空. 算法描述: Status InitList_L(Li ...

  5. 《数据结构》c语言版学习笔记——其他链表(线性表的链式存储结构Part2)

    线性表的链式存储结构 数据结构系列文章 第三章 循环链表.双向链表 文章目录 线性表的链式存储结构 前言 一.循环链表 (一)定义 (二)尾指针 二.双向链表 (一)定义 (二)代码 总结 前言 提示 ...

  6. 单链表的插入删除以及逆转

    一.背景说明 参加了某团购网站2014年的校招笔试,里面考到了一道单链表反转的题目.要求每隔k个元素反转一次. 如k=1时,链表1,2,3,4,5,6,7,8反转后为1,2,3,4,5,6,7,8 k ...

  7. 双链表——双链表的定义及其基本操作(初始化、头插法尾插法建表、插入、查找、删除、判空等)

    文章目录 双链表的定义 双链表上的操作 初始化 插入操作 建立双链表 头插法建立双链表 尾插法建立双链表 遍历操作 求双链表的长度 查找操作 按值查找 按位查找 删除操作 判空操作 完整代码及实例 总 ...

  8. 数据结构-图(图的定义、分类、基本术语和存储结构)

    图 图(Graph)是由莱昂哈德·欧拉1在1736年首先引进的一类很重要的非线性结构,可称为图形结构或网状结构.图的应用领域非常广泛,例如:电路分析.工程规划.化合物分类.统计力学.自动化.语言学等. ...

  9. 数据结构--图的存储结构

    系列文章目录 第九话  数据结构之图的存储 文章目录 一.了解什么是图 二.图的定义和基本术语 三.存储结构之邻接矩阵 1.邻接矩阵的介绍 2.邻接矩阵的创建 3.主函数中实现 四.存储结构之邻接表 ...

  10. 图——基本的图算法(一)图的存储结构

    图--基本的图算法(一)图的存储结构 1. 图的存储结构概述 对于图G=(V, E)来说,可以有两种标准的表示方法,一个是邻接矩阵,另一个是邻接链表,这两种方法都可以表示有向图和无向图.除此之外,图的 ...

最新文章

  1. 算力觉醒后,智慧距离勃发就只差一个想法
  2. 树莓内核驱动io框架
  3. 腾讯微博即将关停,十年了,你用过吗?
  4. 【Python】KNN简单的判别预测
  5. 《Head First Python》第四章--持久存储
  6. python自学笔记之开源小工具:SanicDB介绍
  7. 基于Modbus RTU协议的开关量控制采集简介
  8. [html] 写html代码时,怎样才加速写代码的速度呢?你有什么方法?
  9. java流换行符方法_java换行符的使用方法
  10. 水晶底是什么材质_蓝宝石水晶镜面,贵是有道理的!
  11. 【Java】对Java构造器参数问题的若干思考
  12. 常用加密算法概述、比较及使用场景说明
  13. 一流程序员都有哪些高效编程习惯?
  14. js判断浏览器是否安装或启用了flash的方法总结
  15. jq 实现头像(气泡式浮动)
  16. 2011年智能手机:Android继续闪耀或暗淡?
  17. Python-实现九宫格
  18. 基于WADE框架开发流程
  19. MySQL GROUP_CONCAT()函数的排序方法
  20. 抽象类+接口+内部类作业题及答案

热门文章

  1. 画仓鼠大赛 评比开始!
  2. bs架构用php编写,BS架构(bs架构开发用什么语言)
  3. 分布式项目-谷粒商城。
  4. Mybatis08:使用注解开发
  5. 用AI取代SGD?无需训练ResNet-50,AI秒级预测全部2400万个参数,准确率60% | NeurIPS 2021...
  6. Matplotlib的中文字体显示为方块的问题
  7. vmwaretools与open-vm-tools都无法使用的解决方法
  8. thinkPHP3.2.3使用163邮箱发送邮件
  9. 复合平面波超声成像(Matlab Field II仿真)
  10. DS SIMULIA CST STUDIO SUITE 2021.03 SP3 Update Only x64