├── .gitignore ├── README.markdown ├── doc ├── index.html ├── src │ ├── .mkdwiki.cache~ │ ├── .mkdwikiignore │ ├── Makefile │ ├── index.mkd │ └── tpl.html └── static │ ├── img │ └── forkme_right_darkblue_121621.png │ └── style.css └── src ├── list.c └── list.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | test/ 3 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | ####API 2 | 3 | ```c 4 | 5 | /** 6 | * return value: if the API function has return value.return 0 for fail.return 1 for success. 7 | **/ 8 | 9 | void list_init(list_t *list); 10 | 11 | int list_len(list_t *list); 12 | 13 | void list_append(list_t *list, void *data); 14 | 15 | int list_get(list_t *list, int position, void **data_ptr); 16 | 17 | int list_set(list_t *list, int pos, void *data); 18 | 19 | int list_pop_tail(list_t *list); 20 | 21 | int list_pop(list_t *list, int position); 22 | 23 | int list_iter(list_t *list, void **data_ptr, int *pos_ptr); //iterator for list, get value and index in loop 24 | 25 | void list_extend(list_t *list_a, list_t *list_b); 26 | 27 | int list_swap(list_t *list, int pos_a, int pos_b); 28 | 29 | void list_reverse(list_t *list); 30 | 31 | int list_index(list_t *list, void *data); //lookup data in list.if found success, return its first found position, else return -1; 32 | 33 | void list_cycle(list_t *list, void **data_ptr, int *pos_ptr); //cycle iter for list.infinite iterator 34 | 35 | int list_from_array(list_t *list, void *ptr, int size, int len); //make a list from array. 36 | 37 | ``` 38 | 39 | ### data type 40 | 41 | ``` 42 | list_t 43 | ``` 44 | 45 | ### Structure 46 | 47 | ```c 48 | typedef struct node { 49 | void *data; 50 | struct node *next; 51 | } node_t; 52 | 53 | typedef struct list { 54 | node_t *head; 55 | } list_t; 56 | ``` 57 | 58 | ### wiki 59 | 60 | 中文wiki见:[http://hit9.org/wiki/C-list/](http://hit9.org/wiki/C-list/) 61 | -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | C-list - C语言实现的单链表WIKI 5 | 6 | 7 | 8 | Fork me on GitHub 9 |

C-list - C语言实现的单链表WIKI

10 |

author:hit9

11 |

email:nz2324#126.com

12 |

C-list:github.com/hit9/C-list

13 |

简单的单链表的C语言封装

14 |
15 | 34 |
35 |

code example

36 |
#include <stdio.h>
 37 | #include <stdlib.h>
 38 | #include "list.h"
 39 | int main(int argc, const char *argv[])
 40 | {
 41 |     list_t *list = (list_t *)malloc(sizeof(list_t)); 
 42 |     list_init(list); //初始化链表
 43 | 
 44 |     list_append(list, "hello"); //追加结点
 45 |     list_append(list, "world"); 
 46 |     list_append(list, "hehe"); 
 47 | 
 48 |     int i; 
 49 |     char *temp; 
 50 | 
 51 |     for (i = 0; i < list_len(list); i++){//list_len获取链表的长度
 52 |         list_get(list, i, (void **)&temp); //取得位置为i的结点的数据
 53 |         printf("%s\n", temp);
 54 |     }
 55 |     return 0;
 56 | }
 57 | 
58 | 59 | 60 |

编译:gcc <path-to>list.c test.c -I<path-to-list.h>

61 |

数据类型

62 |
list_t
 63 | 
64 | 65 | 66 |

链表的数据结构

67 |
typedef struct node {
 68 |     void *data;
 69 |     struct node *next;
 70 | } node_t; 
 71 | 
 72 | typedef struct list {
 73 |     node_t *head; 
 74 | } list_t; 
 75 | 
76 | 77 | 78 |

list_init

79 |
void list_init(list_t *list);
 80 | 
81 | 82 | 83 |

传入一个list_t *指针, 把链表头指向NULL

84 |

list_len

