企业级链表设计思路

在这里插入图片描述

注意插入和删除的时候的pos

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//节点结构体
struct LinkNode {
    
    
	LinkNode* next;//指针域
};
//链表结构体
struct LList {
    
    
	LinkNode pHeader;//头节点结构体
	int size;//链表长度
};
//取个别名
typedef  void* LinkList;
//链表的初始化:返回链表结构体
LinkList init_LinkList()
{
    
    
	struct LList* mylist = (LList*)malloc(sizeof(LList));
	if (mylist == NULL)
		return NULL;
	mylist->pHeader.next = NULL;
	mylist->size = 0;
	return mylist;
}
//插入  
//第一个参数相当于void* list,这样用户就无法修改堆区结构体数据
//这边如果不用两个指针一前一后移动来插入,要注意curNode指针的移动位置,不要让其移到空位
void insert_LinkList(LinkList list,int pos,void* data)
{
    
    
	if (list == NULL)
		return;
	struct LList* mylist = (LList*)list;
	if (pos<0 || pos>mylist->size)
	{
    
    
		//尾插
		pos = mylist->size;
	}
	//指向当前节点
	LinkNode* curNode = &mylist->pHeader;
	//将curNode移到要插入位置的前驱节点
	for(int i = 0; i < pos; i++)
	{
    
    
		curNode = curNode->next;
	}
	//找到位置后,进行插入操作
	//将newNode指针指向用户传入的结构体首地址,获取前四个字节的数据
	struct LinkNode* newNode = (LinkNode*)data;
	newNode->next = NULL;

	newNode->next = curNode->next;
	curNode->next = newNode;
	//更新链表长度
	mylist->size++;
}
//遍历链表
void foreach_LinkList(LinkList list,void(*print)(void*))
{
    
    
	if (list == NULL)
		return;
	if (print == NULL)
		return;
	LList* mylist = (LList*)list;
	//指向当前节点
	LinkNode* curNode = mylist->pHeader.next;
	while (curNode)
	{
    
    
		//这里传入当前要打印的节点,传入的是一个指针指向在堆区开辟的结构体前四个字节,步长为4
		//用户通过自己写打印函数,将步长变为要打印的结构体步长
		print(curNode);
		curNode = curNode->next;
	}
}
//删除指定位置的节点----有效数据下标从0开始
void del_LinkList(LinkList mylist, int pos)
{
    
    
	if (mylist == NULL)
		return;
	LList* list = (LList*)mylist;
	if (pos<0 || pos>=list->size)
		return;
	//当前节点
	LinkNode* curNode = &list->pHeader;
	//将curNode移到要删除位置的前驱节点
	for (int i = 0; i <pos; i++)
	{
    
    
		curNode = curNode->next;
	}
	//记录待删除的节点
	LinkNode* delNode = curNode->next;
	curNode->next = delNode->next;

	//free(delNode); 数据是用户取管理释放,因为不知道是开辟在栈区还是堆区
	//delNode->next = NULL;
	//更新链表长度
	list->size--;
}
//按照值来删除
void del_LinkList(LinkList mylist,void* data,int(*compare)(void*,void*))
{
    
    
	if (mylist == NULL)
		return;
	if (data == NULL)
		return;
	LList* list =(LList*)mylist;
	//当前节点
	LinkNode* curNode = &list->pHeader;
	for (int i = 0; i < list->size; i++)
	{
    
    
		curNode = curNode->next;
		if (compare(curNode, data))
		{
    
    
			del_LinkList(list, i);
		}
	}
}
//清空链表
void clear_List(LinkList list)
{
    
    
	if (list == NULL)
		return;
	LList* mylist = (LList*)list;
	当前节点
	//LinkNode* curNode = &mylist->pHeader;
	//while (curNode)
	//{
    
    
	//	curNode = curNode->next;
	//	//保存住下一个节点的位置
	//	LinkNode* nextNode = curNode->next;
	//	//free(curNode);数据是用户取管理释放,因为不知道是开辟在栈区还是堆区
	//	curNode = nextNode;
	//}
	mylist->pHeader.next = NULL;
	mylist->size = 0;
}
//返回链表的长度
int size_List(LinkList list)
{
    
    
	if (list == NULL)
		return NULL;
	LList* mylist = (LList*)list;
	return mylist->size;
}
//销毁链表
void destory_List(LinkList list)
{
    
    
	if (list == NULL)
		return;
	free(list);
	list == NULL;
}
struct person 
{
    
    
	void* data;
	char name[32];
	int age;
};
void print(void* val)
{
    
    
	person* p = (person*)val;
	printf("姓名:%s\t年龄:%d\n", p->name, p->age);
}
int compare(void* v1, void* v2)
{
    
    
	person* p1 = (person*)v1;
	person* p2 = (person*)v2;
	if (p1->age == p2->age && strcmp(p1->name, p2->name)==0)
	{
    
    
		return 1;
	}
	return 0;
}

int main()
{
    
    
	//用户只能在main函数里面拿到一个void*指针,该指针指向堆区开辟的链表结构体
	//但用户无法知晓void*指向的堆区开辟内存里面存放的数据类型,也就无法通过强制类型转换对堆区的链表结构体数据进行修改
	LinkList list = init_LinkList();
	person p1 = {
    
     NULL,"大忽悠",19 };
	person p2 = {
    
     NULL,"like",18 };
	person p3 = {
    
     NULL,"小朋友",19 };
	insert_LinkList(list, 0,&p1);
	insert_LinkList(list, -1, &p2);
	insert_LinkList(list, 10, &p3);
	printf("打印链表结果如下:\n");
	foreach_LinkList(list, print);
	printf("\n按位置删除链表后:\n");
	del_LinkList(list,2);
	foreach_LinkList(list, print);
	printf("\n按值删除链表后:\n");
	del_LinkList(list, &p1, compare);
	foreach_LinkList(list, print);
	printf("\n链表的长度:%d\n", size_List(list));
	clear_List(list);
	printf("清空链表结果如下:\n");
	foreach_LinkList(list, print);
	printf("\n链表的长度:%d\n", size_List(list));
	destory_List(list);
	printf("\n链表的长度:%d\n", size_List(list));
	return 0;
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_53157173/article/details/114251287