線性表的鏈式存儲結構,是用一組任意的存儲單元來存儲線性表的數據元素,這些單元能夠分散在內存中的任意位置,即不要求邏輯上相鄰的兩個元素在物理上也相鄰;而是經過「鏈」創建起數據元素之間的邏輯關係。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!