golang double linked list implementation code example
- 2020-07-21 08:27:52
- OfStack
The realization of double linked list
The basic concept
Each node stores Pointers to the previous and next nodes
Implementation approach
Create 1 node structure
Each node has a pointer to the upper node and a pointer to the lower node Each node has 1 key = > valueCreate 1 linked list structure
Linked list size property Linked list size property Linked list lock, to achieve concurrent security Link head node List tail nodeImplement the linked list operation method
Add the header node operation AppendHead Add a tail node to operate AppendTail Append the tail node to operate Append Insert any node to operate Insert Remove any node operation Remove Remove the header node operation RemoveHead Remove the tail node operation RemoveTail Gets the node Get at the specified location Search for any node Search Gets the linked list size GetSize Print all node operations Print Reverse all node operations Reverseconclusion
Learning algorithm well is a process of continuous accumulation When learning, we also need to combine knowledge and practice 1 Implementation requires more use case testing.
Code parsing
Defines the structure of a node
type DoubleNode struct {
Key int // key
Value interface{} // value
Prev *DoubleNode // on 1 Node pointer
Next *DoubleNode // Under the 1 Node pointer
Freq int // Number of frequency . In order to give LFU The use of
}
Defines the structure of a double linked list
// define 1 A double linked list structure
type DoubleList struct {
lock *sync.RWMutex // The lock
Capacity uint // The maximum capacity
Size uint // Current capacity
Head *DoubleNode // Head node
Tail *DoubleNode // The tail node
}
Make a double linked list at the beginning
// Make a double linked list at the beginning
func New(capacity uint) *DoubleList {
list := new(DoubleList)
list.Capacity = capacity
list.lock = new(sync.RWMutex)
list.Size = 0
list.Head = nil
list.Tail = nil
return list
}
Add header node
Implementation approach
func (list *DoubleList) AddHead(node *DoubleNode) bool {
// Determine if the capacity is 0
if list.Capacity == 0 {
return false
}
list.lock.Lock()
defer list.lock.Unlock()
// Determines whether the header node is nil
if list.Head == nil {
list.Head = node
list.Tail = node
} else { // There are header nodes
list.Head.Prev = node // Put the old header node on 1 Five nodes point to a new node
node.Next = list.Head // Under the new head node 1 Three nodes point to the old header node
list.Head = node // Set a new header node
list.Head.Prev = nil // Put a new header node on it 1 Node setting NIL
}
list.Size++
return true
}
Add a tail element
Implementation approach
Determine the capacity first To determine whether the tail is empty, If null, add a new node If not null, change the existing node and add
func (list *DoubleList) AddTail(node *DoubleNode) bool {
// Determine if there is capacity ,
if list.Capacity == 0 {
return false
}
list.lock.Lock()
defer list.lock.Unlock()
// Determine if the tail is empty
if list.Tail == nil {
list.Tail = node
list.Head = node
} else {
// The next node in the old tail points to the new node
list.Tail.Next = node
// When a new node is appended , First the node The previous node points to the old tail node
node.Prev = list.Tail
// Set the new tail node
list.Tail = node
// The next node in the new tail is set to null
list.Tail.Next = nil
}
// Double linked list size +1
list.Size++
return true
}
Add any location element
Implementation approach
Determine capacity size Determine the size of the list Type 1: The tail is added if the inserted position is greater than the current length Type 2: If the insertion position is equal to 0, the header is added Type 3: Intermediate insertion node First extract the node to be inserted, and pretend to be C node One B node is inserted between A and C The lower node of A should be B, that is, the upper node of C should be B The upper node of B is the upper node of C The next node of B is C
// Add any location element
func (list *DoubleList) Insert(index uint, node *DoubleNode) bool {
// Capacity is full
if list.Size == list.Capacity {
return false
}
// If there are no nodes
if list.Size == 0 {
return list.Append(node)
}
// The tail is added if the inserted position is greater than the current length
if index > list.Size {
return list.AddTail(node)
}
// If the insertion position is equal to 0 the , Add the head
if index == 0 {
return list.AddHead(node)
}
// Fetch the node at the position to be inserted
nextNode := list.Get(index)
list.lock.Lock()
defer list.lock.Unlock()
// The middle insert :
// Assumptions have been A, C node , Now I'm gonna insert B node
// nextNode That is C node ,
//A The next node should be B, namely C The lower node of the upper node of is B
nextNode.Prev.Next = node
//B The last node of theta is theta C On the node
node.Prev = nextNode.Prev
//B The next node is C
node.Next = nextNode
//C The last node of theta is theta B
nextNode.Prev = node
list.Size++
return true
}
Delete header node
Implementation approach
// Delete header node
func (list *DoubleList) RemoveHead() *DoubleNode {
// Determines whether the header node is empty
if list.Head == nil {
return nil
}
list.lock.Lock()
defer list.lock.Unlock()
// Remove the head node
node := list.Head
// Determine if the head is down 1 A node
if node.Next != nil {
list.Head = node.Next
list.Head.Prev = nil
} else { // If it doesn't 1 A node , That only 1 A node
list.Head, list.Tail = nil, nil
}
list.Size--
return node
}
Delete tail node
Implementation approach
// Delete tail node
func (list *DoubleList) RemoveTail() *DoubleNode {
// Determine if the tail node is empty
if list.Tail == nil {
return nil
}
list.lock.Lock()
defer list.lock.Unlock()
// Take out the tail node
node := list.Tail
// Determine the top of the tail node 1 Whether or not
if node.Prev != nil {
list.Tail = node.Prev
list.Tail.Next = nil
}
list.Size--
return node
}
Delete any element
Implementation approach
Determine if it is a header node Determine if it is a tail node Otherwise, it is an intermediate node, and the pointer position of the upper and lower nodes needs to be moved Points the next node pointer from the previous node to the next node Points the upper node pointer of the next node to the upper node
// Delete any element
func (list *DoubleList) Remove(node *DoubleNode) *DoubleNode {
// Determine if it is a header node
if node == list.Head {
return list.RemoveHead()
}
// Determine if it is a tail node
if node == list.Tail {
return list.RemoveTail()
}
list.lock.Lock()
defer list.lock.Unlock()
// The nodes are intermediate nodes
// You need to :
// Will be on 1 The bottom of the node 1 The node pointer points to the lower node
// Will the 1 On a node 1 The node pointer points to the upper node
node.Prev.Next = node.Next
node.Next.Prev = node.Prev
list.Size--
return node
}
View the complete source code