# 目录 - [目录](#目录) - [数据结构](#数据结构) - [架构梳理](#架构梳理) - [静态库与动态库](#静态库与动态库) - [静态库](#静态库) - [以链式双向链表的`lib2`为例。](#以链式双向链表的lib2为例) - [动态库](#动态库) - [还是以`lib2`为例。](#还是以lib2为例) - [以链式存储栈为例,`libstack`依赖`libllist`。](#以链式存储栈为例libstack依赖libllist) # 数据结构 ## 架构梳理 - 线性(1:1) - 线性表 - 顺序存储 --> `arr` - 链式存储 --> 指针 (有头,无头) 有头是指有一个不存数据的头,始终作为这个链表的起点。 会更加简单,无头的话,更改首部节点会麻烦。 头节点不仅可以作为起点,还可以作为存储信息的仓库,因为头节点只有*next是必须的。 - 单链表 - 循环 - 不循环 - 双向链表 `lib`四个版本,第一个最基础完善,第二个改成了变长结构体,第三个在第二个的基础上封装了函数指针,第四个在第二个的基础上隐藏了数据结构,只暴露接口。 - 循环 - 不循环 学到这里可以去读一下内核有关**list**的实现,主要都是宏和内联函数。 - 栈 - 队列 练习: 1. 表达式计算 2. 球钟算法 三个栈,1h,5min,1min。27个球,过了多久队列里又是1到27的顺序。 - 树状(1:N) **递归**。**递归**转**非递归**。 - 深度:层数 - 度:子树的个数 - 叶子:边缘节点 - 孩子:与父节点对应 - 兄弟:相同父节点 - 堂兄弟:相同爷节点 - 二叉树: - 满二叉树:深度为`k`且节点为`2^k-1`的二叉树 - 完全二叉树:一颗二叉树,只有倒数两层可以存在不满两个孩子的节点,且单个孩子时只能是左孩子 - 存储: - 顺序:直观,但是浪费空间 满二叉树:父节点`n`,左孩子`2n`,右孩子`2n+1` - 链式:灵活,空间利用率高 - 遍历 - 按行 - 先序(根,左,右) - 中序(左,根,右) - 后序(左,右,根) 先加中,或者,中加后,都可以逆推出树。先加后不行。 - 平衡: 有很多种条件判定。 这棵树的左右子树个数差值为jj1。 - 广义表 `( root ( left ) ( right) )`,进行嵌套。 - 搜索树 空间换时间,查找是**o(1)**。 **课后作业:词频统计** - 图(N:M) ## 静态库与动态库 - 静态库: - 私家车,可以不在标准的位置下。 - 编译时引入,代码膨胀但是不影响运行时间。 - 动态库(共享库): - 公交车,只能在指定的路径。 - 运行时引入,占用运行时间。 ### 静态库 1. `libxx.a` xx 指代库名 2. `ar -cr libxx.a yyy.o` 3. 发布到 `/usr/local/include` `/usr/local/lib` 4. `gcc -L/usr/local/lib -o main main.o -lxx` 如果路径都是这个默认的,可省略。 `-l`参数必须在最后,有依赖 5. `ldd -print shared libirary dependencies` 打印所用到的动态库的内容 #### 以链式双向链表的`lib2`为例。 ```bash *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ ldd ./main linux-vdso.so.1 (0x00007ffffa3d0000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa6c123a000) /lib64/ld-linux-x86-64.so.2 (0x00007fa6c142b000) *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ gcc -c llist.c *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ ls  llist.c  llist.o  Makefile  llist.h  main.c *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ ar -cr libllist.a llist.o *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ ls  libllist.a  llist.h  main.c  llist.c  llist.o  Makefile *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ sudo cp llist.h /usr/local/include *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ sudo cp libllist.a /usr/local/lib *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ gcc -o main main.c -lllist *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ ls  libllist.a  llist.h  main  Makefile  llist.c  llist.o  main.c *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ ./main 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 5 std5 62 27 4 std4 49 21 3 std3 86 92 2 std2 93 35 1 std1 77 15 0 std0 83 86 ``` 这时`main.c`路径下都不需要`llist.c`和`llist.h`了,`#include`时也从`"llist.h"`变为``。 ### 动态库 1. `libxx.so` xx为库名 2. `gcc -shared -fpic -o libxx.so yyy.c` 3. 发布到 `/usr/local/include` `/usr/local/lib` 4. 在`/etc/ld.so.conf`中添加路径 5. `/sbin/ldconfig` 重读`/etc/ld.so.conf`` 6. ``gcc -I/usr/local/include -L/usr/local/lib -o ... -lxx` 如果路径都是这个默认的,可省略。 7. 非root用户发布,可以自己定义一个位置,例如`~/lib` ```bash cp xx.co ~/lib export LD_LIBRARY_PATH= ~/lib ``` #### 还是以`lib2`为例。 ```bash *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ ls  llist.c  llist.h  main  main.c  Makefile *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ gcc -shared -fpic -o libllist.so llist.c *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ ls  libllist.so  llist.h  main.c  llist.c  main  Makefile *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ sudo mv libllist.so /usr/local/lib *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ sudo vi /etc/ld.so.conf *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ sudo /sbin/ldconfig *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ gcc -o main main.c -lllist *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ ./main 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 5 std5 62 27 4 std4 49 21 3 std3 86 92 2 std2 93 35 1 std1 77 15 0 std0 83 86 *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ ldd ./main linux-vdso.so.1 (0x00007ffd963ee000) libllist.so => /usr/local/lib/libllist.so (0x00007fda74025000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fda73e44000) /lib64/ld-linux-x86-64.so.2 (0x00007fda7403a000) ``` > [!NOTE] > > 当动态库和静态库重名,会优先链接**静态库**。 #### 以链式存储栈为例,`libstack`依赖`libllist`。 ```bash *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/stack/list]$ ls  llist.c  main  Makefile  stack.o  llist.h  main.c  stack.c  llist.o  main.o  stack.h *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/stack/list]$ gcc -shared -fpic -o libstack.so stack.c *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/stack/list]$ ls  libstack.so  llist.o  main.o  stack.h  llist.c  main  Makefile  stack.o  llist.h  main.c  stack.c *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/stack/list]$ sudo mv libstack.so /usr/local/lib *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/stack/list]$ sudo cp stack.h /usr/local/include *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/stack/list]$ code main.c *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/stack/list]$ ls  llist.c  main  Makefile  stack.o  llist.h  main.c  stack.c  llist.o  main.o  stack.h *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/stack/list]$ gcc -o main main.c -lstack /usr/bin/ld: /usr/local/lib/libstack.so: undefined reference to `llist_create' /usr/bin/ld: /usr/local/lib/libstack.so: undefined reference to `llist_fetch' /usr/bin/ld: /usr/local/lib/libstack.so: undefined reference to `llist_destroy' /usr/bin/ld: /usr/local/lib/libstack.so: undefined reference to `llist_insert' collect2: error: ld returned 1 exit status *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/stack/list]$ gcc -o main main.c -lstack -lllist *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/stack/list]$ ./main ./main: error while loading shared libraries: libstack.so: cannot open shared object file: No such file or directory *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/stack/list]$ sudo /sbin/ldconfig /sbin/ldconfig: Can't link /usr/lib/wsl/lib/libnvoptix_loader.so.1 to libnvoptix.so.1 /sbin/ldconfig: /usr/lib/wsl/lib/libcuda.so.1 is not a symbolic link *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/stack/list]$ gcc -o main main.c -lstack -lllist *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/stack/list]$ ./main 6 stu6 90 59 5 stu5 62 27 4 stu4 49 21 3 stu3 86 92 2 stu2 93 35 1 stu1 77 15 0 stu0 83 86 ``` 添加动态库记得重载配置文件`sudo /sbin/ldconfig`!