目录
1、什么是链表?
链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
如上图所示:链式结构在逻辑上是连续的,但在物理存储方面并不一定是连续的;现实中的结点一般都是从堆上申请出来的;另外从堆上申请的空间,是按照一定的策略来分配的,两次申请的空间可能连续,也可能不连续。
2、链表的分类
2.1 单向或者双向
2.2 带头或者不带头
2.3 循环或者非循环
通过以上三种大类类型的不同组合,对于链表而言总共有8中组合,但一般而言,我们常用的就是无头单向非循环链表和带头双向循环链表这两种结构,如下所示:
2.4 无头单向非循环链表和带头双向循环链表对比
- 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构得子结构,如哈希桶、图得领接表等。
- 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用得链表数据结构都是带头双向循环链表,虽然该结构相比其他类型的链表最复杂,但使用代码实现了以后,会给数据结构的使用带来诸多优势,后面将会通过代码的形式展现出来。
3、无头单向非循环链表
为了方便阅读,在后面的学习过程中,将无头单向非循环链表简称为:单向链表;将带头双向循环链表简称为:双向链表。
3.1 总体学习框架
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//利用结构体定义单链表结点
typedef int SLTDataType;
typedef struct SListNode
{
SLTDataType data;
//记录下一个结点的地址
struct SLIistNode*next;
}SLTNode;
//打印单链表函数
void SListPrint(SLTNode*phead);
//尾插
void SListPushBack(SLTNode**pphead, SLTDataType x);
//因为会重复使用创建节点,所以创建节点函数
SLTNode*BuyListNode(SLTDataType x);
//头插
void SListPushFront(SLTNode**pphead, SLTDataType x);
//尾删
void SListPopBack(SLTNode**pphead);
//头删
void SListPopFront(SLTNode**pphead);
//查找
SLTNode* SListFind(SLTNode*pphead, SLTDataType x);
//在某一位置插入
void SListInsert(SLTNode**pphead, SLTNode*pos, SLTDataType x);
//在某一位置删除
void SListErase(SLTNode**pphead, SLTNo