线性表的链式存储结构,是用一组任意的存储单元来存储线性表的数据元素,这些单元能够分散在内存中的任意位置,即不要求逻辑上相邻的两个元素在物理上也相邻;而是经过“链”创建起数据元素之间的逻辑关系。node
type data interface{}
type Node struct {
Data data // 数据域
Next *Node // 指针域
}
type LinkList struct {
Head *Node
len int
}
// 初始化一个链表
func New() *LinkList {
l := &LinkList{Head: &Node{}}
l.len = 0
return l
}
复制代码
查找分为按值查找,和按序号查找,不过在算法的思想上基本是一致的:算法
一、从表头开始找,判断当前节点是否知足查找条件;ui
二、若是不知足,则将指针后移一位,指向下一个结点,继续判断条件;spa
三、找到知足查找条件的结点,则退出循环,返回该结点,若是没找到,则返回null指针
// 按序号查找
func (l *LinkList) FindKth(k int) *Node {
if k < 1 || k > l.len {
return nil
}
current := l.Head
for i := 1; i <= k; i++ {
current = current.Next
}
return current
}
// 按值查找
func (l *LinkList) Find(value data) *Node {
for current := l.Head; current != nil; current = current.Next {
if current.Data == value {
return current
}
}
return nil
}
复制代码
在第i-1(1<=i<=n+1)个结点以后插入一个值为X的新结点,算法思想:code
一、构建一个新的结点s;cdn
二、找到第i-1个结点p;blog
三、修改指针,插入新的结点。内存
其中第3步,咱们用图表示: it
s.Next = p.Next // 1处创建连接
p.Next = s // 2处创建连接
复制代码
若是将这两行代码的顺序交换一下会怎么样?
先执行p.Next = s,这个时候就p.Next指向了s结点,而后执行s.Next = p.Next,可是p.Next已是s结点了,所以也就变成了s.Next = s。这个时候插入就会失败。因此这两句是不管如何不能弄反的。
func (l *LinkList) Insert(value data, i int) bool {
preNode := l.FindKth(i - 1)
if preNode == nil {
return false
}
node := &Node{Data: value}
node.Next = preNode.Next
preNode.Next = node
l.len++
return true
}
复制代码
删除链表的第i(1<=i<=n)个位置的结点,算法思想:
一、找到第i-1个结点,为p;
二、用s保存p.Next的结点,即第i个结点;
三、将p.Next指向s.Next,断开结点的连接;
四、用e保存s的值,释放s结点,返回e。
func (l *LinkList) Delete(i int) (data, bool) {
preNode := l.FindKth(i - 1)
if preNode == nil {
return nil, false
}
deleteNode := preNode.Next
preNode.Next = deleteNode.Next
value := deleteNode.Data
deleteNode = nil
l.len--
return value, true
}
复制代码
咱们可使用头插法,或者尾插法的方式,建立链表。
即在建立链表时,每一个元素都按顺序的插在表头。
一、给链表添加一个在表头插入一个元素的方法,称为InsertHead;
二、依次使用InsertHead将元素加入链表中。
func (l *LinkList) InsertHead(value data) {
node := &Node{Data: value}
node.Next = l.Head.Next
l.Head.Next = node
l.len++
}
// 头插法建立
l := LinkList.New()
for i := 1; i <= 5; i++ {
// 将1到5依次插入表头
l.InsertHead(i)
}
复制代码
查看链表的结构:
即在建立链表时,每一个元素都按顺序的插在表尾。
一、给链表添加一个在表头插入一个元素的方法,InsertTail;
二、依次使用InsertTail将元素加入链表中。
func (l *LinkList) InsertTail(value data) {
node := &Node{Data: value}
current := l.Head
for current.Next != nil {
current = current.Next
}
current.Next = node
l.len++
}
// 尾插法建立
l := LinkList.New()
for i := 1; i <= 5; i++ {
// 将1到5依次插入表尾
l.InsertTail(i)
}
复制代码
链表结构:
咱们从时间和空间上对比一下线性表的链式存储与顺序存储:
查找:
插入和删除:
Thanks!