The complete code of single linked list, circular linked list, two-way linked list and Linux kernel "shared" double linked list is attached at the end of the article
catalogue
1, Detailed explanation of linked list principle
2, Implementation of single linked list algorithm
2.1 concept of single linked list
2.2 single linked list initialization
2.3 adding elements to the single linked list
2.3.2 tail interpolation method
2.3.3 insertion at any position
2.4 single linked list traversal
2.5 obtaining elements from single linked list
2.6 single linked list lookup elements
2.7 deleting elements from single linked list
2.8 destruction of single linked list
3, Implementation of circular linked list algorithm
4, Implementation of bidirectional linked list algorithm
4.1 initialization of bidirectional linked list
4.2 adding elements to the two-way linked list
4.2.2 tail interpolation method
4.2.3 insertion at any position
4.3 two way linked list traversal
4.4 obtaining elements from bidirectional linked list
4.5 deleting elements from a two-way linked list
4.6 destruction of two-way linked list
5, Linux kernel "shared" bidirectional linked list
Single linked list complete code
Complete code of circular linked list
Two way linked list complete code
1, Detailed explanation of linked list principle
A linked list is a chain storage method of a linear list. Logically, the storage locations of adjacent data in the computer do not have to be adjacent
How to express logical adjacency? You can attach a pointer field to each element, pointing to the storage bit of the next element
Set. As shown in the figure:
As can be seen from the figure, each node contains two fields: data field and pointer field. The pointer field stores the address of the next node,
Therefore, the type pointed to by the pointer is also a node type.
Core elements of linked list:
I each node consists of data field and pointer field
The II pointer field points to the memory address of the next node
Its structure definition typedef struct LinkNode{ ElemType data; struct LinkNode *next; }LinkList, LinkNode;
2, Implementation of single linked list algorithm
2.1 concept of single linked list
The nodes of the linked list all point to the next node in one direction, forming a one-way access data chain
2.2 single linked list initialization
typedef struct _LinkNode { int data; //Data field of node struct _LinkNode *next; //Pointer field of node }LinkNode, LinkList; //Linked list node, linked list bool InitList(LinkList* &L){//Construct an empty single linked list L L=new LinkNode; //Generate a new node as the head node, and point to the head node with the head pointer L if(!L)return false; //Failed to generate node L->next=NULL; //The pointer field of the header node is set to null return true; }
2.3 adding elements to the single linked list
2.3.1 forward interpolation
//Forward interpolation bool ListInsert_front(LinkList* &L, LinkNode * node){ if(!L || !node ) return false; node->next = L->next; L->next = node; return true; }
2.3.2 tail interpolation method
//Tail interpolation bool ListInsert_back(LinkList* &L, LinkNode *node){ LinkNode *last = NULL; if(!L || !node ) return false; //Last node found last = L; while(last->next) last=last->next; //The new node is linked to the tail node->next = NULL; last->next = node; return true; }
2.3.3 insertion at any position
//Arbitrary position interpolation bool LinkInsert(LinkList* &L, int i, int &e){//Insertion of single linked list //Insert a new node with a value of e at the ith position in the single linked list L of the leading node int j; LinkList *p, *s; p=L; j=0; while (p&&j<i-1){ //Find the i-1 node, and p points to it p=p->next; j++; } if (!p || j>i-1){//i > n+1 or i < 1 return false; } s=new LinkNode; //Generate new node s->data=e; //Set the data field of the new node to e s->next=p->next; //Point the pointer field of the new node to the node ai p->next=s; //Point the pointer field of node p to node s return true; }
2.4 single linked list traversal
void LinkPrint(LinkList* &L) {//Output of single linked list LinkNode* p; p=L->next; while (p){ cout <<p->data <<"\t"; p=p->next; } cout<<endl; }
2.5 obtaining elements from single linked list
bool Link_GetElem(LinkList* &L, int i, int &e){//Value of single linked list //Find the ith element in the single linked list L of the leading node //Record the value of the ith data element in L with e int j; LinkList* p; p=L->next;//p points to the first node, j=1; //j is the counter while (j<i && p){ //Scan the chain domain backward until p points to the ith element or p is empty p=p->next; //p points to the next node j++; //Counter j is incremented by 1 accordingly } if (!p || j>i){ return false; //Illegal i value i > n or i < = 0 } e=p->data; //Take the data field of the ith node return true; }
2.6 single linked list lookup elements
bool Link_FindElem(LinkList *L, int e){ //Find by value //Find the element with value e in the single linked list L of the leading node LinkList *p; p=L->next; while (p && p->data!=e){//Scan the chain domain backward until p is empty or the data domain of the node referred to by p is equal to e p=p->next; //p points to the next node } if(!p)return false; //Lookup failed. p is NULL return true; }
2.7 deleting elements from single linked list
bool LinkDelete(LinkList* &L, int i){ //Deletion of single linked list //In the single linked list L of the leading node, delete the ith position LinkList *p, *q; int j; p=L; j=0; while((p->next)&&(j<i-1)){ //Find the i-1 node, and p points to it p=p->next; j++; } if (!(p->next)||(j>i-1))//When I > n or I < 1, the deletion position is unreasonable return false; q=p->next; //Temporarily save the address of the deleted node for free space p->next=q->next; //Change the pointer field of the precursor node of the deleted node delete q; //Free up space for deleted nodes return true; }
2.8 destruction of single linked list
void LinkDestroy(LinkList* &L) {//Destruction of single linked list //Define the temporary node p to point to the header node LinkList *p = L; cout<<"Destroy linked list!"<<endl; while(p){ L=L->next; //L points to the next node cout<<"Delete element: "<<p->data<<endl; delete p; //Delete current node p=L; //p move to next node } }
Complete code implementation:
3, Implementation of circular linked list algorithm
Joseph problem
There are 10 children in numbered order 1, 2,..., 10 circle clockwise. Starting from No. 1, clockwise 1, 2,..., 9. Those who report 9 are listed (obviously, the first circle is numbered 9).
What is the number of the last person out of the circle? What is the number of the fifth person out of the circle?
The complete code of circular linked list is attached at the end of the article~
4, Implementation of bidirectional linked list algorithm
In addition to storing its own data, each node in the single linked list also stores the address of the next node, so you can easily access the next node and subsequent nodes, but you can't go back if you want to access the previous node. For example, when deleting node p, first find its previous node q, and then delete node p. the one-way linked list can only go back, not forward. What if you need to move forward?
You can attach two pointer fields to each element based on the single linked list, one to store the address of the previous element and the other to store the address of the next element. This kind of linked list is called bidirectional linked list.
Its structure definition: typedef struct _LinkNode { int data; //Data field of node struct _LinkNode *next; //Pointer field of the next node struct _LinkNode *prev; //Pointer field of the previous node }LinkNode, LinkList; //LinkList is the pointer type to the structure LNode
4.1 initialization of bidirectional linked list
typedef struct _DoubleLinkNode { int data; //Data field of node struct _DoubleLinkNode* next; //Pointer field of the next node struct _DoubleLinkNode* prev; //Pointer field of the previous node }DbLinkNode, DbLinkList; //LinkList is the pointer type to the structure LNode bool DbInit_List(DbLinkList*& L){//Construct an empty two-way linked list L L = new DbLinkNode; //Generate a new node as the head node, and point to the head node with the head pointer L if (!L)return false; //Failed to generate node L->next = NULL; //The next pointer field of the header node is null L->prev = NULL; //The pointer field of the header node is set to null L->data = -1; return true; }
4.2 adding elements to the two-way linked list
4.2.1 forward interpolation
//Forward interpolation bool DbListInsert_front(DbLinkList*& L, DbLinkNode* node) { if (!L || !node) return false; //1. Only header nodes if (L->next == NULL) { node->next = NULL; node->prev = L; //The new node prev pointer points to the header node L->next = node; //The next pointer of the header node points to the new node } else { L->next->prev = node; //The prev of the second node points to the new node node->next = L->next; //The new node next pointer points to the second node node->prev = L; //The new node prev pointer points to the header node L->next = node; //The next pointer of the header node points to the new node to complete the insertion } return true; }
4.2.2 tail interpolation method
//Tail interpolation bool DbListInsert_back(DbLinkList*& L, DbLinkNode* node) { DbLinkNode* last = NULL; if (!L || !node) return false; last = L; while (last->next) last = last->next; node->next = NULL; node->prev = last; return true; }
4.2.3 insertion at any position
//Insert at specified location bool DbLink_Insert(DbLinkList*& L, int i, int& e) { if (!L || !L->next) return false; if (i < 1) return false; int j = 0; DbLinkList* p, * s; p = L; while (p && j < i) {//Find the node with position i, and p points to the node p = p->next; j++; } if (!p || j != i) { cout << "Node does not exist:" << i << endl; return false; } cout << "p: " << p << endl; s = new DbLinkNode;//Generate new node s->data = e; s->next = p; s->prev = p->prev; p->prev->next = s; p->prev = s; return true; }
4.3 two way linked list traversal
//Traversal output of bidirectional linked list void DbLink_Print(DbLinkList*& L) { DbLinkNode* p = NULL; if (!L) { cout << "The linked list is empty." << endl; return; } p = L; while (p->next) { cout << p->next->data << "\t"; p = p->next; } //Reverse printing cout << endl << "Reverse printing" << endl; while (p) { cout << p->data << "\t"; p = p->prev; } cout << endl; }
4.4 obtaining elements from bidirectional linked list
bool DbLink_GetElem(DbLinkList*& L, int i, int& e){//Value of bidirectional linked list //Find the ith element in the two-way linked list L of the leading node //Record the value of the ith data element in L with e int index; DbLinkList* p; if (!L || !L->next) return false; p = L->next; index = 1; while (p && index < i) {//Scan the list backward until p points to the ith element or p is empty p = p->next; //p points to the next node index++; //The counter index is incremented by 1 accordingly } if (!p || index > i) { return false; //Illegal value of i, i > n or i < = 0 } e = p->data; return true; }
4.5 deleting elements from a two-way linked list
//Delete anywhere bool DbLink_Delete(DbLinkList*& L, int i) //Deletion of bidirectional linked list { DbLinkList* p; int index = 0; if (!L || !L->next) { cout << "The two-way linked list is empty!" << endl; return false; } if (i < 1) return false; //You cannot delete a header node p = L; while (p && index < i) { p = p->next; index++; } if (!p) { //Failure is returned when the node does not exist return false; } p->prev->next = p->next; //Change the next pointer field of the predecessor node of the deleted node if (p->next) { p->next->prev = p->prev; //Change the prev pointer field of the successor node after deleting the node } delete p; //Free up space for deleted nodes return true; }
4.6 destruction of two-way linked list
void DbLink_Destroy(DbLinkList*& L){ //Destruction of bidirectional linked list //Define the temporary node p to point to the header node DbLinkList* p = L; cout << "Destroy linked list!" << endl; while (p) { L = L->next;//L points to the next node cout << "Delete element: " << p->data << endl; delete p; //Delete current node p = L; //p move to next node } }
5, Linux kernel "shared" bidirectional linked list
In the linux kernel, a large number of data structures need to use two-way linked lists, such as processes, files, modules, pages and so on. If we adopt the traditional implementation of two-way linked list, we need to maintain their own linked list for these data structures, and design operation functions such as insert and delete for each linked list. Because the next and prev pointers used to maintain the linked list point to the corresponding types of objects, the linked list operation function of one data structure cannot be used to operate the linked list of other data structures.
For example, we need to define the linked list structure of stars and web server timeout respectively:
one. web Linked list structure of server timeout typedef struct { int fd ; time_t timeout; // Use the timestamp of the timeout time }ConnTimeout; struct Link_Node{ ConnTimeout conn; struct Link_Node *next; } two.Linked list structure of bright starry sky typedef struct { int x; //x coordinate of the star int y; //y coordinates of stars enum STATUS stat; //state unsigned radius; //Radius of stars int step; //Interval per jump int color; //The color of stars }STAR; struct Link_Node{ STAR star; struct Link_Node *next; }
Is there a way for multiple linked lists to share the same set of linked lists? See the figure below:
typedef struct _DoubleLinkNode { struct _DoubleLinkNode *next; //Pointer field of the next node struct _DoubleLinkNode *prev; //Pointer field of the previous node }DbLinkNode; typedef struct { int fd ; time_t timeout; // Use the timestamp of the timeout time DbLinkNode node; // Bidirectional linked list node "Pendant" }ConnTimeout;
typedef struct { int x; //x coordinate of the star int y; //y coordinates of stars enum STATUS stat; //state unsigned radius; //Radius of stars int step; //Interval per jump int color; //The color of stars DbLinkNode node; // Bidirectional linked list node "Pendant" }STAR;
Key points:
offsetof can be used to deduce the position of structure variable according to the address of linked list node in structure
For example:
typedef struct { int fd ; time_t timeout; // Use the timestamp of the timeout time DbLinkNode node; // Bidirectional linked list node "Pendant" }ConnTimeout; //Access the data hosted by the node through the node ConnTimeout *ct = new ConnTimeout; DbLinkNode *p = &(ct->node); cout<<"Please enter the value corresponding to the timeout node fd: "; cin>>ct->fd; cout<<"\n Access the data carried on the node through the node in the linked list:"<<endl; int offset = offsetof(ConnTimeout, node); ConnTimeout *tmp = (ConnTimeout *)((size_t)p-offset); printf("offset: %d\n", offset); printf("Through linked list node node Data accessed:%d\n", tmp->fd);
Source code implementation
#include<iostream> #include<string> #include<stdlib.h> using namespace std; typedef struct _DoubleLinkNode { //int data; // Data field of node struct _DoubleLinkNode* next; //Pointer field of the next node struct _DoubleLinkNode* prev; //Pointer field of the previous node }DbLinkNode, DbLinkList; //LinkList is the pointer type to the structure LNode typedef struct { int fd; time_t timeout; // Use the timestamp of the timeout time DbLinkNode node; // Bidirectional linked list node "Pendant" }ConnTimeout; typedef struct { int x; //x coordinate of the star int y; //y coordinates of stars enum STATUS stat; //state unsigned radius; //Radius of stars int step; //Interval per jump int color; //The color of stars DbLinkNode node; // Bidirectional linked list node "Pendant" }STAR; bool DbList_Init(DbLinkList& L){//Construct an empty two-way linked list L L.next = NULL; //The next pointer field of the header node is null L.prev = NULL; //The prev pointer field of the header node is null return true; } //Tail interpolation bool DbListInsert_back(DbLinkList & L, DbLinkNode & node) { DbLinkNode* last = NULL; last = &L; while (last->next) last = last->next; node.next = NULL; last->next = &node; node.prev = last; return true; } int main(void) { ConnTimeout* cl = NULL, * s = NULL; STAR* sl = NULL; int n = 0; //1. Initialize an empty two-way linked list cl = new ConnTimeout; cl->fd = -1; sl = new STAR; sl->x = -1; DbList_Init(cl->node); DbList_Init(sl->node); //2. Insert data using tail interpolation cout << "Creating bidirectional linked list by tail interpolation" << endl; std::cout << "Please enter the number of elements n: "; cin >> n; cout << "\n Please enter in sequence n File handle for elements:" << endl; while (n > 0) { s = new ConnTimeout; //Generate new node s cin >> s->fd; printf("s Address of:%p node: %p\n", s, &(s->node)); DbListInsert_back(cl->node, s->node); n--; } //3. Access data according to linked list nodes DbLinkNode* p = NULL; p = &(cl->node); cout << "Traverse the nodes in the connection timeout linked list:" << endl; while (p) { int offset = offsetof(ConnTimeout, node); ConnTimeout* ct = (ConnTimeout*)((size_t)p - offset); cout << ct->fd << endl; p = p->next; } //4. Destroy the two-way linked list p = &(cl->node); cout << "Destroy nodes in the connection timeout linked list:" << endl; while (p) { int offset = offsetof(ConnTimeout, node); ConnTimeout* ct = (ConnTimeout*)((size_t)p - offset); printf("offset: %u ct: %p p:%p\n", offset, ct, p); cout << ct->fd << endl; p = p->next; delete ct; } system("pause"); return 0; }
Single linked list complete code
#include<iostream> #include<string> #include<stdlib.h> using namespace std; typedef struct _LinkNode { int data; //Data field of node struct _LinkNode* next; //Pointer field of node }LinkNode, LinkList; //LinkList is the pointer type to the structure LNode bool InitList(LinkList*& L) { L = new LinkNode; if (!L) return false;//Failed to generate node L->next = NULL; L->data = -1; return true; } //Forward interpolation bool ListInsert_front(LinkList*& L, LinkNode* node) { if (!L || !node) return false; node->next = L->next; L->next = node; return true; } //Tail interpolation bool ListInsert_back(LinkList*& L, LinkNode* node) { LinkNode* last = NULL; if (!L || !node) return false; last = L; while (last->next) last = last->next; node->next = NULL; last->next = node; return true; } //Insert at specified location bool LinkInsert(LinkList*& L, int i, int& e) { if (!L) return false; int j = 0; LinkList* p, * s; p = L; while (p && j < i - 1) {//Find the node with position i-1, and p points to the node p = p->next; j++; } if (!p || j > i - 1) { return false; } s = new LinkNode;//Generate new node s->data = e; s->next = p->next; p->next = s; return true; } void LinkPrint(LinkList*& L) { LinkNode* p = NULL; if (!L) { cout << "The linked list is empty." << endl; return; } p = L->next; while (p) { cout << p->data << "\t"; p = p->next; } cout << endl; } bool Link_GetElem(LinkList*& L, int i, int& e)//Value of single linked list { //Find the ith element in the single linked list L of the leading node //Record the value of the ith data element in L with e int index; LinkList* p; if (!L || !L->next) return false; p = L->next; index = 1; while (p && index < i) {//Scan the list backward until p points to the ith element or p is empty p = p->next; //p points to the next node index++; //The counter index is incremented by 1 accordingly } if (!p || index > i) { return false; //Illegal value of i, i > n or i < = 0 } e = p->data; return true; } bool Link_FindElem(LinkList* L, int e, int& index) //Find by value { //Find the element with value e in the single linked list L of the leading node LinkList* p; p = L->next; index = 1; if (!L || !L->next) { index = 0; return false; } while (p && p->data != e) { p = p->next; index++; } if (!p) { index = 0; return false;//No such value found } return true; } bool LinkDelete(LinkList*& L, int i) //Deletion of single linked list { LinkList* p, * q; int index = 0; p = L; if (!L || !L->next) { return false; } while ((p->next) && (index < i - 1)) { p = p->next; index++; } if (!p->next || (index > i - 1)) { //When I > n or I < 1, the deletion position is unreasonable return false; } q = p->next; //Temporarily save the address of the deleted node for free space p->next = q->next;//Change the pointer field of the precursor node of the deleted node delete q; //Free up space for deleted nodes return true; } void LinkDestroy(LinkList*& L) //Destruction of single linked list { //Define the temporary node p to point to the header node LinkList* p = L; cout << "Destroy linked list!" << endl; while (p) { L = L->next;//L points to the next node cout << "Delete element: " << p->data << endl; delete p; //Delete current node p = L; //p move to next node } } int main(void) { LinkList* L = NULL; LinkNode* s = NULL; //1. Initialize an empty linked list InitList(L); //2. Insert data using forward interpolation /*int n; cout<<"Create single linked list "< < endl" by pre interpolation; std::cout<<"Please enter the number of elements n: "; cin>>n; cout<<"\n Please enter n elements in sequence: "< < endl; while(n>0){ s = new LinkNode; //Generate new node s cin>>s->data; ListInsert_front(L, s); n--; } */ //3. Insert data using tail interpolation /*int n; cout<<"Create single linked list "< < endl" by tail interpolation; std::cout<<"Please enter the number of elements n: "; cin>>n; cout<<"\n Please enter n elements in sequence: "< < endl; while(n>0){ s = new LinkNode; //Generate new node s cin>>s->data; ListInsert_back(L, s); n--; } //4. Output of single linked list LinkPrint(L); */ //5. Insert elements anywhere for (int j = 0; j < 3; j++) { int i, x; cout << "Please enter the insertion position and elements (separated by spaces):"; cin >> i; cin >> x; if (LinkInsert(L, i, x)) { cout << "Insert successful.\n\n"; } else { cout << "Insert failed!\n\n"; } LinkPrint(L); } //6. The single linked list obtains elements according to location int element = 0; if (Link_GetElem(L, 2, element)) { cout << "Getting the second element succeeded, Value:" << element << endl; } else { cout << "Failed to get the second element!" << endl; } //7. The single linked list queries the location of the element according to the value int index = 0; if (Link_FindElem(L, 10, index)) { cout << "Find element 10 exists,location: " << index << endl; } else { cout << "Element 10 does not exist." << endl; } //8. Delete elements from single linked list if (LinkDelete(L, 2)) { cout << "The second element was deleted successfully!" << endl; LinkPrint(L); } else { cout << "Failed to delete the 2nd element!" << endl; } //9. Destroy the single linked list LinkDestroy(L); system("pause"); return 0; }
Complete code of circular linked list
#include<iostream> #include<string> #include<stdlib.h> using namespace std; typedef struct _LinkNode { int data; //Data field of node struct _LinkNode* next; //Pointer field of node }LinkNode, LinkList; //LinkList is the pointer type to the structure LNode void LinkPrint(LinkList* L); bool InitList(LinkList*& L){//Construct an empty circular linked list L L = new LinkNode; //Generate a new node as the head node, and point to the head node with the head pointer L if (!L)return false; //Failed to generate node L->next = L; //The pointer field of the header node points to itself L->data = -1; return true; } //Tail interpolation bool ListInsert_back(LinkList*& L, LinkNode* node) { LinkNode* last = NULL; if (!L || !node) return false; //Last node found last = L; while (last->next != L) last = last->next; //The new node is linked to the tail node->next = L; last->next = node; return true; } bool Joseph(LinkList*& L, int interval) { //In the circular linked list L of the leading node, each interval circularly deletes the node LinkList* p, * q; int j = 0, i = 0; int times = 0, num = 0; p = L; if (!L || p->next == L) { cout << "The linked list is empty!" << endl; return false; } if (interval < 1) { cout << "The number elimination password cannot be less than 1!" << endl; return false; } do { i += interval; while ((p->next)){ //Find the ith node, and p points to the previous node of the node if (p->next != L) j++; if (j >= i) break; p = p->next; } times++; /*if (!(p->next)||(j>i))//When I > n or I < 1, the deletion position is unreasonable return false;*/ q = p->next; //Temporarily save the address of the deleted node for free space num = q->data; if (times == 5) cout << "The number of the fifth out circle is:" << num << endl; printf("cur: %d last: %d next:%d\n", q->data, p->data, q->next->data); p->next = q->next; //Change the pointer field of the precursor node of the deleted node delete q; //Free up space for deleted nodes LinkPrint(L); } while (L->next != L);//The linked list is not empty. Continue counting cout << "The number of the last circle is:" << num << endl; return true; } void LinkPrint(LinkList* L) //Output of circular linked list { LinkList* p; if (!L || L == L->next) { cout << "The linked list is empty!" << endl; return; } p = L->next; while (p != L){ cout << p->data << "\t"; p = p->next; } cout << endl; } int main() { int i, x; LinkList* L; LinkNode* s; //1. Initialize an empty circular linked list if (InitList(L)) { cout << "Initialize an empty circular linked list!\n"; } //2. Create a circular linked list (tail insertion method) std::cout << "Creating circular linked list by tail interpolation, Insert 10 elements..." << endl; i = 0; while ((++i) <= 10){ s = new LinkNode;//Generate new node s->data = i; //The input element value is assigned to the data field of the new node s->next = NULL; if (ListInsert_back(L, s)) { cout << "Insert successful!" << endl; } else { cout << "Insert failed!" << endl; } } cout << "Tail interpolation method to create circular linked list output results:\n"; LinkPrint(L); //3. Answer Joseph's questions Joseph(L, 9); system("pause"); return 0; }
Two way linked list complete code
#include<iostream> #include<string> #include<stdlib.h> using namespace std; typedef struct _DoubleLinkNode { int data; //Data field of node struct _DoubleLinkNode* next; //Pointer field of the next node struct _DoubleLinkNode* prev; //Pointer field of the previous node }DbLinkNode, DbLinkList; //LinkList is the pointer type to the structure LNode bool DbList_Init(DbLinkList*& L){//Construct an empty two-way linked list L L = new DbLinkNode; //Generate a new node as the head node, and point to the head node with the head pointer L if (!L)return false; //Failed to generate node L->next = NULL; //The next pointer field of the header node is null L->prev = NULL; //The prev pointer field of the header node is null L->data = -1; return true; } //Forward interpolation bool DbListInsert_front(DbLinkList*& L, DbLinkNode* node) { if (!L || !node) return false; //1. Only header nodes if (L->next == NULL) { node->next = NULL; node->prev = L; //The new node prev pointer points to the header node L->next = node; //The next pointer of the header node points to the new node } else { L->next->prev = node; //The prev of the second node points to the new node node->next = L->next; //The new node next pointer points to the second node node->prev = L; //The new node prev pointer points to the header node L->next = node; //The next pointer of the header node points to the new node to complete the insertion } return true; } //Tail interpolation bool DbListInsert_back(DbLinkList*& L, DbLinkNode* node) { DbLinkNode* last = NULL; if (!L || !node) return false; last = L; while (last->next) last = last->next; node->next = NULL; last->next = node; node->prev = last; return true; } //Insert at specified location bool DbLink_Insert(DbLinkList*& L, int i, int& e) { if (!L || !L->next) return false; if (i < 1) return false; int j = 0; DbLinkList * p, * s; p = L; while (p && j < i) {//Find the node with position i, and p points to the node p = p->next; j++; } if (!p || j != i) { cout << "Node does not exist:" << i << endl; return false; } cout << "p: " << p << endl; s = new DbLinkNode;//Generate new node s->data = e; s->next = p; s->prev = p->prev; p->prev->next = s; p->prev = s; return true; } void DbLink_Print(DbLinkList*& L) { DbLinkNode* p = NULL; if (!L) { cout << "The linked list is empty." << endl; return; } p = L; while (p->next) { cout << p->next->data << "\t"; p = p->next; } //Reverse printing cout << endl << "Reverse printing" << endl; while (p) { cout << p->data << "\t"; p = p->prev; } cout << endl; } bool DbLink_GetElem(DbLinkList*& L, int i, int& e){//Value of bidirectional linked list //Find the ith element in the two-way linked list L of the leading node //Record the value of the ith data element in L with e int index; DbLinkList* p; if (!L || !L->next) return false; p = L->next; index = 1; while (p && index < i) {//Scan the list backward until p points to the ith element or p is empty p = p->next; //p points to the next node index++; //The counter index is incremented by 1 accordingly } if (!p || index > i) { return false; //Illegal value of i, i > n or i < = 0 } e = p->data; return true; } bool DbLink_Delete(DbLinkList*& L, int i){ //Deletion of bidirectional linked list DbLinkList* p; int index = 0; if (!L || !L->next) { cout << "The two-way linked list is empty!" << endl; return false; } if (i < 1) return false; //You cannot delete a header node p = L; while (p && index < i) { p = p->next; index++; } if (!p) { //Failure is returned when the node does not exist return false; } p->prev->next = p->next; //Change the next pointer field of the predecessor node of the deleted node p->next->prev = p->prev; //Change the prev pointer field of the successor node after deleting the node delete p; //Free up space for deleted nodes return true; } void DbLink_Destroy(DbLinkList*& L) {//Destruction of bidirectional linked list //Define the temporary node p to point to the header node DbLinkList* p = L; cout << "Destroy linked list!" << endl; while (p) { L = L->next;//L points to the next node cout << "Delete element: " << p->data << endl; delete p; //Delete current node p = L; //p move to next node } } int main(void) { DbLinkList* L = NULL; DbLinkNode* s = NULL; //1. Initialize an empty two-way linked list DbList_Init(L); //2. Insert data using forward interpolation int n; cout << "Creating bidirectional linked list by forward interpolation" << endl; std::cout << "Please enter the number of elements n: "; cin >> n; cout << "\n Please enter in sequence n Elements:" << endl; while (n > 0) { s = new DbLinkNode; //Generate new node s cin >> s->data; DbListInsert_front(L, s); n--; } //3. Insert data using tail interpolation cout << "Creating bidirectional linked list by tail interpolation" << endl; std::cout << "Please enter the number of elements n: "; cin >> n; cout << "\n Please enter in sequence n Elements:" << endl; while (n > 0) { s = new DbLinkNode; //Generate new node s cin >> s->data; DbListInsert_back(L, s); n--; } //4. Output of bidirectional linked list DbLink_Print(L); //5. Insert elements anywhere for (int j = 0; j < 3; j++) { int i, x; cout << "Please enter the insertion position and elements (separated by spaces):"; cin >> i; cin >> x; if (DbLink_Insert(L, i, x)) { cout << "Insert successful.\n\n"; } else { cout << "Insert failed!\n\n"; } DbLink_Print(L); } //6. The two-way linked list obtains elements according to location int element = 0; if (DbLink_GetElem(L, 2, element)) { cout << "Getting the second element succeeded, Value:" << element << endl; } else { cout << "Failed to get the second element!" << endl; } //7. Delete elements from the two-way linked list if (DbLink_Delete(L, 2)) { cout << "The second element was deleted successfully!" << endl; DbLink_Print(L); } else { cout << "Failed to delete the 2nd element!" << endl; } if (DbLink_Delete(L, 1)) { cout << "The first element was deleted successfully!" << endl; DbLink_Print(L); } else { cout << "Failed to delete the first element!" << endl; } //8. Destroy the two-way linked list DbLink_Destroy(L); system("pause"); return 0; }