带头节点的双向循环链表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

posted @ 2022-10-08 22:50  轩邈、  阅读(25)  评论(0编辑  收藏  举报