链式存储结构:用一组物理位置任意的存储单元来存放线性表的数据元素。
这组存储单元既可以是连续的,也可以是不连续的,甚至是零散分布内存中的任意位置。
链表中的元素的逻辑次序与物理次序不一定相同
例子:
线性表(赵,钱,孙,李,周,吴,郑,王)
顺序表:存储地址依次增加
链表:存储地址不规律,存储每一个元素时,也要存储下一个元素的存储地址。没有下一个元素,既为NULL。
结点=数据域+指针域(链指针)数据元素的存储映像。
数据域:存储元素数字数据
指针域:存储直接后继结点的存储位置
链表:n个结点由指针链组成一个链表
它是线性表的链式存储映像,称为线性表的链式存储结构。
单链表,双链表,循环链表
1.结点只有一个指针域的链表,称为单链表或者线性链表。
2.结点有两个指针域的链表,称为双链表。
3.首尾相接的链表称为循环链表
头节点,头指针,首元结点:
头指针:是指向链表中第一个结点的指针。
首元结点:是指链表中存储第一个数据元素a1的结点。
头结点:是在链表的首元结点之前附设的一个结点。
(1):不带头结点:第一个数直接指向a1
(2):带头结点:第一个数指向一个地址,任何下一个才是a1。
如何表示空表;
1.无头结点时,头指针为空时表示空表
2.有头结点时,当头结点的指针域为空时表示空表。
讨论2:在链表中设置头结点有什么好处?
1.便于首元结点的处理
首元结点的地址保存在头结点的指针域中,所以在链表的第一个位置上的操作和其它位置一致,无需进行特殊处理。
2.便于空表和非空表的统一处理
无论链表是否为空,头指针都是指向头结点的非空指针,因此空表和非空表的处理也就统一了。
讨论3:头结点的数据域内装的是什么?
头结点的数据域可以为空,也可以存放线性表长度等附加信息,但此结点不能计入链表长度值。
链式(链式存储结构)的特点:
(1).结点在存储器中的位置是任意的,既逻辑上相邻的数据元素在物理上不一定相邻。
(2).访问时只能通过头指针进入链表,并通过每个结点域依次向后顺序扫描其余结点,所以寻找第一个结点和最后一个结点所花费的时间不等。
顺序存取法:每个结点域依次向后顺序扫描其余结点。
顺序表-->随机抽取 链表---->顺序存取
带头结点的单链表
空表:带头结点。
单链表是由表头决定的,因此单链表可以用头指针的名字来命名,若头指针名是L,则把链表称为表L。
单链表的存储结构:
数据域 data 指针域next
typedef struct Lnode{//声明结点的类型和指向结点的指针类型
ElemType data;//结点的数据域
struct Lnode *next;//结点的指针域
}Lnode,*LinkList;//LinkList为指向结构体Lnode的指针类型。
定义链表:LinkList L;
定义结点指针p :LNode *p;<==>LinkList p;
例子:存储学生的学号,姓名,成绩的单链表结点类型定义:
typedef Struct student{
char num[8];//数据域
char name[8];//数据域
int score;//数据域
struct student *next;//指针域
}Lnode,*LinkList;
LinkList L;.
单链表的基本操作的实现
带头结点单链表的初始化:既构造一个空表。
算法步骤:
1.生成新结点作头结点,用头指针L指向头结点。
2.将头结点的指针域置空。
Status InitList_L(LinkList &L){
L=new LNode;
L->next=NULL;
return OK;
}
判断链表是否为空
算法思路:判断头结点指针域是否为空
int ListEmpty(LinkList L){
if(L->next)return 0;//非空
else return 1;
}
单链表的销毁:链表销毁后不存在
算法思路:从头开始,依次释放所有结点
Status DestroyList_L(LinkList &L)//销毁单链表L
{
Lnode *p;
while(L){
p=L;
L=L->next;
delete p;(new)//free(p)malloc().
}
return OK;
}
清空单链表:链表仍然存在,但是无元素,成为空链表,头指针和头结点依然存在。
算法思路:依次释放所有的结点,并将头结点指针域设置为空。
status ClearList(ListList &L)
{
Lnode *p,*q;
p=L->next;
while(p){
q=p->next;
delete p;
p=q;
}
L->next=NULL;
return OK;
}
求链表的表长
算法思路:从首元结点开始,依次计数所有的结点
int ListLength_L(LinkList L){
LinkList p;//Lnode *p;
p=L->next;//P指向第一个结点
i=0;
while(p){
i++;
p=p->next;
}
return i;
}