数据结构 一、 顺序存储的线性表 gcc
提供了许多的宏,如printf("%d\n",__LINE__)
可用于打印出程序中的行,用于测试程序是那一部分出现了问题
1.sqlist.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 #ifndef SQLIST_H_ #define SQLIST_H_ #define DATASIZE 1024 typedef int datatype;struct node_st { datatype data[DATASIZE]; int last; }; typedef struct node_st sqlist ;sqlist *sqlist_create () ; int sqlist_insert (sqlist *me,int i,datatype *data) ;int sqlist_delete (sqlist *me,int i) ;int sqlist_destory (sqlist *me) ;int sqlist_find (sqlist *me,datatype *data) ;int sqlist_isempty (sqlist *me) ;int sqlist_setempty (sqlist *me) ;int sqlist_getnum (sqlist *me) ;int sqlist_union (sqlist *list1, sqlist *list2) ;void sqlist_display (sqlist *me) ;#endif
2.sqlist.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 #include <stdio.h> #include <stdlib.h> #include "sqlist.h" sqlist *sqlist_create () { sqlist *me; me = malloc (sizeof (*me)); if (me == NULL ) { return NULL ; } me->last = -1 ; return me; } int sqlist_insert (sqlist *me,int i,datatype *data) { if (me->last == DATASIZE-1 ) return -1 ; if (i<0 || i>me->last+1 ) return -2 ; for (int j=me->last; i<=j ; j--) me->data[j+1 ] = me->data[j]; me->data[i] = *data; me->last++; return 0 ; } int sqlist_delete (sqlist *me,int i) { if (i<0 || i>me->last) return -1 ; for (int j = i+1 ;j<=me->last;j++) me->data[j-1 ] = me->data[j]; me->last--; return 0 ; } int sqlist_destory (sqlist *me) { free (me); return 0 ; } int sqlist_find (sqlist *me,datatype *data) { if (sqlist_isempty(me) == 0 ) return -1 ; for (int i = 0 ;i<=me->last;i++) if (me->data[i] == *data) return i; return -2 ; } int sqlist_isempty (sqlist *me) { if (me->last == -1 ) return 0 ; else return -1 ; } int sqlist_setempty (sqlist *me) { me->last = -1 ; return 0 ; } int sqlist_getnum (sqlist *me) { return (me->last + 1 ); } int sqlist_union (sqlist *list1, sqlist *list2) { int i =0 ; while (i<=list2->last) { if (sqlist_find(list1,&list2->data[i]) < 0 ) { sqlist_insert(list1,i,&list2->data[i]); } i++; } } void sqlist_display (sqlist *me) { if (me->last == -1 ) return ; for (int i=0 ; i<=me->last; i++) { printf ("%d " ,me->data[i]); } printf ("\n" ); return ; }
3.main.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 #include <stdio.h> #include <stdlib.h> #include "sqlist.h" int main () { sqlist *list ; sqlist *list1; list = sqlist_create(); list1 = sqlist_create(); datatype arr[6 ] = {11 ,22 ,33 ,44 ,55 ,66 }; datatype arr1[6 ] = {77 ,88 ,99 ,1010 ,1111 ,2222 }; int i; int err; if (list == NULL ) { fprintf (stderr , "sqlist_create() failed!\n" ); exit (1 ); } if (list1 == NULL ) { fprintf (stderr , "sqlist_create() failed!\n" ); exit (1 ); } for (i = 0 ;i<sizeof (arr)/sizeof (*arr);i++) { err = sqlist_insert(list ,i,&arr[i]); if (err != 0 ) { if (err == -1 ) fprintf (stderr ,"the arr is full!\n" ); else if (err == -2 ) fprintf (stderr ,"the pose you want to insert is wrong!\n" ); else fprintf (stderr ,"ERROR!\n" ); exit (1 ); } } for (i = 0 ;i<sizeof (arr1)/sizeof (*arr1);i++) { err = sqlist_insert(list1,i,&arr1[i]); if (err != 0 ) { if (err == -1 ) fprintf (stderr ,"the arr is full!\n" ); else if (err == -2 ) fprintf (stderr ,"the pose you want to insert is wrong!\n" ); else fprintf (stderr ,"ERROR!\n" ); exit (1 ); } } sqlist_display(list ); sqlist_display(list1); # if 0 if (sqlist_delete(list ,1 )==-1 ) fprintf (stderr ,"输入的参数出错!\n" ); sqlist_display(list ); # endif sqlist_union(list ,list1); sqlist_display(list ); sqlist_destory(list ); sqlist_destory(list1); exit (0 ); }
makefile
1 2 3 4 5 6 7 8 9 10 11 mytool:main.o sqlist.o gcc main.o sqlist.o -o mytool main.o:main.c gcc main.c -c -o main.o sqlist.o:sqlist.c gcc sqlist.c -c -o sqlist.o clean: rm *.o mytool -rf
makefile
1 2 3 4 5 6 7 8 9 10 11 OBJS = main.o sqlist.o CC = gcc mytool: $(OBJS) $(CC) $^ -o $@ %.o:%.c $(CC) $^ -c -o $@ clean: rm *.o mytool -rf
CMakeLists.txt
1 2 3 4 5 cmake_minimum_required(VERSION 3.16 ) project(sqlist) # 添加可执行文件 直接编译 add_executable(1 sqlist.h sqlist.c main.c)
4.运行结果: make
或者cmake(对应于写了CMakeLists.txt的情况)
二、链式存储 1.单向带头链表的实现 有头链表的实现,插入元素从索引0开始
在if
的判断中,若判断条件的值小于0也为True,为0的时候才为False
链表形式如图所示:
(1) list.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #ifndef LIST_H_ #define LIST_H_ typedef int datatype;typedef struct node_st { datatype data; struct node_st *next ; }list ; list *list_create () ;int list_insert_at (list *,int i,datatype *) ;int list_order_insert (list *, datatype *) ;int list_delete_at (list *,int i,datatype *) ;int list_delete (list *,datatype *) ;int list_isempty (list *) ;void list_destory (list *) ;void list_display (list *) ;#endif
(2) list.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 #include <stdio.h> #include <stdlib.h> #include "list.h" list *list_create () { list *me; me = malloc (sizeof (*me)); if (me==NULL ) fprintf (stderr ,"create() failed!\n" ); me->next = NULL ; return me; } int list_insert_at (list *me,int i,datatype *data) { int j = 0 ; list *node = me; list *newnode; if (i<0 ) return -1 ; while (j<i && node != NULL ) { node = node -> next; j++; } if (node) { newnode = malloc (sizeof (*newnode)); if (newnode == NULL ) return -2 ; newnode->data = *data; newnode->next = NULL ; newnode->next = node->next; node->next = newnode; return 0 ; } else return -3 ; } int list_order_insert (list *me, datatype *data) { list *p = me; list *q; while (p->next && p->next->data < *data) p = p->next; q = malloc (sizeof (*q)); q->next=NULL ; if (q==NULL ) return -1 ; q->data = *data; q->next = p->next; p->next = q; return 0 ; } int list_delete_at (list *me,int i,datatype *data) { int j = 0 ; list *p = me; *data = -1 ; if (i<0 ) return -1 ; while (j<i && p) { p = p->next; j++; } if (p) { list *q = p->next; p->next = p->next->next; *data = q->data; free (q); q = NULL ; return 0 ; } else return -2 ; } int list_delete (list *me,datatype *data) { list *p = me; while (p->next && p->next->data!=*data) p = p->next; if (p->next==NULL ) return -1 ; else { list *q = p->next; p->next = p->next->next; free (q); } } int list_isempty (list *me) { if (me->next == NULL ) { return 0 ; } return 1 ; } void list_destory (list *me) { list *node,*next; for (node = me->next;node!=NULL ;node=next) { next = node -> next; free (node); } free (me); return ; } void list_display (list *me) { list *node = me->next; if (list_isempty(me) == 0 ) return ; while (node!=NULL ) { printf ("%d " ,node->data); node = node -> next; } printf ("\n" ); return ; }
(3) main.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #include <stdio.h> #include <stdlib.h> #include "list.h" int main () { list *l; datatype delete_value; datatype err; l = list_create(); datatype arr[] = {11 ,9 ,8 ,5 ,2 ,1 ,22 ,33 ,44 ,55 }; if (l == NULL ) exit (1 ); for (int i=0 ;i<sizeof (arr)/sizeof (*arr);i++) { if (list_order_insert(l,&arr[i])) exit (-1 ); } list_display(l); int value = 22 ; list_delete(l,&value); list_display(l); err = list_delete_at(l,2 ,&delete_value); if (err) exit (-1 ); list_display(l); printf ("detele:%d\n" ,delete_value); list_destory(l); }
(4) makefile 1 2 3 4 5 6 7 8 9 10 11 OBJS = main.o list .o CC = gcc mytool: $(OBJS) $(CC) $^ -o $@ %.o:%.c $(CC) $^ -c -o $@ clean: rm *.o mytool -rf
运行结果:
2.二级指针
1 数据类型 ** 指针变量名 = &一级指针变量名
1 2 3 4 5 6 7 8 9 10 11 12 #include <stdio.h> #include <stdlib.h> int main () { int age = 18 ; int *p = &age; int **pp = &p; printf ("&age=%p p=%p *pp=%p &p=%p pp=%p age=%d *p =%d **pp=%d &pp=%p\n" ,&age,p,*pp,&p,pp,age,*p,**pp,&pp); return 0 ; }
笔误:上图的*pp
为为**pp
二级指针
指针*p
指向age
,则指针变量p
存放的为整型变量age
的地址,*p
得到age
的值。而二级指针变量pp
存放的是一级指针变量p
的地址,*pp
得到为指针变量p
内存放的值。*pp
将得到age
的值。
3.单向无头链表的实现 使用二级指针传参数
无头链表的实现必须使用二级指针进行传参数,进行链表的插入与删除
(1)nohead_link.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #ifndef NOHEAD_LINK_H__ #define NOHEAD_LINK_H__ #define NAMESIZE 1024 struct score_st { int id; char name[NAMESIZE]; int math; int chinese; }; struct node_st { struct score_st data ; struct score_st *next ; }; int list_insert (struct node_st **,struct score_st *data) ;void list_show () ;int list_delete (struct node_st **) ;struct score_st *list_find (struct node_st *,int id) ;void list_destory (struct node_st *) ;#endif
(2)nohead_link.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 #include "nohead_link.h" #include <stdlib.h> #include <stdio.h> int list_insert (struct node_st **list ,struct score_st *data) { struct node_st *new ; new = malloc (sizeof (*new)); if (new == NULL ) return -1 ; new->data = *data; new->next = *list ; *list = new; return 0 ; } void list_show (struct node_st *list ) { struct node_st *cur ; for (cur = list ; cur != NULL ; cur = cur->next) { printf ("%d %s %d %d\n" ,cur->data.id,cur->data.name,cur->data.math,cur->data.chinese); } } int list_delete (struct node_st **list ) { struct node_st *cur ; if (*list == NULL ) return -1 ; cur = *list ; *list = (*list )->next; free (cur); return 0 ; } struct score_st *list_find (struct node_st *list ,int id) { struct node_st *cur ; for (cur = list ; cur != NULL ; cur = cur->next) { if (cur->data.id == id) return &cur->data; } return NULL ; } void list_destory (struct node_st *list ) { struct node_st *cur ; if (list ==NULL ) return ; for (cur=list ;cur!=NULL ;cur=list ) { list = cur->next; free (cur); } }
(3)main.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #include <stdio.h> #include <stdlib.h> #include "nohead_link.h" int main () { int ret; struct node_st *list = NULL ; struct score_st tmp ; for (int i = 0 ;i < 7 ;i++) { tmp.id = i; snprintf (tmp.name,NAMESIZE,"stu%d" ,i); tmp.math = rand() % 100 ; tmp.chinese = rand() % 100 ; ret = list_insert(&list ,&tmp); if (ret != 0 ) exit (1 ); } list_show(list ); struct score_st *find_data ; int id = 8 ; find_data = list_find(list ,id); if (find_data != NULL ) { printf ("the id = %d is exist!\n" ,id); } else printf ("the id = %d is not exist!\n" ,id); list_destory(list ); return 0 ; }
(4)makefile 1 2 3 4 5 6 7 8 9 10 11 OBJS = main.o nohead_link.o CC = gcc mytool: $(OBJS) $(CC) $^ -o $@ %.o:%.c $(CC) $^ -c -o $@ clean: rm *.o mytool -rf
运行结果:
4.约瑟夫算法 使用无头环路链表进行实现
约瑟夫问题: n个人围成一圈,初始编号从1~n排列,从约定编号为x的人开始报数,数到第m个人出圈,接着又从1开始报数,报到第m个数的人又退出圈,以此类推,最后圈内只剩下一个人,这个人就是赢家,求出赢家的编号。
问题定义:
1 2 3 4 #define JOSE_NUM 10 #define m 3
mian.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 #include <stdio.h> #include <stdlib.h> #define JOSE_NUM 10 #define m 3 struct node_st { int data; struct node_st *next ; }; struct node_st *jose_create (int num) { int i = 1 ; struct node_st *me ; me = malloc (sizeof (*me)); if (me == NULL ) return NULL ; me->data = i; me->next = me; i++; struct node_st *flag = me; for (;i<=num;i++) { struct node_st *new ; new = malloc (sizeof (*new)); if (new == NULL ) return NULL ; new->data = i; new -> next = me; flag -> next = new; flag = new; } return me; } void jose_kill (struct node_st **me,int n) { struct node_st *cur = *me; struct node_st *node ; int flag = 1 ; while (cur != cur->next) { while (flag < n) { node = cur; cur = cur -> next; flag++; } printf ("%d " ,cur->data); node->next = cur->next; free (cur); cur = node->next; flag = 1 ; } *me = cur; printf ("\n" ); } void jose_show (struct node_st *me) { struct node_st *cur ; for (cur=me;cur->next!=me;cur=cur->next) { printf ("%d " ,cur->data); } printf ("%d \n" ,cur->data); } int main () { struct node_st *list ; list = jose_create(JOSE_NUM); if (list == NULL ) exit (1 ); jose_show(list ); jose_kill(&list ,m); jose_show(list ); exit (0 ); }
代码解析:
1 2 3 4 5 struct node_st { int data; struct node_st *next ; };
链表中每个节点的结构如上的结构体
(1)jose_create()
创建无头的环路链表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 struct node_st *jose_create (int num) { int i = 1 ; struct node_st *me ; me = malloc (sizeof (*me)); if (me == NULL ) return NULL ; me->data = i; me->next = me; i++; struct node_st *flag = me; for (;i<=num;i++) { struct node_st *new ; new = malloc (sizeof (*new)); if (new == NULL ) return NULL ; new->data = i; new -> next = me; flag -> next = new; flag = new; } return me; }
解析:
(2)jose_kill()
数数到n的人出局 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 void jose_kill (struct node_st **me,int n) { struct node_st *cur = *me; struct node_st *node ; int flag = 1 ; while (cur != cur->next) { while (flag < n) { node = cur; cur = cur -> next; flag++; } printf ("%d " ,cur->data); node->next = cur->next; free (cur); cur = node->next; flag = 1 ; } *me = cur; printf ("\n" ); }
解析:
5.双向循环链表 io
函数 在tmp.name
位置 可用内存大小为NAMESIZE
写入"stu%d"
其中%d
为 i
1 snprintf (tmp.name,NAME_SIZE,"std%d" ,i);
memcpy()
从存储区 str2
复制 n
个字节到存储区 str1
1 2 #include <string.h> void *memcpy (void *str1, const void *str2, size_t n)
typedef
1 2 typedef void llist_op (const void *) ;
项目结构目录:
1 2 3 4 5 6 7 8 9 10 11 12 13 $ tree . ├── bin │ └── doubleLinklist ├── build ├── CMakeLists.txt ├── include │ └── llist.h ├── lib │ └── libd_link.so ├── main.c └── src └── llist.c
(1)llist.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #pragma once #define LLIST_FORWARD 1 #define LLIST_BACKWARD 2 typedef void llist_op (const void *) ;typedef int llist_cmp (const void *, const void *) ;struct llist_node_st { struct llist_node_st *pre ; struct llist_node_st *next ; void *data; }; typedef struct { int size; struct llist_node_st head ; }LLIST; LLIST * llist_create (int initsize) ; int llist_insert (LLIST *,const void *data, int mode) ;void * llistt_find (LLIST *ptr,const void *key,llist_cmp *) ;int llist_delete (LLIST *ptr,const void *key,llist_cmp *cmp) ;int llist_fetch (LLIST *ptr,const void *key,llist_cmp *cmp,void *data) ;void llist_travel (LLIST *,llist_op *) ;int llist_destory (LLIST * list_head) ;
注意 :
const void *a
定义一个指针a,a可以指向任意类型的值,且它指向的值必须是常量 。在这种情况下,我们不能修改被指向的对象,但可以使指针指向其他对象。
void* const a
定义了一个const
指针a,a可以指向任意类型的值,但a是指向某个对象的常量指针。我们不能修改指针中存储的地址,但可以修改指针指向的对象。
const void *a
;中const
修饰的是*a
。在void* const a
中,const
修饰的是a
(2)llist.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 #include <stdlib.h> #include <string.h> #include <stdio.h> #include "../include/llist.h" LLIST * llist_create (int init_size) { LLIST *new; new = malloc (sizeof (*new)); if (new==NULL ) { return NULL ; } new->size = init_size; new->head.data=NULL ; new->head.pre = &new->head; new->head.next = &new->head; return new; } int llist_insert (LLIST *ptr,const void *data, int mode) { struct llist_node_st *new_node ; new_node = malloc (sizeof (*new_node)); if (new_node == NULL ) return -1 ; new_node->data = malloc (ptr->size); if (new_node->data == NULL ) return -2 ; memcpy (new_node->data, data, ptr->size); if (mode == LLIST_FORWARD){ new_node->pre = &(ptr->head); new_node->next = ptr->head.next; new_node->pre->next = new_node; new_node->next->pre = new_node; }else if (mode == LLIST_BACKWARD){ new_node->pre = ptr->head.pre; new_node->next = &(ptr->head); new_node->pre->next = new_node; new_node->next->pre = new_node; } else { return -3 ; } return 0 ; } static struct llist_node_st *find_ (LLIST *ptr,const void *key,llist_cmp *cmp) { struct llist_node_st *cur ; for (cur = ptr->head.next; cur != &(ptr->head); cur = cur->next) { if (cmp(key,cur->data) == 0 ) { break ; } } return cur; } void * llistt_find (LLIST *ptr,const void *key,llist_cmp *cmp) { return find_(ptr,key,cmp)->data; } int llist_delete (LLIST *ptr,const void *key,llist_cmp *cmp) { struct llist_node_st *node ; node = find_(ptr,key,cmp); if (node == &(ptr->head)) return -1 ; node -> pre ->next = node->next; node->next->pre = node->pre; free (node->data); free (node); return 0 ; } int llist_fetch (LLIST *ptr,const void *key,llist_cmp *cmp,void *data) { struct llist_node_st *node ; node = find_(ptr,key,cmp); if (node == &(ptr->head)) return -1 ; node -> pre ->next = node->next; node->next->pre = node->pre; if (data!=NULL ) memcpy (data,node->data,ptr->size); free (node->data); free (node); return 0 ; } void llist_travel (LLIST *ptr,llist_op *op) { struct llist_node_st *cur ; for (cur = ptr->head.next; cur != &(ptr->head); cur = cur->next) { op(cur->data); } } int llist_destory (LLIST * ptr) { struct llist_node_st *cur ,*next ; for (cur = ptr->head.next; cur != &(ptr->head); cur = next) { next = cur->next; free (cur->data); free (cur); } free (ptr); }
static
修饰函数 :函数的返回类型前加上关键字static,函数就被定义成为静态函数 .函数的定义和声明默认情况下是extern
的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用
(3)main.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 #include <stdio.h> #include <stdlib.h> #include "include/llist.h" #include "string.h" #define NAME_SIZE 32 struct score_st { int id; char name[NAME_SIZE]; int math; int chinese; }; static void print_s (const void *record) { const struct score_st *r = record; printf ("%d %s %d %d \n" ,r->id,r->name,r->math,r->chinese); } static int id_cmp (const void *key,const void *record) { const int *k = key; const struct score_st *r = record; return (*k - r->id); } static int name_cmp (const void *key,const void *record) { const char *k = key; const struct score_st *r = record; return strcmp (k,r->name); } int main () { LLIST *handler; if (handler == NULL ) exit (1 ); handler = llist_create(sizeof (struct score_st)); struct score_st tmp ; for (int i = 0 ; i < 7 ; i++) { tmp.id = i; snprintf (tmp.name,NAME_SIZE,"std%d" ,i); tmp.math = rand()%100 ; tmp.chinese = rand()%100 ; int ret = llist_insert(handler,&tmp,LLIST_FORWARD); if (ret) exit (1 ); } llist_travel(handler,print_s); printf ("\n\n" ); int id_delete = 3 ; int ret = llist_delete(handler,&id_delete, id_cmp); if (ret) printf ("delete failed!\n" ); llist_travel(handler,print_s); printf ("\n\n" ); int id = 4 ; struct score_st *data ; data = llistt_find(handler,&id,id_cmp); if (data == NULL ) printf ("Can not find!\n" ); else print_s(data); llist_destory(handler); return 0 ; }
(4)CMakeLists.txt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 cmake_minimum_required (VERSION 3.20 )project (doubleLinklist C)set (CMAKE_C_STANDARD 99 )set (HOME ${PROJECT_SOURCE_DIR} /bin)set (EXECUTABLE_OUTPUT_PATH ${HOME} )include_directories (${PROJECT_SOURCE_DIR} /include )file (GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR} /src/*.c)set (LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR} /lib)datatype add_library (d_link SHARED ${SRC_LIST} )add_executable (doubleLinklist main.c)target_link_libraries (doubleLinklist d_link)
(5)运行结果 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 6 std6 90 59 5 std5 62 27 4 std4 49 21 3 std3 86 92 2 std2 93 35 1 std1 77 15 0 std0 83 86 6 std6 90 59 5 std5 62 27 4 std4 49 21 2 std2 93 35 1 std1 77 15 0 std0 83 86 4 std4 49 21
重点: 当前的程序llist.h
中,每一个一般节点中均存在一个指向数据域的指针*data
,用户可以在main.c
中对data
指针所指向的数据类型进行自主的定义,但是在一般节点中,void *data
指针实际也是占用了四个字节的内存,如何避免这多余的四个字节的内存的浪费?下面的第6节进行解答
6.双向循环链表(一般节点的变长结构体实现) 在第5小节中,llist.h
中的双向环链中一般节点struct llist_node_st
中的void *data
指针不是必要的,可以进行变化,将整个struct llist_node_st
变为一个变长的数据结构体
c99
标准才支持长度为0的数组
将上述的struct llist_node_st
变为一个变长的数据结构体
1 2 3 4 5 6 struct llist_node_st { struct llist_node_st *pre ; struct llist_node_st *next ; char data[0 ]; };
将第5小节代码中的free(cur->data)
进行注释,因为这不是一个动态开辟的内存了,是一个数组
将llist_inseert.c
中的new_node->data = malloc(ptr->size)
注释
(1)llist.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #pragma once #define LLIST_FORWARD 1 #define LLIST_BACKWARD 2 typedef void llist_op (const void *) ;typedef int llist_cmp (const void *, const void *) ;struct llist_node_st { struct llist_node_st *pre ; struct llist_node_st *next ; char data[0 ]; }; typedef struct { int size; struct llist_node_st head ; }LLIST; LLIST * llist_create (int initsize) ; int llist_insert (LLIST *,const void *data, int mode) ;void * llist_find (LLIST *ptr,const void *key,llist_cmp *) ;int llist_delete (LLIST *ptr,const void *key,llist_cmp *cmp) ;int llist_fetch (LLIST *ptr,const void *key,llist_cmp *cmp,void *data) ;void llist_travel (LLIST *,llist_op *) ;int llist_destory (LLIST * list_head) ;
(2)llist.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 #include <stdlib.h> #include <string.h> #include <stdio.h> #include "../include/llist.h" LLIST * llist_create (int init_size) { LLIST *new; new = malloc (sizeof (*new)); if (new==NULL ) { return NULL ; } new->size = init_size; new->head.pre = &new->head; new->head.next = &new->head; return new; } int llist_insert (LLIST *ptr,const void *data, int mode) { struct llist_node_st *new_node ; new_node = malloc (sizeof (*new_node) + ptr->size); if (new_node == NULL ) return -1 ; if (new_node->data == NULL ) return -2 ; memcpy (new_node->data, data, ptr->size); if (mode == LLIST_FORWARD){ new_node->pre = &(ptr->head); new_node->next = ptr->head.next; new_node->pre->next = new_node; new_node->next->pre = new_node; }else if (mode == LLIST_BACKWARD){ new_node->pre = ptr->head.pre; new_node->next = &(ptr->head); new_node->pre->next = new_node; new_node->next->pre = new_node; } else { return -3 ; } return 0 ; } static struct llist_node_st *find_ (LLIST *ptr,const void *key,llist_cmp *cmp) { struct llist_node_st *cur ; for (cur = ptr->head.next; cur != &(ptr->head); cur = cur->next) { if (cmp(key,cur->data) == 0 ) { break ; } } return cur; } void * llistt_find (LLIST *ptr,const void *key,llist_cmp *cmp) { struct llist_node_st *node ; node = find_(ptr,key,cmp); if (node == &(ptr->head)) return NULL ; return node->data; } int llist_delete (LLIST *ptr,const void *key,llist_cmp *cmp) { struct llist_node_st *node ; node = find_(ptr,key,cmp); if (node == &(ptr->head)) return -1 ; node -> pre ->next = node->next; node->next->pre = node->pre; free (node); return 0 ; } int llist_fetch (LLIST *ptr,const void *key,llist_cmp *cmp,void *data) { struct llist_node_st *node ; node = find_(ptr,key,cmp); if (node == &(ptr->head)) return -1 ; node -> pre ->next = node->next; node->next->pre = node->pre; if (data!=NULL ) memcpy (data,node->data,ptr->size); free (node); return 0 ; } void llist_travel (LLIST *ptr,llist_op *op) { struct llist_node_st *cur ; for (cur = ptr->head.next; cur != &(ptr->head); cur = cur->next) { op(cur->data); } } int llist_destory (LLIST * ptr) { struct llist_node_st *cur ,*next ; for (cur = ptr->head.next; cur != &(ptr->head); cur = next) { next = cur->next; free (cur); } free (ptr); }
(3)main.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 #include <stdio.h> #include <stdlib.h> #include "include/llist.h" #include "string.h" #define NAME_SIZE 32 struct score_st { int id; char name[NAME_SIZE]; int math; int chinese; }; static void print_s (const void *record) { const struct score_st *r = record; printf ("%d %s %d %d \n" ,r->id,r->name,r->math,r->chinese); } static int id_cmp (const void *key,const void *record) { const int *k = key; const struct score_st *r = record; return (*k - r->id); } static int name_cmp (const void *key,const void *record) { const char *k = key; const struct score_st *r = record; return strcmp (k,r->name); } int main () { LLIST *handler; if (handler == NULL ) exit (1 ); handler = llist_create(sizeof (struct score_st)); struct score_st tmp ; for (int i = 0 ; i < 7 ; i++) { tmp.id = i; snprintf (tmp.name,NAME_SIZE,"std%d" ,i); tmp.math = rand()%100 ; tmp.chinese = rand()%100 ; int ret = llist_insert(handler,&tmp,LLIST_FORWARD); if (ret) exit (1 ); } llist_travel(handler,print_s); printf ("\n\n" ); int id_delete = 3 ; int ret = llist_delete(handler,&id_delete, id_cmp); if (ret) printf ("delete failed!\n" ); llist_travel(handler,print_s); printf ("\n\n" ); int id = 4 ; struct score_st *data ; data = llistt_find(handler,&id,id_cmp); if (data == NULL ) printf ("Can not find!\n" ); else print_s(data); llist_destory(handler); return 0 ; }
7.双向循环链表(封装为类) (1)llist.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #pragma once #define LLIST_FORWARD 1 #define LLIST_BACKWARD 2 typedef void llist_op (const void *) ;typedef int llist_cmp (const void *, const void *) ;struct llist_node_st { struct llist_node_st *pre ; struct llist_node_st *next ; char data[0 ]; }; typedef struct llist_head { int size; struct llist_node_st head ; int (*insert)(struct llist_head *,const void *,int ); void * (*find)(struct llist_head *ptr,const void *key,llist_cmp *); int (*delete)(struct llist_head *ptr,const void *key,llist_cmp *cmp); int (*fetch)(struct llist_head *ptr,const void *key,llist_cmp *cmp,void *data); void (*travel)(struct llist_head *,llist_op *); int (*destory)(struct llist_head * list_head); }LLIST; LLIST * llist_create (int initsize) ;
(2)llist.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 #include <stdlib.h> #include <string.h> #include <stdio.h> #include "../include/llist.h" int llist_insert (LLIST *,const void *data, int mode) ;void *llistt_find (LLIST *ptr,const void *key,llist_cmp *) ;int llist_delete (LLIST *ptr,const void *key,llist_cmp *cmp) ;int llist_fetch (LLIST *ptr,const void *key,llist_cmp *cmp,void *data) ;void llist_travel (LLIST *,llist_op *) ;int llist_destory (LLIST * list_head) ;LLIST * llist_create (int init_size) { LLIST *new; new = malloc (sizeof (*new)); if (new==NULL ) { return NULL ; } new->size = init_size; new->head.pre = &new->head; new->head.next = &new->head; new->insert = llist_insert; new->find = llistt_find; new->delete = llist_delete; new->fetch = llist_fetch; new->travel = llist_travel; new->destory = llist_destory; return new; } int llist_insert (LLIST *ptr,const void *data, int mode) { struct llist_node_st *new_node ; new_node = malloc (sizeof (*new_node) + ptr->size); if (new_node == NULL ) return -1 ; if (new_node->data == NULL ) return -2 ; memcpy (new_node->data, data, ptr->size); if (mode == LLIST_FORWARD){ new_node->pre = &(ptr->head); new_node->next = ptr->head.next; new_node->pre->next = new_node; new_node->next->pre = new_node; }else if (mode == LLIST_BACKWARD){ new_node->pre = ptr->head.pre; new_node->next = &(ptr->head); new_node->pre->next = new_node; new_node->next->pre = new_node; } else { return -3 ; } return 0 ; } static struct llist_node_st *find_ (LLIST *ptr,const void *key,llist_cmp *cmp) { struct llist_node_st *cur ; for (cur = ptr->head.next; cur != &(ptr->head); cur = cur->next) { if (cmp(key,cur->data) == 0 ) { break ; } } return cur; } void * llistt_find (LLIST *ptr,const void *key,llist_cmp *cmp) { struct llist_node_st *node ; node = find_(ptr,key,cmp); if (node == &(ptr->head)) return NULL ; return node->data; } int llist_delete (LLIST *ptr,const void *key,llist_cmp *cmp) { struct llist_node_st *node ; node = find_(ptr,key,cmp); if (node == &(ptr->head)) return -1 ; node -> pre ->next = node->next; node->next->pre = node->pre; free (node); return 0 ; } int llist_fetch (LLIST *ptr,const void *key,llist_cmp *cmp,void *data) { struct llist_node_st *node ; node = find_(ptr,key,cmp); if (node == &(ptr->head)) return -1 ; node -> pre ->next = node->next; node->next->pre = node->pre; if (data!=NULL ) memcpy (data,node->data,ptr->size); free (node); return 0 ; } void llist_travel (LLIST *ptr,llist_op *op) { struct llist_node_st *cur ; for (cur = ptr->head.next; cur != &(ptr->head); cur = cur->next) { op(cur->data); } } int llist_destory (LLIST * ptr) { struct llist_node_st *cur ,*next ; for (cur = ptr->head.next; cur != &(ptr->head); cur = next) { next = cur->next; free (cur); } free (ptr); }
(3)main.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 #include <stdio.h> #include <stdlib.h> #include "include/llist.h" #include "string.h" #define NAME_SIZE 32 struct score_st { int id; char name[NAME_SIZE]; int math; int chinese; }; static void print_s (const void *record) { const struct score_st *r = record; printf ("%d %s %d %d \n" ,r->id,r->name,r->math,r->chinese); } static int id_cmp (const void *key,const void *record) { const int *k = key; const struct score_st *r = record; return (*k - r->id); } static int name_cmp (const void *key,const void *record) { const char *k = key; const struct score_st *r = record; return strcmp (k,r->name); } int main () { LLIST *handler; if (handler == NULL ) exit (1 ); handler = llist_create(sizeof (struct score_st)); struct score_st tmp ; for (int i = 0 ; i < 7 ; i++) { tmp.id = i; snprintf (tmp.name,NAME_SIZE,"std%d" ,i); tmp.math = rand()%100 ; tmp.chinese = rand()%100 ; int ret = handler->insert(handler,&tmp,LLIST_FORWARD); if (ret) exit (1 ); } handler->travel(handler,print_s); printf ("\n\n" ); int id_delete = 3 ; int ret = handler->delete(handler,&id_delete, id_cmp); if (ret) printf ("delete failed!\n" ); handler->travel(handler,print_s); printf ("\n\n" ); int id = 4 ; struct score_st *data ; data = handler->find(handler,&id,id_cmp); if (data == NULL ) printf ("Can not find!\n" ); else print_s(data); handler->destory(handler); return 0 ; }
8.双向循环链表(封装为类-将来使用llist.c
作为动态库使用) 将真正的数据结构进行隐藏,之后直接可以链接llist.c
动态库使用其函数,更加保护源码
(1)llist.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #pragma once #define LLIST_FORWARD 1 #define LLIST_BACKWARD 2 typedef void LLIST;typedef void llist_op (const void *) ;typedef int llist_cmp (const void *, const void *) ;LLIST * llist_create (int initsize) ; int llist_insert (LLIST *,const void *data, int mode) ;void * llistt_find (LLIST *p,const void *key,llist_cmp *) ;int llist_delete (LLIST *p,const void *key,llist_cmp *cmp) ;int llist_fetch (LLIST *p,const void *key,llist_cmp *cmp,void *data) ;void llist_travel (LLIST *,llist_op *) ;int llist_destory (LLIST * list_head) ;
(2)llist.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 #include <stdlib.h> #include <string.h> #include <stdio.h> #include "../include/llist.h" struct llist_node_st { struct llist_node_st *pre ; struct llist_node_st *next ; char data[0 ]; }; struct llist_head_st { int size; struct llist_node_st head ; }; LLIST * llist_create (int init_size) { struct llist_head_st *new ; new = malloc (sizeof (*new)); if (new==NULL ) { return NULL ; } new->size = init_size; new->head.pre = &new->head; new->head.next = &new->head; return new; } int llist_insert (LLIST *p,const void *data, int mode) { struct llist_node_st *new_node ; struct llist_head_st *ptr = p; new_node = malloc (sizeof (*new_node) + ptr->size); if (new_node == NULL ) return -1 ; if (new_node->data == NULL ) return -2 ; memcpy (new_node->data, data, ptr->size); if (mode == LLIST_FORWARD){ new_node->pre = &(ptr->head); new_node->next = ptr->head.next; new_node->pre->next = new_node; new_node->next->pre = new_node; }else if (mode == LLIST_BACKWARD){ new_node->pre = ptr->head.pre; new_node->next = &(ptr->head); new_node->pre->next = new_node; new_node->next->pre = new_node; } else { return -3 ; } return 0 ; } static struct llist_node_st *find_ (struct llist_head_st *ptr,const void *key,llist_cmp *cmp) { struct llist_node_st *cur ; for (cur = ptr->head.next; cur != &(ptr->head); cur = cur->next) { if (cmp(key,cur->data) == 0 ) { break ; } } return cur; } void * llistt_find (LLIST *p,const void *key,llist_cmp *cmp) { struct llist_node_st *node ; struct llist_head_st *ptr = p; node = find_(ptr,key,cmp); if (node == &(ptr->head)) return NULL ; return node->data; } int llist_delete (LLIST *p,const void *key,llist_cmp *cmp) { struct llist_node_st *node ; struct llist_head_st *ptr = p; node = find_(ptr,key,cmp); if (node == &(ptr->head)) return -1 ; node -> pre ->next = node->next; node->next->pre = node->pre; free (node); return 0 ; } int llist_fetch (LLIST *p,const void *key,llist_cmp *cmp,void *data) { struct llist_node_st *node ; struct llist_head_st *ptr = p; node = find_(ptr,key,cmp); if (node == &(ptr->head)) return -1 ; node -> pre ->next = node->next; node->next->pre = node->pre; if (data!=NULL ) memcpy (data,node->data,ptr->size); free (node); return 0 ; } void llist_travel (LLIST *p,llist_op *op) { struct llist_node_st *cur ; struct llist_head_st *ptr = p; for (cur = ptr->head.next; cur != &(ptr->head); cur = cur->next) { op(cur->data); } } int llist_destory (LLIST * p) { struct llist_node_st *cur ,*next ; struct llist_head_st *ptr = p; for (cur = ptr->head.next; cur != &(ptr->head); cur = next) { next = cur->next; free (cur); } free (ptr); }
(3)main.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 #include <stdio.h> #include <stdlib.h> #include "include/llist.h" #include "string.h" #define NAME_SIZE 32 struct score_st { int id; char name[NAME_SIZE]; int math; int chinese; }; static void print_s (const void *record) { const struct score_st *r = record; printf ("%d %s %d %d \n" ,r->id,r->name,r->math,r->chinese); } static int id_cmp (const void *key,const void *record) { const int *k = key; const struct score_st *r = record; return (*k - r->id); } static int name_cmp (const void *key,const void *record) { const char *k = key; const struct score_st *r = record; return strcmp (k,r->name); } int main () { LLIST *handler; if (handler == NULL ) exit (1 ); handler = llist_create(sizeof (struct score_st)); struct score_st tmp ; for (int i = 0 ; i < 7 ; i++) { tmp.id = i; snprintf (tmp.name,NAME_SIZE,"std%d" ,i); tmp.math = rand()%100 ; tmp.chinese = rand()%100 ; int ret = llist_insert(handler,&tmp,LLIST_FORWARD); if (ret) exit (1 ); } llist_travel(handler,print_s); printf ("\n\n" ); int id_delete = 3 ; int ret = llist_delete(handler,&id_delete, id_cmp); if (ret) printf ("delete failed!\n" ); llist_travel(handler,print_s); printf ("\n\n" ); int id = 4 ; struct score_st *data ; data = llistt_find(handler,&id,id_cmp); if (data == NULL ) printf ("Can not find!\n" ); else print_s(data); llist_destory(handler); return 0 ; }
(4)CMakeLists.txt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 cmake_minimum_required (VERSION 3.16 )project (doubleLinklist_5 C)set (CMAKE_C_STANDARD 99 )set (HOME ${PROJECT_SOURCE_DIR} /bin)set (EXECUTABLE_OUTPUT_PATH ${HOME} )include_directories (${PROJECT_SOURCE_DIR} /include )link_directories (./lib)add_executable (doubleLinklist main.c)target_link_libraries (doubleLinklist libd_link.so)
9.顺序栈的实现 栈 数据结构,先入后出,顺序栈使用数组作为数据区域的存储结构,其 数据结构如下定义:
1 2 3 4 5 6 7 8 9 10 #define MAXSIZE 5 typedef int datatype;typedef struct node_st { datatype data[MAXSIZE]; int top; }sqstack;
项目结构目录:
1 2 3 4 5 6 7 8 9 10 11 12 13 $ tree . ├── bin │ └── sqstack ├── build ├── CMakeLists.txt ├── include │ └── sqstack.h ├── lib │ └── libstack_arr.so ├── main.c └── src └── sqstack.c
(1)sqstack.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #pragma once #define MAXSIZE 5 typedef int datatype;typedef struct node_st { datatype data[MAXSIZE]; int top; }sqstack; sqstack *st_create (void ) ; int st_push (sqstack *,datatype *) ;int st_pop (sqstack *,datatype *) ;int st_top (sqstack *,datatype *) ;void st_travel (sqstack *) ;void st_destory (sqstack *) ;int st_isempty (sqstack *) ;
(2)sqstack.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 #include <stdio.h> #include <stdlib.h> #include "sqstack.h" sqstack *st_create (void ) { sqstack *st; st = malloc (sizeof (*st)); if (st == NULL ) return NULL ; st->top = -1 ; return st; } int st_push (sqstack *st,datatype *data) { if (st->top == MAXSIZE -1 ) return -1 ; st->data[++st->top] = *data; return 0 ; } int st_pop (sqstack *st,datatype *data) { if (st_isempty(st)) return -1 ; *data = st->data[st->top]; st->top--; return 0 ; } int st_top (sqstack *st,datatype *data) { if (!st_isempty(st)) return -1 ; *data = st->data[st->top]; return 0 ; } void st_travel (sqstack *st) { if (st_isempty(st)) return ; for (int i=0 ;i<=st->top;i++ ) { printf ("%d " ,st->data[i]); } printf ("\n" ); } void st_destory (sqstack *st) { free (st); } int st_isempty (sqstack *st) { if (st->top == -1 ) return 1 ; else return 0 ; }
(3)main.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include <stdio.h> #include <stdlib.h> #include "sqstack.h" int main () { datatype arr[] = {15 ,45 ,20 ,36 }; sqstack *st = st_create(); if (st == NULL ) exit (1 ); for (int i = 0 ;i<=sizeof (arr)/sizeof (*arr)-1 ;i++) st_push(st,&arr[i]); st_travel(st); datatype tmp = 22 ; int ret = st_push(st,&tmp); if (ret != 0 ) printf ("st_push failed. \n" ); else st_travel(st); datatype tmp_1; while (st_pop(st,&tmp_1) == 0 ) { printf ("%d " ,tmp_1); } printf ("\n" ); st_destory(st); return 0 ; }
(4)CMakeLists.txt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 cmake_minimum_required(VERSION 3.16 ) project(arr C) # 设置编译标准 set (CMAKE_C_STANDARD 99 )# 定义可执行文件的输出路径 set (HOME ${PROJECT_SOURCE_DIR}/bin)# 指定可执行文件的输出路径 set (EXECUTABLE_OUTPUT_PATH ${HOME})# 包含头文件 include_directories(${PROJECT_SOURCE_DIR}/include) # 搜索 src 目录下的源文件,并且存储值SRC_LIST中(数组) file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/src
10.链式栈的实现 链式栈,从之前的变长结构体的双向循环链表进行二次封装
使用变长结构体的双向循环链表 作为链式栈的底层实现
项目结构目录:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 $ tree . ├── bin │ └── list_stack ├── build ├── CMakeLists.txt ├── include │ └── stack.h │ └── llist.h ├── lib │ └── liblink_stack.so ├── main.c └── src └── sqstack.c └── llist.c
(1)llist.h & stack.h llist.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #pragma once #define LLIST_FORWARD 1 #define LLIST_BACKWARD 2 typedef void llist_op (const void *) ;typedef int llist_cmp (const void *, const void *) ;struct llist_node_st { struct llist_node_st *pre ; struct llist_node_st *next ; char data[0 ]; }; typedef struct { int size; struct llist_node_st head ; }LLIST; LLIST * llist_create (int initsize) ; int llist_insert (LLIST *,const void *data, int mode) ;void * llistt_find (LLIST *ptr,const void *key,llist_cmp *) ;int llist_delete (LLIST *ptr,const void *key,llist_cmp *cmp) ;int llist_fetch (LLIST *ptr,const void *key,llist_cmp *cmp,void *data) ;void llist_travel (LLIST *,llist_op *) ;int llist_destory (LLIST * list_head) ;
stack.h
1 2 3 4 5 6 7 8 9 10 11 12 13 # pragma once #include <stdio.h> #include "llist.h" typedef LLIST STACK;STACK *stack_create (int initsize) ; int stack_push (STACK *ptr,const void *data) ;int stack_pop (STACK *ptr,void *data) ;void stack_destory (STACK *ptr) ;
(2)llist.c & stack.c llist.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 #include <stdlib.h> #include <string.h> #include <stdio.h> #include "../include/llist.h" LLIST * llist_create (int init_size) { LLIST *new; new = malloc (sizeof (*new)); if (new==NULL ) { return NULL ; } new->size = init_size; new->head.pre = &new->head; new->head.next = &new->head; return new; } int llist_insert (LLIST *ptr,const void *data, int mode) { struct llist_node_st *new_node ; new_node = malloc (sizeof (*new_node) + ptr->size); if (new_node == NULL ) return -1 ; if (new_node->data == NULL ) return -2 ; memcpy (new_node->data, data, ptr->size); if (mode == LLIST_FORWARD){ new_node->pre = &(ptr->head); new_node->next = ptr->head.next; new_node->pre->next = new_node; new_node->next->pre = new_node; }else if (mode == LLIST_BACKWARD){ new_node->pre = ptr->head.pre; new_node->next = &(ptr->head); new_node->pre->next = new_node; new_node->next->pre = new_node; } else { return -3 ; } return 0 ; } static struct llist_node_st *find_ (LLIST *ptr,const void *key,llist_cmp *cmp) { struct llist_node_st *cur ; for (cur = ptr->head.next; cur != &(ptr->head); cur = cur->next) { if (cmp(key,cur->data) == 0 ) { break ; } } return cur; } void * llistt_find (LLIST *ptr,const void *key,llist_cmp *cmp) { struct llist_node_st *node ; node = find_(ptr,key,cmp); if (node == &(ptr->head)) return NULL ; return node->data; } int llist_delete (LLIST *ptr,const void *key,llist_cmp *cmp) { struct llist_node_st *node ; node = find_(ptr,key,cmp); if (node == &(ptr->head)) return -1 ; node -> pre ->next = node->next; node->next->pre = node->pre; free (node); return 0 ; } int llist_fetch (LLIST *ptr,const void *key,llist_cmp *cmp,void *data) { struct llist_node_st *node ; node = find_(ptr,key,cmp); if (node == &(ptr->head)) return -1 ; node -> pre ->next = node->next; node->next->pre = node->pre; if (data!=NULL ) memcpy (data,node->data,ptr->size); free (node); return 0 ; } void llist_travel (LLIST *ptr,llist_op *op) { struct llist_node_st *cur ; for (cur = ptr->head.next; cur != &(ptr->head); cur = cur->next) { op(cur->data); } } int llist_destory (LLIST * ptr) { struct llist_node_st *cur ,*next ; for (cur = ptr->head.next; cur != &(ptr->head); cur = next) { next = cur->next; free (cur); } free (ptr); }
stack.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #include "stack.h" STACK *stack_create (int initsize) { return llist_create(initsize); } int stack_push (STACK *ptr,const void *data) { return llist_insert(ptr,data,LLIST_FORWARD); } static int always_match (const void *p1,const void *p2) { return 0 ; } int stack_pop (STACK *ptr,void *data) { return llist_fetch(ptr,(void *)0 ,always_match,data); } void stack_destory (STACK *ptr) { llist_destory(ptr); }
注意 :(void *)0
通常可以视作为NULL
(3)main.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 #include <stdio.h> #include <stdlib.h> #include "include/llist.h" #include "include/stack.h" #define NAME_SIZE 32 struct score_st { int id; char name[NAME_SIZE]; int math; int chinese; }; static void print_s (const void *record) { const struct score_st *r = record; printf ("%d %s %d %d \n" ,r->id,r->name,r->math,r->chinese); } int main () { STACK *st; struct score_st tmp ; int i; int ret; st = stack_create(sizeof (struct score_st)); if (st == NULL ) { exit (1 ); } for (i = 0 ;i<7 ;i++) { tmp.id = i; snprintf (tmp.name,NAME_SIZE,"stu%d" ,i); tmp.chinese = rand()%100 ; tmp.math = rand()%100 ; if (stack_push(st,&tmp)) exit (1 ); } while (1 ) { ret = stack_pop(st,&tmp); if (ret == -1 ) break ; print_s(&tmp); } exit (0 ); }
(4)CMakeLists.txt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 cmake_minimum_required(VERSION 3.20 ) project(list_stack C) # 设置编译标准 set (CMAKE_C_STANDARD 99 )# 定义可执行文件的输出路径 set (HOME ${PROJECT_SOURCE_DIR}/bin)# 指定可执行文件的输出路径 set (EXECUTABLE_OUTPUT_PATH ${HOME})# 包含头文件 include_directories(${PROJECT_SOURCE_DIR}/include) # 搜索 src 目录下的源文件,并且存储值SRC_LIST中(数组) file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/src
11.顺序存储队列的实现 队列先入先出
存在一个队头指针 队尾指针
每次增加一个元素 入队 队尾指针向后移动一次
每次减少一个元素 出队 队首指针向后移动一次
项目结构目录:
1 2 3 4 5 6 7 8 9 10 11 12 13 $ tree . ├── bin │ └── arr_quene ├── build ├── CMakeLists.txt ├── include │ └── queue .h ├── lib │ └── liba_queue.so ├── main.c └── src └── sqeue.c
(1)quene.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #pragma once typedef int datatype;#define MAXSIZE 1024 typedef struct score_st { datatype data[MAXSIZE]; int head,tail; }queue ; queue * qu_create () ;int qu_isempty (queue *) ;int qu_enqueue (queue *,datatype *) ;int qu_dequeue (queue *,datatype *) ;void qu_travel (queue *) ;void qu_clear (queue * ) ;void qu_destroy (queue *) ;
(2)quene.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 #include <stdio.h> #include <stdlib.h> #include "queue.h" queue * qu_create () { queue *sq; sq = malloc (sizeof (*sq)); if (sq == NULL ) return NULL ; sq->head = 0 ; sq->tail = 0 ; return sq; } int qu_isempty (queue *sq) { if (sq->head == sq->tail) return 1 ; return 0 ; } int qu_enqueue (queue *sq,datatype *data) { if ((sq->tail + 1 ) % MAXSIZE == sq->head) return -1 ; sq->tail = (sq->tail + 1 ) % MAXSIZE; sq->data[sq->tail] = *data; return 0 ; } int qu_dequeue (queue *sq,datatype *data) { if (qu_isempty(sq)) return -1 ; sq->head = (sq->head + 1 ) % MAXSIZE; *data = sq->data[sq->head]; return 0 ; } void qu_travel (queue *sq) { int i; if (qu_isempty(sq)) return ; i = (sq->head + 1 ) % MAXSIZE; while (i != sq->tail) { printf ("%d " ,sq->data[i]); i = (i+1 )%MAXSIZE; } printf ("%d\n" , sq->data[i]); } void qu_clear (queue *sq) { sq->head = sq->tail; } void qu_destroy (queue *sq) { free (sq); }
(3)main.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <stdio.h> #include "queue.h" #include <stdlib.h> int main () { queue *sq; datatype arr[6 ] = {2 ,34 ,98 ,12 ,3 ,5 }; int i,ret; sq = qu_create(); if (sq==NULL ) exit (1 ); for (i = 0 ;i<sizeof (arr)/sizeof (*arr);i++) { qu_enqueue(sq,&arr[i]); } qu_travel(sq); datatype tmp = 100 ; ret = qu_enqueue(sq,&tmp); if (ret == -1 ) printf ("queue is full!\n" ); else qu_travel(sq); datatype de_tmp; ret = qu_dequeue(sq,&de_tmp); if (ret == -1 ) printf ("queue is empty!dequeue failed!\n" ); else printf ("DEQUEUE:%d\n" ,de_tmp); qu_travel(sq); qu_destroy(sq); exit (0 ); }
(4)CMakeLists.txt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 cmake_minimum_required(VERSION 3.16 ) project(arr_queue C) # 设置编译标准 set (CMAKE_C_STANDARD 99 )# 定义可执行文件的输出路径 set (HOME ${PROJECT_SOURCE_DIR}/bin)# 指定可执行文件的输出路径 set (EXECUTABLE_OUTPUT_PATH ${HOME})# 包含头文件 include_directories(${PROJECT_SOURCE_DIR}/include) # 搜索 src 目录下的源文件,并且存储值SRC_LIST中(数组) file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/src
12.链式存储队列的实现 链式队列,从之前的变长结构体的双向循环链表进行二次封装
使用变长结构体的双向循环链表 作为链式队列的底层实现
项目结构目录:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 $ tree . ├── bin │ └── link_queue ├── build ├── CMakeLists.txt ├── include │ └── stack.h │ └── queue.h ├── lib │ └── libl_queue.so ├── main.c └── src └── queue.c └── llist.c
(1)llist.h & queue.h llist.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #pragma once #define LLIST_FORWARD 1 #define LLIST_BACKWARD 2 typedef void llist_op (const void *) ;typedef int llist_cmp (const void *, const void *) ;struct llist_node_st { struct llist_node_st *pre ; struct llist_node_st *next ; char data[0 ]; }; typedef struct { int size; struct llist_node_st head ; }LLIST; LLIST * llist_create (int initsize) ; int llist_insert (LLIST *,const void *data, int mode) ;void * llistt_find (LLIST *ptr,const void *key,llist_cmp *) ;int llist_delete (LLIST *ptr,const void *key,llist_cmp *cmp) ;int llist_fetch (LLIST *ptr,const void *key,llist_cmp *cmp,void *data) ;void llist_travel (LLIST *,llist_op *) ;void llist_destory (LLIST * list_head) ;
queue.h
1 2 3 4 5 6 7 8 9 10 11 12 13 #pragma once #include "llist.h" typedef LLIST QUEUE;QUEUE *qu_create (int initsize) ; int qu_en (QUEUE *ptr,void *data) ;int qu_de (QUEUE *ptr,void *data) ;void qu_destroy (QUEUE *ptr) ;
(2)llist.c & queue.c llist.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 #include <stdlib.h> #include <string.h> #include <stdio.h> #include "../include/llist.h" LLIST * llist_create (int init_size) { LLIST *new; new = malloc (sizeof (*new)); if (new==NULL ) { return NULL ; } new->size = init_size; new->head.pre = &new->head; new->head.next = &new->head; return new; } int llist_insert (LLIST *ptr,const void *data, int mode) { struct llist_node_st *new_node ; new_node = malloc (sizeof (*new_node) + ptr->size); if (new_node == NULL ) return -1 ; if (new_node->data == NULL ) return -2 ; memcpy (new_node->data, data, ptr->size); if (mode == LLIST_FORWARD){ new_node->pre = &(ptr->head); new_node->next = ptr->head.next; new_node->pre->next = new_node; new_node->next->pre = new_node; }else if (mode == LLIST_BACKWARD){ new_node->pre = ptr->head.pre; new_node->next = &(ptr->head); new_node->pre->next = new_node; new_node->next->pre = new_node; } else { return -3 ; } return 0 ; } static struct llist_node_st *find_ (LLIST *ptr,const void *key,llist_cmp *cmp) { struct llist_node_st *cur ; for (cur = ptr->head.next; cur != &(ptr->head); cur = cur->next) { if (cmp(key,cur->data) == 0 ) { break ; } } return cur; } void * llistt_find (LLIST *ptr,const void *key,llist_cmp *cmp) { struct llist_node_st *node ; node = find_(ptr,key,cmp); if (node == &(ptr->head)) return NULL ; return node->data; } int llist_delete (LLIST *ptr,const void *key,llist_cmp *cmp) { struct llist_node_st *node ; node = find_(ptr,key,cmp); if (node == &(ptr->head)) return -1 ; node -> pre ->next = node->next; node->next->pre = node->pre; free (node); return 0 ; } int llist_fetch (LLIST *ptr,const void *key,llist_cmp *cmp,void *data) { struct llist_node_st *node ; node = find_(ptr,key,cmp); if (node == &(ptr->head)) return -1 ; node -> pre ->next = node->next; node->next->pre = node->pre; if (data!=NULL ) memcpy (data,node->data,ptr->size); free (node); return 0 ; } void llist_travel (LLIST *ptr,llist_op *op) { struct llist_node_st *cur ; for (cur = ptr->head.next; cur != &(ptr->head); cur = cur->next) { op(cur->data); } } void llist_destory (LLIST * ptr) { struct llist_node_st *cur ,*next ; for (cur = ptr->head.next; cur != &(ptr->head); cur = next) { next = cur->next; free (cur); } free (ptr); }
queue.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include <stdio.h> #include <stdlib.h> #include "queue.h" QUEUE *qu_create (int initsize) { return llist_create(initsize); } int qu_en (QUEUE *ptr,void *data) { return llist_insert(ptr,data,LLIST_BACKWARD); } static int always_match (const void *p1,const void *p2) { return 0 ; } int qu_de (QUEUE *ptr,void *data) { return llist_fetch(ptr,(void *)0 ,always_match,data); } void qu_destroy (QUEUE *ptr) { llist_destory(ptr); }
注意 :(void *)0
通常可以视作为NULL
(3)main.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 #include <stdio.h> #include "queue.h" #include <stdlib.h> #define NAME_SIZE 1024 struct score_st { int id; char name[NAME_SIZE]; int math; int chinese; }; static void print_s (const void *record) { const struct score_st *r = record; printf ("%d %s %d %d \n" ,r->id,r->name,r->math,r->chinese); } int main () { struct score_st tmp ; int i; int ret; QUEUE *qu; qu = qu_create(sizeof (struct score_st)); if (qu ==NULL ) exit (1 ); for (i = 0 ;i<7 ;i++) { tmp.id = i; snprintf (tmp.name,NAME_SIZE,"stu%d" ,i); tmp.chinese = rand()%100 ; tmp.math = rand()%100 ; if (qu_en(qu,&tmp)) exit (1 ); } while (1 ) { ret = qu_de(qu,&tmp); if (ret == -1 ) break ; print_s(&tmp); } exit (0 ); }
(4)CMakeLists.txt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 cmake_minimum_required(VERSION 3.20 ) project(list_stack C) # 设置编译标准 set (CMAKE_C_STANDARD 99 )# 定义可执行文件的输出路径 set (HOME ${PROJECT_SOURCE_DIR}/bin)# 指定可执行文件的输出路径 set (EXECUTABLE_OUTPUT_PATH ${HOME})# 包含头文件 include_directories(${PROJECT_SOURCE_DIR}/include) # 搜索 src 目录下的源文件,并且存储值SRC_LIST中(数组) file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/src
13.动态库以及静态库 (1)静态库 libxx.a
xx 指代库名
可是使用gcc
命令将.o(目标文件gcc -c xx.c -o xx.o
)文件编译为静态库
发布到linux
系统下
1 2 cp xx.h /usr/local/include # 头文件 cp libxx.a /usr/local/lib # 静态库
gcc
命令行链接静态库
1 2 3 gcc -o main main.c -lxx # main 生成的目标文件名字 main.c为生成main所依赖的文件 -lxx -l 为链接的意思 xx 为库名 或者 gcc -L /usr/local/lib -o main main.c -lxx # -L /usr/local/li 为链接库文件的路径
此时可以通过
1 ldd ./xx # 查看xx目标文件所依赖的库
(2)动态库 libxx.so
使用gcc
生成动态库
1 gcc -shared -fpic -o libxx.so yyy.c # -yyy.c 为动态库所依赖的c文件
-fpic
为位置无关代码
发布到linux
系统下
1 2 cp xx.h /usr/local/include # 头文件 cp libxx.so /usr/local/lib # 动态库
动态库需要在/etc/lb.so.confg
中添加路径
1 2 # /etc/lib.so.confg 文件下添加动态库路径 /usr/local/lib/
添加路径之后,需要在终端中使用命令重读刚刚修改的配置文件
1 $ /sbin/ldconfg # /etc/lib.so.confg 配置文件
编译调用链接库的.c
文件
1 2 3 4 gcc -I /usr/local/include/ -L /usr/local/lib -o main main.c -lxx # -I 后引出动态库所需要的头文件路径 # -L 后引出动态库所需要的库文件路径 # main 为main.c所生成的目标文件 -lxx xx文件为动态库库名
当一个目录下存在重名 的动态库以及静态库则会优先链接动态库
非root
用户
1 2 cp xx.so ~/lib export LD_LIBRARY_PATH = ~/lib
当链接的多个库彼此之间存在链接关系时 ,如 生成main目标文件时,需要依赖libx.a
但是libx.a
有需要依赖 liby.a
1 gcc -o main main.c -lx -ly # 被依赖的库写在后面
14.树状存储 (1)基本概念 二叉树的顺序存储非常浪费空间
二叉树链式存储,包含左孩子指针与右孩子指针
遍历方式
按层序遍历、先序、后序 、中序
(2)二叉树的链式存储实现 插入数据方式:遍历数组,小的数字放在左节点 大的节点放在右节点
main.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 #include <stdio.h> #include <stdlib.h> #define NAMESIZE 1024 struct score_st { int id; char name[NAMESIZE]; int math; int chinese; }; struct node_st { struct score_st data ; struct node_st *l ,*r ; }; int insert (struct node_st **root,struct score_st *data) { struct node_st *node ; if (*root == NULL ) { node = malloc (sizeof (*node)); if (node ==NULL ) return -1 ; node->data = *data; node->l = NULL ; node->r = NULL ; *root = node; return 0 ; } if (data->id <= (*root)->data.id) { return insert(&((*root)->l),data); } else return insert(&((*root)->r),data);; } struct score_st *find (struct node_st *root,int id) { if (root == NULL ) return NULL ; if (id == root->data.id) return &(root->data); if (id < root->data.id) return find(root->l,id); else return find(root->r,id); } void print_s (struct score_st *d) { printf ("%d %s %d %d \n" ,d->id,d->name,d->math,d->chinese); } int main () { int i ; int arr[] = {1 ,2 ,3 ,7 ,6 ,5 ,9 ,8 ,4 }; struct node_st *tree = NULL ; struct score_st tmp ; struct score_st *datap ; for (i = 0 ; i < sizeof (arr)/sizeof (*arr);i++) { tmp.id = arr[i]; snprintf (tmp.name,NAMESIZE,"stu%d" ,arr[i]); tmp.math = rand()%100 ; tmp.chinese = rand()%100 ; insert(&tree,&tmp); } int tmpid = 2 ; datap = find(tree,tmpid); if (datap == NULL ) printf ("Can not find the id %d\n" ,tmpid); else print_s(datap); return 0 ; }
1 2 3 4 5 6 cmake_minimum_required (VERSION 3.16 )project (Btree C)set (CMAKE_C_STANDARD 99 )add_executable (Btree main.c)