
线性表
线性表 : 零个或多个元素的有限序列
抽象数据类型定义
ADT 线性表 (List)
Data
线性表的数据对象集合为 {a1, a2, ..., an},每个元素类型均为 DataType。其中,除第一个元素外,每个元素有且只有一个直接前驱元素。除了最后一个元素外,每一个元素有且只有一个直接后继元素。数据元素之间的关系是一对一关系。
Operation
InitList(*L) : 初始化操作,建立一个空的线性表 L
ListEmpty(L) : 若线性表为空,返回 true,否则返回 false
ClearList(*L) : 将线性表清空
GetElem(L, i, *e) : 将线性表 L 中的第 i 个元素值返回给 e
LocateElem(L, e) : 在线性表中查找给定元素,如果查找成功,返回该元素在表中序列号。否则,返回 -1 表示失败
ListInsert(*L, i, e) : 在线性表中的第 i 个位置插入新元素 e
ListDelete(*L, i, *e) : 删除线性表 L 中的第 i 个位置元素,并用 e 返回其值
ListLength(L) : 返回线性表 L 的元素个数
endADT
线性表的顺序储存结构
线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素。
结构定义
type int TYPE
var MAXSIZE int = 10
type List struct {
Data [MAXSIZE]TYPE
Length int
}
顺序储存结构的插入与删除
插入
func (list *List) ListInsert(i int, e TYPE) error {
if i < 0 || i > MAXSIZE - 1 || list.Length - 1 < i {
return errors.New("错误")
} else {
// 插入点的数据依次向后移动
for j := list.Length - 1; j >= i; j -- {
list.Data[j + 1] = list.Data[j]
}
}
list.Data[i] = e
list.Length += 1
return nil
}
删除
func (list *LIst) ListDelete(i int, e *TYPE) error {
if list.Length == 0 || i < 0 || i >list.Length {
return errors.New("错误")
} else if i < list.Length {
*e = list.Data[i]
// 删除点的元素依次向前移动
for int j := i; j < list.Length - 1; j ++ {
list.Data[j] = list.Data[j + 1]
}
}
list.Length -= 1
return nil
}
优缺点
优点 : 无需为表示表中元素之间的逻辑关系而增加额外的空间。可以快速地存取表中任意位置的元素
缺点 : 插入和删除操作需要移动大量元素。当线性表长度变化较大时,难以确定存储空间的容量。造成存储空间的“碎片”。
线性表的链式储存结构
n 个节点链结成一个链表,即为线性表的链式存储结构。
type LinkedList struct {
Data TYPE
Next *LinkedList
}
单链表的插入与删除
插入
func (list *LinkedList) ListInsert(i int, e TYPE) error {
int foo := 0
for list != nil && foo < i {
list = list.Next
foo += 1
}
if list == nil || foo > i {
return errors.New("错误")
}
node = LinkedList{Data : e, Next : nil}
// 将插入元素的 Next 指向当前节点的下一个节点
node.Next = list.Next
// 当前节点的 Next 为被插入元素
list.Next = node
return nil
}
删除
func (list *LinkedList) ListDelete(i int, e *TYPE) error {
int foo := 0
for list != nil && foo < i {
list = list.Next
foo += 1
}
if list == nil || foo > i {
return errors.New("错误")
}
*e = list.Next.Data
// 当前节点的 Next 指向下一个节点的 Next
// 等待 gc 自动回收
list.Next = list.Next.Next
return nil
}
单链表结构与顺序储存结构优缺点
储存分配方式 :
- 顺序储存结构用一段连续的存储单元依次存储线性表的数据元素。
- 单链表采用链式存储结构,用一组任意的存储单元存放线性表的元素。
时间性能 : - 查找
- 顺序储存结构 O(1)
- 单链表 O(n)
- 插入与删除
- 顺序存储结构需要平均移动表长一半的元素,时间为 O(n)
- 单链表在找出某位置的指针后,插入和删除时间仅为 O(1)
- 空间性能
- 顺序存储结构需要预分配存储空间,分大了,浪费,分小了容易发生上溢。
- 单链表不需要分配存储空间,只要有就可以分配,元素个数也不受限制。
当线性表中元素个数变化较大或者根本不知道有多大时,最好用单链表结构。而如果事先知道线性表的大致长度,用顺序结构效率会高