24

单链表、双链表的 Golang 实现 - ZZIR's Blog

 4 years ago
source link: https://zzir.cn/2020/go-linked-list.html?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

单链表定义

此处将 NodeList 分开定义,方便理解,官方的方法是把两个结构合并,
戳:https://golang.org/src/container/list/list.go?s=2063:2093#L14

type Node struct {
	value interface{}
	next  *Node
}

type List struct {
	len  int
	head *Node
	tail *Node
}

非必要可以省略此步骤,此处使用 Interface 只是为了方便阅读和展示。

type SingleLinkedList interface {
	Init()
	Len() int
	PushFront(v interface{})
	PushBack(v interface{})
	Insert(v interface{}, index int) error
	RemoveFront() interface{}
	RemoveBack() interface{}
	Remove(index int) interface{}
	GetHead() *Node
	Get(index int) interface{}
}

初始化操作,需要手动初始化,也可以实现在首次插入时进行初始化操作。

func (l *List) Init() {
	l.len = 0
	l.head = nil
	l.tail = nil
}
func (l *List) Len() int {
	return l.len
}

新节点三种插入方式,分别是 头部插入、末尾插入、指定位置插入。

// 从链表头部插入一个新节点
func (l *List) PushFront(v interface{}) {
	node := &Node{
		value: v,
		next:  nil,
	}
	if l.len == 0 {
		l.tail = node
	} else {
		node.next = l.head
	}
	l.head = node
	l.len++
}

// 从链表尾部插入一个新节点
func (l *List) PushBack(v interface{}) {
	node := &Node{
		value: v,
		next:  nil,
	}
	if l.len == 0 {
		l.head = node
	} else {
		l.tail.next = node
	}
	l.tail = node
	l.len++
}

// 指定位置,插入新节点
func (l *List) Insert(v interface{}, index int) error {
	if index >= l.len {
		return errors.New("index error")
	}
	if index == 0 {
		l.PushFront(v)
		return nil
	}
	node := &Node{
		value: v,
		next:  nil,
	}
	prev := l.head
	for i := 1; i < l.len; i++ {
		if i == index {
			node.next = prev.next
			prev.next = node
			l.len++
			return nil
		}
		prev = prev.next
	}

	return errors.New("insert error")
}

三种移除操作,移除头部、移除尾部、指定位置移除。

// 移除头部节点
func (l *List) RemoveFront() interface{} {
	if l.len == 0 {
		return nil
	}
	node := l.head
	l.head = l.head.next
	l.len--
	return node.value
}

// 移除尾部节点
func (l *List) RemoveBack() interface{} {
	if l.len == 0 {
		return nil
	}
	node := l.head
	for i := 1; i < l.len-1; i++ {
		node = node.next
	}
	tmp := node.next
	node.next = nil
	l.tail = node
	l.len--
	return tmp.value
}

// 指定位置移除节点
func (l *List) Remove(index int) interface{} {
	if l.len == 0 {
		return nil
	}
	if index == 0 {
		return l.RemoveFront()
	} else if index == l.len-1 {
		return l.RemoveBack()
	}
	node := l.head
	for i := 1; i < index; i++ {
		node = node.next
	}
	tmp := node.next
	node.next = node.next.next
	l.len--
	return tmp.value
}
// 获取头部节点
func (l *List) GetHead() *Node {
	return l.head
}

// 获取指定位置的节点值
func (l *List) Get(index int) interface{} {
	if index >= l.len {
		return nil
	}
	node := l.head
	for i := 0; i < l.len; i++ {
		if i == index {
			return node.value
		}
		node = node.next
	}
	return nil
}

测试用例:

func main() {
	var sl SingleLinkedList = &List{}
	sl.Init()
	sl.PushFront(6)
	sl.PushFront(7)
	sl.PushFront(8)
	sl.PushBack(1)
	sl.PushBack(2)
	sl.PushBack(3)
	fmt.Println("r", sl.RemoveFront())
	_ = sl.Insert(9, 0)
	_ = sl.Insert(8, 5)
	fmt.Println("r", sl.RemoveBack())
	fmt.Println("r", sl.RemoveBack())
	fmt.Println("rm", sl.Remove(1))
	fmt.Println("rm", sl.Remove(2))

	fmt.Println("len", sl.Len())
	node := sl.GetHead()
	for {
		fmt.Println(">>>", node.value)
		if node.next == nil {
			break
		}
		node = node.next
	}
	fmt.Println(sl.Get(1))
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK