当前位置:网站首页>List of linked lists
List of linked lists
2022-07-05 08:06:00 【Car chezi】
List of articles
Last blog post Linked list SLIST_ The car (chezi)-CSDN Blog Said ,queue.h There are 5 Species linked list , Namely :
- SLIST
- LIST
- STAILQ
- TAILQ
- CIRCLEQ
This article says LIST
LIST Sketch Map
LIST It is a two-way tailless acyclic linked list . A two-way linked list has a forward pointer , Therefore, some forward operations can be performed .
Look closely at the picture and you will find ,le_next This pointer points to the large structure behind , This is not unusual ; What's strange is that ,le_prev This pointer , It does not refer to the large structure in front , It's the one in front le_next. Why is it so designed ? Fetch a imprison son , The answer is in my future articles .
Interface and implementation
Be careful : Different versions , The code may be different .
/*
* List declarations.
*/
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define LIST_HEAD_INITIALIZER(head) \
{ NULL }
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
/*
* List functions.
*/
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
#define LIST_FIRST(head) ((head)->lh_first)
#define LIST_FOREACH(var, head, field) \
for ((var) = LIST_FIRST((head)); \
(var); \
(var) = LIST_NEXT((var), field))
#define LIST_INIT(head) do { \
LIST_FIRST((head)) = NULL; \
} while (0)
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
LIST_NEXT((listelm), field)->field.le_prev = \
&LIST_NEXT((elm), field); \
LIST_NEXT((listelm), field) = (elm); \
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
} while (0)
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.le_prev = (listelm)->field.le_prev; \
LIST_NEXT((elm), field) = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
} while (0)
#define LIST_INSERT_HEAD(head, elm, field) do { \
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
LIST_FIRST((head)) = (elm); \
(elm)->field.le_prev = &LIST_FIRST((head)); \
} while (0)
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_REMOVE(elm, field) do { \
if (LIST_NEXT((elm), field) != NULL) \
LIST_NEXT((elm), field)->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
} while (0)
give an example
Let's give an example of , Code from https://manpages.courier-mta.org/htmlman3/list.3.html, I changed it a little bit .
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>
struct entry {
int data;
LIST_ENTRY(entry) entries; /* List */
};
LIST_HEAD(listhead, entry);
int
main(void)
{
struct entry *n1, *n2, *n3, *np;
struct listhead head; /* List head */
int i;
LIST_INIT(&head); /* Initialize the list */
n1 = malloc(sizeof(struct entry)); /* Insert at the head */
n1->data = 1; // I add the
LIST_INSERT_HEAD(&head, n1, entries);
n2 = malloc(sizeof(struct entry)); /* Insert after */
n2->data = 2; // I add the
LIST_INSERT_AFTER(n1, n2, entries);
n3 = malloc(sizeof(struct entry)); /* Insert before */
n3->data = 3; // I add the
LIST_INSERT_BEFORE(n2, n3, entries);
/* Forward traversal */
LIST_FOREACH(np, &head, entries)
printf("%i\n", np->data);
LIST_REMOVE(n2, entries); /* Deletion */
free(n2);
/* Forward traversal */
LIST_FOREACH(np, &head, entries)
printf("%i\n", np->data);
/* List deletion */
n1 = LIST_FIRST(&head);
while (n1 != NULL) {
n2 = LIST_NEXT(n1, entries);
free(n1);
n1 = n2;
}
LIST_INIT(&head);
exit(EXIT_SUCCESS);
}
The code analysis
What about code? , It's just such a code . Let's watch it bit by bit .
LIST_ENTRY and LIST_HEAD
struct entry {
int data;
LIST_ENTRY(entry) entries; /* List */
};
LIST_HEAD(listhead, entry);
Macro expansion is :
struct entry {
int data;
struct {
// Structure without label
struct entry *le_next;
struct entry **le_prev;
} entries;
};
struct listhead {
struct entry *lh_first;
};
and slist Very similar , The only difference is entries There are 2 A pointer to the , Because it's two-way , Of course. 2 It's a pointer . Be careful ,le_prev The type of is a pointer to a pointer , I.e. secondary pointer , Why is that ?
LIST_INIT and LIST_INSERT_HEAD
struct entry *n1, *n2, *n3, *np;
struct listhead head; /* List head */
int i;
LIST_INIT(&head); /* Initialize the list */
n1 = malloc(sizeof(struct entry)); /* Insert at the head */
n1->data = 1; // I add the
LIST_INSERT_HEAD(&head, n1, entries);
The first 5 Line is (&head)->lh_first = NULL;
Initialize an empty linked list
The first 9 Line macro replacement is :
if (((n1)->entries.le_next = (&head)->lh_first) != ((void *)0))
(&head)->lh_first->entries.le_prev = &(n1)->entries.le_next;
(&head)->lh_first = (n1);
(n1)->entries.le_prev = &(&head)->lh_first;
The first 1 The first half of the line ((n1)->entries.le_next = (&head)->lh_first)
And the 3 Line completion header insertion
The second half of the first line determines whether the original is an empty linked list , If it is ,if Conditions not established , Otherwise, the second 2 That's ok .
The first 4 That's ok : Give Way n1 Of entries.le_prev Point to (&head)->lh_first;lh_first The type is struct entry *, and le_prev The type is struct entry **
The first 2 OK, it's hard to understand , Let the first node before inserting entries.le_prev Point to n1 Of entries.le_next.
therefore ,le_prev Defined as struct entry ** You can understand , The author's intention is to make it point to struct entry * type , such as lh_first and le_next
At this time, look at the figure at the beginning of this article , I understand. .
node It is equivalent to struct entry
SLIST_INSERT_HEAD(&head, n1, entries) It means : hold n1 Insert the node into the linked list head The head of ; The first parameter is the address of the header , The second parameter is the address of the node to be inserted , The third parameter is the member name of the unlabeled structure .
LIST_INSERT_AFTER
n2 = malloc(sizeof(struct entry)); /* Insert after */
n2->data = 2; // I add the
LIST_INSERT_AFTER(n1, n2, entries);
LIST_INSERT_AFTER(n1, n2, entries) Indicates that the node n2 Insert into n1 Behind .
The first 3 That's ok , The macro is replaced by
if (((n2)->entries.le_next = (n1)->entries.le_next) != ((void *)0))
(n1)->entries.le_next->entries.le_prev = &(n2)->entries.le_next;
(n1)->entries.le_next = (n2);
(n2)->entries.le_prev = &(n1)->entries.le_next;
Node n2 Insert into n1 Behind , Let's see which pointers need to be changed
- n1 Of entries.le_next
- n2 Of entries.le_next
- n2 Of entries.le_prev
- Before insertion n1 The back node ( Call it n0 Well ) Of entries.le_prev; If n0 be equal to NULL, You don't need to think about it
The first 1 Yes (n2)->entries.le_next = (n1)->entries.le_next
The solution is 2
The first 2 Line code solves 4
The first 3 Line of code solves 1
The first 4 Line of code solves 3
LIST_INSERT_BEFORE
n3 = malloc(sizeof(struct entry)); /* Insert before */
n3->data = 3; // I add the
LIST_INSERT_BEFORE(n2, n3, entries);
LIST_INSERT_BEFORE(n2, n3, entries) Meaning is to put the n3 Insert into n2 In front of
The first 3 The line macro is replaced by :
(n3)->entries.le_prev = (n2)->entries.le_prev;
(n3)->entries.le_next = (n2);
*(n2)->entries.le_prev = (n3);
(n2)->entries.le_prev = &(n3)->entries.le_next;
hold n3 Insert into n2 In front of , Let's see which pointers need to be changed
- n2 Of entries.le_prev
- n3 Of entries.le_next
- n3 Of entries.le_prev
- In the insert n3 Before , n2 The front node ( Call it n1 Well ) Of entries.le_next;
The first 1 OK, it's solved 3
The first 2 OK, it's solved 2
The first 3 OK, it's solved 4, It's a little complicated .(n2)->entries.le_prev Point to n1 Of entries.le_next, Yes (n2)->entries.le_prev Quoting , What you get is n1 Of entries.le_next, After inserting , because n1 At the back is n3, therefore n1 Of entries.le_next = n3;
The first 4 OK, it's solved 1
LIST_FOREACH
/* Forward traversal */
LIST_FOREACH(np, &head, entries)
printf("%i\n", np->data);
After macro expansion is :
for ((np) = ((&head)->lh_first); (np); (np) = ((np)->entries.le_next))
printf("%i\n", np->data);
Traverse each node , This is easier to understand .
Be careful , This traversal cannot be deleted , Because if you put np The node pointed to is deleted ,
(np) = ((np)->entries.le_next)
This sentence is wrong .
LIST_FOREACH(np, &head, entries) Used to traverse each node of the linked list . The first parameter is a temporary variable , Point to the current node , The second parameter is the address of the header , Third entries Is the member name of the unlabeled structure .
LIST_REMOVE
LIST_REMOVE(n2, entries); /* Deletion */
The macro is replaced by
if ((n2)->entries.le_next != ((void *)0))
(n2)->entries.le_next->entries.le_prev = (n2)->entries.le_prev;
*(n2)->entries.le_prev = (n2)->entries.le_next;
To delete n2, Let's see which pointers need to be changed
- n2 The front node ( The assumption is n1) Of entries.le_next
- n2 The back node ( The assumption is n3) Of entries.le_prev; If n3 yes NULL, No need
The first 3 OK, it's solved 1
1-2 OK, it's solved 2
LIST_FIRST and LIST_NEXT
n1 = LIST_FIRST(&head);
while (n1 != NULL) {
n2 = LIST_NEXT(n1, entries);
free(n1);
n1 = n2;
}
1: After deployment is n1 = ((&head)->lh_first);
LIST_FIRST(&head) Represents the first node of the linked list
3: After deployment is n2 = ((n1)->entries.le_next);
LIST_NEXT(n1, entries) It means taking nodes n1 The next node of
Reference material
https://manpages.courier-mta.org/htmlman3/list.3.html
边栏推荐
- C, Numerical Recipes in C, solution of linear algebraic equations, LU decomposition source program
- Global and Chinese market of urban rail connectors 2022-2028: Research Report on technology, participants, trends, market size and share
- Can't find real-time chat software? Recommend to you what e-commerce enterprises are using!
- The browser cannot access Baidu
- 如何将EasyCVR平台RTSP接入的设备数据迁移到EasyNVR中?
- H264 (I) i/p/b frame gop/idr/ and other parameters
- 1-stm32 operation environment construction
- Global and Chinese market of core pallets 2022-2028: Research Report on technology, participants, trends, market size and share
- Bluetooth hc-05 pairing process and precautions
- Global and Chinese markets for recycled boilers 2022-2028: Research Report on technology, participants, trends, market size and share
猜你喜欢
Shell脚本基本语法
Reasons for rapid wear of conductive slip rings
Ads learning record (lna_atf54143)
Connection mode - bridge and net
MLPerf Training v2.0 榜单发布,在同等GPU配置下百度飞桨性能世界第一
[untitled] record the visual shock of the Winter Olympics and the introduction of the display screen
Record the visual shock of the Winter Olympics and the introduction of the screen 2
Measurement fitting based on Halcon learning [II] meaure_ pin. Hdev routine
Some thoughts on extracting perspectives from ealfa and Ebeta
Volatile of C language
随机推荐
Class of color image processing based on Halcon learning_ ndim_ norm. hdev
The global and Chinese market of lithographic labels 2022-2028: Research Report on technology, participants, trends, market size and share
Soem EtherCAT source code analysis II (list of known configuration information)
Detailed explanation of SQL server stored procedures
Record the opening ceremony of Beijing Winter Olympics with display equipment
Can't find real-time chat software? Recommend to you what e-commerce enterprises are using!
Shell script basic syntax
Makefile application
Consul安装
Programming knowledge -- assembly knowledge
Cadence learning records
How to migrate the device data accessed by the RTSP of the easycvr platform to easynvr?
OLED 0.96 inch test
【论文阅读】2022年最新迁移学习综述笔注(Transferability in Deep Learning: A Survey)
Reasons for rapid wear of conductive slip rings
MLPerf Training v2.0 榜单发布,在同等GPU配置下百度飞桨性能世界第一
Live555 push RTSP audio and video stream summary (I) cross compilation
Ads learning record (lna_atf54143)
[trio basic from introduction to mastery tutorial 20] trio calculates the arc center and radius through three points of spatial arc
C WinForm [get file path -- traverse folder pictures] - practical exercise 6