文章目录
前言
重新学习数据结构,从单链表开始,前面的数组就不看了。
文中图表是用GitMind制作,浏览器搜一下就能在线使用。
一、单链表的定义
1.什么是单链表
链表和顺序表(数组)一样,都是在逻辑上线性存储,所以都归于线性表的行列。但在物理存储上不一样,顺序表在逻辑还是物理上都是顺序存储,链表在物理存储上是离散型的存储。这样的存储结构就使得链表可以很方便地改变容量、删除结点、增加结点,但同时也让链表存取一个数据变得很麻烦。
2.定义代码
typedef struct LNode {
ElemType data; //数据域
struct LNode* next; //指针域
}LNode, *LinkList;
注意:
- 若定义时不用typedef,则以后使用LNode类型都要加上struct关键字
- 使用LNode时,是为了强调这是一个结点
- 使用LinkList时,是为了强调这是一个链表
二、单链表的操作
1.初始化
①带头结点
bool InitList(LinkList &L)
{
//初始化一个带头结点的单链表
L = new LNode;
if (L == NULL)
return false; //内存不足,分配失败
L->next = NULL;
return true;
}
头指针指向头结点,头结点的数据域通常不存放数据(也可以用来存放链表长度这样的信息),头结点的指针域所指向的才是链表真正的第一个结点。
补充:new的用法
int* p = new int[5]; //分配5个int类型的空间,并将这片空间的地址给p
int* p = new int(5); //分配1个int类型的空间,并赋初值5
②不带头结点
bool InitList(LinkList &L)
{
//初始化一个不带头结点的空表
L = NULL;
return true;
}
2.判空
bool Empty(LinkList L)
{
//判断单链表是否为空
if(L->next == NULL) //若是不带头结点,则替换为 if(L == NULL)
return true;
else
return false;
}
3.插入
要想在链表(带头结点)的第i个位置插入一个元素,就需要先通过遍历找到第i-1个位置,再创建一个新的结点并把数据e存入新的结点,最后把这个新结点与链表连在一起。
若是不带头结点的链表想插入数据要稍微麻烦些,需要对i=1进行特殊处理多写几行代码,其余部分代码相同。
bool ListInsert(LinkList &L, int i