英文:
next:下一个
prev:上一个
list:链表
head:头
tail:尾
node:节点
回顾:
1.文件操作库函数
fopen/fclose/fread/fwrite/rewind/fseek
2.结构体数组
3.结构体和函数指针配合
4.Makefile提升:
4.1.伪目标:没有依赖的目标
例如:clean:
rm helloworld helloworld.o
当执行make clean时执行对应的命令
4.2.Makefile的变量
Makefile的变量类似C语言的#define宏,提高Makefile的可移植性
变量名建议用大写
定义形式:
a) OBJ=helloworld.o
b) OBJ:=helloworld.o
c) OBJ = helloworld.o
OBJ += test.o #结果OBJ=helloworld.o test.o
d)OBJ ?= helloworld.o #结果OBJ=helloworld.o
或者
OBJ = test.o
OBJ ?= helloworld.o #结果:OBJ=test.o
e)引用变量值用:$(OBJ)
#定义变量
BIN=list3_test
OBJ=list3_test.o
OBJ+=list3.o
#CROSS_COMPILE=arm-linux-
CC=$(CROSS_COMPILE)gcc #CC=arm-linux-gcc / CC=gcc
#制定规则
$(BIN):$(OBJ)
$(CC) -o $(BIN) $(OBJ)
@echo "程序编译完成"
%.o:%.c
$(CC) -c -o $@ $<
clean:
rm $(OBJ) $(BIN)
@echo "文件清理完毕"
4.数据结构
描述数据的关系和数据的存储方式
分类:
逻辑结构
集合结构
强调整体,不强调数据之间的关系
线性结构
一对一的前后关系
树形结构
一对多的关系
网状结构
多对多的关系
物理结构
顺序
数组
链式
链表
运算结构
5.数据结构实现方式:栈,队列,单链表,双链表,有序二叉树
5.1.栈
先进后出/后进先出
只操作栈顶
5.2.队列
FIFO:先进先出
经典的三大队列:消息队列,工作队列,等待队列
5.3.单链表
特点:体现一对一的前后关系
节点的数据结构:
struct node {
数据;
struct node *next; //指向下一个节点,多余占4字节
};
链表的数据结构:
struct list {
head;
tail;
};
注意:每个节点的内存不一定连续,不像数组一样连续
/*单链表初级代码*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h> //memset
//声明描述每个节点信息的数据结构
typedef struct node {
int data; //数据
struct node *next; //保存下一个节点的首地址
}node_t;
//声明描述整个单链表的数据结构
typedef struct list {
struct node *head; //指向头节点
struct node *tail; //指向尾节点
}list_t;
int main(void)
{
//1.定义链表并且初始化头节点和尾节点
list_t list;
list.head = (node_t *)malloc(sizeof(node_t));
list.tail = (node_t *)malloc(sizeof(node_t));
memset(list.head, 0, sizeof(node_t));
memset(list.tail, 0, sizeof(node_t));
//2.定义三个节点
node_t node1 = {.data = 10, .next = NULL};
node_t node2 = {.data = 20, .next = NULL};
node_t node3 = {.data = 30, .next = NULL};
//3.将三个节点和链表的头和尾连接起来
list.head->next = &node1;
node1.next = &node2;
node2.next = &node3;
node3.next = list.tail;
//4.遍历链表,打印每个节点的数据
for(node_t *pnode = list.head;
pnode != list.tail; pnode=pnode->next) {
//5.定义三个游标
node_t *pfirst = pnode;
node_t *pmid = pfirst->next;
node_t *plast = pmid->next;
if(pmid != list.tail)
printf("%d ", pmid->data);
}
printf("\n");
//5.由小到大插入一个节点:15
node_t node4 = {.data = 15, .next = NULL}; //造节点15
for(node_t *pnode = list.head;
pnode != list.tail; pnode=pnode->next) {
//定义三个游标
node_t *pfirst = pnode;
node_t *pmid = pfirst->next;
node_t *plast = pmid->next;
if(pmid->data > node4.data || pmid == list.tail) {
pfirst->next = &node4;
node4.next = pmid;
break;
}
}
//6.遍历链表,打印每个节点的数据
for(node_t *pnode = list.head;
pnode != list.tail; pnode=pnode->next) {
//定义三个游标
node_t *pfirst = pnode;
node_t *pmid = pfirst->next;
node_t *plast = pmid->next;
if(pmid != list.tail)
printf("%d ", pmid->data);
}
printf("\n");
//7.前插:总是插入到head和第一个节点之间,例如node5
node_t node5 = {.data = 5, .next = NULL};
node_t *pnode = list.head->next; //先获取第一个节点的地址,临时保存
list.head->next = &node5;
node5.next = pnode;
node_t node6 = {.data = 2, .next = NULL};
pnode = list.head->next; //先获取第一个节点的地址,临时保存
list.head->next = &node6;
node6.next = pnode;
//8.遍历链表,打印每个节点的数据
for(node_t *pnode = list.head;
pnode != list.tail; pnode=pnode->next) {
//定义三个游标
node_t *pfirst = pnode;
node_t *pmid = pfirst->next;
node_t *plast = pmid->next;
if(pmid != list.tail)
printf("%d ", pmid->data);
}
printf("\n");
//9.后插:总是插入到tail和最后一个节点之间,例如:node6
node_t node7 = {.data = 50, .next = NULL};
for(node_t *pnode = list.head;
pnode != list.tail; pnode=pnode->next) {
//定义三个游标
node_t *pfirst = pnode;
node_t *pmid = pfirst->next;
node_t *plast = pmid->next;
if(pmid == list.tail) {
//pfirst指向最后一个节点,pmid指向尾节点
pfirst->next = &node7;
node7.next = pmid;
break;
}
}
//10.遍历链表,打印每个节点的数据
for(node_t *pnode = list.head;
pnode != list.tail; pnode=pnode->next) {
//定义三个游标
node_t *pfirst = pnode;
node_t *pmid = pfirst->next;
node_t *plast = pmid->next;
if(pmid != list.tail)
printf("%d ", pmid->data);
}
printf("\n");
//11.删除20这个节点
for(node_t *pnode = list.head;
pnode != list.tail; pnode=pnode->next) {
//定义三个游标
node_t *pfirst = pnode;
node_t *pmid = pfirst->next;
node_t *plast = pmid->next;
if(pmid->data == 20 && pmid != list.tail) {
pfirst->next = plast;
}
}
//12.遍历链表,打印每个节点的数据
for(node_t *pnode = list.head;
pnode != list.tail; pnode=pnode->next) {
//定义三个游标
node_t *pfirst = pnode;
node_t *pmid = pfirst->next;
node_t *plast = pmid->next;
if(pmid != list.tail)
printf("%d ", pmid->data);
}
printf("\n");
return 0;
}