85 |
int list_len(list_t *list); 
 86 | 
87 | 88 | 89 |

返回链表的长度.

90 |

list_append

91 |
void list_append(list_t *list, void *data); 
 92 | 
93 | 94 | 95 |

在链表的末尾追加一个结点, 其数据为data

96 |

list_get

97 |
int list_get(list_t *list, int position, void **data_ptr); 
 98 | 
99 | 100 | 101 |

获取位置为position的数据, 执行失败返回0, 执行成功返回1

102 |

list_set

103 |
int list_set(list_t *list, int pos, void *data); 
104 | 
105 | 106 | 107 |

把位置为pos的数据设置为data.执行失败返回0, 执行成功返回1

108 |

list_pop_tail

109 |
int list_pop_tail(list_t *list); 
110 | 
111 | 112 | 113 |

删除末尾元素, 执行成功返回1, 失败返回0

114 |

list_pop

115 |
int list_pop(list_t *list, int position); 
116 | 
117 | 118 | 119 |

删除位置为position的元素, 执行成功返回1, 失败返回0

120 |

list_iter

121 |
int list_iter(list_t *list, void **data_ptr, int *pos_ptr); 
122 | 
123 | 124 | 125 |

迭代链表.函数每执行一次, 取出数据data和位置, 并移动到下一元素.取出成功返回1, 否则返回0(迭代完毕)

126 |

例子:

127 |
list_t *list = (list_t *)malloc(sizeof(list_t)); 
128 | list_init(list); 
129 | 
130 | list_append(list, "hello"); 
131 | list_append(list, "world"); 
132 | list_append(list, "hehe"); 
133 | 
134 | char *data; //用来取出数据
135 | int pos; //用来记录位置
136 | 
137 | while(list_iter(list, (void **)&data, &pos))//迭代打印链表
138 |     printf("%s %d\n", data, pos);
139 | 
140 | 141 | 142 |

list_extend

143 |
void list_extend(list_t *list_a, list_t *list_b); 
144 | 
145 | 146 | 147 |

把链表list_b连接到list_a后面.

148 |

list_swap

149 |
int list_swap(list_t *list, int pos_a, int pos_b); 
150 | 
151 | 152 | 153 |

交换位置为pos_a和pos_b上的元素, 成功返回1, 否则返回0

154 |

list_reverse

155 |
void list_reverse(list_t *list); 
156 | 
157 | 158 | 159 |

反转一个链表

160 |

list_index

161 |
int list_index(list_t *list, void *data); 
162 | 
163 | 164 | 165 |

在链表中查找数据为data的结点, 返回找到的第一个符合条件的结点的位置, 否则找不到的话返回-1

166 |

list_from_array

167 |
int list_from_array(list_t *list, void *ptr, int size, int len); //make a list from array.
168 | 
169 | 170 | 171 |

从一个数组生成一个链表(list必须是空链表才可以).

172 |

例子

173 |
list_t *list = (list_t *)malloc(sizeof(list_t)); 
174 | 
175 | list_init(list); 
176 | 
177 | char str[] = "hello"; 
178 | //根据str字符数组生成一个链表
179 | list_from_array(list, (void *)str, sizeof(char), 5); 
180 | //打印链表
181 | char *data; 
182 | int pos; 
183 | while(list_iter(list, (void **)&data, &pos))
184 |     printf("%c %d\n", *data, pos);
185 | 
186 | 187 | 188 |

或者根据一个整数数组来生成:

189 |
list_t *list = (list_t *)malloc(sizeof(list_t)); 
190 | 
191 | list_init(list); 
192 | int arr[6] = {1, 2, 3, 4, 5, 6}; 
193 | list_from_array(list, (void *)arr, sizeof(int), 6); 
194 | //打印链表
195 | int *data; 
196 | int pos; 
197 | while(list_iter(list, (void **)&data, &pos))
198 |     printf("%d %d\n", *data, pos);
199 | 
200 | 201 | 202 |

但是如下的数组arr是不可以的:

