链表的特点

  • 头插速度快
  • 尾部查入要遍历到最后
  • 链表 适用于 频繁到 删除和插入,查询少不需要知道长度,遍历到nil 跳出
  • 数组 适用于 频繁到查找 ,删除和插入比较少, 要知道长度
  • 进程列表 双链表

单链表实现

代码编写记忆:

head 元素 value 一直为nil 即 list.head.pNext 才为第一个节点

单链表示意图

节点

 1package singlylinkedlist
 2
 3type SingleLinkNode struct {
 4	value interface{}
 5	pNext *SingleLinkNode
 6}
 7
 8//构造一个节点
 9func NewSingleLinkNode(data interface{}) *SingleLinkNode {
10	var node = new(SingleLinkNode)
11	node.value = data
12	return node
13}
14
15// 返回值
16func (node *SingleLinkNode) Value() interface{} {
17	return node.value
18}
19
20// 返回下一个节点
21func (node *SingleLinkNode) Pnext() *SingleLinkNode {
22	return node.pNext
23}

单链表实现

  1package singlylinkedlist
  2
  3import (
  4	"fmt"
  5)
  6
  7type SingleLink interface {
  8	GetFirstNode() *SingleLinkNode        //获取头节点
  9	InsertNodeFront(node *SingleLinkNode) //头部插入
 10	InsertNodeBack(node *SingleLinkNode)  // 尾部插入
 11	//在一个节点之后插入
 12	InsertNodeValueBack(dest interface{}, node *SingleLinkNode) bool
 13	//在一个节点之前插入
 14	InsertNodeValueFront(dest interface{}, node *SingleLinkNode) bool
 15	//根据索引抓取指定位置的节点
 16	GetNodeAtIndex(index int) *SingleLinkNode
 17	// 删除一个节点
 18	DeleteNode(dest *SingleLinkNode) bool
 19	//删除指定位置的节点
 20	DeleteAtIndex(index int) bool
 21	String() string // //返回链表字符串
 22}
 23
 24type SingLinkList struct {
 25	head   *SingleLinkNode
 26	length int // 链表的长度
 27}
 28
 29//创建链表
 30
 31func NewSingLinkList() *SingLinkList {
 32	head := NewSingleLinkNode(nil)
 33	return &SingLinkList{head: head, length: 0}
 34}
 35
 36// 第一个元素
 37func (list *SingLinkList) GetFirstNode() *SingleLinkNode {
 38	return list.head.pNext
 39}
 40
 41//头部插入
 42func (list *SingLinkList) InsertNodeFront(node *SingleLinkNode) {
 43	// 如果没有头元素
 44	if list.head == nil {
 45		list.head.pNext = node
 46		node.pNext = nil
 47	} else {
 48		bak := list.head
 49		node.pNext = bak.pNext
 50		list.head.pNext = node
 51	}
 52	list.length++
 53}
 54
 55//尾部插入
 56func (list *SingLinkList) InsertNodeBack(node *SingleLinkNode) {
 57	if list.head == nil {
 58		list.head.pNext = node
 59		node.pNext = nil
 60	} else {
 61		bak := list.head
 62		for bak.pNext != nil {
 63			bak = bak.pNext
 64		}
 65		bak.pNext = node
 66	}
 67	list.length++
 68}
 69
 70//节点值 前追加
 71func (list *SingLinkList) InsertNodeValueFront(dest interface{}, node *SingleLinkNode) bool {
 72	var isFind = false
 73	bak := list.head
 74	for bak.pNext != nil {
 75		if bak.pNext.value == dest {
 76			isFind = true
 77			break
 78		}
 79		bak = bak.pNext
 80	}
 81	if isFind {
 82		node.pNext = bak.pNext
 83		bak.pNext = node
 84		list.length++
 85	}
 86
 87	return isFind
 88}
 89
 90//节点值 后追加
 91func (list *SingLinkList) InsertNodeValueBack(dest interface{}, node *SingleLinkNode) bool {
 92	var isFind = false
 93	bak := list.head
 94	for bak.pNext != nil {
 95		if bak.value == dest {
 96			isFind = true
 97			break
 98		}
 99		bak = bak.pNext
100	}
101	if isFind {
102		node.pNext = bak.pNext
103		bak.pNext = node
104		list.length++
105	}
106
107	return isFind
108}
109
110//获得指定位置的节点 从0开始-》lenth-1  .
111func (list *SingLinkList) GetNodeAtIndex(index int) *SingleLinkNode {
112	if index > list.length-1 || index < 0 {
113		return nil
114	}
115	/*
116		phead:=list.head
117		for index >-1{
118			phead=phead.pNext //向后循环
119			index-- //向后循环过程
120		}
121		return phead
122	*/
123	var i int
124	node := list.head
125	for node.pNext != nil {
126		node = node.pNext
127		if index == i {
128			//break
129			return node
130		}
131		i++
132	}
133	return node
134}
135
136//删除节点
137func (list *SingLinkList) DeleteNode(dest *SingleLinkNode) bool {
138	if dest == nil {
139		return false
140	}
141	node := list.head
142	for node.pNext != nil {
143		if node.pNext == dest {
144			node.pNext = node.pNext.pNext
145			list.length--
146			return true
147		}
148		node = node.pNext
149	}
150	return false
151}
152
153//删除指定位置的节点
154func (list *SingLinkList) DeleteAtIndex(index int) bool {
155	if index > list.length-1 || index < 0 {
156		return false
157	}
158	var i int
159	node := list.head
160	for node.pNext != nil {
161		if index == i {
162			node.pNext = node.pNext.pNext
163			return true
164		}
165		node = node.pNext
166		i++
167	}
168	return false
169}
170
171//打印链表
172func (list *SingLinkList) String() string {
173	var listString string
174	node := list.head //头部节点
175	for node.pNext != nil {
176		listString += fmt.Sprintf("%v-->", node.pNext.value)
177		node = node.pNext //循环
178	}
179	listString += fmt.Sprintf("nil")
180	return listString //打印链表字符串
181}
182
183
184
185//获得中间节点
186func (list *SingLinkList) GetMid() *SingleLinkNode {
187	node := list.head //头部节点
188	if node == nil {
189		return nil
190	}
191	phead1 := list.head
192	phead2 := list.head
193	for phead2 != nil && phead2.pNext != nil {
194		phead1 = phead1.pNext
195		phead2 = phead2.pNext.pNext
196	}
197	return phead1
198}
199
200// 链表反转
201// 下一个节点 指向 前一个节点, 头节点指向 原来的最后一个节点
202func (list *SingLinkList) ReverseList() {
203	if list.head == nil || list.head.pNext == nil {
204		return //链表为空或者链表只有一个节点
205	} else {
206		var pre *SingleLinkNode                   //前面节点
207		var cur *SingleLinkNode = list.head.pNext //当前节点
208		for cur != nil {
209			curNext := cur.pNext // 后续节点
210			cur.pNext = pre      //反转第一步
211
212			pre = cur     //持续推进
213			cur = curNext //持续推进
214		}
215		// fmt.Println(pre)
216		// list.head.pNext.pNext=nil
217		list.head.pNext = pre
218	}
219}
220
221
222/*
223
2241 -> 2-》3-》4-》5->nil                            2
225  curNext   2-》3-》4-》5->nil                    3-》4-》5->nil 
226cur: 1->nil                                     cur 2->1->nil
227pre =  1->nil                                   pre  2->1->nil     ...      5->4->3->2->1->nil
228cur =   2-》3-》4-》5->nil                       3-》4-》5->nil     
229*/

