1.2 线性表
1. 线性表的逻辑结构
线性表: 是具有相同特征的数据元素的一个有限序列,除第一个和最后一个元素外,每个元素都只有一个之间前驱和一个直接后驱。表示为:(a1,a2,… ai… an)
逻辑结构: 是线性结构。
2. 线性表的存储结构
线性表的存储结构有两种: 顺序存储结构 和 链接存储结构 。
顺序表:具有顺序存储结构的线性表
线性链表:具有链接存储结构的线性表
线性链表:
单链表:每个结点有一个指针域,有一个头指针h而无尾指针,表中最后一个结点的指针域是空的。其结构简单,但查找效率不高(查某结点总要从头开始)
循环链表:每个结点有一个指针域,有一个头指针h和一个尾指针r,表中最后一个结点的指针域不是空的,尾指针指向表的第一个结点。它形成环行结构,可显著提高查找效率(从任何结点出发都能查到所需结点)。
双向链表:每个结点有两个指针域,一个指向直接前驱,一个指向直接后驱。它形成双环行结构,可进一步提高查找效率(从某结点出发,既可以向前查又可以向后查).
3. 线性表的运算
(1) 基本运算
插入:在表中任一位置插入一个结点
删除:删除表中任一结点
修改:修改表中给定结点的值
读值:读取表中给定结点的数据
求长:计算表中结点的个数
清表:清除表中结点,使其成为空表
检索:找出表中给定特征的结点
排序:按给定要求对表中元素重新排序
(2) 常用算法举例
· 顺序表的插入
例题: ** 向线性表中第i个元素位置插入一个新元素 **
算法步骤:
1)检查i值是否超出所允许的范围(1≤i≤n+1),若超出,则进行“超出范围”错误处理;
2)将线性表的第i个元素和它后面的所有元素均向后移动一个位置;
3)将新元素写入到空出的第I个位置上;
4)使线性表的长度增1。
· 顺序表的删除
例题: ** 删除线性表中第i个元素 **
算法步骤:
1)检查i值是否超出所允许的范围(1≤i≤n),若超出,则进行“超出范围”错误处理;
2)将线性表的第i个元素后面的所有元素均向前移动一个位置;
3)使线性表的长度减1。
· 单链表的插入
例题: ** 向单链表中第i个结点(i≥0)之后插入一个元素为b的结点 **
算法步骤:
1)为待插入元素b分配一个结点(假定是由s指针变量所指向的结点,即s↑结点) ,并把b赋给s↑结点的值域;
2) 如果i=0,则将s↑结点插入表头后返回;
3) 从单链表中查找第i个结点;
4)若查找成功,则在第i个结点后插入s↑结点,。否则表明值超出单链表的长度,应进行错误处理。
PROCEDURE insert(head,i,b)
BEGIN
1) NEW(S) ; S↑.data:=b;
2) IF i=0 THEN [s↑.next:= head; head:=s; RETURN];
3) P:=head; j:=1 ; < color="#0000ff">{用指针P指向单链表中第j个结点}
While (p< > nil) and (j<i) do
j:=j+1;
p:=p↑.next;
4) IF p< >nil THEN < color="#0000ff">{ 若条件成立,则表明查找成功 }
s↑.next:=p↑.next; < color="#0000ff">{使s↑结点的指针域指向p↑结点的后继 }
p↑.next:=s; < color="#0000ff">{使p↑结点的指针域指向s↑结点}
ELSE error ('error')
END;
· 单链表的删除
例题: ** 在单链表中删除结点d **
算法步骤:
1) 如果单链表为空,则进行出错处理;
2) 如果表头结点是被删除结点,则删除该结点后返回;
3) 从单链表中查找其值等于d的结点,直到查找结束(成功或失败)为止;
4)若查找成功,则删除被查找到的结点后,否则进行错误处理。
PROCEDURE delete(head,d)
BEGIN
1) IF head=nil THEN error('this is a empty list');
2) IF head↑.data =d THEN
p:=head; < color="#0000ff">{把表头指针赋给P,以便删除表头结点后收回该结点}
head:=head↑.next; < color="#0000ff">{删除表头结点}
dispose(p); < color="#0000ff">{系统回收由p所指向的结点,即原表头结点}
RETURN ; < color="#0000ff">{返回}
< color="#0000ff">
3) q:=head; p:=q↑.next ;< color="#0000ff">{ P指向待比较的结点,q指向p的前驱结点}
While p< > nil do
IF p↑.data=d THEN exit
ELSE [q:=p; p:=p↑.next];
4) IF p< >nil THEN
q↑.next:=p↑.next; < color="#0000ff">{删除p↑结点,即值为d的结点}
dispose(p); < color="#0000ff">{回收p结点}
ELSE error('error')
END;
结论:在表很长时,采用顺序方式时插入和删除元素的效率很低,只有在很少进行插入和删除运算的情况下,采用顺序表才是合适的。而线性链表的插入和删除运算效率总是很高,与表长无关。
4. 线性表的应用
线性表是应用最广的数据结构。常见的有:
(1)高级语言中的数组
(2)操作系统中的文件系统、目录系统
(3)事务管理中的表格