The common data structure of Go source reading (list)

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Originally intended to use go to implement the common Java collection, simple implementation of ArrayList, after the official website of the package, found container/list that its implementation is very concise, so the study record as follows:

List Implementation Readiness

If you want to implement a list, first think of solving the problem:

    • What is data type handling?
    • Does the go have a universal data type like object in Java?

Thanks interface{} to this versatile data type in go, the problem is solved!

Take a look at my ArrayList implementation design:

type ArrayList struct {    size int32    data []interface{}}

I use slice it to implement a simple list (one-way list) operation, and then look at the implementation of the official website:

type Element struct {    prev, next *Element    list       *List    Value      interface{}}type List struct {    root Element    len  int}

Haha, such a contrast, I am a little shy! The official network is more object-oriented, the List elements are abstracted into Element , Element coexist in their own read before and after the node method.

Get operation in Element

    • Gets the value of itself
    • Get precursor node
    • Get subsequent nodes

One of the features of Go is that its access rights are distinguished by the first letter case, the element can get its value directly, and the front and back nodes provide a method:

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

No wonder, why the type is *Element ? Of course, it's changing its value!
The pointer passes the object's reference, not the pointer to the object's copy, and the pointer uses the following rule:

    • You must use pointers whenever you need to modify an object, which is not a go language constraint, but a natural constraint.
    • Sometimes the object is small and it's not worth the use of pointers.

Initialization of the list

ListBy invoking the New() method to initialize a list, the New() method implements the following code, which Init() root.next root.prev all points to root , which will pave the way for the following implementation

//Init initializes or clears list lfunc (l *List) Init() *List {    l.root.next = &l.root // next ---> root    l.root.prev = &l.root // next ---> root    //l.root.list = l //    l.len = 0    return l}func New() *List {    //new 申请内存初始化    list := new(List)    return list.Init()}

New()after execution, a similar {{0x000001, 0x000001, nil, nil}, 0} object (0x000001 is just a chestnut) is generated, but this address is element.list, which guarantees consistency in the list.

Storage operations in the list

The following methods are stored in the list:

    • Func (L List) InsertAfter (v interface{}, Mark Element) *element: Adding elements after the mark element
    • Func (L List) insertbefore (v interface{}, Mark Element) *element: Adding elements before the Mark element
    • Func (L List) pushback (v interface{}) element: Adding elements at the end of the list
    • Func (L list) pushbacklist ( other list): Add element list at the end of list
    • Func (L List) Pushfront (v interface{}) element: Adding elements to the List header
    • Func (L list) pushfrontlist ( other list): Adds an element list to the list header

As these public methods are built on insert(e, at *Element)和insertValue(v interface{}, at *Element) the method, the code is as follows:

//insert e after atfunc (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++    fmt.Println("l.root.prev:", l.root.prev, "  l.root.next:", l.root.next)    return e}func (l *List) insertValue(v interface{}, at *Element) *Element {    //创建新的节点    return l.insert(&Element{Value: v}, at)}

It is important to note that the insert(e, at *Element) implementation is to put E at the back of the, which is helpful in understanding the following code.
Attached PushBack(v interface{}) Flowchart:


Pushback.png


As the PushFront(v interface{}) execution process is the PushBack(v interface{}) opposite, the following figure is attached, and the difference is known by careful observation:


Pushfront.png

Assuming that the above element addresses are 0x001,0x002,0x003, 2 and 3 are placed in the list, respectively.
The implementation of the above method is very simple, all in the establishment of "Insertvalue (v interface{}, at *element)" above, so do not paste the code in the article!

Get operation in List

    • Func (L List) back () Element: Get last Node
    • Func (L List) Front () Element: Gets the first node

Initially initialized node, is to hold the head node and tail nodes pointer, so the Back() operation returns its L.root.prev, the Front() operation returns its l.root.next to be done!

Delete operation in list

    • Func (L List) Remove (e Element) interface{}

However, the above method is called internally remove(e *Element) , and the code is as follows:

func (l *List) remove(e *Element) *Element {    e.prev.next = e.next    e.next.prev = e.prev    //avoid memory leaks    e.prev = nil    e.next = nil    e.list = nil    l.len--    return e}

The function of this method is to modify the precursor and successor nodes that need to delete the nodes , and finally, the front and back node pointers are empty to prevent memory anomalies.

Move operations in the list

    • Func (L List) MoveAfter (E, Mark Element)
    • Func (L List) MoveBefore (E, Mark Element)
    • Func (L List) movetoback (e Element)
    • Func (L List) Movetofront (e Element)

So the mobile operation, all with the help of insertValue(v interface{}, e *Element) and method to do remove(e *Element) , the use of is really ingenious, the specific view of the source bar!

Note: The list is not a co-process safe.

Overall, by flipping through the list source, mastered its code implementation of the list storage structure, more experience of the Ood thought! (This article is mainly the two pictures above)

Reference documents

    • https://golang.org/pkg/container/list/#pkg-overview
    • Https://golang.org/src/container/list/list.go?s=922:955#L21
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.