了解更多知识请点我:学习C语言之路(汇总篇)
目录
概念
链表大致示意图,通过一系类的链表将有效数据通过链式方式连接。
准备工作
-
vscode
-
ubuntu
-
makefile
makefile 如下
object = main.o slist.o
main : $(object)
cc -o main $(object)
%.o: %.c
gcc -c $<
.PHONY : clean
clean :
rm *.o
rm main
第一版:一个错误的链表案例
main.c
#include "slist.h"
int main(int argc, char **argv)
{
slist_node_t *p_head = NULL;
slist_node_t node1;
slist_node_t *p_tmp;
node1.date = 1;
slist_add_end(p_head, &node1);
p_tmp = p_head;
while (p_tmp != NULL){
printf("%d ", p_tmp->date);
p_tmp = p_tmp -> next;
}
}
slist.c
#include "slist.h"
int slist_add_end(slist_node_t *p_head, slist_node_t *p_node)
{
if (p_head == NULL){
p_head = p_node;
p_node -> next = NULL;
}
return 0;
}
slist.h
#ifndef _INCLUDE_H
#define _INCLUDE_H
#include "stdio.h"
typedef struct _slist_node{
int date;
struct _slist_node *next;
}slist_node_t;
int slist_add_end(slist_node_t *p_head, slist_node_t *p_node);
#endif // !_INCLUDE_H
第一版:修改完成后
main.c
#include "slist.h"
int main(int argc, char **argv)
{
slist_node_t *p_head = NULL;
slist_node_t node1;
slist_node_t *p_tmp;
node1.date = 1;
slist_add_end(&p_head, &node1);
p_tmp = p_head;
while (p_tmp != NULL){
printf("%d ", p_tmp->date);
p_tmp = p_tmp -> next;
}
}
slist.c
#include "slist.h"
int slist_add_end(slist_node_t **p_head, slist_node_t *p_node)
{
if (*p_head == NULL){
*p_head = p_node;
p_node -> next = NULL;
}
return 0;
}
slist.h
#ifndef _INCLUDE_H
#define _INCLUDE_H
#include "stdio.h"
typedef struct _slist_node{
int date;
struct _slist_node *next;
}slist_node_t;
int slist_add_end(slist_node_t **p_head, slist_node_t *p_node);
#endif // !_INCLUDE_H
第二版:再添加一个node值
main.c
#include "slist.h"
int main(int argc, char **argv)
{
slist_node_t *p_head = NULL;
slist_node_t node1,node2,node3;
slist_node_t *p_tmp;
node1.date = 1;
slist_add_end(&p_head, &node1);
node2.date = 2;
slist_add_end(&p_head, &node2);
node3.date = 3;
slist_add_end(&p_head, &node3);
p_tmp = p_head;
while (p_tmp != NULL){
printf("%d \r\n", p_tmp->date);
p_tmp = p_tmp -> next;
}
}
slist.c
#include "slist.h"
int slist_add_end(slist_node_t **p_head, slist_node_t *p_node)
{
if (*p_head == NULL){
*p_head = p_node;
p_node -> next = NULL;
}
else{
//先找到节点的尾部然后在尾部添加新节点
slist_node_t *p_temp = *p_head;
while (p_temp->next != NULL){
p_temp = p_temp->next;
}
p_temp->next = p_node;
p_node->next = NULL;
}
return 0;
}
slist.h
#ifndef _INCLUDE_H
#define _INCLUDE_H
#include "stdio.h"
typedef struct _slist_node{
int date;
struct _slist_node *next;
}slist_node_t;
int slist_add_end(slist_node_t **p_head, slist_node_t *p_node);
#endif // !_INCLUDE_H
第三版:链表自带head
main.c
#include "slist.h"
int main(int argc, char **argv)
{
slist_node_t p_head = {0,NULL};
slist_node_t node1,node2,node3;
slist_node_t *p_tmp;
node1.date = 1;
slist_add_end(&p_head, &node1);
node2.date = 2;
slist_add_end(&p_head, &node2);
node3.date = 3;
slist_add_end(&p_head, &node3);
p_tmp = &p_head;
while (p_tmp != NULL){
printf("%d \r\n", p_tmp->date);
p_tmp = p_tmp -> next;
}
}
slist.c
#include "slist.h"
int slist_add_end(slist_node_t *p_head, slist_node_t *p_node)
{
//先找到节点的尾部然后在尾部添加新节点
slist_node_t *p_temp = p_head;
while (p_temp->next != NULL){
p_temp = p_temp->next;
}
p_temp->next = p_node;
p_node->next = NULL;
return 0;
}
slist.h
#ifndef _INCLUDE_H
#define _INCLUDE_H
#include "stdio.h"
typedef struct _slist_node{
int date;
struct _slist_node *next;
}slist_node_t;
int slist_add_end(slist_node_t *p_head, slist_node_t *p_node);
#endif // !_INCLUDE_H
第四版:当date为结构体&数据量很大
main.c
#include "slist.h"
int main(int argc, char **argv)
{
slist_node_t p_head = {{0},NULL};
slist_node_t node1= {{"Chirs",'m',180.12,65.34},NULL};
slist_node_t *p_tmp;
slist_add_end(&p_head, &node1);
p_tmp = &p_head;
while (p_tmp != NULL){
printf("name = %s \r\n", p_tmp->date.name);
printf("sex = %c \r\n", p_tmp->date.sex);
printf("height = %f \r\n", p_tmp->date.height);
printf("weight = %f \r\n", p_tmp->date.weight);
printf("-------------\r\n");
p_tmp = p_tmp -> next;
}
}
slist.c
#include "slist.h"
int slist_add_end(slist_node_t *p_head, slist_node_t *p_node)
{
//先找到节点的尾部然后在尾部添加新节点
slist_node_t *p_temp = p_head;
while (p_temp->next != NULL){
p_temp = p_temp->next;
}
p_temp->next = p_node;
p_node->next = NULL;
return 0;
}
slist.h
#ifndef _INCLUDE_H
#define _INCLUDE_H
#include "stdio.h"
//定义一个学生类型结构体
typedef struct _student{
char name[10];
char sex;
float height,weight;
}student_t;
//为什么要定义void * 节省了空间 链表只占4个字节 使用的时候强制转化即可
typedef student_t element_type_t;
typedef struct _slist_node{
element_type_t date;
struct _slist_node *next;
}slist_node_t;
int slist_add_end(slist_node_t *p_head, slist_node_t *p_node);
#endif // !_INCLUDE_H
第五版:链表和数据分离
main.c
#include "slist.h"
int main(int argc, char **argv)
{
slist_node_t p_head = {NULL};
slist_init_t node1,node2,node3;
slist_node_t *p_tmp;
node1.data = 1;
slist_add_end(&p_head, &node1.node);
node2.data = 2;
slist_add_end(&p_head, &node2.node);
node3.data = 3;
slist_add_end(&p_head, &node3.node);
p_tmp = &p_head;
while (p_tmp != NULL){
printf("%d \r\n", ((slist_init_t *)p_tmp)->data);
p_tmp = p_tmp -> next;
}
}
slist.c
#include "slist.h"
int slist_add_end(slist_node_t *p_head, slist_node_t *p_node)
{
//先找到节点的尾部然后在尾部添加新节点
slist_node_t *p_temp = p_head;
while (p_temp->next != NULL){
p_temp = p_temp->next;
}
p_temp->next = p_node;
p_node->next = NULL;
return 0;
}
slist.h
#ifndef _INCLUDE_H
#define _INCLUDE_H
#include "stdio.h"
//定义一个学生类型结构体
typedef struct _student{
char name[10];
char sex;
float height,weight;
}student_t;
//为什么要定义void * 节省了空间 链表只占4个字节 使用的时候强制转化即可
typedef int element_type_t;
//单独链表
typedef struct _slist_node{
struct _slist_node *next;
}slist_node_t;
//定义链表和数据相互结合
typedef struct _slist_init{
slist_node_t node;
element_type_t data;
}slist_init_t;
int slist_add_end(slist_node_t *p_head, slist_node_t *p_node);
#endif // !_INCLUDE_H
第五版:链表和数据分离(优化)使用函数接口(优化)
main.c
#include "slist.h"
int main(int argc, char **argv)
{
slist_node_t p_head = {NULL};
slist_init_t node1,node2,node3;
slist_node_t *p_tmp;
slist_init(&p_head);
node1.data = 1;
slist_add_end(&p_head, &node1.node);
node2.data = 2;
slist_add_end(&p_head, &node2.node);
node3.data = 3;
slist_add_end(&p_head, &node3.node);
p_tmp = p_head.next;
while (p_tmp != NULL){
printf("%d \r\n", ((slist_init_t *)p_tmp)->data);
p_tmp = p_tmp -> next;
}
}
slist.c
#include "slist.h"
int slist_init(slist_head_t *p_head)
{
if(p_head == NULL){
return -1;
}
p_head->next = NULL;
return 0;
}
int slist_add_end(slist_head_t *p_head, slist_node_t *p_node)
{
//先找到节点的尾部然后在尾部添加新节点
slist_node_t *p_temp = p_head;
if((p_head == NULL)||(p_node == NULL)){
return -1;
}
while (p_temp->next != NULL){
p_temp = p_temp->next;
}
p_temp->next = p_node;
p_node->next = NULL;
return 0;
}
slist.h
#ifndef _INCLUDE_H
#define _INCLUDE_H
#include "stdio.h"
//定义一个学生类型结构体
typedef struct _student{
char name[10];
char sex;
float height,weight;
}student_t;
//为什么要定义void * 节省了空间 链表只占4个字节 使用的时候强制转化即可
typedef int element_type_t;
//单独链表
typedef struct _slist_node{
struct _slist_node *next;
}slist_node_t;
typedef slist_node_t slist_head_t;
//定义链表和数据相互结合
typedef struct _slist_init{
slist_node_t node;
element_type_t data;
}slist_init_t;
int slist_add_end(slist_node_t *p_head, slist_node_t *p_node);
int slist_init(slist_head_t *p_head);
#endif // !_INCLUDE_H
第六版:新增开始位置、结束位置、下个节点返回等接口函数
main.c
#include "slist.h"
int main(int argc, char **argv)
{
slist_node_t p_head = {NULL};
slist_init_t node1,node2,node3;
slist_init(&p_head);
node1.data = 1;
slist_add_end(&p_head, &node1.node);
node2.data = 2;
slist_add_end(&p_head, &node2.node);
node3.data = 3;
slist_add_end(&p_head, &node3.node);
slist_node_t *p_tmp = slist_begin_get(&p_head);
slist_node_t *p_end = slist_end_get(&p_head);
while (p_tmp != p_end){
printf("%d \r\n", ((slist_init_t *)p_tmp)->data);
p_tmp = slist_next_get(&p_head, p_tmp);
}
}
slist.c
#include "slist.h"
int slist_init(slist_head_t *p_head)
{
if(p_head == NULL){
return -1;
}
p_head->next = NULL;
return 0;
}
slist_node_t *slist_begin_get (slist_head_t *p_head)
{
return slist_next_get(p_head,p_head);
}
slist_node_t *slist_next_get (slist_head_t *p_head, slist_node_t *p_pos)
{
if(p_pos){
return p_pos->next;
}
return NULL;
}
slist_node_t *slist_end_get (slist_head_t *p_head)
{
return NULL;
}
int slist_add_end(slist_head_t *p_head, slist_node_t *p_node)
{
//先找到节点的尾部然后在尾部添加新节点
slist_node_t *p_temp = p_head;
if((p_head == NULL)||(p_node == NULL)){
return -1;
}
while (p_temp->next != NULL){
p_temp = p_temp->next;
}
p_temp->next = p_node;
p_node->next = NULL;
return 0;
}
slist.h
#ifndef _INCLUDE_H
#define _INCLUDE_H
#include "stdio.h"
//定义一个学生类型结构体
typedef struct _student{
char name[10];
char sex;
float height,weight;
}student_t;
//为什么要定义void * 节省了空间 链表只占4个字节 使用的时候强制转化即可
typedef int element_type_t;
//单独链表
typedef struct _slist_node{
struct _slist_node *next;
}slist_node_t;
typedef slist_node_t slist_head_t;
//定义链表和数据相互结合
typedef struct _slist_init{
slist_node_t node;
element_type_t data;
}slist_init_t;
int slist_add_end(slist_node_t *p_head, slist_node_t *p_node);
slist_node_t *slist_begin_get (slist_head_t *p_head);//获取开始位置,第一个用户节点
slist_node_t *slist_next_get (slist_head_t *p_head, slist_node_t *p_pos); //获取某个节点的后一个位置
slist_node_t *slist_end_get (slist_head_t *p_head);//结束位置。尾节点下一个节点的位置
int slist_init(slist_head_t *p_head);
#endif // !_INCLUDE_H
第七版:链表和数据处理分割、使用回调方法
main.c
#include "slist.h"
int main(int argc, char **argv)
{
slist_node_t p_head = {NULL};
slist_init_t node1,node2,node3;
slist_init(&p_head);
node1.data = 1;
slist_add_end(&p_head, &node1.node);
node2.data = 2;
slist_add_end(&p_head, &node2.node);
node3.data = 3;
slist_add_end(&p_head, &node3.node);
slist_foreach(&p_head,node_process_int,NULL);
}
slist.c
#include "slist.h"
int slist_init(slist_head_t *p_head)
{
if(p_head == NULL){
return -1;
}
p_head->next = NULL;
return 0;
}
slist_node_t *slist_begin_get (slist_head_t *p_head)
{
return slist_next_get(p_head,p_head);
}
slist_node_t *slist_next_get (slist_head_t *p_head, slist_node_t *p_pos)
{
if(p_pos){
return p_pos->next;
}
return NULL;
}
slist_node_t *slist_end_get (slist_head_t *p_head)
{
return NULL;
}
int slist_add_end(slist_head_t *p_head, slist_node_t *p_node)
{
//先找到节点的尾部然后在尾部添加新节点
slist_node_t *p_temp = p_head;
int ret;
if((p_head == NULL)||(p_node == NULL)){
return -1;
}
while (p_temp->next != NULL){
p_temp = p_temp->next;
}
p_temp->next = p_node;
p_node->next = NULL;
return 0;
}
int slist_foreach(slist_head_t *p_head, slist_node_process_t pfn_node_process, void *p_arg)
{
slist_node_t *p_start;
slist_node_t *p_end;
int ret;
if((p_head == NULL)||(pfn_node_process == NULL))
return -1;
p_start = slist_begin_get(p_head);
p_end = slist_end_get(p_head);
while(p_start != p_end)
{
ret = pfn_node_process(p_arg, p_start);
if(ret<0) return -1;
p_start = slist_next_get(p_head,p_start);
}
}
//***********************回调函数 节点处理函数****************************//
int node_process_int(void *p_arg, slist_node_t *p_node)
{
printf("%d\r\n",((slist_init_t *)p_node)->data);
}
slist.h
#ifndef _INCLUDE_H
#define _INCLUDE_H
#include "stdio.h"
//定义一个学生类型结构体
typedef struct _student{
char name[10];
char sex;
float height,weight;
}student_t;
//为什么要定义void * 节省了空间 链表只占4个字节 使用的时候强制转化即可
typedef int element_type_t;
//单独链表
typedef struct _slist_node{
struct _slist_node *next;
}slist_node_t;
typedef slist_node_t slist_head_t;
//定义链表和数据相互结合
typedef struct _slist_init{
slist_node_t node;
element_type_t data;
}slist_init_t;
int slist_add_end(slist_node_t *p_head, slist_node_t *p_node);
slist_node_t *slist_begin_get (slist_head_t *p_head);//获取开始位置,第一个用户节点
slist_node_t *slist_next_get (slist_head_t *p_head, slist_node_t *p_pos); //获取某个节点的后一个位置
slist_node_t *slist_end_get (slist_head_t *p_head);//结束位置。尾节点下一个节点的位置
int slist_init(slist_head_t *p_head);
//****************************************************************
//对每个节点的使用
typedef int (*slist_node_process_t) (void *p_arg, slist_node_t *p_node);
//用户使用API
int slist_foreach(slist_head_t *p_head, slist_node_process_t pfn_node_process, void *p_arg);
int node_process_int(void *p_arg, slist_node_t *p_node);
#endif // !_INCLUDE_H
第八版:可用版-进一步抽象(静态方法)
main.c
#include "dlist.h"
int main(int argc, char **argv)
{
slist_node_t p_head ;
slist_init_t node1,node2,node3;
slist_init(&p_head);
node1.data = 1;
slist_add_head(&p_head, &node1.node);
node2.data = 2;
slist_add_head(&p_head, &node2.node);
node3.data = 3;
slist_add_tail(&p_head, &node3.node);
slist_foreach(&p_head,node_process_int,NULL);
slist_del(&p_head, &node3.node);
slist_foreach(&p_head,node_process_int,NULL);
}
slist.c
#include "dlist.h"
int slist_init(slist_head_t *p_head)
{
if(p_head == NULL){
return -1;
}
p_head->next = NULL;
return 0;
}
slist_node_t *slist_begin_get (slist_head_t *p_head)
{
return slist_next_get(p_head,p_head);
}
slist_node_t *slist_prev_get (slist_head_t *p_head, slist_node_t *p_current)
{
slist_node_t *p_temp = p_head;
while((p_temp!=NULL) && (p_temp->next!=p_current))
{
p_temp = p_temp->next;
}
return p_temp;
}
slist_node_t *slist_next_get (slist_head_t *p_head, slist_node_t *p_current)
{
if(p_current){
return p_current->next;
}
return NULL;
}
slist_node_t *slist_tail_get (slist_head_t *p_head)
{
return slist_prev_get(p_head, NULL);
}
slist_node_t *slist_end_get (slist_head_t *p_head)
{
return NULL;
}
int slist_add (slist_head_t *p_head, slist_node_t *p_current, slist_node_t *p_node_new)
{
p_node_new->next= p_current->next;
p_current->next = p_node_new;
return 0;
}
int slist_add_tail(slist_head_t *p_head, slist_node_t *p_node)
{
//先找到节点的尾部然后在尾部添加新节点
slist_node_t *p_temp = slist_tail_get(p_head);
return slist_add(p_head,p_temp,p_node);
}
int slist_add_head(slist_head_t *p_head, slist_node_t *p_node)
{
return slist_add(p_head, p_head, p_node); // 添加头文件之后
}
int slist_del(slist_head_t *p_head, slist_node_t *p_current)
{
slist_node_t *p_prev = slist_prev_get(p_head,p_current);
if(p_prev){
p_prev->next = p_current->next;
p_current->next = NULL;
return 0;
}
return -1;
}
int slist_foreach(slist_head_t *p_head, slist_node_process_t pfn_node_process, void *p_arg)
{
slist_node_t *p_start;
slist_node_t *p_end;
int ret;
if((p_head == NULL)||(pfn_node_process == NULL))
return -1;
p_start = slist_begin_get(p_head);
p_end = slist_end_get(p_head);
while(p_start != p_end)
{
ret = pfn_node_process(p_arg, p_start);
if(ret<0) return -1;
p_start = slist_next_get(p_head,p_start);
}
printf("------end--------\r\n");
return 0;
}
//***********************回调函数 节点处理函数****************************//
int node_process_int(void *p_arg, slist_node_t *p_node)
{
printf("%d\r\n",((slist_init_t *)p_node)->data);
return 0;
}
slist.h
#ifndef _INCLUDE_H
#define _INCLUDE_H
#include "stdio.h"
//定义一个学生类型结构体
typedef struct _student{
char name[10];
char sex;
float height,weight;
}student_t;
//为什么要定义void * 节省了空间 链表只占4个字节 使用的时候强制转化即可
typedef int element_type_t;
//单独链表
typedef struct _slist_node{
struct _slist_node *next;
}slist_node_t;
typedef slist_node_t slist_head_t;
//定义链表和数据相互结合
typedef struct _slist_init{
slist_node_t node;
element_type_t data;
}slist_init_t;
int slist_add (slist_head_t *p_head, slist_node_t *p_current, slist_node_t *p_node_new); //把new添加到当前之后
int slist_add_tail(slist_head_t *p_head, slist_node_t *p_node);
int slist_add_head(slist_head_t *p_head, slist_node_t *p_node);
slist_node_t *slist_begin_get (slist_head_t *p_head);//获取开始位置,第一个用户节点
slist_node_t *slist_next_get (slist_head_t *p_head, slist_node_t *p_current); //获取某个节点的后一个位置
slist_node_t *slist_prev_get (slist_head_t *p_head, slist_node_t *p_current);
slist_node_t *slist_tail_get (slist_head_t *p_head);
slist_node_t *slist_end_get (slist_head_t *p_head);//结束位置。尾节点下一个节点的位置
int slist_init(slist_head_t *p_head);
int slist_del(slist_head_t *p_head, slist_node_t *p_current);//删除当前指针
//****************************************************************
//对每个节点的使用
typedef int (*slist_node_process_t) (void *p_arg, slist_node_t *p_node);
//用户使用API
int slist_foreach(slist_head_t *p_head, slist_node_process_t pfn_node_process, void *p_arg);
int node_process_int(void *p_arg, slist_node_t *p_node);
#endif // !_INCLUDE_H
第九版:可用版-进一步抽象(动态内存 malloc)修改节点添加函数
main.c
#include "dlist.h"
int main(int argc, char **argv)
{
slist_head_t *p_head = (slist_head_t *)malloc(sizeof(slist_head_t));
slist_init(p_head);
my_list_add(p_head, 1);
my_list_add(p_head, 2);
my_list_add(p_head, 3);
slist_foreach(p_head, node_process_int, NULL);
my_list_del(p_head, 1);
my_list_del(p_head, 2);
my_list_del(p_head, 3);
free(p_head);
}
slist.c
#include "dlist.h"
int slist_init(slist_head_t *p_head)
{
if(p_head == NULL){
return -1;
}
p_head->next = NULL;
return 0;
}
slist_node_t *slist_begin_get (slist_head_t *p_head)
{
return slist_next_get(p_head,p_head);
}
slist_node_t *slist_prev_get (slist_head_t *p_head, slist_node_t *p_current)
{
slist_node_t *p_temp = p_head;
while((p_temp!=NULL) && (p_temp->next!=p_current))
{
p_temp = p_temp->next;
}
return p_temp;
}
slist_node_t *slist_next_get (slist_head_t *p_head, slist_node_t *p_current)
{
if(p_current){
return p_current->next;
}
return NULL;
}
slist_node_t *slist_tail_get (slist_head_t *p_head)
{
return slist_prev_get(p_head, NULL);
}
slist_node_t *slist_end_get (slist_head_t *p_head)
{
return NULL;
}
int slist_add (slist_head_t *p_head, slist_node_t *p_current, slist_node_t *p_node_new)
{
p_node_new->next= p_current->next;
p_current->next = p_node_new;
return 0;
}
int slist_add_end(slist_head_t *p_head, slist_node_t *p_node)
{
//先找到节点的尾部然后在尾部添加新节点
slist_node_t *p_temp = slist_tail_get(p_head);
return slist_add(p_head,p_temp,p_node);
}
int slist_add_head(slist_head_t *p_head, slist_node_t *p_node)
{
return slist_add(p_head, p_head, p_node); // 添加头文件之后
}
int slist_del(slist_head_t *p_head, slist_node_t *p_current)
{
slist_node_t *p_prev = slist_prev_get(p_head,p_current);
if(p_prev){
p_prev->next = p_current->next;
p_current->next = NULL;
return 0;
}
return -1;
}
int slist_foreach(slist_head_t *p_head, slist_node_process_t pfn_node_process, void *p_arg)
{
slist_node_t *p_start;
slist_node_t *p_end;
int ret;
if((p_head == NULL)||(pfn_node_process == NULL))
return -1;
p_start = slist_begin_get(p_head);
p_end = slist_end_get(p_head);
while(p_start != p_end)
{
ret = pfn_node_process(p_arg, p_start);
if(ret<0) return -1;
p_start = slist_next_get(p_head,p_start);
}
return 0;
}
//***********************回调函数 节点处理函数****************************//
int node_process_int(void *p_arg, slist_node_t *p_node)
{
printf("%d\r\n",((slist_init_t *)p_node)->data);
return 0;
}
//动态内存分配 用户只要将数据data和头结点给函数就OK
int my_list_add(slist_head_t *p_head, int data)
{
slist_init_t *p_node = (slist_init_t *)malloc(sizeof(slist_init_t));
if(p_node == NULL){
printf("malloc data fail");
return -1;
}
p_node->data = data;
slist_add_head(p_head,&(p_node->node));
return 0;
}
int my_list_del (slist_head_t *p_head, int data)
{
slist_node_t *p_start;
slist_node_t *p_end;
p_start = slist_begin_get(p_head);
p_end = slist_end_get(p_head);
while(p_start!=p_end)
{
if (((slist_init_t *)p_start)->data == data){
printf("find the delet data = %d\r\n",((slist_init_t *)p_start)->data);
slist_del(p_head,p_start);
free(p_start);
break;
}
p_start = slist_next_get(p_head,p_start);
}
slist_foreach(p_head,node_process_int,NULL);
return 0;
}
slist.h
#ifndef _INCLUDE_H
#define _INCLUDE_H
#include "stdio.h"
#include <malloc.h>
//定义一个学生类型结构体
typedef struct _student{
char name[10];
char sex;
float height,weight;
}student_t;
//为什么要定义void * 节省了空间 链表只占4个字节 使用的时候强制转化即可
typedef int element_type_t;
//单独链表
typedef struct _slist_node{
struct _slist_node *next;
}slist_node_t;
typedef slist_node_t slist_head_t;
//定义链表和数据相互结合
typedef struct _slist_init{
slist_node_t node;
element_type_t data;
}slist_init_t;
int slist_add (slist_head_t *p_head, slist_node_t *p_current, slist_node_t *p_node_new); //把new添加到当前之后
int slist_add_end(slist_node_t *p_head, slist_node_t *p_node);
int slist_add_head(slist_head_t *p_head, slist_node_t *p_node);
slist_node_t *slist_begin_get (slist_head_t *p_head);//获取开始位置,第一个用户节点
slist_node_t *slist_next_get (slist_head_t *p_head, slist_node_t *p_current); //获取某个节点的后一个位置
slist_node_t *slist_prev_get (slist_head_t *p_head, slist_node_t *p_current);
slist_node_t *slist_tail_get (slist_head_t *p_head);
slist_node_t *slist_end_get (slist_head_t *p_head);//结束位置。尾节点下一个节点的位置
int slist_init(slist_head_t *p_head);
int slist_del(slist_head_t *p_head, slist_node_t *p_current);//删除当前指针
//****************************************************************
//对每个节点的使用
typedef int (*slist_node_process_t) (void *p_arg, slist_node_t *p_node);
//-----------------------
int slist_foreach(slist_head_t *p_head, slist_node_process_t pfn_node_process, void *p_arg);
int node_process_int(void *p_arg, slist_node_t *p_node);
//-------------提供给用户使用 动态分配内存-----------------
int my_list_add(slist_head_t *p_head, int data);
int my_list_del (slist_head_t *p_head, int data);
#endif // !_INCLUDE_H
第10版:案例–数据处理使用学生结构
main.c
#include "slist.h"
int main(int argc, char **argv)
{
slist_head_t p_head;
slist_student_t s1, s2, s3, s4, s5;
student_info_read(&s1.data);
student_info_read(&s2.data);
student_info_read(&s3.data);
student_info_read(&s4.data);
student_info_read(&s5.data);
slist_add_head(&p_head, &s1.node);
slist_add_head(&p_head, &s2.node);
slist_add_head(&p_head, &s3.node);
slist_add_head(&p_head, &s4.node);
slist_add_head(&p_head, &s5.node);
slist_foreach(&p_head, list_process_student, NULL);
}
slist.c
#include "slist.h"
int slist_init(slist_head_t *p_head)
{
if(p_head == NULL){
return -1;
}
p_head->next = NULL;
return 0;
}
slist_node_t *slist_begin_get (slist_head_t *p_head)
{
return slist_next_get(p_head,p_head);
}
slist_node_t *slist_prev_get (slist_head_t *p_head, slist_node_t *p_current)
{
slist_node_t *p_temp = p_head;
while((p_temp!=NULL) && (p_temp->next!=p_current))
{
p_temp = p_temp->next;
}
return p_temp;
}
slist_node_t *slist_next_get (slist_head_t *p_head, slist_node_t *p_current)
{
if(p_current){
return p_current->next;
}
return NULL;
}
slist_node_t *slist_end_get (slist_head_t *p_head)
{
return slist_prev_get(p_head, NULL);
// return NULL;
}
int slist_add (slist_head_t *p_head, slist_node_t *p_current, slist_node_t *p_node_new)
{
p_node_new->next= p_current->next;
p_current->next = p_node_new;
return 0;
}
int slist_add_end(slist_head_t *p_head, slist_node_t *p_node)
{
//先找到节点的尾部然后在尾部添加新节点
slist_node_t *p_temp = slist_end_get(p_head);
return slist_add(p_head,p_temp,p_node);
}
int slist_add_head(slist_head_t *p_head, slist_node_t *p_node)
{
return slist_add(p_head, p_head, p_node); // 添加头文件之后
}
int slist_del(slist_head_t *p_head, slist_node_t *p_current)
{
slist_node_t *p_prev = slist_prev_get(p_head,p_current);
if(p_prev){
p_prev->next = p_current->next;
p_current->next = NULL;
return 0;
}
return -1;
}
int slist_foreach(slist_head_t *p_head, slist_node_process_t pfn_node_process, void *p_arg)
{
slist_node_t *p_start;
slist_node_t *p_end;
int ret;
if((p_head == NULL)||(pfn_node_process == NULL))
return -1;
p_start = slist_begin_get(p_head);
p_end = slist_end_get(p_head);
while(p_start != p_end)
{
ret = pfn_node_process(p_arg, p_start);
if(ret<0) return -1;
p_start = slist_next_get(p_head,p_start);
}
return 0;
}
//***********************回调函数 节点处理函数****************************//
int node_process_int(void *p_arg, slist_node_t *p_node)
{
printf("%d\r\n",((slist_init_t *)p_node)->data);
return 0;
}
int list_process_student(void *p_arg, slist_node_t *p_node)
{
student_t *p_s = &(((slist_student_t *)p_node)->data);
printf("%s : %c %.2f %.2f\n", p_s->name, p_s->sex, p_s->height, p_s->weight);
return 0;
}
//动态内存分配 用户只要将数据data和头结点给函数就OK
int my_list_add(slist_head_t *p_head, int data)
{
slist_init_t *p_node = (slist_init_t *)malloc(sizeof(slist_init_t));
if(p_node == NULL){
printf("malloc data fail");
return -1;
}
p_node->data = data;
slist_add_head(p_head,&(p_node->node));
return 0;
}
int my_list_del(slist_head_t *p_head, int data)
{
slist_node_t *p_start;
slist_node_t *p_end;
p_start = slist_begin_get(p_head);
p_end = slist_end_get(p_head);
while(p_start!=p_end->next)
{
if (((slist_init_t *)p_start)->data == data){
printf("find the delet data = %d\r\n",((slist_init_t *)p_start)->data);
slist_del(p_head,p_start);
free(p_start);
break;
}
p_start = slist_next_get(p_head,p_start);
}
slist_foreach(p_head,node_process_int,NULL);
return 0;
}
int student_info_read (student_t *p_student)
{
int i;
for (i = 0; i < 9; i++) {
p_student->name[i] = (rand() % ('z' - 'a')) + 'a';
}
p_student->name[i]= '\0';
p_student->sex = (rand() & 0x01) ? 'F' : 'M';
p_student->height = (float)rand() / rand();
p_student->weight = (float)rand() / rand();
return 0;
}
slist.h
#ifndef _INCLUDE_H
#define _INCLUDE_H
#include "stdio.h"
#include <malloc.h>
#include <stdlib.h>
//定义一个学生类型结构体
typedef struct _student{
char name[10];
char sex;
float height,weight;
}student_t;
//单独链表
typedef struct _slist_node{
struct _slist_node *next;
}slist_node_t;
typedef slist_node_t slist_head_t;
//定义链表和数据相互结合
//案例说明 数据处理为int
//案例说明 数据处理为 student_t
typedef int element_type_t;
typedef student_t element_student_t;
//案例一 int 类型
typedef struct _slist_init{
slist_node_t node;
element_type_t data;
}slist_init_t;
//案例一 student 类型
typedef struct _slist_init_student{
slist_node_t node;
element_student_t data;
}slist_student_t;
int slist_add (slist_head_t *p_head, slist_node_t *p_current, slist_node_t *p_node_new); //把new添加到当前之后
int slist_add_end(slist_node_t *p_head, slist_node_t *p_node);
int slist_add_head(slist_head_t *p_head, slist_node_t *p_node);
slist_node_t *slist_begin_get (slist_head_t *p_head);//获取开始位置,第一个用户节点
slist_node_t *slist_next_get (slist_head_t *p_head, slist_node_t *p_current); //获取某个节点的后一个位置
slist_node_t *slist_prev_get (slist_head_t *p_head, slist_node_t *p_current);
slist_node_t *slist_end_get (slist_head_t *p_head);//结束位置。尾节点下一个节点的位置
int slist_init(slist_head_t *p_head);
int slist_del(slist_head_t *p_head, slist_node_t *p_current);//删除当前指针
//****************************************************************
//对每个节点的使用
typedef int (*slist_node_process_t) (void *p_arg, slist_node_t *p_node);
//-----------------------
int slist_foreach(slist_head_t *p_head, slist_node_process_t pfn_node_process, void *p_arg);
int node_process_int(void *p_arg, slist_node_t *p_node); //int 类型数据处理
int list_process_student(void *p_arg, slist_node_t *p_node); //student 类型数据处理
//-------------提供给用户使用 动态分配内存-----------------
int my_list_add(slist_head_t *p_head, int data);
int my_list_del (slist_head_t *p_head, int data);
int student_info_read (student_t *p_student);
#endif // !_INCLUDE_H