Abstract: this chapter mainly describes the implementation of circular double linked list
Introduction to this chapter
In this chapter, I will not describe the implementation logic of the code in detail. If you have read the previous articles or written your own single linked list, you will grasp the implementation of circular double linked list in this article; If you are not clear about some of the logic, you can draw your own pictures to understand. Here I will only draw two pictures as a demonstration. Others can draw their own pictures. Drawing is really important!
1. Logical structure of circular double linked list
Here, I take the circular double linked list of the leading node as an example:
Each node has a data field and two pointer fields. Prev points to the previous element of the node and next points to the next node of the node. The connection between each two nodes is bidirectional, so we can find the direct precursor and direct successor of the node through any node; It is worth noting that the prev of the head node points to the tail node, and the next field of the tail node points to the head node, which forms a circular linked list.
2. Code implementation of circular double linked list
2.1 define the storage structure of circular double linked list
// Defines the type of linked list data field typedef int LTDataType; // Define linked list type typedef struct ListNode { struct ListNode* prev; // Point to the previous node, that is, point to the direct precursor node struct ListNode* next; // Point to the next node, that is, point to the direct successor node LTDataType data; // Data domain } ListNode;
2.2 creating nodes
// New node ListNode* BuyListNode(LTDataType* data) { if (!data) { printf("Data field cannot be empty\n"); return NULL; } // Create a new node ListNode* newNode = (ListNode*)malloc(sizeof(ListNode)); // Air judgment if (!newNode) { perror("Failed to open up space"); return NULL; } // insert data newNode->data = *data; // next points to null newNode->next = NULL; // prev points to null newNode->prev = NULL; return newNode; }
2.2 initializing header nodes
When there is only one node in the circular double linked list, that is, the head node, the prev field and the next field of the head node point to themselves.
void ListInit(ListNode** pphead) { int a = 10; // Create a new node ListNode* newNode = BuyListNode(&a); // Point to yourself newNode->next = newNode; newNode->prev = newNode; *pphead = newNode; }
2.3 calculate the length of the linked list
When calculating the length of the circular double linked list, we will keep the linked list variable. Then the problem comes. As long as the leading node circular double linked list is not empty, it will always have a direction. What should be our cycle termination condition? Very simple, when the current node is the head node, it means that the double linked list has been traversed.
// Calculate the length of the double linked list, excluding the head node size_t ListSize(ListNode* phead) { // Record current node ListNode* cur = phead->next; // Record length size_t size = 0; // If the current node is not a header node while ( cur != phead ) { cur = cur->next; size ++; } return size; }
2.4 tail interpolation
void ListPushBack(ListNode* phead, LTDataType* data) { assert(phead); // Create a new node ListNode* newNode = BuyListNode(data); // Save tail node ListNode* tail = phead->prev; // The next of the tail node points to the new node tail->next = newNode; // The prev of the new node points to the tail node newNode->prev = tail; // The next of the new node points to the header node newNode->next = phead; // The prev of the head node points to the new node phead->prev = newNode; // Complete insertion }
2.5 tail deletion method
// Tail deletion void ListPopBack(ListNode* phead) { assert(phead); // If the linked list is empty, it will be interrupted assert(phead->next != phead); // Calculate linked list length size_t size = ListSize(phead); // If the size is less than 1, there are only header nodes in the linked list if (size < 1) { printf("There are no nodes in the linked list\n"); exit(-1); } // Save tail node ListNode* tail = phead->prev; // Save the previous node of the tail node ListNode* tailPrev = tail->prev; tailPrev->next = phead; phead->prev = tail->prev; free(tail); tail = NULL; }
2.6 print linked list
void ListPrint(ListNode* phead) { assert(phead); // Record current node ListNode* cur = phead->next; while ( cur != phead) { printf("%p\t%d\t%p\t%p\n", cur->prev, cur->data, cur->next, cur); cur = cur->next; } }
2.7 head insertion method
// Head insert void ListPushFront(ListNode* phead, LTDataType* data) { // Create a new node ListNode* newNode = BuyListNode(data); // Method 1: the sequence of the following codes in this method cannot be disordered, otherwise header insertion cannot be realized /*newNode->prev = phead; newNode->next = phead->next; phead->next->prev = newNode; phead->next = newNode;*/ // Method 2: the code order of this method can be changed ListNode* pheadNext = phead->next; phead->next = newNode; newNode->prev = phead; pheadNext->prev = newNode; newNode->next = pheadNext; }
2.8 header deletion
// Header deletion void ListPopFront(ListNode* phead) { // Header node cannot be empty assert(phead); // Calculate linked list length assert(phead->next != phead); // Method 1: the following code sequence can be disrupted ListNode* target = phead->next; ListNode* targetNext = target->next; phead->next = targetNext; targetNext->prev = phead; free(target); // Method 2: the following code sequence cannot be disturbed /*phead->next = phead->next->next; free(phead->next->prev); phead->next->prev = phead;*/ }
2.9 finding nodes with specified data
// Find the node with the specified data field and return the pointer of the node ListNode* ListFind(ListNode* phead, LTDataType* data) { assert(phead); assert(phead->next != NULL); ListNode* cur = phead->next; while (cur != phead) { if (cur->data == *data) return cur; cur = cur->next; } return NULL; }
2.10 find nodes at specified locations
// Find the node of the location. The value of pos is [0,size-1] ListNode* ListFindByPos(ListNode* phead, size_t pos) { assert(phead); // Interrupt if there is only a header node assert(phead->next != phead); // Calculate the length of the current linked list size_t size = ListSize(phead); assert(pos < size); // Used to record nodes with pos position ListNode* posNode = phead->next; for (int i = 0; i < pos; i++) { posNode = posNode->next; } return posNode; }
2.11 insert node before any node
// Insert a new node before any node target void ListInsert(ListNode* target, LTDataType* data) { assert(target); ListNode* targetPrev = target->prev; // Create a new node ListNode* newNode = BuyListNode(data); targetPrev->next = newNode; newNode->prev = targetPrev; newNode->next = target; target->prev = newNode; }
2.12 find the specified node
// Find whether there is a specified node in the linked list. The node is returned, but NULL is not returned ListNode* ListIsExistNode(ListNode* phead, ListNode* target) { assert(phead && target); assert(phead->next != phead); ListNode* cur = phead->next; while (cur && (cur != phead)) { if (cur == target) return cur; cur = cur->next; } return NULL; }
2.13 delete specified node
// Delete specified node void ListErase(ListNode* target) { assert(target); ListNode* targetPrev = target->prev; ListNode* targetNext = target->next; targetPrev->next = targetNext; targetNext->prev = targetPrev; free(target); }
2.14 empty linked list
// Clear the linked list and keep the header node void ListClear(ListNode* phead) { assert(phead && phead->next != phead); ListNode* cur = phead->next; while (cur != phead) { ListNode* next = cur->next; free(cur); cur = next; } phead->next = phead; phead->prev = phead; }
2.15 release linked list
// Release the linked list, including the header node void ListDestory(ListNode** pphead) { assert(*pphead); // Empty linked list memory ListClear(*pphead); // Release head free(*pphead); // Set the linked list to empty *pphead = NULL; }
3. Source code link
[document description]
file name | explain |
---|---|
SList.h | Type definition and function declaration of linked list |
SList.c | Implementation of specific functions |
test.c | Test code |
Postscript
My level is limited and mistakes are inevitable. I hope you can correct me.
This is the end of the double linked list. Thank you for reading!!! If the content is helpful to you, remember to give me sanlianya (praise, collection and attention)
All articles in my blog are original. Some articles or cite relevant materials, but the source has been clearly indicated. You can reprint and share at will, but you need to add a link to this article and a copyright description.