链表
可以解决顺序表存储空间上限,插入和删除效率低的问题
概念
链表:链式存储的线性表
链表的组成:由一个个节点组成
节点:由数据域和指针域组成
数据域:存放数据的区域
指针域:存放下一个节点地址的指针
种类
单向链表,双向链表,循环链表
单向链表
概念
只能通过头节点或者头指针单向的访问后继节点的链表,称为单向链表。每个节点的指针域只记录其后继节点的地址。(火车结构)
单向链表的组成
头节点结构体格式:
struct head
{
int len; //头节点的数据域
struct node *next;
}
普通节点结构体格式:
struct node
{
int data; //普通节点的数据域
struct node *next;
}
单向链表节点的结构体格式
typedef int DataType;
typedef struct node
{
union
{
int len; //头节点的数据域
DataType data; //普通节点的数据域
};
struct node *next; //节点的指针域
}linkList,*linkListPtr;
单向链表的相关操作(功能函数的封装)
创建
创建应该头节点,在堆区申请头节点大小的空间,返回给主程序使用
函数返回值:节点指针类型
注意判断申请的空间是否合法
申请成功,需要将头节点的数据域置0,指针域置NULL
判空
判断头节点的数据域是否为0,或者指针域是否指向NULL
函数返回值:逻辑值--->int
参数列表:
注意判断申请的空间是否合法
申请成功,需要将头节点的数据域置0,指针域置NULL
申请节点封装数据
头插
将数据节点插入链表中
参数列表:头指针,要插入的·数据
注意判断申请的空间是否合法
遍历
从第一个普通节点开始遍历,依次打印输出节点数据域里的数据
参数列表:头指针
尾插
在尾部插入数据
参数列表:头指针,插入数据
注意判断申请的空间是否合法
任意位置插入
在任意位置插入数据
参数列表:头指针,插入位置,插入数据
注意判断申请的空间是否合法
头删
参数列表:头指针
注意判断申请的空间是否合法
需要判空
尾删
参数列表:头指针
注意判断申请的空间是否合法
需要判空
任意位删除
参数列表:头指针,删除位置
注意判断申请的空间是否合法
需要判空
按位置修改
参数列表:头指针,修改位置,新值
注意判断申请的空间是否合法
需要判空
判断修改位置是否合法
按值查找返回地址(不考虑数值相同,若相同返回第一个)
参数列表:头指针,修改位置,新值
注意判断申请的空间是否合法
需要判空
判断修改位置是否合法
反转
参数列表:头指针
注意判断申请的空间是否合法
销毁
参数列表:头指针
注意判断申请的空间是否合法
单向链表的优缺点
优点:存储空间没有上限,插入删除效率高
缺点:修改和查找效率低,只能单向的向后遍历后续节点,不能向前遍历前驱节点
双向链表
概念
由于单向链表只能通过指针单向的访问后继节点,不能向前遍历前驱节点,所以要引入双向链表。
双向链表:在保持单向链表的基础上,既可以向后遍历后继节点,也可以向前遍历前驱节点。 双向链表的组成
头节点结构体格式:
struct head
{
int len; //头节点的数据域
struct node *next;
}
普通节点结构体格式:
struct node
{
int data; //普通节点的数据域
struct node *next;
}
双向链表节点的结构体格式
typedef int DataType;
typedef struct node
{
union
{
int len; //头节点的数据域
DataType data; //普通节点的数据域
};
struct node *next; //指向下一个节点的指针
struct node *prior; //指向前一个节点的指针
}doubleLink,*doubleLinkPtr;
双
向链表的相关操作(功能函数的封装)
创建
函数返回值:节点指针类型
注意判断申请的空间是否合法
申请成功,需要将数据域置0,指针域置NULL
判空
参数列表:头指针
注意判断申请的空间是否合法
申请节点,封装数据
参数列表:插入数据
注意判断申请的空间是否合法
头插
参数列表:头指针,插入数据
注意判断申请的空间是否合法
遍历
参数列表:头指针
注意判断申请的空间是否合法
任意位置插入
参数列表:头指针,插入位置,插入数据
注意判断申请的空间是否合法