This is a creation in Article, where the information may have evolved or changed.
First, what is a doubly linked list
And the single-linked list, the elements of the two-way list not only know their downline, but also know their online (more and more like the MLM organization). The small coal car to open, the figure can be seen, each compartment in addition to a point to the back of the car's arrows, there is a pointing to the front of the car's arrows (head, car tail except). The front only points to the rear compartment of the arrow, the rear of the car only pointed to the arrow.
Two, two-way linked list and go of the corresponding structure
1. Node
Let's break down the compartment first. Each compartment is composed of 4 parts: coal, bodywork, pull-up carriages, ropes, pull-back carriages. The car body is our transportation tool, in the go language we use the structure to raise the dnode to represent, the coal represents the cargo which transports, uses the data variable to express, pulls the front carriage rope and the pull back carriage rope we respectively use the pointer prev and next to indicate. Such a carriage, in the go language is described as follows:
type DNode struct { data Object prev *DNode next *DNode}
2. Doubly linked list
A coal-truck fleet is a doubly linked list. The team has to have the front, car, tail, as the head of the team also need to know how long the team. In the go language, the team with the structure of the dlist, the car head with a variable, the parking space with the tail variable, the length of the fleet is expressed in size, the expression together:
type DList struct { size uint64 head *DNode tail *DNode}
The structure is finished, the following talk about how to increase, reduce the carriage, that is, the interface of the doubly linked list.
Third, the interface description and implementation
The interface is mainly divided into these categories. One is the doubly linked list itself, and the other is the node. The list itself is also divided into public and private two kinds. Let's talk about these interfaces in more detail below.
1. Initialize the list of links init
Two-way list initialization, it can be understood that Chengdawei ready to buy a team ready to transport coal. The first step, to obtain the approval of the State authorities, with the approval of the Davido can buy the car to transport coal. But when it was approved, brother David's motorcade had nothing, no front, no tail, no car. Go Language code implementation:
func (dList *DList) Init() { _dList := *(dList) _dList.size = 0 // 没车厢 _dList.head = nil // 没车头 _dList.tail = nil // 没车尾}
2. New Data Append
David Brother bought a new car, and bought the car to hang behind the team. The first compartment is the front.
func (dList *DList) Append(data Object) { newNode := new(DNode) (*newNode).data = data if (*dList).GetSize() == 0 { // 买个车头 (*dList).head = newNode (*dList).tail = newNode (*newNode).prev = nil (*newNode).next = nil } else { // 挂在车队尾部 (*newNode).prev = (*dList).tail (*newNode).next = nil (*((*dList).tail)).next = newNode (*dList).tail = newNode } (*dList).size++;}
3. Insert data behind the node Insertnext
Sometimes, the carriages are not placed in the tail of the motorcade, but in the middle, for example, it is best to put together an apple carriage.
func (dList *DList) InsertNext(elmt *DNode, data Object) bool { if elmt == nil { // apend return false } if dList.isTail(elmt) { // 恰好在车队尾巴 dList.Append(data) } else { newNode := new(DNode) (*newNode).data = data (*newNode).prev = elmt (*newNode).next = (*elmt).next (*elmt).next = newNode (*((*newNode).next)).prev = newNode (*dList).size++; } return true}
5. Insert data in front of the node Insertprev
Inserting data in front of a node can be understood as inserting data behind a node before the current node.
func (dList *DList) InsertPrev(elmt *DNode, data Object) bool { if elmt == nil { return false } if dList.isHead(elmt) { // 如果是新增一个车头就特殊处理 newNode := new(DNode) (*newNode).data = data (*newNode).next = dList.GetHead() (*newNode).prev = nil (*(dList.head)).prev = newNode dList.head = newNode dList.size++ return true } else { prev := (*elmt).prev return dList.InsertNext(prev, data) }}
The ishead here is to determine whether the node is the front, David introduction.
6. Delete a node remove
Some carriages are in trouble and need to be repaired, so they must be removed from the convoy.
func (dList *DList) Remove(elmt *DNode) Object { if elmt == nil { return false } prev := (*elmt).prev next := (*elmt).next if dList.isHead(elmt) { dList.head = next } else { (*prev).next = next } if dList.isTail(elmt) { dList.tail = prev } else { (*next).prev = prev } dList.size-- return (*elmt).GetData() }
After unloading, the data in the compartment is still to be retained.
7. Find the node where the specified data is located search
For example, find out which compartment the apple is in. It is necessary to use the search function.
func (dList *DList) Search(data Object, yourMatch ...MatchFun) *DNode { if dList.GetSize() == 0 { return nil } match := defaultMatch if len(yourMatch) > 0 { match = yourMatch[0] } node := dList.GetHead() for ; node != nil; node = node.GetNext() { if match(node.GetData(), data) == 0 { break } } return node}
Match is a matching function, defined as follows:
type MatchFun func (data1 Object, data2 Object) int
If data1 and data2 are equal, returns 0,data1 greater than Data2 and returns a positive number, less than a negative number.
8, get the link table length GetSize
func (dList *DList) GetSize() uint64 { return (*dList).size}
9. node GetHead
func (dList *DList) GetHead() *DNode { return (*dList).head}
10, get the tail node GetTail
func (dList *DList) GetTail() *DNode { return (*dList).tail}
11, whether the node is the head node Ishead
func (dList *DList) isHead(elmt *DNode) bool { return dList.GetHead() == elmt}
12, whether the node is the tail of the list Istail
func (dList *DList) isTail(elmt *DNode) bool { return dList.GetTail() == elmt}
13. Get the data GetData in the node
func (dNode *DNode) GetData() Object { return (*dNode).data}
This is the method of the node, not the linked list. Used to get what's inside the compartment.
14. Get the next node GetNext
func (dNode *DNode) GetNext() *DNode { return (*dNode).next}
This is also a node method to help the car find the next compartment.
15. Get the previous node GetPrev
func (dNode *DNode) GetPrev() *DNode { return (*dNode).prev}
Here is also the method of the node. Used to find the last compartment.
Code download