单链表测试

 1package singlylinkedlist
 2
 3import (
 4	"github.com/stretchr/testify/assert"
 5	"testing"
 6)
 7
 8func TestArrayList(t *testing.T) {
 9	node1 := NewSingleLinkNode(1)
10	node2 := NewSingleLinkNode(2)
11	node3 := NewSingleLinkNode(3)
12	node4 := NewSingleLinkNode(4)
13	node5 := NewSingleLinkNode(5)
14	node6 := NewSingleLinkNode(6)
15	node10 := NewSingleLinkNode(10)
16	link := NewSingLinkList()
17	t.Log(link.String())
18	link.InsertNodeFront(node1)
19	t.Log(link.String())
20	link.InsertNodeFront(node2)
21	t.Log(link.String())
22	link.InsertNodeFront(node3)
23	t.Log(link.String())
24	t.Log("中间节点:", (link.GetMid().Value()))
25	link.InsertNodeBack(node10)
26	t.Log(link.String())
27	t.Log(link.GetFirstNode().Value())
28	link.InsertNodeValueBack(3, node4)
29	t.Log(link.String())
30	link.InsertNodeValueFront(2, node5)
31	t.Log(link.String())
32	t.Log("中间节点:", (link.GetMid().Value()))
33	link.InsertNodeValueFront(3, node6)
34	t.Log(link.String())
35
36	firstNode := link.GetNodeAtIndex(0)
37	assert.Equal(t, firstNode.Value(), 6, "根据索引获得节点失败")
38	twoNode := link.GetNodeAtIndex(1)
39	assert.Equal(t, twoNode.Value(), 3, "根据索引获得节点失败")
40	//链表反转
41	link.ReverseList()
42	t.Log(link.String())
43	link.DeleteAtIndex(0)
44	t.Log(link.String())
45	link.DeleteAtIndex(3)
46	t.Log(link.String())
47	link.DeleteNode(node10)
48	t.Log(link.String())
49	link.DeleteNode(node4)
50	t.Log(link.String())
51
52}

结果

 1=== RUN   TestArrayList
 2--- PASS: TestArrayList (0.00s)
 3    singleLink_test.go:17: nil
 4    singleLink_test.go:19: 1-->nil
 5    singleLink_test.go:21: 2-->1-->nil
 6    singleLink_test.go:23: 3-->2-->1-->nil
 7    singleLink_test.go:24: 中间节点: 2
 8    singleLink_test.go:26: 3-->2-->1-->10-->nil
 9    singleLink_test.go:27: 3
10    singleLink_test.go:29: 3-->4-->2-->1-->10-->nil
11    singleLink_test.go:31: 3-->4-->5-->2-->1-->10-->nil
12    singleLink_test.go:32: 中间节点: 5
13    singleLink_test.go:34: 6-->3-->4-->5-->2-->1-->10-->nil
14    singleLink_test.go:41: 链表反转
15    singleLink_test.go:43: 10-->1-->2-->5-->4-->3-->6-->nil
16    singleLink_test.go:45: 1-->2-->5-->4-->3-->6-->nil
17    singleLink_test.go:47: 1-->2-->5-->3-->6-->nil
18    singleLink_test.go:49: 1-->2-->5-->3-->6-->nil
19    singleLink_test.go:51: 1-->2-->5-->3-->6-->nil
20PASS
21ok      datastruct/list/singlylinkedlist        0.014s

郝林 Go语言核心36讲 第8讲