如何开发一个通用型的链表c/c++(数据结构算法)

本文介绍了如何在C++中使用C语言编写的链表库,包括通用链表设计、节点结构、初始化、插入、删除、获取长度、打印和查找等算法,并提供了一个完整的代码示例。通过理解跨语言接口和C++扩展,读者将掌握链表操作的基础和扩展能力。
摘要由CSDN通过智能技术生成

     首先,我是用的c语言来实现这个链表,因为c++中本来就有许多强大的库函数,有相应的接口直接调用就行(list容器),不需要敲这些繁琐的代码。但是计算语言的的学习,是要自己动手敲一些数据结构和算法,才能更加透彻的理解和驾驭项目开发的过程。才能走得更远。

1、首先,自己用C语言开发的库函数如何在c++中也能使用?

      只要在头文件中加入c++的扩展代码就行,具体如下:

#pragma once

#ifdef __cplusplus
extern"C" {
#endif

	
//在此处写c的具体实行,之后c++使用加入此头文件就能正常使用





#ifdef __cplusplus
}
#endif

2、通用链表设计

      ①链表节点设计

链表是由一个个节点组成,每个节点有一个数据域和一个指针域,要想设计的链表能够存放所有类型的数据,我们就必须用一个可以指向任何数据的的指针,所以我设计的节点的数据域是一个 void*指针(可以指向任何数据,指证域则是指向自身的指针。

    ②链表设计

链表最重要的是第一个节点,以及有多少个节点。所以链表存放的一个头节点和一个链表的大小。

#pragma once
#include<stdio.h>
#include<stdlib.h>

#ifdef __cplusplus
extern"C" {
#endif

	// 链表节点;
		typedef struct LIKNNODE {
		void* data;              //节点数据指针
		struct LIKNNODE* next;    //指向下一个节点的指针
	}LinkNode;



	//链表
	typedef struct LINKLIST {
		LinkNode* head;  //头节点;
		int size;       //链表大小
	}LinkList; 


#ifdef __cplusplus
}
#endif

3、算法需求设计。

需要实现的是算法就是以下类容,如果还需要什么功能可以自己添加。具体的实现我会根据每个需要用的功能说明。以上步骤是再头文件(LinkList.h)。具体的算法实现在包含头文件的原文件中实现。一下代码也就是整个项目的头文件。

#pragma once
#include<stdio.h>
#include<stdlib.h>

#ifdef __cplusplus
extern"C" {
#endif

	// 链表节点;
		typedef struct LIKNNODE {
		void* data;              //节点数据指针
		struct LIKNNODE* next;    //指向下一个节点的指针
	}LinkNode;



	//链表
	typedef struct LINKLIST {
		LinkNode* head;  //头节点;
		int size;       //链表大小
	}LinkList;

	

	//初始化链表
	LinkList* Init_LinkList();

	//项链表中插入一个值;
	void Insert_LinkList(LinkList*list, int pos, void *data);

	//根据位置删除链表中的值
	void Remove_LinkList(LinkList*list, int pos);

	//获得链表长度
	int Size_LinkList(LinkList*list);

	//返回一个头节点的值
	void*Front_LinkList(LinkList*list);

	//释放链表
	void Free_LinkList(LinkList*list);

	//打印链表
	
	typedef void(*PRINTLINKLIST)(void *);    //函数指针,指向一个打印方式的函数,用户自己编写。

	void Print_LinkList(LinkList*list, PRINTLINKLIST print);

	//查找
	int  Find_LinkList(LinkList*list, void *data);




#ifdef __cplusplus
}
#endif

4、算法实现。

   ①初始化链表

//初始化链表
LinkList* Init_LinkList()
{
	LinkList* list= (LinkList*)malloc (sizeof(LinkList));//在堆上开辟一个链表
	list->size = 0;

	//头节点,不保存数据
	list->head =(LinkNode*) malloc(sizeof(LinkNode));
	list->head->data = NULL;
	list->head->next = NULL;

	return list;
}

  此时链表开辟在堆区,链表这个结构体有链表大小(st->size)。还有链表的节点指针(list->head)。首先将链表的大小设置为0。链表中的有一个头节点指针,所以在堆区也需要开辟节点的空间。最后将节点初始化。返回这个链表的头节点。

    ②插入功能实现

//项链表中插入一个值;
void Insert_LinkList(LinkList*list, int pos, void *data)
{
	//判断
	if (NULL == list) { return; }
	if (NULL == data) { return; }
	//友好操作
	if (pos<0 || pos>list->size) { pos = list->size; }
	//1、创建一个新的节点
	LinkNode* newnode=(LinkNode*)malloc(sizeof(LinkNode));
	newnode->data = data;
	newnode->next = NULL;
	//创建一个赋值指针,用来找到插入的位置
	LinkNode *pCurrent = list->head;
	for (int i = 0;i < pos;++i)
	{
		pCurrent = pCurrent->next;
	}
	//将新建的节点插入链表中
	newnode->next = pCurrent->next;
	pCurrent->next = newnode;
	list->size++;
}

此功能是最重要的功能,怎么去实现呢?首先,我们要将自己的数据出入链表中,我们要有这个链表,也就是函数的第一参数(LinkList* list),作为操作对象。插入到哪个位置(int pos),插入的数据data,由于要实现通用的数据类型,所以要插入数据类型不能写死,和前边节点设计一样,只能用能指向任何数据的指针(void* data)

如何将一个数据插入到链表?(重要)

  a需要用一个辅助指针来找到需要插入的位置,指向节点,多以指针类型也是和节点的类型一样。LinkNode* pCurrent .

    创建一个赋值指针,用来找到插入的位置
    LinkNode *pCurrent = list->head;

    for (int i = 0;i < pos;++i)

{pCurrent = pCurrent->next; }

将新建的节点插入链表中
    newnode->next = pCurrent->next;
    pCurrent->next = newnode; 

 

③根据位置删除链表中的节点

根据位置删除链表中的值
void Remove_LinkList(LinkList*list, int pos)
{
	if (list == NULL) { return; }
	if (pos<0 || pos>=list->size) {
		printf("这个位置没有值\n");
		return;
	}

	//创建辅助个指针
	LinkNode* pCurrent= list->head;
	for (int i = 0;i < pos;i++)
	{
		pCurrent = pCurrent->next;
	}

	//缓存要删除的节点
	LinkNode* pDel = pCurrent->next;
	pCurrent->next = pDel->next;
	free(pDel);

	list->size--;

}

此处和上边不一样的,由于改变链表的指向之后,需要用一个节点指针去记录被删除的节点,然后释放。(LinkNode* pDel);

④释放链表

//释放链表
void Free_LinkList(LinkList*list)
{
	if (list == NULL) { return; }
	
	LinkNode* pCurrent = list->head;
	while (pCurrent != NULL)
	{
		LinkNode*freenode = pCurrent->next;

		free(pCurrent);

		pCurrent = freenode;
	}

	list->size = 0;
	free(list);
	list->head = NULL;

}

⑤打印

void Print_LinkList(LinkList*list, PRINTLINKLIST print)
{
	if (list == NULL) { return; }
	LinkNode* pCurrent = list->head->next;

	while (pCurrent != NULL)
	{
		print(pCurrent->data);
		pCurrent = pCurrent->next;
	}
}

以下是整个算法实现

#include"LinkList.h"
//打印链表函数
typedef void(*PRINTLINKLIST)(void *);
//初始化链表
LinkList* Init_LinkList()
{
	LinkList* list= (LinkList*)malloc (sizeof(LinkList));
	list->size = 0;

	//头节点,不保存数据
	list->head =(LinkNode*) malloc(sizeof(LinkNode));
	list->head->data = NULL;
	list->head->next = NULL;

	return list;
}

//项链表中插入一个值;
void Insert_LinkList(LinkList*list, int pos, void *data)
{
	//判断
	if (NULL == list) { return; }
	if (NULL == data) { return; }

	//友好操作
	if (pos<0 || pos>list->size) { pos = list->size; }

	//1、创建一个新的节点
	LinkNode* newnode=(LinkNode*)malloc(sizeof(LinkNode));
	newnode->data = data;
	newnode->next = NULL;

	//创建一个赋值指针,用来找到插入的位置
	LinkNode *pCurrent = list->head;

	for (int i = 0;i < pos;++i)
	{
		pCurrent = pCurrent->next;
	}

	//将新建的节点插入链表中
	newnode->next = pCurrent->next;
	pCurrent->next = newnode;


	list->size++;

}

//根据位置删除链表中的值
void Remove_LinkList(LinkList*list, int pos)
{
	if (list == NULL) { return; }
	if (pos<0 || pos>=list->size) {
		printf("这个位置没有值\n");
		return;
	}

	//创建辅助个指针
	LinkNode* pCurrent= list->head;
	for (int i = 0;i < pos;i++)
	{
		pCurrent = pCurrent->next;
	}

	//缓存要删除的节点
	LinkNode* pDel = pCurrent->next;
	pCurrent->next = pDel->next;
	free(pDel);

	list->size--;

}

//获得链表长度
int Size_LinkList(LinkList*list)
{
	return list->size;
}

//查找
int Find_LinkList(LinkList*list, void *data)
{

	if (list == NULL) { return -1; }
	if (data == NULL) { return -1; }
	LinkNode *pCurrent = list->head->next;
	/*for (int i = 0;i < list->size;++i)
	{
		if (pCurrent->data == data)
		{
			return i;
		}
		pCurrent = pCurrent->next;
	}*/
	int i = 0;

	while (pCurrent != NULL)
	{
		if (pCurrent->data == data)
		{
			break;
		}
		i++;
		pCurrent = pCurrent->next;
	}

	return i;
}

//返回一个头节点的值
void*Front_LinkList(LinkList*list)
{
	return list->head->next->data;
}

//释放链表
void Free_LinkList(LinkList*list)
{
	if (list == NULL) { return; }
	
	LinkNode* pCurrent = list->head;
	while (pCurrent != NULL)
	{
		LinkNode*freenode = pCurrent->next;

		free(pCurrent);

		pCurrent = freenode;
	}

	list->size = 0;
	free(list);
	list->head = NULL;

}

//打印链表
void Print_LinkList(LinkList*list, PRINTLINKLIST print)
{
	if (list == NULL) { return; }
	LinkNode* pCurrent = list->head->next;

	while (pCurrent != NULL)
	{
		print(pCurrent->data);
		pCurrent = pCurrent->next;
	}
}

5 测试

#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGES
#pragma warning(disable:4996)
#include<string>
#include<cstdlib>
#include"LinkList.h"
typedef struct PERSON {
	char name[64];
	int age;
	int score;

}person;

void print(void*data)
{
	person* p = (person *)data;

	printf("姓名:%s   年纪:%d    分数:%d\n", p->name, p->age, p->score);
	printf("\n");
}

void test02()
{
	LinkList*list = Init_LinkList();



	person p1{ "aaa",18,100 };
	person p2{ "bbb",19,98 };
	person p3{ "ccc",13,88 };
	person p4{ "ddd",15,97 };
	person p5{ "eee",17,96 };

	Insert_LinkList(list, 0, &p1);
	Insert_LinkList(list, 1, &p2);
	Insert_LinkList(list, 2, &p3);
	Insert_LinkList(list, 3, &p4);
	Insert_LinkList(list, 4, &p5);

	Print_LinkList(list, print);


	printf("--------------------------------\n");
	Remove_LinkList(list, 3);
	Print_LinkList(list, print);

	int size = Size_LinkList(list); 
	printf("链表的长度为:%d\n", size);

	int pos= Find_LinkList(list,&p5);
	printf("zai %d\n", pos);

	printf("--------------------------------\n");
	person *ret=(person*)Front_LinkList(list);
	printf("姓名:%s   年纪:%d    分数:%d\n", ret->name, ret->age, ret->score);


}

int main()
{
	//test01();
	test02();

	system("pause");
	return 0;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值