single linked list
A linked list is a commonly used data structure, with the advantage of not needing to move when inserting and deleting elements, the capacity of the table is expandable, and storage space can be discontinuous.
In addition, because it involves pointers, it is very popular with interviewers.
This article will mainly introduce the single linked list, and briefly introduce the next double linked list and ring linked list, and through a series of topics to strengthen this knowledge.
The structure of the linked list node:
template<class DataType>Node{ DataType data; Node<DataType> *next;};
The data stores the node, and next refers to the next node.
For a single-linked list, you need to set the head pointer to the node where the first element is located, and all operations begin with a pointer to the beginning.
Sometimes we can set a sentinel, it is also a node, called the head node, the node does not hold data, only for simplifying the code (plus the head node, regardless of whether the linked list is empty, the head pointer always points to the head node, so the processing of the empty table and non-empty table uniform point).
Below we will take the Sentinel list as an example to implement a single-linked list.
template <class datatype>class linklist{public : linklist (); Linklist (DataType a[], int N); ~linklist (); DataType Get (int i); //bitwise LOOKUP, node I int Locate (DataType x); //Search by value, returns the position of x ordinal void Insert (int I, DataType x); //insert x in the first place DataType Erase (int i); void print (); private : node<datatype> *first; //head pointer };
constructor Function
Template<classDatatype>linklist<datatype>::linklist () {first =Newnode<datatype>; First->next = NULL;}//Head insertion methodTemplate<classDatatype>linklist<datatype>::linklist (DataType a[],intN) {first =Newnode<datatype>; First->next = NULL; Node<datatype> *newnode; for(inti =0; I < n; ++i) {NewNode =Newnode<datatype>; Newnode->data = A[i]; Newnode->next = first->next; First->next = NewNode; }}//tail interpolation methodTemplate<classDatatype>linklist<datatype>::linklist (DataType a[],intN) {first =Newnode<datatype>; Node<datatype> *rail, *newnode; rail = first; for(inti =0; I < n; ++i) {NewNode =Newnode<datatype>; Newnode->data = A[i]; Rail->next = NewNode; rail = NewNode; } Rail->next = NULL;}
Destructors
template<class DataType>LinkList<DataType>::~LinkList(){ Node<DataType> *cur; while (first != NULL) { //暂存释放节点 first = first->next; delete cur; }}
Traversal Operations
template<class DataType>void LinkList<DataType>::print(){ Node<DataType> *cur = first->next; while (cur) { cout‘ ‘; cur = cur->next; } cout << endl;}
Bitwise Lookup
template<class DataType>DataType LinkList<DataType>::get(int i){ Node<DataType> *cur = first->next; int1; while (cur && pos != i) { cur = cur->next; ++pos; } if (NULL == cur) throw"查找失败"; else return cur->data;}
Find by Value
template<class DataType>int LinkList<DataType>::locate(DataType x){ Node<DataType> *cur = first->next; int1; while (cur && cur->data != x) { cur = cur->next; ++pos; } if (NULL == cur) return0//查找失败 else return cur->data;}
Insert
Template<classDatatype>voidLinklist<datatype>::insert (intI, DataType x) {//Considering the i=1 situation, we need to start with the Sentinelnode<datatype> *cur = First;intpos =0;//Find first i-1 locations while(cur && pos! = I1) {cur = cur->next; ++pos; }if(NULL = = cur)Throw "Insert Failed";Else{Node<datatype> *newnode =Newnode<datatype>; Newnode->data = x; Newnode->next = cur->next; Cur->next = NewNode; }}
Delete
Template<classDatatype>datatype Linklist<datatype>::erase (inti) {node<datatype> *cur = first;intpos =0;intRet//Find first i-1 locations while(cur && pos! = I1) {cur = cur->next; ++pos; }if(NULL = = Cur | | NULL = = Cur->next)//Note that the I-1 node was found, possibly the I node does not exist! Throw "Insert Failed";Else{node<datatype> *tmpnode = cur->next;//Temporary storageRET = tmpnode->data; Cur->next = tmpnode->next;//Pick-chain DeleteTmpnode;returnRet }}
Circular single-linked list
A circular list is simply a single-linked list that connects it to the end.
For a circular linked list, if you still use first to point to the head pointer, since we have only the next flag, there is no pre flag, so it is not easy to find the tail.
Therefore, in a circular list, we often use the tail pointer rear to indicate the last node. As a result, the first node can be obtained using Rear->next->next (Rear->next as Sentinel), and rear gets the last node, which facilitates a lot of access.
Double Linked list
A doubly linked list has a prior to point to the precursor node than a single-linked list node:
template<class DataType>DulNode{ DataType data; DulNode<DataType> *prior, *next;};
Most operations of a doubly linked list are similar to a single linked list, with the advantage of being "able to go back" and allowing easy access to the predecessor successor.
Insert
//在p节点后插入新节点ss->=//插入s->= p->//插入p->next->=//换链p->=//换链
Delete
//p指向待删除节点p->prior->= p->next;p->next->= p->prior;delete p;
static Linked list
A static linked list is an array of linked lists, using the subscript of an array element to simulate a single-linked list of pointers. This method is more flexible and faster, but the space limit is relatively large.
A more typical example is: moving a small ball
The example can use two array left[],right[] to simulate a doubly linked list to improve efficiency.
Commonly used static linked list storage structure:
constint100;template <class DataType>struct SNode{ DataType data; int next} SList[Maxsize];
A static list requires two pointers: first is the head pointer of a static list, and Avai is the head pointer of the idle chain.
In other words, our slist will be divided into two chains, one is used, one is idle.
For ease of operation, our static list is also with the top node.
//initialize first = 0 ; Slist[first].next =-1 ; //used chain only the head node avail = 1 ; //the remaining nodes string into the idle chain for (int i = avail; i < Maxsize-1 ; ++i) {slist[i].next = I+1 ;} Slist[maxsize-1 ].next =-1 ;
//在节点p后面插入新节点if (-1 == avail) "链表已满";int//获取一个空闲的节点avail = SList[avail].next;SList[newNodeIndex].next = SList[p].next;SList[p].next = newNodeIndex;
//删除节点p的后继节点int//暂存被删除的节点//摘链//删除的节点插到空闲链头部avail = q;
* * Insert Delete only needs to modify cursor, do not need to move element.
Related Topics
Delete a linked list node at O (1) Time
Given a one-way list of head pointers and a node pointer, define a function to delete the node at O (1) time. The linked list nodes and functions are defined as follows:
struct ListNode{ intvalue; ListNode *next;};void DeleteNode(ListNode** head, ListNode* p);
The first limitation of time makes it impossible to traverse from the beginning.
To be sure, to delete the node p, we need to have the predecessor of P next point to the successor of P. Our conventional idea is to change the predecessor of P's next, but because it cannot be accessed directly, so the mountain does not come over, I used to-move the successor of P to the position of P.
So the question is simple:
If the subsequent existence of P, recorded as Q, then we will copy the Q to P, then the original position of the Q can be de-chain and free memory, and indirectly delete the node P (actually p at the memory is not released, releasing the subsequent memory of P).
A special case to note is that if p is not followed, it cannot be resolved with the above method, and it still needs to be traversed from the beginning.
Another special case is that if there is only one node in the list, then the head must be null after deletion.
voidDeletenode (listnode** phead, listnode* p) {if(!phead | |!p)return;if(P->next)//presence of successor nodes{ListNode *pnext = p->next; P->value = pnext->value; P->next = pnext->next;DeletePnext; }Else if(*head = = p)//Only one node, head node{*head = NULL;DeleteP p = NULL; }Else //Multiple nodes, delete tail node{ListNode *pnext = *head; while(Pnext->next! = p) Pnext = pnext->next; Pnext = NULL;DeleteP p = NULL; }}
The last thing to note is that you need to make sure that P is present in the list before this function is called.
K-node of the penultimate page
Enter a list to output the last K nodes of the linked list, counting from 1 onwards.
Idea 1: Traverse to get the chain table length n, and then traverse to find the N-k+1 node.
Idea 2: Using 2 pointers, the first one goes k-1, followed by two pointers, until the first pointer goes to the end (that is, its next is null).
ListNode * Findkthtotail (ListNode*head, unsignedintK) {if(NULL = = Head | |0= = k)return;//Note k=0The situation ListNode*node1= Head,*node2= head;intCNT =0; while(Node1 && CNT < K-1) {Node1 = node1->Next; ++cnt; }if(NULL = = node1)//list length less than kreturnNULL; while(node1->Next) {Node1 = node1->Next; Node2 = node2->Next; }returnNode2;}
Reverse Linked list
Suppose there are 3 nodes: PRE->CUR->NXT.
We will pre->cur reverse and get pre<-cur nxt.
There is a disconnect in the middle, for the next time we have access to the NXT, we have to stage the NXT, and we need access to the pre for the reversal, so we also need to stage the pre. So, to achieve the reversal, we need 3 pointers pointing to the top three, respectively.
Some boundary conditions need to be noted:
The list is empty, and the list has only 1 nodes.
*head){ if (NULL == head) return ; *pre*cur*nxt = NULL; *reverseHead = NULL; while (cur) { nxt = cur->next; if (NULL == nxt) reverseHead = cur; cur->next = pre; pre = cur; cur = nxt; } return reverseHead;}
About the list of topics there are many ~ here is not an example of ~
Next time we will learn about binary tree related content!
Resources:
Data structure (c + + Edition) (2nd edition)-Wang Hu Ming Wang Tao
"The sword means offer"-huang
Make a little progress every day, Come on!
(●’?’●)
I have limited level, such as the content of the article has errors and omissions, please point out the reader, thank you!
"Daily algorithm" chain List & Examples selection