c++小白数据结构——————3企业链表

1.前言 

单链表一般企业用到比较少,用的比较多是的企业链表,下图是企业链表的结构

单链表结构如图

 个人理解:单链表存储的时候可能要指定数据类型,当然也可以用void*代表任意数据类型的数据,但是企业链表可以由用户指定数据类型,我们只需要创造链表,通过指针将链表串起来

2.代码组成

2.1 EnterpriseLinkList.h 头文件,定义企业链表有哪些功能

#pragma once
#include<iostream>
#pragma once
//链表小节点
typedef struct LINKNODE {
	struct LINKNODE* next;
}LinkNode;

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

//遍历函数指针
typedef void(*PRINTNODE)(LinkNode*);
//比较函数指针
typedef int(*COMPARRE)(LinkNode*, LinkNode*);

//初始化链表
LinkList* Init_LinkList();
//插入
void Insert_LinkList(LinkList* list, int pos, LinkNode* data);
//删除
void Remove_LinkList(LinkList* list, int pos);
//查找
int Find_LinkList(LinkList* list, LinkNode* data, COMPARRE compare);
//返回链表的大小
int Size_LinkList(LinkList* list);
//打印
void Print_LinkList(LinkList* list, PRINTNODE print);
//释放链表内存
void FreeSpace_LinkList(LinkList* list);

注意 链表节点中用的是LinkNode而不是LinkNode* 

2.2 EnterpriseLinkList.cpp 源文件

#include"EnterpriseLinkList.h"
//初始化链表
LinkList* Init_LinkList()
{
	LinkList* list = new LinkList;
	list->head.next = NULL;
	list->size = 0;
	return list;
}
//插入
void Insert_LinkList(LinkList* list, int pos, LinkNode* data)
{
	if (list == NULL)return;
	if (data == NULL)return;
	if (pos<0 || pos>list->size) {
		pos = list->size;
	}
	//查找插入位置
	LinkNode* pCurrent = &(list->head);
	for (int i = 0; i < pos; i++) {
		pCurrent = pCurrent->next;
	}
	data->next = pCurrent->next;
	pCurrent->next = data;
	list->size++;
}
//删除
void Remove_LinkList(LinkList* list, int pos)
{
	if (list == NULL)return;
	if (pos<0 || pos>=list->size) return;
	LinkNode* pCurrent = &(list->head);
	for (int i = 0; i < pos; i++) {
		pCurrent = pCurrent->next;
	}
	pCurrent->next = pCurrent->next->next;
	list->size--;
}
//查找
int Find_LinkList(LinkList* list, LinkNode* data, COMPARRE compare)
{
	if (list == NULL)return -1;
	if (data == NULL)return -1;
	LinkNode* pCurrent = list->head.next;
	int index = 0;
	int flag = -1;
	while (pCurrent != NULL) {
		if (compare(pCurrent, data) == 0) {
			flag = index;
			break;
		}
		pCurrent = pCurrent->next;
		index++;
	}
	return flag;
}
//返回链表的大小
int Size_LinkList(LinkList* list)
{
	return list->size;
}
//打印
void Print_LinkList(LinkList* list, PRINTNODE print)
{
	if (list == NULL)return;
	LinkNode* pCurrent = list->head.next;
	while (pCurrent!=NULL)
	{
		print(pCurrent);
		pCurrent = pCurrent->next;
	}

}
//释放链表内存
void FreeSpace_LinkList(LinkList* list)
{
	if (list == NULL)return;
	delete list;
}

 2.2.1 初始化链表LinkList* Init_LinkList()

在堆区人为开辟LinkList类型,将头节点的指针置空(NULL或者nullptr都可以),将list的大小置0

