zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    2018年7月10日笔记
    2018年7月7日笔记
    2018年7月5日笔记
    2018年7月3日笔记
    sed 命令详解
    《软件构架实践》阅读笔记01
    《掌握需求过程》阅读笔记06
    《掌握需求过程》阅读笔记05
    第十二周进度条
    《掌握需求过程》阅读笔记04
  • 原文地址:https://www.cnblogs.com/westfly/p/2007549.html
Copyright © 2011-2022 走看看