《大話數據結構》學習筆記 —— 03 線性表之單鏈表(golang實現)


單鏈表


定義

如果鏈表中的每個結點只包含一個指針,則該鏈表稱爲單鏈表

單鏈表結構如圖所示:

在這裏插入圖片描述



代碼實現

package SingleLinkling

import (
	"fmt"
)

// 定義單鏈表接口
type SingleLink interface {

	// 返回第一個數據結點
	GetFirstNode() *SingleLinkNode

	// 插入結點(頭插法)
	InsertNodeFront(node *SingleLinkNode)

	// 插入結點(尾插法)
	InsertNodeBack(node *SingleLinkNode)

	// 插入某結點前
	InsertNodeValueFront(dest interface{}, node *SingleLinkNode) bool

	// 插入某結點後
	InsertNodeValueBack(dest interface{}, node *SingleLinkNode) bool

	// 獲取指定索引上的結點
	GetNodeAtIndex(index int) *SingleLinkNode

	// 刪除結點
	DeleteNode(dest *SingleLinkNode) bool

	// 刪除指定索引上的結點
	DeleteAtIndex(index int) bool

	// 返回字符串
	String() string
}

// 單鏈表
type SingleLinkList struct {
	// 頭指針
	head *SingleLinkNode
	// 長度
	length int
}

// 初始化單鏈表
func NewSingleLinkList() *SingleLinkList {

	// 初始化頭結點
	head := NewSingleLinkNode(nil)

	return &SingleLinkList{
		head:   head,
		length: 0,
	}
}

// 獲取第一個數據結點
func (list *SingleLinkList) GetFirstNode() *SingleLinkNode {
	return list.head.pNext
}

// 獲取指定索引上的結點
func (list *SingleLinkList) GetNodeAtIndex(index int) *SingleLinkNode {

	// 索引越界
	if index > list.length-1 || index < 0 {
		return nil
	}

	// 備份頭結點
	bak := list.head

	// 向後循環
	for index > -1 {
		bak = bak.pNext
		index--
	}

	return bak
}

// 頭部插入
func (list *SingleLinkList) InsertNodeFront(node *SingleLinkNode) {

	// 空鏈表
	if list.head == nil {

		// 第一個數據結點設爲新結點
		list.head.pNext = node

		// 新結點指針指向nil
		node.pNext = nil

		list.length++
		return
	}

	// 備份頭結點
	bak := list.head

	// 新結點的指針,指向原來的第一個數據結點
	node.pNext = bak.pNext

	// 頭結點指向新結點
	bak.pNext = node

	list.length++
	return
}

// 尾部插入
func (list *SingleLinkList) InsertNodeBack(node *SingleLinkNode) {

	// 空鏈表
	if list.head == nil {

		// 第一個數據結點設爲新結點
		list.head.pNext = node

		// 新結點指針指向nil
		node.pNext = nil

		list.length++
		return
	}

	// 備份頭結點
	bak := list.head

	// 循環到鏈表末尾
	for bak.pNext != nil {
		bak = bak.pNext
	}

	// 終端結點的指針指向新結點
	bak.pNext = node

	list.length++
	return
}

// 插入某結點前
func (list *SingleLinkList) InsertNodeValueFront(dest interface{}, node *SingleLinkNode) bool {

	// 備份頭結點
	bak := list.head

	// 循環到末尾,直至找到目標結點
	for bak.pNext != nil && bak.pNext.value != dest {
		bak = bak.pNext
	}

	// 找到
	if bak.pNext.value == dest {

		// 目標結點的上一個數據結點的指針,賦值給新結點的指針
		node.pNext = bak.pNext

		// 目標結點的上一個數據結點的指針,指向新結點
		bak.pNext = node

		list.length++
		return true
	}

	return false

}

// 插入某結點後
func (list *SingleLinkList) InsertNodeValueBack(dest interface{}, node *SingleLinkNode) bool {

	// 備份頭結點
	bak := list.head

	// 循環到末尾,直至找到目標結點
	for bak.pNext != nil && bak.pNext.value != dest {
		bak = bak.pNext
	}

	// 找到
	if bak.pNext.value == dest {

		// 目標結點的指針賦值給新結點的指針
		node.pNext = bak.pNext.pNext

		// 目標結點的指針指向新結點
		bak.pNext.pNext = node

		list.length++
		return true
	}

	return false

}

// 刪除結點
func (list *SingleLinkList) DeleteNode(dest *SingleLinkNode) bool {

	// 備份頭結點
	bak := list.head

	// 循環到末尾,直至找到目標結點
	for bak.pNext != nil && bak.pNext != dest {
		bak = bak.pNext
	}

	// 找到
	if bak.pNext == dest {

		// 目前結點的指針賦值給目標結點的上一個數據結點的指針
		bak.pNext = bak.pNext.pNext

		list.length--
		return true
	}

	return false
}

// 刪除指定索引上的結點
func (list *SingleLinkList) DeleteAtIndex(index int) bool {

	// 索引越界
	if index > list.length-1 || index < 0 {
		return false
	}

	// 備份頭結點
	bak := list.head

	// 向後循環,找到前一個結點
	for index > 0 {
		bak = bak.pNext
		index--
	}

	// 目前結點的指針賦值給目標結點的上一個數據結點的指針
	bak.pNext = bak.pNext.pNext
	list.length--

	return true
}

// 獲取鏈表中間結點
func (list *SingleLinkList) GetMid() *SingleLinkNode {

	// 鏈表只有一個結點
	if list.head.pNext == nil {
		return nil
	}

	phead1 := list.head
	phead2 := list.head

	for phead2 != nil && phead2.pNext != nil {
		phead1 = phead1.pNext
		phead2 = phead2.pNext.pNext
	}

	return phead1
}

// 鏈表反轉
func (list *SingleLinkList) ReverseList() {

	// 鏈表爲空或者只有一個結點
	if list.head == nil || list.head.pNext == nil {
		return
	}

	// 前一個結點
	var pre *SingleLinkNode

	// 當前結點
	cur := list.head.pNext

	for cur != nil {
		pre, cur, cur.pNext = cur, cur.pNext, pre
	}

	list.head.pNext = pre

}

// 返回字符串
func (list *SingleLinkList) String() string {

	var listString string

	// 頭結點
	p := list.head

	// 循環輸出
	for p.pNext != nil {
		listString += fmt.Sprintf("%v-->", p.pNext.value)
		p = p.pNext
	}

	listString += fmt.Sprintf("nil")

	return listString
}



時間複雜度

單鏈表,在讀數據時,時間複雜度爲O(n);

而在進行插入、刪除操作時,時間複雜度爲O(1)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章