C语言实现静态链表

分享一段代码,一个静态链表的C语言实现,其中包含着一种简单的内存管理策略:固定大小的链式管理。

在动手之前我一直以为静态链表和动态链表没有什么差别,细细一想才发现,原来静态链表之中隐藏着一个非常值得讨论的话题——内存管理。

静态链表的“静态”二字是指内存的来源为静态内存(通常用全局数组)。与动态链表不同,在静态链表中节点内存的申请与释放都需要自行维护,由于这里是链表,也很容易想到将空余的节点链接起来形成一个free_list,每次需要时从free_list头部取出一个节点,释放时再将节点加到头部,这样就能够非常容易的实现链表的其他操作。

  1 // 静态链表 的实现
  2 #include <stdio.h>
  3 
  4 #define MAXN 16 // capacity of list.
  5 typedef int element; // element type.
  6 
  7 // define boolean type:
  8 typedef int bool;
  9 #define true -1
 10 #define false 0
 11 
 12 #define NPTR -1 // null pointer definition. can not between 0 to MAXN-1.
 13 typedef int pointer;
 14 
 15 #define DEBUGVAL(x) printf("%s: %d\n", #x, (x)); // a macro for debug.
 16 
 17 struct __node
 18 {
 19     element data;
 20     pointer next;
 21 }SLList[MAXN];
 22 pointer ifree, idata;
 23 
 24 #define nextof(p) SLList[p].next
 25 #define dataof(p) SLList[p].data
 26 
 27 #define _alloc(d) ifree; dataof(ifree)=(d); ifree != NPTR ? ifree=nextof(ifree) : NPTR
 28 #define _free(p)  nextof(p)=ifree; ifree = p
 29 
 30 void init()
 31 {
 32     int i;
 33     ifree = 0;
 34     idata = NPTR;
 35     for( i=0; i < MAXN-1; i++) 
 36         nextof(i) = i+1;
 37     nextof(i) = NPTR;
 38 }
 39 
 40 // clear all nodes.
 41 void clear() { init(); }
 42 
 43 // push val to front.
 44 bool push_front(element val)
 45 {
 46     pointer tmp, np;
 47     if( ifree != NPTR ) {
 48         np = _alloc(val);
 49         nextof(np) = idata;
 50         idata = np;
 51         return true;
 52     }
 53     return false;
 54 }
 55 
 56 // push val to end of list.
 57 bool push_back(element val)
 58 {
 59     if( idata == NPTR ) { // 空表,直接写入
 60         idata = _alloc(val);
 61         nextof(idata) = NPTR;
 62         return true;
 63     }
 64     if( ifree != NPTR ) { // 非空,先找到最后一个节点
 65         pointer last = idata, np;
 66         while( nextof(last) != NPTR ) last = nextof(last);        
 67         np = _alloc(val);
 68         nextof(np) = NPTR;
 69         nextof(last) = np;
 70         return true;
 71     }
 72     return false;
 73 }
 74 
 75 // insert val to after p pointed node.
 76 bool insert_after(pointer p, element val)
 77 {
 78     if( ifree != NPTR && p != NPTR ) {
 79         pointer pn = _alloc(val);
 80         nextof(pn) = nextof(p);
 81         nextof(p)  = pn;        
 82         return true;
 83     }
 84     return false;
 85 }
 86 
 87 // insert to the position in front of p.
 88 bool insert(pointer ptr, element val)
 89 {
 90     if( ifree == NPTR ) return false;  // 没有结点,直接返回
 91     if( ptr == idata ) { // 有一个节点
 92         pointer np = _alloc(val);
 93         nextof(np) = idata;
 94         idata = np;    
 95         return true;
 96     }
 97     else { // 其他情况,先找 ptr 的前驱,再插入
 98         pointer p = idata;
 99         while(  p != NPTR ) {
100             if( nextof(p) == ptr ) { // find p -- the prev node of ptr.
101                 return insert_after(p, val); // insert val after p.            
102             }
103            p = nextof(p);
104         }
105     }
106     return false;
107 }
108 
109 // find element, return the prev node pointer.
110 pointer find_prev(element val)
111 {
112     pointer p = idata;
113     while(  p != NPTR ) {
114         if( dataof( nextof(p) ) == val )
115             return p;
116         p = nextof(p);
117     }
118     return NPTR;
119 }
120 
121 // find element, return the node  pointer.
122 pointer find(element val)
123 {
124     pointer p = idata;
125     while(  p != NPTR ) {
126         if( dataof(p) == val ) return p;
127         p = nextof(p);
128     }
129     return NPTR;
130 }
131 
132 // pop front element.
133 void pop_front()
134 {
135     if( idata != NPTR ) { // 将 data list 最前面的节点 移到 free list 上
136 #if 0
137         pointer p = idata;        
138         idata = nextof(idata); // idata = nextof(idata);
139         nextof(p) = ifree;  // SLList[p].next = ifree;
140         ifree = p; 
141 #else
142         pointer p = idata;
143         idata = nextof(idata);
144         _free(p);
145 #endif
146     }
147 }
148 
149 // pop back element.
150 void pop_back()
151 {
152     if( idata == NPTR ) return;
153     if( nextof(idata) == NPTR ) { // only 1 node.
154         nextof(idata) = ifree;
155         ifree = idata;
156         idata = NPTR;
157     }
158     else { // 找到最后一个节点 p,以及它的前驱 q.
159         // TODO: find the last node p, and it's perv node q. 
160         pointer p = idata, q; 
161         while( nextof(p) != NPTR ) {
162             q = p;
163             p = nextof( p );
164         }
165         // remove *p to free list, update nextof(q) to NPTR.
166         nextof(p) = ifree;
167         ifree = p;
168         nextof(q) = NPTR;
169     }
170 }
171 
172 void show()
173 {
174     pointer p = idata;
175     for( ; p != NPTR; p = nextof(p) ) {
176         printf(" %3d ", dataof(p) );
177     }
178     printf("\n");
179 }
180 
181 #define INFOSHOW
182 void info()
183 {
184 #ifdef INFOSHOW
185     int i;    
186     DEBUGVAL(ifree);
187     DEBUGVAL(idata);
188     puts("====================\n"
189         "index\tdata\tnext\n"
190         "--------------------");
191     for(i=0; i<MAXN; i++) {
192         printf("%d\t%d\t%d\n", i, SLList[i].data, SLList[i].next);
193     }
194     puts("====================\n");
195 #endif
196 }
197 
198 /*
199     测试程序:
200 */
201 int main()
202 {
203     int i;
204     init();
205 
206 #if 1  // push_front test:
207     puts("push_front test:");
208     for(i=0; i<MAXN+2; i++)    {
209         push_front(2*i+1);
210         show();    
211     }
212     
213     puts("pop_front test:");
214     for(i=0; i<MAXN+2; i++)    {
215         pop_front();
216         show();
217     }
218 #endif
219 
220 #if 1 // push_back test:
221     puts("push_back test:");
222     for(i=0; i<MAXN+2; i++)    {
223         push_back((i+1)*10);
224         show();    
225     }
226 
227     puts("pop_back test:");
228     for(i=0; i<MAXN+1; i++)
229     {
230         pop_back();
231         show();
232     }
233 #endif
234     
235 #if 1 // insert test:
236     puts("insert test:");
237     for(i=0; i<MAXN+2; i++)
238     {
239         insert(idata, (i+1)*10);
240         show();
241     }
242     puts("clear...\n");
243     clear();
244 #endif
245 
246 #if 1 // insert_after test:
247     puts("insert_after test:");
248     push_back(-99);
249     for(i=0; i<MAXN+1; i++) {
250         insert_after(idata, i+1);
251         show();
252     }
253     puts("clear...\n");
254     clear();
255 #endif
256     
257 #if 1 // find test:
258     puts("find test:");
259     for(i=0; i<MAXN/2; i++) {
260         push_front(MAXN-i);
261         push_back(MAXN/2-i);
262         //show();
263     }
264     show();
265     info();
266     for(i=0; i<MAXN; i++) {
267         int val = rand()%(2*MAXN);
268         pointer p = find(val);
269         if( p != NPTR )
270             printf("%3d %3d found at %d\n", val, dataof(p), p);
271         else
272             printf("%3d not found\n", val);
273     }
274 #endif
275 
276 #if 1
277     puts("\nfind_prev test:");
278     for(i=0; i<MAXN; i++) {
279         int val = rand()%(2*MAXN);
280         pointer p = find_prev(val);
281         if( p != NPTR )
282             printf("%3d %3d found at %d's next.\n", val, dataof(nextof(p)), p);
283         else
284             printf("%3d not found\n", val);
285     }
286 #endif 
287 
288 #if 1 // find_prev and insert_after test:
289     clear();
290     puts("\nfind_prev and insert_after test:");
291     for(i=0; i<MAXN/2; i++)    {
292         push_front(MAXN/2-i);
293     }
294     show();
295     for(i=0; i<MAXN/2; i++) {
296         int val = rand()%(2*MAXN), n=-(i+1);
297         pointer p = find_prev(val);
298         if( p != NPTR ) {
299             printf("insert %d to front of %d:", n, val);
300             insert_after(p, n);
301             show();
302         }
303     }    
304 #endif    
305 
306 #if 1 // find and insert test:
307     clear();
308     puts("\nfind and insert test:");
309     for(i=0; i<MAXN/2; i++)    {
310         push_front(MAXN/2-i);
311     }
312     show();
313         for(i=0; i<MAXN/2; i++) {
314         int val = rand()%MAXN, n=-(i+1);
315         pointer p = find(val);
316         if( p != NPTR ) {
317             printf("insert %d to after of %d:", n, val);
318             insert_after(p, n);
319             show();
320         }
321     }
322 #endif
323     
324     puts("end of main().");    
325     return 0;
326 }
327 
328 // 