203 |
char *arr[] = {"hello", "world", "hi"}; //因为这个数组存储的各个指针之间不是等差连续的
204 | 
205 | 206 | 207 |

但是这个arr可以:

208 |
char a[] = "hello"; 
209 | char b[] = "world"; 
210 | char c[] = "hi"; 
211 | char *arr[] = {a, b, c}; 
212 | 
213 | 214 | 215 |

list_cycle

216 |
void list_cycle(list_t *list, void **data_ptr, int *pos_ptr); 
217 | 
218 | 219 | 220 |

循环迭代器.相比list_iter而言, 就是不断重复的遍历到尾再回到头.

221 |

例子:

222 |
list_t *list = (list_t *)malloc(sizeof(list_t)); 
223 | 
224 | list_init(list); 
225 | 
226 | int arr[6] = {1, 2, 3, 4, 5, 6}; 
227 | 
228 | list_from_array(list, (void *)arr, sizeof(int), 6); 
229 | 
230 | int *data;
231 | int k = 20, pos; 
232 | while(k--){
233 |     list_cycle(list, (void **)&data, &pos); 
234 |     printf("%d %d\n", *data, pos);
235 | }
236 | 
237 | 238 |
240 | 251 | 252 | 253 | 254 | -------------------------------------------------------------------------------- /doc/src/.mkdwiki.cache~: -------------------------------------------------------------------------------- 1 | (dp0 2 | S'./index.mkd' 3 | p1 4 | F1351279342.3326573 5 | s. -------------------------------------------------------------------------------- /doc/src/.mkdwikiignore: -------------------------------------------------------------------------------- 1 | Makefile 2 | *.swp 3 | -------------------------------------------------------------------------------- /doc/src/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | mkdwiki . -o .. 3 | 4 | clean: 5 | rm ../index.html 6 | rm .mkdwiki.cache~ 7 | -------------------------------------------------------------------------------- /doc/src/index.mkd: -------------------------------------------------------------------------------- 1 | %title C-list - C语言实现的单链表WIKI 2 | 3 | author:[hit9](http://hit9.org) 4 | 5 | email:[nz2324#126.com](mailto:nz2324@126.com) 6 | 7 | C-list:[github.com/hit9/C-list](http://github.com/hit9/C-list) 8 | 9 | 简单的单链表的C语言封装 10 | 11 | [TOC] 12 | 13 | 14 | ## code example 15 | 16 | ```c 17 | #include 18 | #include 19 | #include "list.h" 20 | int main(int argc, const char *argv[]) 21 | { 22 | list_t *list = (list_t *)malloc(sizeof(list_t)); 23 | list_init(list); //初始化链表 24 | 25 | list_append(list, "hello"); //追加结点 26 | list_append(list, "world"); 27 | list_append(list, "hehe"); 28 | 29 | int i; 30 | char *temp; 31 | 32 | for (i = 0; i < list_len(list); i++){//list_len获取链表的长度 33 | list_get(list, i, (void **)&temp); //取得位置为i的结点的数据 34 | printf("%s\n", temp); 35 | } 36 | return 0; 37 | } 38 | ``` 39 | 40 | 编译:`gcc list.c test.c -I` 41 | 42 | ## 数据类型 43 | 44 | ```c 45 | list_t 46 | ``` 47 | 48 | ## 链表的数据结构 49 | 50 | ``` 51 | typedef struct node { 52 | void *data; 53 | struct node *next; 54 | } node_t; 55 | 56 | typedef struct list { 57 | node_t *head; 58 | } list_t; 59 | ``` 60 | 61 | ## list_init 62 | 63 | ```c 64 | void list_init(list_t *list); 65 | ``` 66 | 67 | 传入一个list_t *指针, 把链表头指向NULL 68 | 69 | ## list_len 70 | 71 | ```c 72 | int list_len(list_t *list); 73 | ``` 74 | 返回链表的长度. 75 | 76 | ## list_append 77 | ```c 78 | void list_append(list_t *list, void *data); 79 | ``` 80 | 在链表的末尾追加一个结点, 其数据为data 81 | ## list_get 82 | ```c 83 | int list_get(list_t *list, int position, void **data_ptr); 84 | ``` 85 | 获取位置为position的数据, 执行失败返回0, 执行成功返回1 86 | ## list_set 87 | 88 | ```c 89 | int list_set(list_t *list, int pos, void *data); 90 | ``` 91 | 把位置为pos的数据设置为data.执行失败返回0, 执行成功返回1 92 | 93 | ## list_pop_tail 94 | 95 | ```c 96 | int list_pop_tail(list_t *list); 97 | ``` 98 | 删除末尾元素, 执行成功返回1, 失败返回0 99 | 100 | ## list_pop 101 | 102 | ```c 103 | int list_pop(list_t *list, int position); 104 | ``` 105 | 删除位置为position的元素, 执行成功返回1, 失败返回0 106 | 107 | ## list_iter 108 | 109 | ```c 110 | int list_iter(list_t *list, void **data_ptr, int *pos_ptr); 111 | ``` 112 | 迭代链表.函数每执行一次, 取出数据data和位置, 并移动到下一元素.取出成功返回1, 否则返回0(迭代完毕) 113 | 114 | 例子: 115 | 116 | ```c 117 | list_t *list = (list_t *)malloc(sizeof(list_t)); 118 | list_init(list); 119 | 120 | list_append(list, "hello"); 121 | list_append(list, "world"); 122 | list_append(list, "hehe"); 123 | 124 | char *data; //用来取出数据 125 | int pos; //用来记录位置 126 | 127 | while(list_iter(list, (void **)&data, &pos))//迭代打印链表 128 | printf("%s %d\n", data, pos); 129 | ``` 130 | ## list_extend 131 | 132 | ```c 133 | void list_extend(list_t *list_a, list_t *list_b); 134 | ``` 135 | 把链表list_b连接到list_a后面. 136 | 137 | ## list_swap 138 | 139 | ```c 140 | int list_swap(list_t *list, int pos_a, int pos_b); 141 | ``` 142 | 交换位置为pos_a和pos_b上的元素, 成功返回1, 否则返回0 143 | 144 | ## list_reverse 145 | 146 | ```c 147 | void list_reverse(list_t *list); 148 | ``` 149 | 150 | 反转一个链表 151 | 152 | ## list_index 153 | 154 | ```c 155 | int list_index(list_t *list, void *data); 156 | ``` 157 | 在链表中查找数据为data的结点, 返回找到的第一个符合条件的结点的位置, 否则找不到的话返回-1 158 | 159 | ## list_from_array 160 | 161 | ```c 162 | int list_from_array(list_t *list, void *ptr, int size, int len); //make a list from array. 163 | ``` 164 | 165 | 从一个数组生成一个链表(list必须是空链表才可以). 166 | 167 | 例子 168 | ```c 169 | list_t *list = (list_t *)malloc(sizeof(list_t)); 170 | 171 | list_init(list); 172 | 173 | char str[] = "hello"; 174 | //根据str字符数组生成一个链表 175 | list_from_array(list, (void *)str, sizeof(char), 5); 176 | //打印链表 177 | char *data; 178 | int pos; 179 | while(list_iter(list, (void **)&data, &pos)) 180 | printf("%c %d\n", *data, pos); 181 | ``` 182 | 183 | 或者根据一个整数数组来生成: 184 | ```c 185 | list_t *list = (list_t *)malloc(sizeof(list_t)); 186 | 187 | list_init(list); 188 | int arr[6] = {1, 2, 3, 4, 5, 6}; 189 | list_from_array(list, (void *)arr, sizeof(int), 6); 190 | //打印链表 191 | int *data; 192 | int pos; 193 | while(list_iter(list, (void **)&data, &pos)) 194 | printf("%d %d\n", *data, pos); 195 | ``` 196 | 但是如下的数组arr是不可以的: 197 | ```c 198 | char *arr[] = {"hello", "world", "hi"}; //因为这个数组存储的各个指针之间不是等差连续的 199 | ``` 200 | 但是这个arr可以: 201 | ```c 202 | char a[] = "hello"; 203 | char b[] = "world"; 204 | char c[] = "hi"; 205 | char *arr[] = {a, b, c}; 206 | ``` 207 | 208 | ## list_cycle 209 | 210 | ```c 211 | void list_cycle(list_t *list, void **data_ptr, int *pos_ptr); 212 | ``` 213 | 214 | 循环迭代器.相比list_iter而言, 就是不断重复的遍历到尾再回到头. 215 | 216 | 例子: 217 | ```c 218 | list_t *list = (list_t *)malloc(sizeof(list_t)); 219 | 220 | list_init(list); 221 | 222 | int arr[6] = {1, 2, 3, 4, 5, 6}; 223 | 224 | list_from_array(list, (void *)arr, sizeof(int), 6); 225 | 226 | int *data; 227 | int k = 20, pos; 228 | while(k--){ 229 | list_cycle(list, (void **)&data, &pos); 230 | printf("%d %d\n", *data, pos); 231 | } 232 | ``` 233 | -------------------------------------------------------------------------------- /doc/src/tpl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %title% 5 | 6 | 7 | 8 | Fork me on GitHub 9 |

%title%

10 | %content% 11 | 12 |
14 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /doc/static/img/forkme_right_darkblue_121621.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hit9/C-list/63ae4c661219b14434122d08857af23db28b5f0a/doc/static/img/forkme_right_darkblue_121621.png -------------------------------------------------------------------------------- /doc/static/style.css: -------------------------------------------------------------------------------- 1 | html{ 2 | width:100%; 3 | } 4 | body{ 5 | margin-left:7%; 6 | margin-right:7%; 7 | line-height:19px; 8 | font-size:14px; 9 | font-family: "Inconsolata-g",Consolas,Liberation Mono, "Courier New", Courier,monospace; 10 | } 11 | h1{ 12 | text-align:center; 13 | } 14 | ul{ 15 | list-style:none; 16 | } 17 | .toc{ 18 | max-height:400px; 19 | font-size:14px; 20 | line-height:19px; 21 | overflow:scroll; 22 | z-index:11; 23 | position:fixed; 24 | top:40px; 25 | right:3%; 26 | border:solid 1px #999; 27 | background-color:#fff; 28 | } 29 | pre { 30 | background: url('img/noise.png?1350420938') top left; 31 | font-family: "Inconsolata-g",Consolas,Liberation Mono,"Courier New", Courier,monospace !important; 32 | -webkit-border-radius: 0.4em; 33 | -moz-border-radius: 0.4em; 34 | -ms-border-radius: 0.4em; 35 | -o-border-radius: 0.4em; 36 | border-radius: 0.4em; 37 | border: 1px solid #CCCCCC; 38 | line-height: 1.5em; 39 | font-size: 14px; 40 | margin-bottom: 2.1em; 41 | padding: .8em 1em; 42 | overflow: auto; 43 | } 44 | pre code{ 45 | border:none; 46 | padding:0; 47 | } 48 | code{ 49 | border: 1px solid #CCCCCC; 50 | font-family: "Inconsolata-g",Consolas,Liberation Mono,"Courier New", Courier,monospace; 51 | font-size:12px; 52 | padding: 1px 5px; 53 | } 54 | .codehilite .hll { background-color: #ffffcc } 55 | .codehilite .c { color: #999988; font-style: italic } /* Comment */ 56 | .codehilite .err { color: #a61717; background-color: #e3d2d2 } /* Error */ 57 | .codehilite .k { color: #000000; font-weight: bold } /* Keyword */ 58 | .codehilite .o { color: #000000; font-weight: bold } /* Operator */ 59 | .codehilite .cm { color: #999988; font-style: italic } /* Comment.Multiline */ 60 | .codehilite .cp { color: #999999; font-weight: bold; font-style: italic } /* Comment.Preproc */ 61 | .codehilite .c1 { color: #999988; font-style: italic } /* Comment.Single */ 62 | .codehilite .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ 63 | .codehilite .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ 64 | .codehilite .ge { color: #000000; font-style: italic } /* Generic.Emph */ 65 | .codehilite .gr { color: #aa0000 } /* Generic.Error */ 66 | .codehilite .gh { color: #999999 } /* Generic.Heading */ 67 | .codehilite .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ 68 | .codehilite .go { color: #888888 } /* Generic.Output */ 69 | .codehilite .gp { color: #555555 } /* Generic.Prompt */ 70 | .codehilite .gs { font-weight: bold } /* Generic.Strong */ 71 | .codehilite .gu { color: #aaaaaa } /* Generic.Subheading */ 72 | .codehilite .gt { color: #aa0000 } /* Generic.Traceback */ 73 | .codehilite .kc { color: #000000; font-weight: bold } /* Keyword.Constant */ 74 | .codehilite .kd { color: #000000; font-weight: bold } /* Keyword.Declaration */ 75 | .codehilite .kn { color: #000000; font-weight: bold } /* Keyword.Namespace */ 76 | .codehilite .kp { color: #000000; font-weight: bold } /* Keyword.Pseudo */ 77 | .codehilite .kr { color: #000000; font-weight: bold } /* Keyword.Reserved */ 78 | .codehilite .kt { color: #445588; font-weight: bold } /* Keyword.Type */ 79 | .codehilite .m { color: #009999 } /* Literal.Number */ 80 | .codehilite .s { color: #d01040 } /* Literal.String */ 81 | .codehilite .na { color: #008080 } /* Name.Attribute */ 82 | .codehilite .nb { color: #0086B3 } /* Name.Builtin */ 83 | .codehilite .nc { color: #445588; font-weight: bold } /* Name.Class */ 84 | .codehilite .no { color: #008080 } /* Name.Constant */ 85 | .codehilite .nd { color: #3c5d5d; font-weight: bold } /* Name.Decorator */ 86 | .codehilite .ni { color: #800080 } /* Name.Entity */ 87 | .codehilite .ne { color: #990000; font-weight: bold } /* Name.Exception */ 88 | .codehilite .nf { color: #990000; font-weight: bold } /* Name.Function */ 89 | .codehilite .nl { color: #990000; font-weight: bold } /* Name.Label */ 90 | .codehilite .nn { color: #555555 } /* Name.Namespace */ 91 | .codehilite .nt { color: #000080 } /* Name.Tag */ 92 | .codehilite .nv { color: #008080 } /* Name.Variable */ 93 | .codehilite .ow { color: #000000; font-weight: bold } /* Operator.Word */ 94 | .codehilite .w { color: #bbbbbb } /* Text.Whitespace */ 95 | .codehilite .mf { color: #009999 } /* Literal.Number.Float */ 96 | .codehilite .mh { color: #009999 } /* Literal.Number.Hex */ 97 | .codehilite .mi { color: #009999 } /* Literal.Number.Integer */ 98 | .codehilite .mo { color: #009999 } /* Literal.Number.Oct */ 99 | .codehilite .sb { color: #d01040 } /* Literal.String.Backtick */ 100 | .codehilite .sc { color: #d01040 } /* Literal.String.Char */ 101 | .codehilite .sd { color: #d01040 } /* Literal.String.Doc */ 102 | .codehilite .s2 { color: #d01040 } /* Literal.String.Double */ 103 | .codehilite .se { color: #d01040 } /* Literal.String.Escape */ 104 | .codehilite .sh { color: #d01040 } /* Literal.String.Heredoc */ 105 | .codehilite .si { color: #d01040 } /* Literal.String.Interpol */ 106 | .codehilite .sx { color: #d01040 } /* Literal.String.Other */ 107 | .codehilite .sr { color: #009926 } /* Literal.String.Regex */ 108 | .codehilite .s1 { color: #d01040 } /* Literal.String.Single */ 109 | .codehilite .ss { color: #990073 } /* Literal.String.Symbol */ 110 | .codehilite .bp { color: #999999 } /* Name.Builtin.Pseudo */ 111 | .codehilite .vc { color: #008080 } /* Name.Variable.Class */ 112 | .codehilite .vg { color: #008080 } /* Name.Variable.Global */ 113 | .codehilite .vi { color: #008080 } /* Name.Variable.Instance */ 114 | .codehilite .il { color: #009999 } /* Literal.Number.Integer.Long */ 115 | -------------------------------------------------------------------------------- /src/list.c: -------------------------------------------------------------------------------- 1 | #ifndef LIST_H 2 | 3 | #include "list.h" 4 | #define LIST_H 1 5 | 6 | #endif 7 | 8 | #include 9 | 10 | void list_init(list_t *list) 11 | { 12 | list->head = NULL; 13 | } 14 | 15 | int list_len(list_t *list) 16 | { 17 | int i = 0; 18 | node_t *head = list->head; 19 | 20 | for (; head; head = head->next, i++); 21 | return i; 22 | } 23 | 24 | 25 | static node_t *new_node(void *data) 26 | { 27 | node_t *node = (node_t *)malloc(sizeof(node_t)); 28 | node->data = data; 29 | node->next = NULL; 30 | return node; 31 | } 32 | 33 | static int get_index_by_node(list_t *list, node_t *p) 34 | { 35 | int i; 36 | node_t *t = list->head; 37 | for (i = 0; t != p; t = t->next, i++); 38 | return i; 39 | } 40 | 41 | void list_append(list_t *list, void *data) 42 | { 43 | node_t *head = list->head, *node = new_node(data); 44 | 45 | if (head){ 46 | for (; head->next; head = head->next); //goto the last node 47 | head->next = node; 48 | }else list->head = node; 49 | } 50 | 51 | int list_pop_tail(list_t *list) 52 | { 53 | node_t *head = list->head; 54 | 55 | if (!head) return 0; //only 0 eles, pop fail 56 | 57 | if (!(head->next)){ //only 1 node , pop it. 58 | free(head); 59 | list->head = NULL; 60 | return 1; 61 | } 62 | 63 | for (; head->next->next; head = head->next); //goto the last second node 64 | free(head->next); 65 | head->next = NULL; 66 | return 1; 67 | } 68 | 69 | int list_pop(list_t *list, int pos) 70 | { 71 | int i = 0; 72 | node_t *head = list->head, *temp = head; 73 | 74 | if (!head) return 0; //no nodes at all 75 | 76 | for (; temp && i != pos; temp = temp->next, i++); //get the node on position pos 77 | 78 | if (!temp) return 0; //unavaliable pos input:go through the list but no position equal pos.temp == NULL means we cycle the list 79 | 80 | if (temp == head){ //if pop node is the head node 81 | list->head = head->next; 82 | free(head); 83 | return 1; 84 | } 85 | 86 | for (; head->next != temp; head = head->next); //else goto the pop node's pre node 87 | 88 | head->next = temp->next; 89 | free(temp); 90 | return 1; 91 | } 92 | 93 | int list_iter(list_t *list, void **data_ptr, int *pos_ptr) 94 | { 95 | static node_t *p = NULL; 96 | static int flag = 0; 97 | 98 | if (!flag){ //p init to head node when the first time 99 | p = list->head; 100 | flag = 1; 101 | } 102 | 103 | if (!p){ 104 | flag = 0; 105 | return 0; 106 | } 107 | *data_ptr = p->data; //get data 108 | *pos_ptr = get_index_by_node(list, p); //get index 109 | //move next 110 | p = p->next; 111 | return 1; 112 | } 113 | 114 | int list_get(list_t *list, int pos, void **data_ptr) 115 | { 116 | node_t *head = list->head; 117 | int i = 0; 118 | 119 | for (; head; head = head->next, i++){ 120 | if (i == pos) { 121 | *data_ptr = head->data; 122 | return 1; 123 | } 124 | } 125 | return 0; 126 | } 127 | 128 | int list_set(list_t *list, int pos, void *data) 129 | { 130 | node_t *t; 131 | int i; 132 | 133 | for (t = list->head, i = 0; t; t = t->next, i++){ 134 | if (i == pos) { 135 | t->data = data; 136 | return 1; 137 | } 138 | } 139 | return 0; 140 | } 141 | 142 | void list_extend(list_t *list_a, list_t *list_b) 143 | { 144 | node_t *t; 145 | if (list_a->head == NULL) list_a->head = list_b->head; 146 | else{ 147 | for (t = list_a->head; t->next; t = t->next); 148 | t->next = list_b->head; 149 | } 150 | } 151 | 152 | int list_swap(list_t *list, int pos_a, int pos_b) 153 | { 154 | node_t *t, *a_pre = 0, *b_pre = 0, *a = 0, *b = 0, *head = list->head; 155 | int i; 156 | 157 | if (pos_a == 0) a = head; 158 | if (pos_b == 0) b = head; 159 | 160 | for (t = head, i = 0; t; t = t->next, i++){ 161 | if (i == pos_a-1) { 162 | a_pre = t; 163 | a = t->next; 164 | } 165 | if (i == pos_b-1) { 166 | b_pre = t; 167 | b = t->next; 168 | } 169 | } 170 | 171 | if (!a || !b) return 0; //wrong input position 172 | if (a == b) return 0; //do not swap the same node 173 | 174 | //change pre node's next 175 | if (a == head){ 176 | list->head = b; 177 | b_pre->next = a; 178 | }else if (b == head){ 179 | list->head = a; 180 | a_pre->next = b; 181 | }else{ 182 | a_pre->next = b; 183 | b_pre->next = a; 184 | } 185 | 186 | //change a and b's next 187 | t = a->next; 188 | a->next = b->next; 189 | b->next = t; 190 | return 1; 191 | } 192 | 193 | void list_reverse(list_t *list) 194 | { 195 | node_t *q = 0, *t, *m = list->head; 196 | for (; m; t = m->next, m->next = q, q = m, m = t); 197 | list->head = q; 198 | } 199 | 200 | int list_index(list_t *list, void *data) 201 | { 202 | node_t *t = list->head; 203 | int i = 0; 204 | 205 | for (; t; t = t->next, i++){ 206 | if (t->data == data) return i; 207 | } 208 | return -1; 209 | } 210 | 211 | 212 | void list_cycle(list_t *list, void **data_ptr, int * pos_ptr) 213 | { 214 | static node_t *p = NULL; 215 | if (!p) p = list->head; 216 | 217 | *data_ptr = p->data;//get data 218 | *pos_ptr = get_index_by_node(list, p); //get index 219 | //move 220 | p = p->next; 221 | } 222 | 223 | int list_from_array(list_t *list, void *ptr, int size, int len) 224 | { 225 | if (list->head) return 0; //list is not empty 226 | 227 | int i; 228 | node_t *t; 229 | 230 | list->head = new_node(ptr); //init head 231 | 232 | for (i = 1, t = list->head; i < len; i++, t = t->next) 233 | t->next = new_node(ptr+size*i); 234 | } 235 | -------------------------------------------------------------------------------- /src/list.h: -------------------------------------------------------------------------------- 1 | #ifndef LIST_H 2 | #define LIST_H 1 3 | 4 | typedef struct node { 5 | void *data; 6 | struct node *next; 7 | } node_t; 8 | 9 | typedef struct list { 10 | node_t *head; 11 | } list_t; 12 | 13 | 14 | void list_init(list_t *); 15 | 16 | int list_len(list_t *); 17 | 18 | void list_append(list_t *, void *); 19 | 20 | int list_pop(list_t *, int); 21 | 22 | int list_pop_tail(list_t *); 23 | 24 | int list_get(list_t *, int, void **); 25 | 26 | int list_set(list_t *, int, void *); 27 | 28 | int list_index(list_t *, void *); 29 | 30 | int list_iter(list_t *, void **, int *); 31 | 32 | void list_extend(list_t *, list_t *); 33 | 34 | int list_swap(list_t *, int, int); 35 | 36 | void list_reverse(list_t *); 37 | 38 | void list_cycle(list_t *, void **, int *); 39 | 40 | int list_from_array(list_t *, void *, int, int); 41 | #endif 42 | --------------------------------------------------------------------------------