华清远见25072班数据结构学习day1
重点内容:
Makefile:
是一个工程管理文件
学Makefile的作用:
1.生成二进制中间文件,.o 2.根据二进制中间文件生成可执行文件
Makefile对编译流程的优化:
当多文件编译时,如果部分文件没有发生修改,重新生成可执行文件时无需重新编译没有修改过的文件
Makefile文件的书写和执行:
make工具用于执行Makefile文件
如果虚拟机中没有装Makefile文件,sudo apt-get install make
测试虚拟机中是否由make工具:直接在终端输入make
make工具的使用:
- Makefile文件是make工具的默认读入文件
- 当makefile和Makefile同时存在时,make默认读makefile
- make -f 指定的文件名
- 在终端直接输入make,默认会读Makefile文件中的第一个目标
- make 目标名 ---->让make读取Makefile中指定的目标
Makefile文件的构成:
- 规则
- 变量
- 函数
Makefile中规则的构成:
目标:依赖 <tab>指令(往往是由依赖生成目标的指令)
一条规则中可以只有目标和依赖没有指令,只描述依赖关系
一条规则中可以只执行指令只有目标,没有依赖
一条规则中必须有一个目标
Makefile生成文件的依据:
Makefile根据文件的时间错,来判断文件是否需要重新生成,如果依赖文件的时间戳比目标文件更新,那么说明目标文件需要重新生成
Makefile中的变量:
变量的赋值方式:
=:递归赋值
+=:追加赋值
?=:条件赋值
:= 立即赋值
变量的使用:
变量名=变量的值
使用变量的值$(变量名) $变量名
伪目标.PHONY:
Makefile默认每条规则都是要生成文件,每个目标都是要生成的文件名
伪目标的作用:无论是否存在和目标同名文件,都去执行目标下的规则
引入函数:
Makefile所编译的文件和Makefile文件在同一个目录下
wildcard:
功能:在当前路径下,根据所给的特征查找文件
使用: $(wildcard 指定格式)
例:$(wildcard *.c) ---->查找当前路径下所有的.c文件
patsubst:
功能:用格式匹配的方式获取新的字符串
使用: $(patsubst 源格式,新格式,要替换的字符串)
例: $(patsubst %.c,%.o,1.c 2.c)
Makefile的最终版本(通用版本):
EXE=fun #可执行文件
CC=gcc #CC用来保存程序所需编译器名字
Objs=$(patsubst %.c,%.o,$(wildcard *.c))
CFlags=-c -o #编译参数
all:$(EXE)
$(EXE):$(Objs)
$(CC) $^ -o $@
%.o:%.c #引入通配符
$(CC) $^ $(CFlags) $@
.PHONY:clean
clean: rm $(EXE) $(Objs)
数据结构:
逻辑结构:
- 线性结构:数据之间是一对一的关系
- 非线性结构:集合、树、图(数据之间没有逻辑关系/不是一对一的关系)
物理结构:
- 顺序存储:内存连续(数组)
- 链式存储:内存不连续,用指针存储下一个数据的地址
- 散列存储:根据关键字为数据分配空间
- 索引存储:一本书的目录和内页
存储类型:
const:
const修饰的变量,拥有常量的属性,不能在代码中更改
const和指针结合:
const在谁前面就修饰谁,在*p前就修饰*p,在p前就修饰p
常量指针:
const int *p = &a;
指向常量的指针,*p不能更改
指针常量:
int * const p = &a;
是一个指针类型的常量,指针的指向不能更改
volatile:
每次去内存中取数据的值(不去cache高速缓存器中取数据)
extern:
外部文件中变量的声明
extern int a; ----->不能写=,只是声明可能会使用到外部文件中的变量a
顺序表:
概念:
是顺序存储的线性表
操作:
顺序表的结构体
申请顺序表的空间
元素前移和后移的问题:
循环前移:从前面开始移动
循环后移:从后面开始移动
作业:
1.多文件编译,一般存在三个文件,但是课上的Makefile中只考虑了两个.c文件,并没有考虑到头文件(.h),如果现在只有.h发生过修改,怎么样让Makefile重新编译。
程序源码:
EXE=fun
CC=gcc
OBJES=$(patsubst %.c,%.o,$(wildcard *.c))
CFLAGS=-c -o
#一般默认第一个规则的目标为all
all:$(EXE)#第一个规则
#fun目标依赖main.o test.o$(EXE):$(OBJES) *.h
$(CC) $^ -o $@
#main.o依赖main.c
# 当目标为main.o,会默认执行下面的规则
# %等价main,展开结果---》main.o:main.c
# 当目标为test.o
# %等价test,会展开结果-->test.o:test.c%.o:%.c
$(CC) $(CFLAGS) $@ $^.phony:clean
#删除所有.o文件以及 hello可执行文件
# @当执行指令时不会在当前终端打印clean:
@rm $(OBJES) $(EXE)
2.实现顺序表的头删、输出
顺序表的头删:
顺序表的打印输出:
程序源码:
(fun.c)
#include "head.h"
int empty_sqlist(list_p sqlist)
{
if(sqlist->len==0)
{
return 1;
}
else
{
return 0;
}
}
int full_sq(list_p sqlist)
{
//检测顺序表是否已满
if(sqlist->len==MAX)
{
return 1;
}
else
{
return 0;
}
}list_p create_list()
{
list_p sqlist=(list_p)malloc(sizeof(list));
if(sqlist==NULL)
{
printf("申请空间失败\n");
return NULL;
}
bzero(sqlist,sizeof(sqlist->data));
sqlist->len=0;
return sqlist;
}
void head_insert(list_p sqlist,int element)
{
//判断顺序表是否存在,是否有其他元素
if(sqlist==NULL)
{
printf("入参为空");
return ;
}
if(full_sq(sqlist))
{
printf("%d",sqlist->len);
printf("顺序表已满");
return;
}
//头部插入
for(int i=sqlist->len-1;i>=0;i--)
{
sqlist->data[i+1]=sqlist->data[i];
}
sqlist->data[0]=element;
sqlist->len++;
}
void head_del(list_p sqlist)
{
if(sqlist==NULL)
{
printf("顺序表不存在\n");
return;
}
if(empty_sqlist(sqlist))
{
printf("顺序表为空,头删无效\n");
return;
}
for(int i=0;i<=sqlist->len-1;i++)
{
sqlist->data[i]=sqlist->data[i+1];
}
sqlist->len--;
}
void outputs(list_p sqlist)
{
//判断顺序表是否存在,是否有其他元素
if(sqlist==NULL)
{
printf("顺序表不存在\n");
return ;
}
if(empty_sqlist(sqlist))
{
printf("顺序表为空\n");
return;
}
for(int i=0;i<sqlist->len;i++)
{
printf("%d\t",sqlist->data[i]);
}
putchar(10);}
main.c
#include "head.h"
int main(int argc, const char *argv[])
{
list_p sqlist=create_list();
int element;
//输入
for(int i=0;i<MAX;i++)
{
scanf("%d",&element);
//调用头插
head_insert(sqlist,element);
}
//调用输出
outputs(sqlist);
head_del(sqlist);
printf("after head_del:\n");
outputs(sqlist);
return 0;
}
head.h
#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 5
typedef struct
{
int data[MAX];
int len;}list,*list_p;
list_p create_list();
void head_insert(list_p sqlist,int element);
void outputs(list_p sqlist);
int full_sqlist(list_p sqlist);
void head_del(list_p sqlist);
#endif
3.在下列前提下,重新完成创建顺序表的函数
fun.c:
#include "head.h"
seq_p seq_create(seq_p *S)
{
*S=(seq_p)malloc(sizeof(seq_list));
if(*S==NULL)
{
printf("申请空间失败\n");
return NULL;
}
//长度置0
(*S)->len=0;
return *S;
}
main.c:#include "head.h"
int main(int argc, const char *argv[])
{
//定义一个结构体指针,指向堆区申请的顺序表的空间seq_p S;
if (seq_create(&S) != NULL)
{
printf("顺序表创建成功,初始长度: %d\n", S->len);
}
return 0;
}
head.h#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>#define MAX 7
typedef struct
{
int data[MAX];
int len;
}seq_list,*seq_p;
seq_p seq_create();
#endif
4.思维导图: