带头节点的双向循环链表part2(李慧芹视频案例)
视频链接:https://www.bilibili.com/video/BV18p4y167Md?p=89&vd_source=a65c3b45fdf7ce45d3ec6422024bc43c
2、链表上添加节点,遍历节点和查找节点的函数(主要通过回调函数实现遍历节点和查找节点的功能)
① 遍历节点的回调函数涉及:
因为不需要返回值,所以在llist.h中我们的llist_callback数据类型设置为void类型,保证数据类型通用性,设置形参为const void*
typedef void llist_callback(const void *)
llist.h中声明查找函数
void llist_display(LIST_HEAD_S *llist,llist_callback *print_Func)
main.c中定义void print_s(const void * score)函数,然后在ist_display(llist,print_s)中将print_s函数传递进llist.c中,并且在llist.c函数中调用print_Func这个函数
main.c文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "llist.h"
#define NAMESIZE 32
void print_s(const void* score);
void idfind_Func(const void* score, int* stuID);
/* 声明普通节点下面挂的数据结构 */
typedef struct llist_score_s
{
int stuID;
char name[NAMESIZE];
int math;
}LLIST_SCORE_S;
int main()
{
/* 声明双向链表 */
LLIST_HEAD_S* llist = NULL;
/* 创建带头结点双向链表llist */
llist = llist_create(sizeof(LLIST_SCORE_S));
/* 在链表上添加节点 */
LLIST_SCORE_S student_A = {20221008,"Lihua",98};
llist_insert(llist, &student_A);
/* 遍历链表 */
llist_display(llist,print_s);
/* 查找节点 */
int stuID = 20221008;
llist_find(llist,idfind_Func,&stuID);
/* 删除链表 */
llist_destroy(llist);
return 0;
}
void print_s(const void * score)
{
const LLIST_SCORE_S* temp = (LLIST_SCORE_S *) score;
printf("学生的学号是%d,姓名是%s,数学成绩是%d\n",temp->stuID,temp->name,temp->math);
}
void idfind_Func(const void *score,int *stuID)
{
const LLIST_SCORE_S* temp = (LLIST_SCORE_S*)score;
if (temp->stuID == *stuID)
printf("找到了学号为%d的学生,学生姓名为%s,学生数学成绩为%d\n", temp->stuID,temp->name,temp->math);
}
llist.c文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "llist.h"
/* ① 定义创建链表的函数 */
LLIST_HEAD_S* llist_create(int initsize)
{
LLIST_HEAD_S* llist = NULL;
llist = (LLIST_HEAD_S*)malloc(sizeof(*llist));
if (NULL == llist)
return NULL;
llist->size = initsize;
llist->head.data = NULL;
llist->head.prev = &llist->head;
llist->head.next = &llist->head;
return llist;
}
/* ② 定义删除链表的函数 */
void llist_destroy(LLIST_HEAD_S* llist)
{
LLIST_NODE_S* curnode;
LLIST_NODE_S* next = NULL;
for (curnode = llist->head.next; curnode != &llist->head; curnode = next)
{
next = curnode->next;
free(curnode->data);
free(curnode);
}
free(llist);
}
/* ③ 定义链表添加节点的函数 */
int llist_insert(LLIST_HEAD_S* llist,void * data)
{
LLIST_NODE_S* newnode;
newnode = (LLIST_NODE_S *)malloc(sizeof(*newnode));
if (NULL == newnode)
return -1;
newnode->data = malloc(llist->size);
if (NULL == newnode->data)
return -2;
memcpy(newnode->data, data, llist->size);
/* 以首部插入方式 */
newnode->next = llist->head.next;
newnode->prev = &llist->head;
newnode->prev->next = newnode;
newnode->next->prev = newnode;
return 0;
}
/* ④ 定义遍历链表节点的函数 */
void llist_display(LLIST_HEAD_S* llist, llist_callback* print_Func)
{
LLIST_NODE_S* curnode;
for (curnode = llist->head.next; &llist->head != curnode; curnode = curnode->next)
{
print_Func(curnode->data);
}
}
/* ⑤ 定义查找节点的函数 */
void llist_find(LLIST_HEAD_S* llist, llist_idfind* idfind_Func,int *stuID)
{
LLIST_NODE_S* curnode;
for (curnode = llist->head.next; &llist->head != curnode; curnode = curnode->next)
{
idfind_Func(curnode->data,stuID);
}
}
llist.h文件
#ifndef LLIST_H_
#define LLIST_H_
typedef void llist_callback(const void*);
typedef void llist_idfind(const void*,int* stuID);
/* 定义普通节点的类型 */
typedef struct llist_node_s
{
void* data;
struct llist_node_s* prev;
struct llist_node_s* next;
}LLIST_NODE_S;
/* 定义头节点的类型 */
typedef struct llist_head_s
{
int size;
LLIST_NODE_S head;
}LLIST_HEAD_S;
/* ① 声明创建链表的函数,本质是创建头节点 */
LLIST_HEAD_S* llist_create(int initsize);
/* ② 声明删除链表的函数 */
void llist_destroy(LLIST_HEAD_S * llist);
/* ③ 声明添加节点的函数 */
int llist_insert(LLIST_HEAD_S *llist,void *data);
/* ④ 声明遍历链表节点的函数 */
void llist_display(LLIST_HEAD_S *llist, llist_callback* print_Func);
/* ⑤ 声明通过学号查找节点的函数 */
void llist_find(LLIST_HEAD_S *llist,llist_idfind *idfind_Func, int* stuID);
#endif