单链表的定义和表示
对于每一个数据元素 a1,除了要存储本身信息外,还要存储下一个数据元素的地址。这里就要用到结构指针。这两部分信息组成的数据元素 a1 的存储映像,称为结点,存储信息的域称为数据域;存储直接后继存储位置的称为指针域。指针域中存储的信息称作指针和链。n 个结点的链结成一个链表,即为线性表。
特点:用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。
typedef struct LNode
{
ElemType data; //结点的数据域
struct LNode *next; //结点的指针域
} LNode, *LinkList; //LinkList为指向结构体LNode的指针类型
一.初始化
1.生成新结点作为头结点,用头指针L指向头结点。
2.头结点的指针域置空。
Status InitList(LinkList &L)
{//构造一个空的单链表L
L = new LNide; //生成新结点作为头结点,用头指针L指向头结点
L->next = NULL; //头结点的指针域置空
return OK;
}
二.取值
1.用指针p指向首元结点,用 j 做计数器初值赋为 1 。
2.从首元结点开始依次顺着链域 next 向下访问,只要指向当前节点的指针 p 不为空(NULL),并且没有到达序号为 i 的结点,则循环执行以下操作。
a. p 指向下一个节点;
b, 计数器 j 相应加 1 。
c. 退出循环时,如果指针 p 为空,或者计数器 j 大于 i,说明指定的序号 i 值不合法(i 大于表长 n 或 i 小于等于 0),取值失败返回ERROR;否则取值成功,此时 j = i时, p 所指的结点就是要找的第 i 个结点用参数 e 保存当前结点的数据域,返回OK。
Status GetElem(LinkList L, int i, ElemType &e)
{//带头节点的单链表L中根据序号i获取元素的值,用e返回L中第i个数据元素的值
p = L->next ;
j = 1; //初始化,p指向首元结点,计数器j初值赋为1
while(p && j < i) //顺链域向后扫描,直到 p 为空或 p 指向第 i 个元素
{
p = p->next; // p 指向下一个结点;
++j; //计数器 j 相应加 1;
}
if(!p || j > 1) return ERROR; //i 值不合法 i > n 或 i <= 0
e = p->data; //取第 i 个结点的数据域
return OK;
}
三.查找
1.用指针 p 指向首元结点。
2.从首元结点开始依次顺着链域 next 向下查找,只要指向当前节点的指针 p 不为空,并且 p 所指向的数据域不等于给定值 e ,则循环执行以下操作:p 指向下一个结点。
3.返回 p 。若查找成功,p 此时即为结点的地址值,若查找失败,p 的值即为NULL。
LNode *LocateElem (LinkList L, ElemType e)
{//在带头节点的单链表L中查找值为e的元素
p = L->next; //初始化,p指向首元结点
while(p && p->data != e) //链域向后扫描,直到p为空或p所指向结点数据域等于e
p = p->next; //p指向下一个结点
return p; //查找成功弄返回值为e的结点地址p,查找失败返回NULL
}
四.插入
1.查找结点 a(i-1),并由指针 p 指向该结点。
2.生成一个新的结点 *s。
3.将新结点 *s 的数据域置为e.
4.将新结点 *s 的指针域指向结点 ai。
5.将结点 *p 的指针域指向新结点 *s。
Status ListInsert(LinkList &L, int i, ElemType e)
{//在带头节点的单链表L中 第i个位置插入值为e的新结点
p = L;
j = 0;
while(p && (j < i - 1))
{ //查找第i - 1个结点,p指向该节点
p = p->next;
++j;
}
if(!p || j > i - 1) return ERROR; //i > n + 1 或者 i < 1
s = new LNode; //生成新结点*s
s->data = e; //将结点*s的数据域置为e
s->next = p->next; //将结点*s的指针域指向结点a
p->next = a; //将结点*p的指针域指向结点*s
return OK;
}
五.删除
1.查找结点 a(i-1),并由指针 p 指向该结点。
2.临时保存待删除结点 ai 的地址在 q 中,以备释放。
3.将结点*p的指针域指向 ai 的直接后继结点。
4.释放结点 ai 的空间。
Status ListDelete(LinkList &L, int i, ElemType e)
{//在带头节点的单链表L中 删除第i个元素
p = L;
j = 0;
while(p->next && (j < i - 1))
{ //查找第i - 1个结点,p指向该节点
p = p->next;
++j;
}
if(!(p->next) || j > i - 1) return ERROR; //i > n 或者 i < 1 ,删除位置不合理
q = p->next; //生成新结点*s
p->next = q->next; //临时保存待删除结点的地址,以备释放。
s->next = p->next; //改变删除结点前驱结点的指针域
delete q; //释放删除结点的空间。
return OK;
}
六.创建单链表(前插法)
1.创建一个只有头结点的空链表。
2.根据待创建链表包括的元素个数 n ,循环 n 次执行以下操作:
a.生成一个新结点 *p。
b.输入元素值赋给新结点 *p 的数据域。
c.将新结点 *p 插入到头结点之后。
void CreatList_H(LinkList &L, int n)
{//逆位序输入n个元素的值,建立带表头结点的单链表L;
L = new LNode;
L->next = NULL; //先建立一个带头结点的空链表
for(i = 0; i < n; ++i)
{
p = new LNode; //生成新结点*p
cin>>p->data; //输入元素值赋给新结点 *p 的数据域。
p->next = L->next;L->next = p; //将新结点 *p 插入到头结点之后。
}
}
七.创建单链表(后插法)
1.创建一个只有头结点的空链表。
2.尾指针 r 初始化,指向头结点。
3.根据待创建链表包括的元素个数 n ,循环 n 次执行以下操作:
a.生成一个新结点 *p。
b.输入元素值赋给新结点 *p 的数据域。
c.将新结点 *p 插入到尾结点 *r 之后。
d.尾指针 r 指向新的尾结点 *p。
void CreatList_R(LinkList &L, int n)
{//正位序输入n个元素的值,建立带表头结点的单链表L;
L = new LNode;
L->next = NULL; //先建立一个带头结点的空链表
r = L; //尾指针 r 初始化,指向头结点。
for(i = 0; i < n; ++i)
{
p = new LNode; //生成新结点*p
cin>>p->data; //输入元素值赋给新结点 *p 的数据域。
p->next = NULL; r->next = p; //将新结点 *p 插入到尾结点 *r 之后。
r = p; //尾指针 r 指向新的尾结点 *p。
}
}
文章借鉴:《数据结构》(C语言版)(第二版)人民邮电出版社