首先,我是用的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;
}