├── .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 |
9 | C-list - C语言实现的单链表WIKI
10 | author:hit9
11 | email:nz2324#126.com
12 | C-list:github.com/hit9/C-list
13 | 简单的单链表的C语言封装
14 |
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 |
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 |
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 |
--------------------------------------------------------------------------------