2.2.2  给位置插数值void Insert_LinkList(LinkList* list, int pos, LinkNode* data)

  • 检查 listdata 是否为空,如果为空(list空说明没有初始化成功,data空证明没有数据)则直接返回,检查 pos 是否在合法范围内
  • 遍历链表找到要插入位置的前一个节点。遍历的次数就是 pos 的值
  • 将要插入节点的 next 指针指向当前位置节点的下一个节点
  • 将当前位置节点的 next 指针指向要插入的节点,完成插入操作
  • 增加链表的大小(size

2.2.3  删除链表数值void Remove_LinkList(LinkList* list, int pos)

如同2.2.2,删除前要先检查。然后找到移除位置的前一个节点,将前一个节点的 next 指针指向要移除节点的下一个节点的下一个节点,这样就跳过了要移除的节点,最后减小链表的大小

2.2.4 根据数值查看位置int Find_LinkList(LinkList* list, LinkNode* data, COMPARRE compare)

此处注意函数的形参有一个COMPARRE compare,这个会在test.cpp给出函数具体内容。

index是链表的位置,也就是从0开始,flag目的是记录要查找值的位置最后返回

2.2.5 链表大小int Size_LinkList(LinkList* list)

2.2.6 打印链表的数值void Print_LinkList(LinkList* list, PRINTNODE print)

同2.2.4一样,注意形参PRINTNODE print,从头节点开始依次遍历直到链表最后

2.2.7 释放链表void FreeSpace_LinkList(LinkList* list)

人为开辟的堆都要释放掉
 

2.3 test.cpp 测试企业链表,包括main函数

#include"EnterpriseLinkList.h"
#include<string>
typedef struct PERSON {
	LinkNode node;
	char name[64];
	int age;
}Person;

void MyPrint(LinkNode* data) {
	auto p = (Person*)data;
	std::cout << "Name:" << p->name << " age:" << p->age  << std::endl;
}
int MyCompare(LinkNode* data1, LinkNode* data2) {
	auto p1= (Person*)data1;
	auto p2 = (Person*)data2;
	if (strcmp(p1->name , p2->name)==0 && p1->age == p2->age) { return 0; }

	return -1;
}
void test_EnterpriseLinkList()
{
	LinkList* list = Init_LinkList();
	Person p1, p2, p3, p4, p5;
	strcpy_s(p1.name, sizeof(p1.name),"aaa");
	strcpy_s(p2.name, sizeof(p2.name), "bbb");
	strcpy_s(p3.name, sizeof(p3.name), "ccc");
	strcpy_s(p4.name, sizeof(p4.name), "ddd");
	strcpy_s(p5.name, sizeof(p5.name), "eee");
	p1.age = 10;
	p2.age = 20;
	p3.age = 30;
	p4.age = 40;
	p5.age = 50;
	Insert_LinkList(list, 0, (LinkNode*)&p1);
	Insert_LinkList(list, 0, (LinkNode*)&p2);
	Insert_LinkList(list, 0, (LinkNode*)&p3);
	Insert_LinkList(list, 0, (LinkNode*)&p4);
	Insert_LinkList(list, 0, (LinkNode*)&p5);

	//打印
	Print_LinkList(list, MyPrint);

	//删除节点
	Remove_LinkList(list, 2);
	std::cout << "----------------------" << std::endl;
	Print_LinkList(list, MyPrint);

	//查找
	Person findP;
	strcpy_s(findP.name,sizeof(findP.name),"aaa");
	findP.age = 10;
	std::cout << "要查找的人的姓名为: " << findP.name << " 年纪为: " << findP.age << std::endl;
	int pos = Find_LinkList(list, (LinkNode*)&findP, MyCompare);
	std::cout << "位置为: " << pos << std::endl;;

	FreeSpace_LinkList(list);
}
int main()
{
	test_EnterpriseLinkList();
	return 0;
}

 注意因为PERSON结构体内姓名的定义是char类型,strcpy会报错,所以我用的是strcpy_s函数

auto是c++11的特性,可以不用auto

auto p = (Person*)data;可以替换成Person* p = (Person*)data

 3.运行结果

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值