当前位置: 首页 > news >正文

数据结构(三)双向链表

一、什么是 make 工具?

make 是一个自动化构建工具,主要用于管理 C/C++ 项目的编译和链接过程。它通过读取 Makefile 文件中定义的规则,自动判断哪些文件被修改,并仅重新编译这些部分,从而大幅提高构建效率。


二、什么是 Makefile?

Makefilemake 工具的配置文件,它以纯文本形式存在,主要用于描述:

  • 构建目标(如:最终生成的可执行文件)

  • 依赖关系(如:源代码、头文件)

  • 构建命令(如:gcc 编译命令)

通过 Makefile,我们可以实现对大型项目的自动化编译管理。


三、Makefile 的基本语法

1. 基本格式

目标文件: 依赖文件列表 命令(以Tab键开头)

注意:命令必须以 Tab 缩进,否则 make 会报错。

示例:

a.out: main.c fun.c

    gcc main.c fun.c -o a.out -I$(INC) -L$(LIB)

  • 目标文件:a.out(最终生成的可执行文件)

  • 依赖文件:main.c、fun.c

  • 命令:gcc 编译命令,带有头文件和库路径参数


四、常用编译参数说明

  • -I$(INC):指定头文件目录(如 include/

  • -L$(LIB):指定库文件目录(如 lib/

  • -o:指定输出文件名称


五、Makefile 中的变量使用

1. 自定义变量

CC = gcc

TARGET = app

SRC = main.c fun.c

INC = ./include

LIB = ./lib

引用变量方式:$(变量名

$(TARGET): $(SRC)

    $(CC) $(SRC) -o $(TARGET) -I$(INC) -L$(LIB)

2. 系统自动变量

  • $@:表示当前规则的目标文件

  • $^:所有依赖文件(去重)

  • $<:第一个依赖文件

示例:

app: main.c fun.c tool.c gcc $^ -o $@

等价于:

gcc main.c fun.c tool.c -o app


六、make 的时间戳机制

make 会对比文件的时间戳来判断是否需要重新编译:

  • 若依赖文件比目标文件更新 → 执行构建命令

  • 否则跳过(显示 make: 'xxx' is up to date.

这种机制确保了编译效率,尤其适合大型项目。


七、GCC 编译的四个阶段

  1. 预处理(Preprocessing)
    处理 #include#define 等预处理指令,生成 .i 文件:

    gcc -E main.c -o main.i

  2. 编译(Compilation)
    .i 转为汇编 .s 文件:

    gcc -S main.i -o main.s

  3. 汇编(Assembly)
    .s 文件生成 .o 目标文件:

    gcc -c main.s -o main.o

  4. 链接(Linking)
    将多个 .o 文件和库链接为可执行程序:

    gcc main.o fun.o -o app


八、Makefile 示例(推荐写法)

# 定义变量  
CC = gcc  
CFLAGS = -I./include -Wall  # 编译选项:指定头文件目录 + 显示警告  
LDFLAGS = -L./lib -lm       # 链接选项:指定库目录 + 链接数学库  
TARGET = app  
SRCS = main.c fun.c  
OBJS = $(SRCS:.c=.o)        # 将 .c 文件转换为 .o 文件(如 main.c → main.o)  # 默认目标(第一个目标为默认)  
all: $(TARGET)  # 生成可执行文件  
$(TARGET): $(OBJS)  $(CC) $(OBJS) -o $@ $(LDFLAGS)  # 生成目标文件(.o)  
%.o: %.c                    # 模式规则:所有 .o 依赖对应的 .c  $(CC) -c $< -o $@ $(CFLAGS)  # 清理编译产物  
clean:  rm -f $(OBJS) $(TARGET)  

使用方法

  • 编译项目:make(默认执行 all 目标)
  • 清理文件:make clean
  • 重新编译:make clean && make

九、Makefile 使用方法

操作命令
编译项目make(默认执行 all)
清理项目make clean
重新编译make clean && make

十、双线链表基础语法

头文件

#ifndef _SIZEOF_DOUBLE_
#define _SIZEOF_DOUBLE_typedef struct stu
{int id;char name[32];int score;
}Data_type;typedef struct dounode
{Data_type data;struct dounode *ppre;struct dounode *pnext;
}DNode;typedef struct doulink
{DNode *phead;int clen;
}Dlink;extern Dlink *creatDoulink();
extern int IsEmptyDouLink(Dlink *pdlink);
extern int insertHeadDouLink(Dlink *pdlink, Data_type data);
extern void printDouLink(Dlink *pdlink, int dir);
extern int insertTailDouLink(Dlink *pdlink, Data_type data);
extern int deleteHeadDouLink(Dlink *pdlink);
extern int deleteTailDouLink(Dlink *pdlink);
extern int DestroyDouLink(Dlink *pdlink);extern DNode *findNameDouLink(Dlink *pdlink, char *s);extern int modifyScoreByName(Dlink *pdlink, char *s, int Score);
extern int deleteNodeByName(Dlink *pdlink, char *s);
#endif

定义函数

#include "doulink.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>Dlink *creatDoulink()
{Dlink *pdlink = malloc(sizeof(Dlink));if (NULL == pdlink){printf("malloc error\n");return NULL;}pdlink->phead = NULL;pdlink->clen = 0;return pdlink;
}int IsEmptyDouLink(Dlink *pdlink)
{return NULL == pdlink->phead;
}int insertHeadDouLink(Dlink *pdlink, Data_type data)
{DNode *pnode = malloc(sizeof(DNode));if(NULL == pnode){printf("malloc error\n");return -1;}pnode->data = data;pnode->pnext = NULL;pnode->ppre = NULL;if(IsEmptyDouLink(pdlink)){pdlink->phead = pnode;}else{pnode->pnext = pdlink->phead;pdlink->phead->ppre = pnode;pdlink->phead = pnode; }pdlink->clen++;return 0;
}void printDouLink(Dlink *pdlink, int dir)
{if(IsEmptyDouLink(pdlink)){return ;}DNode *temp = pdlink->phead;if(dir){while(temp){printf("%d %s %d\n", temp->data.id, temp->data.name, temp->data.score);temp = temp->pnext;}}else{temp = pdlink->phead;while(temp->pnext){temp = temp->pnext;   }while(temp){printf("%d %s %d\n", temp->data.id, temp->data.name, temp->data.score);temp = temp->ppre;}}return ;
}int insertTailDouLink(Dlink *pdlink, Data_type data)
{if(IsEmptyDouLink(pdlink)){insertHeadDouLink(pdlink, data);return 1;}else{DNode *pnode = malloc(sizeof(DNode));if(NULL == pnode){printf("malloc error\n");return -1;}pnode->data = data;pnode->ppre = NULL;pnode->pnext = NULL;DNode *temp = pdlink->phead;while (temp->pnext){temp = temp->pnext;}pnode->ppre = temp;temp->pnext = pnode;pdlink->clen++;return 1;}
}int deleteHeadDouLink(Dlink *pdlink)
{if(IsEmptyDouLink(pdlink)){return -1;}if(pdlink->phead->pnext == NULL){free(pdlink->phead);pdlink->phead = NULL;pdlink->clen--;return 1;}else{DNode *temp = pdlink->phead->pnext;temp->ppre = NULL;free(pdlink->phead);pdlink->phead = temp;pdlink->clen--;return 1;}}int deleteTailDouLink(Dlink *pdlink)
{if(IsEmptyDouLink(pdlink)){return -1;}if(pdlink->phead->pnext == NULL){free(pdlink->phead);pdlink->phead = NULL;pdlink->clen--;return 1;}else{DNode *temp = pdlink->phead;while(temp->pnext){temp = temp->pnext;}temp->ppre->pnext = NULL;free(temp);pdlink->clen--;return 1;}
}int DestroyDouLink(Dlink *pdlink)
{DNode *temp = pdlink->phead;while(temp){pdlink->phead = temp->pnext;free(temp);temp = pdlink->phead;}free(pdlink);return 1;
}DNode *findNameDouLink(Dlink *pdlink, char *s)
{if(IsEmptyDouLink(pdlink)){return NULL;}DNode *temp = pdlink->phead;while(temp){if(strcmp(temp->data.name, s) == 0){return temp;}temp = temp->pnext;}return NULL;
}int modifyScoreByName(Dlink *pdlink, char *s, int Score)
{DNode *temp = findNameDouLink(pdlink, s);if(temp == NULL){return -1;}temp->data.score = Score;return 1;
}int deleteNodeByName(Dlink *pdlink, char *s)
{if(IsEmptyDouLink(pdlink)){return -1;}DNode *temp = findNameDouLink(pdlink, s);if(temp->ppre == NULL){deleteHeadDouLink(pdlink);return 1;}if(temp->pnext == NULL){deleteTailDouLink(pdlink);return 1;}temp->pnext->ppre = temp->ppre;temp->ppre->pnext = temp->pnext;free(temp);pdlink->clen--;return 1;  
}

主函数

#include "doulink.h"
#include<stdio.h>int main(int argc, char const *argv[])
{Data_type stus[5] = {{1, "zhangsan", 99},{2, "lisi", 100},{3, "wangwu", 90},{4, "maliu", 56},{5, "tianqi", 66},};Dlink *pdlink = creatDoulink();if(NULL == pdlink){return -1;}insertHeadDouLink(pdlink, stus[0]);insertHeadDouLink(pdlink, stus[1]);insertHeadDouLink(pdlink, stus[2]);insertHeadDouLink(pdlink, stus[3]);//   insertHeadDouLink(pdlink, stus[4]);printDouLink(pdlink, 1);// printDouLink(pdlink, 0);//   deleteHeadDouLink(pdlink);
//   deleteTailDouLink(pdlink);printf("----------find----------\n");//    insertTailDouLink(pdlink, stus[4]);//    printDouLink(pdlink, 1);DNode * temp = findNameDouLink(pdlink, "lisi");printf("%d %s %d\n", temp->data.id, temp->data.name, temp->data.score);printf("----------modify----------\n");modifyScoreByName(pdlink, "wangwu", 999);printDouLink(pdlink, 1);printf("----------deletes design----------\n");deleteNodeByName(pdlink, "zhangsan");printDouLink(pdlink, 1);DestroyDouLink(pdlink);return 0;
}

http://www.xdnf.cn/news/1246663.html

相关文章:

  • VSCode中使用Qt
  • 7、Redis队列Stream和单线程及多线程模型
  • Pandas query() 方法详解
  • SpringBoot3.x入门到精通系列:4.2 整合 Kafka 详解
  • 基于deepSeek的流式数据自动化规则清洗案例【数据治理领域AI带来的改变】
  • 2025-08-05Gitee + PicGo + Typora搭建免费图床
  • FPGA设计思想与验证方法学系列学习笔记003
  • springboot + maven 使用资源占位符实现动态加载配置文件
  • 【springcloud的配置文件不生效】
  • Linux 系统启动原理2
  • Occ3D: A Large-Scale 3D Occupancy Prediction Benchmark for Autonomous Driving
  • Unity开发者快速认识Unreal 的C++(四)Pawn和Actor
  • 智慧城市SaaS平台|市容环卫管理系统
  • Spring-rabbit使用实战六
  • Could not load the Qt platform plugin “xcb“ in “无法调试与显示Opencv
  • 类内部方法调用,自注入避免AOP失效
  • RK3568 Linux驱动学习——字符设备驱动开发
  • 森赛睿科技成为机器视觉产业联盟会员单位
  • C++ - 仿 RabbitMQ 实现消息队列--服务端核心模块实现(六)
  • Vue.js 教程
  • css3属性总结和浏览器私有属性
  • Matplotlib(六)- 坐标轴定制
  • 【视觉识别】Ubuntu 22.04 上安装和配置 TigerVNC 鲁班猫V5
  • 技术与情感交织的一生 (十一)
  • 漏洞分析:90分钟安全革命
  • 原型模式在C++中的实现与面向对象设计原则
  • vue3 计算属性
  • 前端实现Excel文件的在线预览效果
  • 10-红黑树
  • LINUX 85 SHElL if else 前瞻 实例