• Linux 中的链表list 使用示例


    学习链表的实现,还是觉得linux下的显得不错。

    今天爬取了份可以用在linux下的代码。不必要重复造轮子了。对于这份代码的详细说明,请参考 《Linux Kernel Linked List Explained》

    如下代码的获取路径

    http://isis.poly.edu/kulesh/stuff/src/klist/list.h

    list.h
    1 #ifndef __LIST_H
    2 #define __LIST_H
    3
    4 /* This file is from Linux Kernel (include/linux/list.h)
    5 * and modified by simply removing hardware prefetching of list items.
    6 * Here by copyright, credits attributed to wherever they belong.
    7 * Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu)
    8 */
    9
    10 /*
    11 * Simple doubly linked list implementation.
    12 *
    13 * Some of the internal functions (“__xxx”) are useful when
    14 * manipulating whole lists rather than single entries, as
    15 * sometimes we already know the next/prev entries and we can
    16 * generate better code by using them directly rather than
    17 * using the generic single-entry routines.
    18 */
    19
    20 struct list_head {
    21 struct list_head *next, *prev;
    22 };
    23
    24 #define LIST_HEAD_INIT(name) { &(name), &(name) }
    25
    26 #define LIST_HEAD(name) \
    27 struct list_head name = LIST_HEAD_INIT(name)
    28
    29 static inline void INIT_LIST_HEAD(struct list_head *list)
    30 {
    31 list->next = list;
    32 list->prev = list;
    33 }
    34 /*
    35 * Insert a new entry between two known consecutive entries.
    36 *
    37 * This is only for internal list manipulation where we know
    38 * the prev/next entries already!
    39 */
    40 static inline void __list_add(struct list_head *new,
    41 struct list_head *prev,
    42 struct list_head *next)
    43 {
    44 next->prev = new;
    45 new->next = next;
    46 new->prev = prev;
    47 prev->next = new;
    48 }
    49
    50 /**
    51 * list_add – add a new entry
    52 * @new: new entry to be added
    53 * @head: list head to add it after
    54 *
    55 * Insert a new entry after the specified head.
    56 * This is good for implementing stacks.
    57 */
    58 static inline void list_add(struct list_head *new, struct list_head *head)
    59 {
    60 __list_add(new, head, head->next);
    61 }
    62
    63 /**
    64 * list_add_tail – add a new entry
    65 * @new: new entry to be added
    66 * @head: list head to add it before
    67 *
    68 * Insert a new entry before the specified head.
    69 * This is useful for implementing queues.
    70 */
    71 static inline void list_add_tail(struct list_head *new, struct list_head *head)
    72 {
    73 __list_add(new, head->prev, head);
    74 }
    75
    76 /*
    77 * Delete a list entry by making the prev/next entries
    78 * point to each other.
    79 *
    80 * This is only for internal list manipulation where we know
    81 * the prev/next entries already!
    82 */
    83 static inline void __list_del(struct list_head *prev, struct list_head *next)
    84 {
    85 next->prev = prev;
    86 prev->next = next;
    87 }
    88
    89 /**
    90 * list_del – deletes entry from list.
    91 * @entry: the element to delete from the list.
    92 * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
    93 */
    94 static inline void list_del(struct list_head *entry)
    95 {
    96 __list_del(entry->prev, entry->next);
    97 entry->next = (void *) 0;
    98 entry->prev = (void *) 0;
    99 }
    100
    101 /**
    102 * list_del_init – deletes entry from list and reinitialize it.
    103 * @entry: the element to delete from the list.
    104 */
    105 static inline void list_del_init(struct list_head *entry)
    106 {
    107 __list_del(entry->prev, entry->next);
    108 INIT_LIST_HEAD(entry);
    109 }
    110
    111 /**
    112 * list_move – delete from one list and add as another’s head
    113 * @list: the entry to move
    114 * @head: the head that will precede our entry
    115 */
    116 static inline void list_move(struct list_head *list, struct list_head *head)
    117 {
    118 __list_del(list->prev, list->next);
    119 list_add(list, head);
    120 }
    121
    122 /**
    123 * list_move_tail – delete from one list and add as another’s tail
    124 * @list: the entry to move
    125 * @head: the head that will follow our entry
    126 */
    127 static inline void list_move_tail(struct list_head *list,
    128 struct list_head *head)
    129 {
    130 __list_del(list->prev, list->next);
    131 list_add_tail(list, head);
    132 }
    133
    134 /**
    135 * list_empty – tests whether a list is empty
    136 * @head: the list to test.
    137 */
    138 static inline int list_empty(struct list_head *head)
    139 {
    140 return head->next == head;
    141 }
    142
    143 static inline void __list_splice(struct list_head *list,
    144 struct list_head *head)
    145 {
    146 struct list_head *first = list->next;
    147 struct list_head *last = list->prev;
    148 struct list_head *at = head->next;
    149
    150 first->prev = head;
    151 head->next = first;
    152
    153 last->next = at;
    154 at->prev = last;
    155 }
    156
    157 /**
    158 * list_splice – join two lists
    159 * @list: the new list to add.
    160 * @head: the place to add it in the first list.
    161 */
    162 static inline void list_splice(struct list_head *list, struct list_head *head)
    163 {
    164 if (!list_empty(list))
    165 __list_splice(list, head);
    166 }
    167
    168 /**
    169 * list_splice_init – join two lists and reinitialise the emptied list.
    170 * @list: the new list to add.
    171 * @head: the place to add it in the first list.
    172 *
    173 * The list at @list is reinitialised
    174 */
    175 static inline void list_splice_init(struct list_head *list,
    176 struct list_head *head)
    177 {
    178 if (!list_empty(list)) {
    179 __list_splice(list, head);
    180 INIT_LIST_HEAD(list);
    181 }
    182 }
    183
    184 /**
    185 * list_entry – get the struct for this entry
    186 * @ptr: the &struct list_head pointer.
    187 * @type: the type of the struct this is embedded in.
    188 * @member: the name of the list_struct within the struct.
    189 */
    190 #define list_entry(ptr, type, member) \
    191 ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
    192
    193 /**
    194 * list_for_each - iterate over a list
    195 * @pos: the &struct list_head to use as a loop counter.
    196 * @head: the head for your list.
    197 */
    198 #define list_for_each(pos, head) \
    199 for (pos = (head)->next; pos != (head); \
    200 pos = pos->next)
    201 /**
    202 * list_for_each_prev - iterate over a list backwards
    203 * @pos: the &struct list_head to use as a loop counter.
    204 * @head: the head for your list.
    205 */
    206 #define list_for_each_prev(pos, head) \
    207 for (pos = (head)->prev; pos != (head); \
    208 pos = pos->prev)
    209
    210 /**
    211 * list_for_each_safe - iterate over a list safe against removal of list entry
    212 * @pos: the &struct list_head to use as a loop counter.
    213 * @n: another &struct list_head to use as temporary storage
    214 * @head: the head for your list.
    215 */
    216 #define list_for_each_safe(pos, n, head) \
    217 for (pos = (head)->next, n = pos->next; pos != (head);\
    218 pos = n, n = pos->next)
    219
    220
    221 /**
    222 * list_for_each_entry - iterate over list of given type
    223 * @pos: the type * to use as a loop counter.
    224 * @head: the head for your list.
    225 * @member: the name of the list_struct within the struct.
    226 */
    227 #define list_for_each_entry(pos, head, member) \
    228 for (pos = list_entry((head)->next,typeof(*pos), member); \
    229 &pos->member != (head); \
    230 pos = list_entry(pos->member.next, typeof(*pos), member))
    231
    232 /**
    233 * list_for_each_entry_safe – iterate over list of given type safe against removal of list entry
    234 * @pos: the type * to use as a loop counter.
    235 * @n: another type * to use as temporary storage
    236 * @head: the head for your list.
    237 * @member: the name of the list_struct within the struct.
    238 */
    239 #define list_for_each_entry_safe(pos, n, head, member) \
    240 for (pos = list_entry((head)->next, typeof(*pos), member), \
    241 n = list_entry(pos->member.next, typeof(*pos), member); \
    242 &pos->member != (head); \
    243 pos = n, n = list_entry(n->member.next, typeof(*n), member))
    244
    245 #endif

    下面代码是给出的测试用例(也可以作为其函数的用法示例哦)

    其可以从http://isis.poly.edu/kulesh/stuff/src/klist/test_list.c 下载

    mylist.c
    1 #include <stdio.h>
    2 #include <stdlib.h>
    3
    4 #include "list.h"
    5
    6
    7 struct kool_list{
    8 int to;
    9 struct list_head list;
    10 int from;
    11 };
    12
    13 int main(int argc, char **argv){
    14
    15 struct kool_list *tmp;
    16 struct list_head *pos, *q;
    17 unsigned int i;
    18
    19 struct kool_list mylist;
    20 INIT_LIST_HEAD(&mylist.list);
    21 /* or you could have declared this with the following macro
    22 * LIST_HEAD(mylist); which declares and initializes the list
    23 */
    24
    25 /* adding elements to mylist */
    26 for(i=5; i!=0; --i){
    27 tmp= (struct kool_list *)malloc(sizeof(struct kool_list));
    28
    29 /* INIT_LIST_HEAD(&tmp->list);
    30 *
    31 * this initializes a dynamically allocated list_head. we
    32 * you can omit this if subsequent call is add_list() or
    33 * anything along that line because the next, prev
    34 * fields get initialized in those functions.
    35 */
    36 printf("enter to and from:");
    37 scanf("%d %d", &tmp->to, &tmp->from);
    38
    39 /* add the new item 'tmp' to the list of items in mylist */
    40 list_add(&(tmp->list), &(mylist.list));
    41 /* you can also use list_add_tail() which adds new items to
    42 * the tail end of the list
    43 */
    44 }
    45 printf("\n");
    46
    47
    48 /* now you have a circularly linked list of items of type struct kool_list.
    49 * now let us go through the items and print them out
    50 */
    51
    52
    53 /* list_for_each() is a macro for a for loop.
    54 * first parameter is used as the counter in for loop. in other words, inside the
    55 * loop it points to the current item's list_head.
    56 * second parameter is the pointer to the list. it is not manipulated by the macro.
    57 */
    58 printf("traversing the list using list_for_each()\n");
    59 list_for_each(pos, &mylist.list){
    60
    61 /* at this point: pos->next points to the next item's 'list' variable and
    62 * pos->prev points to the previous item's 'list' variable. Here item is
    63 * of type struct kool_list. But we need to access the item itself not the
    64 * variable 'list' in the item! macro list_entry() does just that. See "How
    65 * does this work?" below for an explanation of how this is done.
    66 */
    67 tmp= list_entry(pos, struct kool_list, list);
    68
    69 /* given a pointer to struct list_head, type of data structure it is part of,
    70 * and it's name (struct list_head's name in the data structure) it returns a
    71 * pointer to the data structure in which the pointer is part of.
    72 * For example, in the above line list_entry() will return a pointer to the
    73 * struct kool_list item it is embedded in!
    74 */
    75
    76 printf("to= %d from= %d\n", tmp->to, tmp->from);
    77
    78 }
    79 printf("\n");
    80 /* since this is a circularly linked list. you can traverse the list in reverse order
    81 * as well. all you need to do is replace 'list_for_each' with 'list_for_each_prev'
    82 * everything else remain the same!
    83 *
    84 * Also you can traverse the list using list_for_each_entry() to iterate over a given
    85 * type of entries. For example:
    86 */
    87 printf("traversing the list using list_for_each_entry()\n");
    88 list_for_each_entry(tmp, &mylist.list, list){
    89 printf("to= %d from= %d\n", tmp->to, tmp->from);
    90 }
    91 list_for_each_entry(tmp,&mylist.list,list){
    92 if(tmp->to == 2)
    93 break;
    94 }
    95 printf("to = %d from %d\n",tmp->to,tmp->from);
    96 printf("\n");
    97
    98
    99 /* now let's be good and free the kool_list items. since we will be removing items
    100 * off the list using list_del() we need to use a safer version of the list_for_each()
    101 * macro aptly named list_for_each_safe(). Note that you MUST use this macro if the loop
    102 * involves deletions of items (or moving items from one list to another).
    103 */
    104 printf("deleting the list using list_for_each_safe()\n");
    105 list_for_each_safe(pos, q, &mylist.list){
    106 tmp= list_entry(pos, struct kool_list, list);
    107 printf("freeing item to= %d from= %d\n", tmp->to, tmp->from);
    108 list_del(pos);
    109 free(tmp);
    110 }
    111
    112 return 0;
    113 }

    编译测试

    gcc mylist.c

  • 相关阅读:
    HDU5418.Victor and World(状压DP)
    POJ2686 Traveling by Stagecoach(状压DP)
    POJ3254Corn Fields(状压DP)
    HDU5407.CRB and Candies(数论)
    CodeForces 352D. Jeff and Furik
    CodeForces 352C. Jeff and Rounding(贪心)
    LightOj 1282 Leading and Trailing
    Ural 1057. Amount of Degrees(数位DP)
    HDU 2089 不要62 (数位DP)
    HDU5366 The mook jong (DP)
  • 原文地址:https://www.cnblogs.com/westfly/p/2007549.html
Copyright © 2020-2023  润新知