List双向链表

container/list是一个双向链表,以下是list的定义与使用

双向链表的结构定义

// Element is an element of a linked list.
type Element struct {
	// Next and previous pointers in the doubly-linked list of elements.
	// To simplify the implementation, internally a list l is implemented
	// as a ring, such that &l.root is both the next element of the last
	// list element (l.Back()) and the previous element of the first list
	// element (l.Front()).
	next, prev *Element

	// The list to which this element belongs.
	list *List

	// The value stored with this element.
	Value interface{}
}

// List represents a doubly linked list.
// The zero value for List is an empty list ready to use.
type List struct {
	root Element // sentinel list element, only &root, root.prev, and root.next are used
	len  int     // current list length excluding (this) sentinel element
}

相应方法

func (e *Element) Next() *Element  //返回链表中e的下一个元素
func (e *Element) Prev() *Element  //返回链表中e的上一个元素
func (l *List) Init() *List        //初始化或重置list
func New() *List                   //创建List对象
func (l *List) Len() int           //元素个数
func (l *List) Front() *Element    //返回第一个元素,如果list为空返回nil
func (l *List) Back() *Element     //返回最后一个元素,如果list为空返回nil
func (l *List) Remove(e *Element) interface{}  //移除e元素
func (l *List) PushFront(v interface{}) *Element   //将v封装成*Element并插入到list的最前面,返回v封装的*Element
func (l *List) PushBack(v interface{}) *Element    //将v封装成*Element并插入到list的最后面,返回v封装的*Element
func (l *List) InsertBefore(v interface{}, mark *Element) *Element    //将v封装成*Element并插入到mark前面,返回v封装的*Element
func (l *List) InsertAfter(v interface{}, mark *Element) *Element     //将v封装成*Element并插入到mark后面,返回v封装的*Element
func (l *List) MoveToFront(e *Element)    //将e移到list的最前面
func (l *List) MoveToBack(e *Element)     //将e移到list的最后面
func (l *List) MoveBefore(e, mark *Element)   //将e移到mark前面
func (l *List) MoveAfter(e, mark *Element)    //将e移到mark后面
func (l *List) PushBackList(other *List)      //将other *List中的所有元素插入到l List的尾部
func (l *List) PushFrontList(other *List)     //将other *List中的所有元素插入到l List的前面

*list.List的所有增删改都会调用其私有的方法插入或移除,func (l *List) insert(e, at *Element) *Element,func (l *List) remove(e *Element) *Element。也是其核心代码

链表插入元素
func (l *List) insert(e, at *Element) *Element {
	n := at.next
	at.next = e
	e.prev = at
	e.next = n
	n.prev = e
	e.list = l
	l.len++
	return e
}
链表移除元素
func (l *List) remove(e *Element) *Element {
	e.prev.next = e.next
	e.next.prev = e.prev
	e.next = nil // avoid memory leaks
	e.prev = nil // avoid memory leaks
	e.list = nil
	l.len--
	return e
}

注意1:在获取list的最后一个元素时在执行Next()时,按道理来说应该返回的是root *Element,但是其返回的是nil,来看源码

func (e *Element) Next() *Element {
	if p := e.next; e.list != nil && p != &e.list.root {
		return p
	}
	return nil
}

如果e.next的指针和e.list.root的指针相同或者e.list(List,也就是根)为nil都返回nil

注意2:在获取list的第一个元素时在执行Prev()时,也会出现注意1的情况

示例:

import (
	"container/list"
	"fmt"
)

func main() {
	list1 := list.New()
	fmt.Println(list1.Len())                //0
	fmt.Println(list1.Back())               // <nil>  注意1
 	list1.PushBack("no.1")                  //["no.1"]
	fmt.Println(list1.Back().Value)         //no.1
	list1.PushBack(1)                       //["no.1",1]
	fmt.Println(list1.Back().Value)         //1
	list1.PushFront(true)                   //[true,"no.1",1]
	fmt.Println(list1.Front().Value)        //true
	list1.MoveToBack(list1.Front())         //["no.1",1,true]
	fmt.Println(list1.Back().Value)         //true
	list1.MoveToFront(list1.Front().Next()) //[1,"no.1",true]
	fmt.Println(list1.Front().Value)        //1
	fmt.Println(list1.Back().Next())        //返回nil
	//list1.MoveToBack(list1.Back().Next())  //报错,(注意1)
	list1.Remove(list1.Front())                         //["no.1",true]
	fmt.Println(list1.Front().Value)                    //no.1
	fmt.Println(list1.Len())                            //2
	list1.InsertAfter(10, list1.Front())                //["no.1",10,true]
	fmt.Println(list1.Front().Next().Value)             //10
	list1.InsertBefore(22, list1.Front())               //[22,"no.1",10,true]
	fmt.Println(list1.Front().Value)                    //22
	list1.MoveAfter(list1.Front(), list1.Back().Prev()) //["no.1",10,22,true]
	fmt.Println(list1.Back().Prev().Value)              //22
	print(list1)  //[no.1 10 22 true ]

	list2 := list.New()
	list2.PushBack(88)
	list2.PushBack(true)
	list2.PushBack("no.2")
	list1.PushBackList(list2)
	print(list1) //[no.1 10 22 true 88 true no.2 ]

	list3 := list.New()
	list3.PushBack(99)
	list3.PushBack(false)
	list3.PushBack("no.3")
	list1.PushFrontList(list3)
	print(list1)  //[99 false no.3 no.1 10 22 true 88 true no.2 ]
}

func print(list *list.List)  {
	for p := list.Front();p != nil;p = p.Next() {
		fmt.Printf("%v ",p.Value)
	}
	fmt.Println()
}

运行结果

0
<nil>
no.1
1
true
true
1
<nil>
no.1
2
10
22
22
no.1 10 22 true 
no.1 10 22 true 88 true no.2 
99 false no.3 no.1 10 22 true 88 true no.2 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值