测试结果如下:

push_front test:
   1 
   3    1 
   5    3    1 
   7    5    3    1 
   9    7    5    3    1 
  11    9    7    5    3    1 
  13   11    9    7    5    3    1 
  15   13   11    9    7    5    3    1 
  17   15   13   11    9    7    5    3    1 
  19   17   15   13   11    9    7    5    3    1 
  21   19   17   15   13   11    9    7    5    3    1 
  23   21   19   17   15   13   11    9    7    5    3    1 
  25   23   21   19   17   15   13   11    9    7    5    3    1 
  27   25   23   21   19   17   15   13   11    9    7    5    3    1 
  29   27   25   23   21   19   17   15   13   11    9    7    5    3    1 
  31   29   27   25   23   21   19   17   15   13   11    9    7    5    3    1 
  31   29   27   25   23   21   19   17   15   13   11    9    7    5    3    1 
  31   29   27   25   23   21   19   17   15   13   11    9    7    5    3    1 
pop_front test:
  29   27   25   23   21   19   17   15   13   11    9    7    5    3    1 
  27   25   23   21   19   17   15   13   11    9    7    5    3    1 
  25   23   21   19   17   15   13   11    9    7    5    3    1 
  23   21   19   17   15   13   11    9    7    5    3    1 
  21   19   17   15   13   11    9    7    5    3    1 
  19   17   15   13   11    9    7    5    3    1 
  17   15   13   11    9    7    5    3    1 
  15   13   11    9    7    5    3    1 
  13   11    9    7    5    3    1 
  11    9    7    5    3    1 
   9    7    5    3    1 
   7    5    3    1 
   5    3    1 
   3    1 
   1 



