Array
Before talking about the linked list, let's first discuss the array. Anyone who has learned the data structure knows that the array hasRandom AccessFor example, the following program:
int a[10]; a[2] = 2; printf("%d\n", *(a+2));
Initialize 2 for the location where the index is 2, and then randomly access the value of this address through the first address offset of 2 * sizeof (INT) of A. ArrayAdvantages of Random AccessAlso make itLost flexibility insert and delete. For example, if the size of an array is 100 (INDEX) * sizeof (char), I want to insert a 'O' at the 3rd index position. I have to change the array from 100th to 4th.
Move one location in turn
The same is true for deleting an element in an array. All elements following the array must forward to a position. this leads to efficiency problems. Some people say that another confirmation is that the array size must be determined before processing a group of data. In fact, this can be used to dynamically allocate space using malloc, then we use the returned pointer to the array. therefore, the data structure of the linked list is extended because it is mainly inserted and deleted.
Unidirectional linked list
As mentioned above, arrays have two major drawbacks: a large number of elements need to be moved during insertion and deletion. for linked lists, this is its advantage. The so-called linked list is a pile of "chain" elements. the data stored in the computer occupies a certain amount of memory space in the memory. This memory space also has a corresponding address, just like your home, the memory address is like your home address which can be uniquely identified. the implementation of the linked list uses the data address.
Node
A node is a basic component of a linked list. It not only stores data, but also stores a pointer to the next storage unit.
Data is the data part, and address stores the address of the next storage unit. after a computer accesses a certain data, it can locate the next node based on the address in the current node, and then access and operate on the data in the next node. let's look back at the insertion and deletion issues. When you need to insert a knot, you just need to point the pointer back to the new data, and the new data points to the data pointed to by the original pointer. deleting a node also changes the pointer direction.
Table header pointer and table tail pointer
The two pointers are introduced here to facilitate operations on the linked list. The header Pointer Points to the first node (also called the header node) of the linked list ), the table tail Pointer Points to the last node of the linked list.
This is an empty one-way linked list. head and tail are the table header and table tail pointers respectively. The header pointer is introduced to facilitate operations on empty tables and non-empty tables. For example
Head-> next = NULL; // It is an empty table.
The introduced tail Pointer Points to the last node of the linked list and points to null. In this way, if the last node is the end pointer of the table, it points to null, and the opposite is true.To locate the tail end in the O (1) time complexity.
Next we will continue to explore the operations of splitting the linked list. In order to make the linked list more flexible, we will use the C ++ template below to implement each operation.
Conception and implementation of table node operations
Node Class ConstructionMust be simpleThe basic operations are as follows:
1. Set the address of another node pointed to by the current node pointer
It sounds a bit difficult, but the pointer is born like this. No way, you can just click it. The following is the implementation:
template <class T>void ListNode<T>::SetLink(ListNode<T>* next) { link = next;}
2. Retrieve the pointing address of the current node.
template <class T>ListNode<T>* ListNode<T>::GetLink() { return link;}
3. retrieve the data part of the current node
template <class T>T& ListNode<T>::GetData() { return data;}
In this way, the basic table node is designed.
One-way linked list operation-insert nodes at the end
With the end node, it is much more convenient to insert it to the end. Simply add a new node to the end of the pointer.
Template <class T> bool list <t>: tailaddnode (T value) {listnode <t> * Add = new listnode <t> (value ); tail-> setlink (ADD); tail = tail-> getlink ();/** <let the tail pointer point to the new tail */tail-> setlink (null ); if (null! = Tail) {return true;} else {return false ;}}
One-way linked list operation-Insert a new node at any index location
To insert a new node at any location, you must first know the index location and value.TraversalTo the index location, and then replace the pointer.
During program design, for program robustness, you must first set model constraints when passing in the index value:
Index> 0 & index <sum points-1
Then traverse to the index location:
ListNode<T>* cur = head; while (index) { cur= cur->GetLink(); index--; }
After cur is taken out, the following is similar to the idea of inserting a new node at the end node.
ListNode<T>* add = new ListNode<T>(value); add->SetLink(cur->GetLink()); cur->SetLink(add); if (cur->GetLink()!=NULL) { return TRUE; } else { return FALSE; }
Then, use the graph to break down the operations:
One-way linked list operation-delete any node
To delete a node with Index = 4, you must first know the 3 node. Therefore, a pointer is required to indicate the forward node. to delete a node, you also need to set the index condition.
Index> 0 & index <sum points-1
3 and the current node are extracted.
Listnode <t> * prenode = head; // The previous node listnode <t> * curnode = head-> getlink (); // the current node while (INDEX) {prenode = prenode-> getlink (); curnode = curnode-> getlink (); index --;}
Then perform the pointer operation:
preNode->SetLink(curNode->GetLink());
In addition, if you delete the last node, you need to set the tail pointer (that is, tail) to the new node.
if (tail == curNode) { tail = preNode; }
One-way linked list operation-empty linked list
To delete all nodes, You need to traverse the linked list once. If each node is malloc, pay attentionMemory leakage,That is, each node must be free.
Listnode <t> * cur; while (Head-> getlink ()! = NULL) {cur = head-> getlink (); head-> setlink (cur-> getlink (); // assign the current point to the header node Delete cur ;}
Linked List Operation-empty Chain List
The linked list is empty. As mentioned earlier, you only need to judge based on the header pointer, that is
head->GetLink() == NULL;
One-way linked list operation-linked list node count
We still need to traverse the linked list once.Random Access is not supported..
template <class T>int List<T>::GetCount() { int count = 0; ListNode<T>* cur= head->GetLink(); while (NULL != cur) { count++; cur = cur->GetLink(); } return count;}
The basic operations of the basic linked list are basically as follows.
Two-way linked list
We can see from the above that it is very troublesome to obtain the front node of a node. If we save the pointer to the front node and the pointer to the back in each node at the same time, the time complexity will be greatly reduced.O (1)
A two-way linked list is similar to a one-way linked list. The difference is that each node has a pointer to the previous node, and the last node of the linked list also includes a pointer, one pointing to the previous node, there is also a header node.
Two APIs need to be added to the linked list node class,One is to set the front node, and the other is to take the front Node
/* --- Set the precursor node --- */template <class T> void listnode <t>: setprior (listnode <t> * pre) {prior = pre ;} /* --- obtain the precursor node --- */template <class T> listnode <t> * listnode <t>: getprior () {return prior ;}
The current node looks like this
The basic operations of a two-way linked list are a bit complicated becauseThe changed pointer operation is more than double the previous one.
Two-way linked list-adding nodes
This is to insert a node to the end of the linked list, including a total of five pointers to be changed.
If it is not inserted at the end, there will be no tail pointer. You only need to change four pointers.
/*! \ @ BREF add node to list tail \ @ input T value \ @ return bool */template <class T> bool doublelist <t>: addtail (T value) {doublelistnode <t> * Add = new doublelistnode <t> (value); tail-> setlink (ADD); add-> setlink (tail ); /** <set the precursor pointer */tail = tail-> getlink (); tail-> setlink (head ); /** <set the end node to point to the head */head-> setprior (ADD ); /** <reset the head precursor * // * --- processed --- */If (null! = Tail) {return true;} else {return false ;}}
Two-way linked list-delete a node
Delete tail Node
Delete the intermediate node
Deleting any node also requires a pointer to save the front node like a one-way linked list. In addition, the pointer to the current node is changed to the pointer to the next node.
DoubleListNode<T>* preNode = cur->GetLink();DoubleListNode<T>* nextNode = cur->GetLink();preNode->GetLink(cur->GetLink());nextNode->GetLink(cur->GetPrior());
In addition to deletion and insertion, the other operations are almost the same. In addition, the query is more convenient than the one-way linked list query, because the precursor pointer is added. two-way query is supported. although it is convenient to add a domain, it also increases the space demand and doubles the overhead of insertion and deletion because more pointers need to be located.
Finally, we will summarize the issues that need attention:
1. Pay attention to pointer initialization during linked list operations. Otherwise, the results of classic segmentation violation and memmory access violation will appear.
2. When implementing the Program, pay attention to the validity of the index. index> 0 & index <sum points-header node (1)
3. When the data in the node information of the linked list contains malloc data, pay attention to free/delete when deleting the node. Otherwise, the memory leak problem will be waiting for you.