企业链表的实现

作用

实际的数据类型链表 相分离,实现 实际的数据类型链表 的解耦。

介绍

    如果我们使用原始的C语言写链表的话,数据类型是被固定死的,如果业务换了 需要另一种数据类型,我们又得重新在写一个链表,这是十分“恶心”的!因此引出了本文的企业链表。

在这里插入图片描述

CompanyLinkList.h

#pragma once
#ifndef __COMPANY_LINKLIST_H__
#define __COMPANY_LINKLIST_H__

typedef enum { TRUE, FASLE } BOOLEAN;//成功状态 FALSE 不成功 TRUE成功
typedef enum { ERROR, OK } STATUS;	//状态信息 ERROR 发生错误 OK 一切正常

typedef struct LinkNode
{
	struct LinkNode* next;
}LinkNode;

typedef struct LinkList
{
	LinkNode head;
	int size;
}LinkList;

//创建链表并初始化
LinkList* Create_LinkList();

//插入数据 根据位置插入
int Insert_LinkList(LinkList* list, int pos, LinkNode* data);

//删除数据 根据位置删除
int Remove_LinkList(LinkList* list, int pos);

//查找数据,根据数据内容
int Find_LinkList(LinkList* list, LinkNode* data, int(*Compare_Function)(LinkNode*, LinkNode*));

//遍历链表
int Foreach_LinkList(LinkList* list, void(*Foreach_Function)(LinkNode*));

//清空数据 链表仍然可用
int Clear_LinkList(LinkList* list);

//销毁链表 链表不可用
int Destroy_LinkList(LinkList* list);


#endif // !__COMPANY_LINKLIST_H__

CompanyLinkList.c

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "CompanyLinkList.h"

//创建链表并初始化
LinkList* Create_LinkList()
{
	LinkList* list = (LinkList*)malloc(sizeof(LinkList));
	list->size = 0;
	list->head.next = NULL;
	return list;
}

//插入结点数据的地址 根据位置插入,pos从1开始
int Insert_LinkList(LinkList* list, int pos, LinkNode* data)
{
	if (NULL == list || NULL == data)
	{
		return ERROR;
	}
	//位置太小插入到第一个位置
	if (pos < 1)
	{
		pos = 1;
	}
	//位置太大插入到 尾部
	if (pos > list->size)
	{
		pos = list->size + 1;
	}
	//找到插入位置的前驱结点
	LinkNode* pre = &list->head;
	for (int i = 1; i < pos; i++)
	{
		pre = pre->next;
	}
	data->next = pre->next;
	pre->next = data;
	list->size++;
	return OK;
}

//删除数据 根据位置删除 pos 从1 开始
int Remove_LinkList(LinkList* list, int pos)
{
	//list为NULL 或者 位置非法, 直接返回
	if (NULL == list || pos < 1 || pos > list->size)
	{
		return ERROR;
	}
	LinkNode* pre = &list->head;
	//同样找到删除结点的前驱
	for (int i = 1; i < pos; i++)
	{
		pre = pre->next;
	}
	//删除节点
	//注意:我们不释放被删除节点的内存,被删除节点的内存由用户释放
	pre->next = pre->next->next;
	list->size--;
	return OK;
}

//查找数据,根据数据内容,返回是链表中的第几个元素,从1开始计数 ,没找到返回-1
//Compare_Function 用户提供 结点元素比较的回调函数
int Find_LinkList(LinkList* list, LinkNode* data, int(*Compare_Function)(LinkNode*, LinkNode*))
{
	if (NULL == list || NULL == data || NULL == Compare_Function)
	{
		return ERROR;
	}
	LinkNode* node = list->head.next;
	int flag = 0;// 是否查找到的标志
	int index = 1;
	while (node != NULL)
	{
		if (Compare_Function(node, data))
		{
			flag = 1;
			break;
		}
		node = node->next;
		index++;
	}
	return flag ? index : -1;
}

//遍历链表
//Foreach_Function 用户提供的遍历链表元素的回调函数
int Foreach_LinkList(LinkList* list, void(*Foreach_Function)(LinkNode*))
{
	if (NULL == list || NULL == Foreach_Function)
	{
		return ERROR;
	}
	LinkNode* node = list->head.next;
	while (NULL != node)
	{
		Foreach_Function(node);
		node = node->next;
	}
	return OK;
}

//清空数据 链表仍然可用
int Clear_LinkList(LinkList* list)
{
	if (NULL == list)
	{
		return ERROR;
	}
	list->size = 0;
	list->head.next = NULL;
	return OK;
}

//销毁链表 链表不可用
int Destroy_LinkList(LinkList* list)
{
	if (NULL == list)
	{
		return ERROR;
	}
	free(list);
	list = NULL;
	return OK;
}

main.cpp 企业链表的使用

#include"CompanyLinkList.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//用户使用企业级链表,只需要在自己定义的类型中将LinkNode 作为第一个成员即可使用
//这样就将 具体的业务和底层链表算法 进行分离了
typedef struct Student
{
	LinkNode node;  //第一个元素,必须是LinkNode
	char name[64];
	int age;
}Student;
//用户定义遍历的回调函数
void Print_Student(LinkNode* node)
{
	Student* stu = (Student*)node; //将LinkNode*强转为Student*
	printf("姓名:%s,年龄%d\n", stu->name, stu->age);
	return;
}
//用户定义结点的比较回调函数
int Compare_Student(LinkNode* node1, LinkNode* node2)
{
	Student* stu1 = (Student*)node1;
	Student* stu2 = (Student*)node2;
	//年龄和名字相同才相同
	if (stu1->age == stu2->age && 0 == strcmp(stu1->name, stu2->name))
	{
		return 1;
	}
	return 0;
}

int main(int argc, char *argv[])
{
	Student s1, s2, s3, s4, s5;
	s1.age = 11; strcpy(s1.name, "aaa");
	s2.age = 12; strcpy(s2.name, "bbb");
	s3.age = 13; strcpy(s3.name, "ccc");
	s4.age = 14; strcpy(s4.name, "ddd");
	s5.age = 15; strcpy(s5.name, "eee");
	
	//创建链表
	LinkList* list = Create_LinkList();

	//插入
	Insert_LinkList(list, 1, (LinkNode*)&s1);
	Insert_LinkList(list, 2, (LinkNode*)&s2);
	Insert_LinkList(list, 3, (LinkNode*)&s3);
	Insert_LinkList(list, 4, (LinkNode*)&s4);
	Insert_LinkList(list, 5, (LinkNode*)&s5);

	printf("插入5条数据后遍历:\n");
	Foreach_LinkList(list, Print_Student);

	//查找
	Student s6; 
	s6.age = 15; strcpy(s6.name, "eee");
	int index = Find_LinkList(list, (LinkNode*)&s6, Compare_Student);
	printf("查找的元素name=eee,age=15,是链表中第%d个元素\n", index);

	//删除元素
	Remove_LinkList(list, 1);

	printf("删除第1个结点后遍历:\n");
	Foreach_LinkList(list, Print_Student);

	system("pause");
	return 0;
}
  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值