push_back test:
  10 
  10   20 
  10   20   30 
  10   20   30   40 
  10   20   30   40   50 
  10   20   30   40   50   60 
  10   20   30   40   50   60   70 
  10   20   30   40   50   60   70   80 
  10   20   30   40   50   60   70   80   90 
  10   20   30   40   50   60   70   80   90  100 
  10   20   30   40   50   60   70   80   90  100  110 
  10   20   30   40   50   60   70   80   90  100  110  120 
  10   20   30   40   50   60   70   80   90  100  110  120  130 
  10   20   30   40   50   60   70   80   90  100  110  120  130  140 
  10   20   30   40   50   60   70   80   90  100  110  120  130  140  150 
  10   20   30   40   50   60   70   80   90  100  110  120  130  140  150  160 
  10   20   30   40   50   60   70   80   90  100  110  120  130  140  150  160 
  10   20   30   40   50   60   70   80   90  100  110  120  130  140  150  160 
pop_back test:
  10   20   30   40   50   60   70   80   90  100  110  120  130  140  150 
  10   20   30   40   50   60   70   80   90  100  110  120  130  140 
  10   20   30   40   50   60   70   80   90  100  110  120  130 
  10   20   30   40   50   60   70   80   90  100  110  120 
  10   20   30   40   50   60   70   80   90  100  110 
  10   20   30   40   50   60   70   80   90  100 
  10   20   30   40   50   60   70   80   90 
  10   20   30   40   50   60   70   80 
  10   20   30   40   50   60   70 
  10   20   30   40   50   60 
  10   20   30   40   50 
  10   20   30   40 
  10   20   30 
  10   20 
  10 


