Linux下C语言教程-李慧芹老师-第十章,第十一章

配套代码笔记仓库

Makefile

makefile与Makefile的区别

make会优先使用makefile,发布的项目一般是一个Makefile,方便用户写自己的makefile

参考资料

跟我一起写Makefile — 跟我一起写Makefile 1.0 文档 (seisman.github.io)

目录

数据结构

架构梳理

  • 线性(1:1)

    • 线性表

      • 顺序存储 –> arr

      • 链式存储 –> 指针 (有头,无头)

        有头是指有一个不存数据的头,始终作为这个链表的起点。

        会更加简单,无头的话,更改首部节点会麻烦。

        头节点不仅可以作为起点,还可以作为存储信息的仓库,因为头节点只有*next是必须的。

        • 单链表

          • 循环
          • 不循环
        • 双向链表

          lib四个版本,第一个最基础完善,第二个改成了变长结构体,第三个在第二个的基础上封装了函数指针,第四个在第二个的基础上隐藏了数据结构,只暴露接口。

          • 循环
          • 不循环

          学到这里可以去读一下内核有关list的实现,主要都是宏和内联函数。

    • 队列

      练习:

      1. 表达式计算

      2. 球钟算法
        三个栈,1h,5min,1min。27个球,过了多久队列里又是1到27的顺序。

  • 树状(1:N)

    递归递归非递归

    • 深度:层数

    • 度:子树的个数

    • 叶子:边缘节点

    • 孩子:与父节点对应

    • 兄弟:相同父节点

    • 堂兄弟:相同爷节点

    • 二叉树:

      • 满二叉树:深度为k且节点为2^k-1的二叉树
      • 完全二叉树:一颗二叉树,只有倒数两层可以存在不满两个孩子的节点,且单个孩子时只能是左孩子
    • 存储:

      • 顺序:直观,但是浪费空间
        满二叉树:父节点n,左孩子2n,右孩子2n+1
      • 链式:灵活,空间利用率高
    • 遍历

      • 按行
      • 先序(根,左,右)
      • 中序(左,根,右)
      • 后序(左,右,根)

      先加中,或者,中加后,都可以逆推出树。先加后不行。

    • 平衡:

      有很多种条件判定。

      这棵树的左右子树个数差值为1。

    • 广义表

      ( 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为例。

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
*[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.cllist.h了,#include时也从"llist.h"变为<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
1
2
cp xx.co ~/lib
export LD_LIBRARY_PATH= ~/lib

还是以lib2为例。

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
*[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

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
*[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!


Linux下C语言教程-李慧芹老师-第十章,第十一章
http://sinlatansen.github.io/2024/04/29/Linux下C语言教程-李慧芹老师-第十章,第十一章/
作者
fugu
发布于
2024年4月29日
许可协议