FreeBSD自带有这几种数据结构的实现,非常简洁通用。man queue和man tree分别可以看到说明,在sys/queue.h里面实现了单向链表、有尾指针的单向链表、双向链表、有尾指针的双向链表。在sys/tree.h里面实现了红黑树和SPLAY树。不用FreeBSD的可以在这里看到这两个文件的源码: http://fxr.watson.org/fxr/source/sys/tree.h http://fxr.watson.org/fxr/source/sys/queue.h 用法比较简单:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/queue.h>
4
5 struct TNode
6 {
7 int Value;
8 SLIST_ENTRY(TNode) Link;
9 };
10
11 SLIST_HEAD(THead, TNode);
12
13 struct THead Head = SLIST_HEAD_INITIALIZER();
14
15
16 int main()
17 {
18 int n = 0;
19 SLIST_INIT(&Head);
20 do
21 {
22 printf("输入一个数字,非数字结束输入:");
23 int Ret = scanf("%d", &n);
24 if (Ret > 0 )
25 {
26 struct TNode *NewNode = (struct TNode*)malloc(sizeof(struct TNode));
27 NewNode->Value = n;
28 SLIST_INSERT_HEAD(&Head, NewNode, Link);
29 }
30 else
31 break;
32 }while(1);
33 printf("你输入的数字列表为:/n");
34 struct TNode* Node = NULL;
35 SLIST_FOREACH(Node, &Head, Link)
36 {
37 printf("%d/n", Node->Value);
38 }
39 return 0;
40 }
SLIST_HEAD定义一个头节点类型,类型结构体名是THead, 链表的节点类型是TNode。 比较难理解的是TNode节点里面的SLIST_ENTRY,但看一下源码就知道这个就是用来保存链表指针的结构。 SLIST是单向链表,其他类型的链表用法也差不多。下面看看SPLAY_TREE的例子:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <strings.h>
4 #include <sys/tree.h>
5
6 struct TNode
7 {
8 int Key;
9 int Value;
10 SPLAY_ENTRY(TNode) Link;
11 };
12
13 int Comp(struct TNode* Elm1, struct TNode* Elm2)
14 {
15 return Elm1->Key - Elm2->Key;
16 }
17
18 SPLAY_HEAD(THead, TNode) Root = SPLAY_INITIALIZER();
19
20 SPLAY_PROTOTYPE(THead, TNode, Link, Comp);
21
22 SPLAY_GENERATE(THead, TNode, Link, Comp)
23
24 int main()
25 {
26 do
27 {
28 printf("input a number:/n");
29 int Key;
30 if (scanf("%d", &Key) <= 0)
31 break;
32 printf("input a number:/n");
33 int Value;
34 if (scanf("%d", &Value) <= 0 )
35 break;
36 struct TNode* NewNode = (struct TNode*) malloc(sizeof(struct TNode));
37 NewNode->Key = Key;
38 NewNode->Value = Value;
39 if (SPLAY_INSERT(THead, &Root, NewNode) != NULL)
40 {
41 free(NewNode);
42 printf("insert failed!!!/n");
43 }
44 printf("insert success/n");
45 }while(1);
46 if (! SPLAY_EMPTY(&Root) )
47 {
48 do
49 {
50 int Key = 0;
51 printf("input key to find:/n");
52 if (scanf("%d", &Key) <= 0)
53 break;
54 struct TNode TmpNode;
55 bzero(&TmpNode, sizeof(struct TNode));
56 TmpNode.Key = Key;
57 struct TNode* Node = SPLAY_FIND(THead, &Root, &TmpNode);
58 if (! Node )
59 printf("cann't find %d/n", Key);
60 else
61 printf("Ok, find it: Key = %d, Value = %d/n", Node->Key, Node->Value);
62 }while(1);
63 }
64 return 0;
65 }
代码很简单,就是实现了节点的插入和查询,SPLAY_PROTOTYPE和SPLAY_GENERATE分别是树的操作函数的声明和实现。RB_TREE的用法也类似,不另外写demo了。这些数据结构都是用宏实现的,不是FreeBSD平台的开发环境也可以把这两个头文件拷过去就直接用了。