insert test:
  10 
  20   10 
  30   20   10 
  40   30   20   10 
  50   40   30   20   10 
  60   50   40   30   20   10 
  70   60   50   40   30   20   10 
  80   70   60   50   40   30   20   10 
  90   80   70   60   50   40   30   20   10 
 100   90   80   70   60   50   40   30   20   10 
 110  100   90   80   70   60   50   40   30   20   10 
 120  110  100   90   80   70   60   50   40   30   20   10 
 130  120  110  100   90   80   70   60   50   40   30   20   10 
 140  130  120  110  100   90   80   70   60   50   40   30   20   10 
 150  140  130  120  110  100   90   80   70   60   50   40   30   20   10 
 160  150  140  130  120  110  100   90   80   70   60   50   40   30   20   10 
 160  150  140  130  120  110  100   90   80   70   60   50   40   30   20   10 
 160  150  140  130  120  110  100   90   80   70   60   50   40   30   20   10 
clear...

insert_after test:
 -99    1 
 -99    2    1 
 -99    3    2    1 
 -99    4    3    2    1 
 -99    5    4    3    2    1 
 -99    6    5    4    3    2    1 
 -99    7    6    5    4    3    2    1 
 -99    8    7    6    5    4    3    2    1 
 -99    9    8    7    6    5    4    3    2    1 
 -99   10    9    8    7    6    5    4    3    2    1 
 -99   11   10    9    8    7    6    5    4    3    2    1 
 -99   12   11   10    9    8    7    6    5    4    3    2    1 
 -99   13   12   11   10    9    8    7    6    5    4    3    2    1 
 -99   14   13   12   11   10    9    8    7    6    5    4    3    2    1 
 -99   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1 
 -99   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1 
 -99   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1 
clear...

find test:
   9   10   11   12   13   14   15   16    8    7    6    5    4    3    2    1 
ifree: -1
idata: 14
====================
index    data    next
--------------------
0    16    1
1    8    3
2    15    0
3    7    5
4    14    2
5    6    7
6    13    4
7    5    9
8    12    6
9    4    11
10    11    8
11    3    13
12    10    10
13    2    15
14    9    12
15    1    -1
====================

  9   9 found at 14
  3   3 found at 11
 30 not found
  4   4 found at 9
  1   1 found at 15
 12  12 found at 8
 22 not found
 14  14 found at 4
 18 not found
 16  16 found at 0
  9   9 found at 14
 17 not found
 17 not found
 27 not found
  9   9 found at 14
 11  11 found at 10

find_prev test:
 19 not found
  6   6 found at 3's next.
 27 not found
 28 not found
  7   7 found at 1's next.
 12  12 found at 10's next.
 30 not found
 25 not found
  4   4 found at 7's next.
 30 not found
 13  13 found at 8's next.
 28 not found
  6   6 found at 3's next.
 23 not found
  7   7 found at 1's next.
 30 not found

find_prev and insert_after test:
   1    2    3    4    5    6    7    8 
insert -4 to front of 8:   1    2    3    4    5    6    7   -4    8 
insert -5 to front of 3:   1    2   -5    3    4    5    6    7   -4    8 
insert -8 to front of 6:   1    2   -5    3    4    5   -8    6    7   -4    8 

find and insert test:
   1    2    3    4    5    6    7    8 
insert -2 to after of 3:   1    2    3   -2    4    5    6    7    8 
insert -6 to after of 8:   1    2    3   -2    4    5    6    7    8   -6 
insert -7 to after of 5:   1    2    3   -2    4    5   -7    6    7    8   -6 
end of main().
原文地址:https://www.cnblogs.com/xusw/p/2964465.html