C++数据结构X篇_05_企业链表的思路和实现(企业链表是企业中经常使用的一种链表;企业链表p_next仅仅指向下一个p_next的地址,链表中并未涉及任何data数据)

接上篇:C++数据结构X篇_04_单向链表框架搭建、实现和测试(链表的定义,常用操作的实现等),比较好的博文参考:C++实现企业链表,本篇基本就是按照该博文进行的整理,视频中介绍的是利用C实现的方法,繁杂且当前我并未完全实现。

1. 企业链表

企业链表是企业中经常使用的一种链表,因此被称为企业链表。企业链表是企业中经常使用的一种链表,因此被称为企业链表。我们首先来看看他的结构与传统链表有啥不同:
在这里插入图片描述
对于一个类或结构体 ,其中包含我们需要存储的数据data与一个指针变量p_next,我们将p_next串起来便形成了企业链表,那它和普通链表有何区别呢?普通链表中p_next指向的是下一个p_next与data组成的类或结构体整体的地址,而企业链表p_next仅仅指向下一个p_next的地址。因此链表中并未涉及任何data数据,企业链表实际存储的数据结构为:
在这里插入图片描述
理论说完了,那如何实现呢?

1.1 首先应定义节点与链表并对其初始化

//链表指针节点节点
class node_p
{
public:
	node_p* next;
};
//链表
class list
{
public:
    //当给list分配内存时,head内存也会同时分配,释放时只需要释放list即可
	node_p head;
	int size;
};
 
//初始化链表
list * list_init()
{
	list* L=new list;
	L->head.next=NULL;
	L->size=0;
	return L;
}

1.2 再确定链表的插入删除函数

/插入
void list_insert(list* L,int pos,node_p* data)
{
	//查找位置
	node_p* pcurrent=&(L->head);
	for (int i = 0; i < pos; i++)
	{
		pcurrent=pcurrent->next;
	}
	//插入新的指针节点
	data->next=pcurrent->next;
	pcurrent->next=data;
	L->size++;
}
 
//删除
void list_delete(list* L,int pos)
{
	//查找位置
	node_p* pcurrent=&(L->head);
	for (int i = 0; i < pos-1; i++)
	{
		pcurrent=pcurrent->next;
	}
	//删除节点
	pcurrent->next=pcurrent->next->next;
	L->size--;
}

到这里除了node的定义中未放入data外,其余操作与普通链表一致。那么企业链表是如何放入数据的呢?

1.3 我们先自定义一个数据节点:

//自定义链表数据节点
class my_data
{
public:
	node_p p_data; //定义为node_p* p_data效果也是一样,后期考虑为什么node_p* next;与此等效
	int num;
};

当我们创建my_data的对象指针p1,将其强转成node_p的对象指针a1,a1->next=p1->p_data(具体原理见C++57个入门知识点_番外1_C++指针偏移在类中的应用及指针偏移原理)。因此p1可以通过a1被插入企业链表中,当需要使用p1->num时,只需要再将a1强转成my_data的对象指针即可正常访问。

1.4 下面提供根据自定义数据提供打印函数:

void my_print(node_p* data)
{
	my_data* p=(my_data*)data;
	cout<<p->num<<"\t";
}
 
//打印链表
void list_print(list* L)
{
	node_p* pcurrent=L->head.next;
	while (pcurrent != NULL)
	{
		my_print(pcurrent);
		pcurrent=pcurrent->next;
	}
	cout<<endl;
}

1.5 实验与结果

int main()
{
	//创建链表
	list* L=list_init();
	//创建数据
	my_data data[9];
	for (int i = 0; i < 10; i++)
	{
		data[i].num=i+1;
	}
	//插入数据1~10
	for (int i = 0; i < 10; i++)
	{
		list_insert(L,i,(node_p*)&data[i]);  //把节点串起来
	}
	//打印数据
	cout<<"链表中数据为:"<<endl;
	list_print(L);
	//删除pos=5的数据(跳过head)
	list_delete(L,5);
	cout<<"删除pos=5后:"<<endl;
	list_print(L);
	system("pause");
	return 0;
}

在这里插入图片描述

1.6 整体代码

#include <iostream>
using namespace std;

//链表指针节点节点
class node_p
{
public:
	node_p* next;
};
//链表
class list
{
public:
	//当给list分配内存时,head内存也会同时分配,释放时只需要释放list即可
	node_p head;
	int size;
};

//自定义链表数据节点
class my_data
{
public:
	node_p p_data;
	int num;
};


//初始化链表
list * list_init()
{
	list* L = new list;
	L->head.next = NULL;
	L->size = 0;
	return L;
}

// 插入
void list_insert(list* L, int pos, node_p* data)
{
	//查找位置
	node_p* pcurrent = &(L->head);
	for (int i = 0; i < pos; i++)
	{
		pcurrent = pcurrent->next;
	}
	//插入新的指针节点
	data->next = pcurrent->next;
	pcurrent->next = data;
	L->size++;
}

//删除
void list_delete(list* L, int pos)
{
	//查找位置
	node_p* pcurrent = &(L->head);
	for (int i = 0; i < pos - 1; i++)
	{
		pcurrent = pcurrent->next;
	}
	//删除节点
	pcurrent->next = pcurrent->next->next;
	L->size--;
}

void my_print(node_p* data)
{
	my_data* p = (my_data*)data;
	cout << p->num << "\t";
}

//打印链表
void list_print(list* L)
{
	node_p* pcurrent = L->head.next;
	while (pcurrent != NULL)
	{
		my_print(pcurrent);
		pcurrent = pcurrent->next;
	}
	cout << endl;
}

int main()
{
	//创建链表
	list* L = list_init();
	//创建数据
	my_data data[9];
	for (int i = 0; i < 10; i++)
	{
		data[i].num = i + 1;
	}
	//插入数据1~10
	for (int i = 0; i < 10; i++)
	{
		list_insert(L, i, (node_p*)&data[i]);  //把节点串起来
	}
	//打印数据
	cout << "链表中数据为:" << endl;
	list_print(L);
	//删除pos=5的数据(跳过head)
	list_delete(L, 5);
	cout << "删除pos=5后:" << endl;
	list_print(L);
	system("pause");
	return 0;
}

1.7 C的实现方法(并未完全实现,后期有时间了再进行补充,作参考)

1.7.1 LinkList.h

#pragma once
#ifndef LINKLIST_H
#define LINKLIST_H

//链表小节点
typedef struct LINKNODE {
	struct LINKNODE* next;
}LinkNode;

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

}LinkList;

//遍历函数指针
typedef void(*PRINTNODE)(LinkNode*);
//比较函数指针
typedef int(*COMPARENODE)(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, COMPARENODE compare);
//返回链表大小
int Size_LinkList(LinkList* list);
//打印
void Print_LinkList(LinkList* list, PRINTNODE print);
//释放链表内存
void FreeSpace_LinkList(LinkList* list);

#endif

1.7.2 LinkList.cpp

#include<iostream>
#include "LinkList.h"
//初始化链表
LinkList* Init_LinkList() {
	LinkList* list = (LinkList*)malloc(sizeof(LinkList));
	list->head.next = nullptr;
	list->size = 0;
	return list;
}
//插入
void Insert_LinkList(LinkList* list, int pos, LinkNode* data) {
	if (list == nullptr) {
		return;
	}
	if (data == nullptr) {
		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 == nullptr) {
		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, COMPARENODE compare) {
	if (list == nullptr) {
		return;
	}
	if (data == nullptr) {
		return;
	}
	//辅助指针变量
	LinkNode* pCurrent = list->head.next;
	int index = 0;
	while (pCurrent != nullptr) {
		if (compare(pCurrent, data) == 0) {
			break;
		}
		pCurrent = pCurrent->next;
		index++;
	}
	
	return index;
}
//返回链表大小
int Size_LinkList(LinkList* list) {
	return 0;
}
//打印
void Print_LinkList(LinkList* list, PRINTNODE print) {
	if (list == nullptr) {
		return;
	}

	//辅助指针
	LinkNode* pCurrent = list->head.next;
	while (pCurrent != nullptr) {
		print(pCurrent);
		pCurrent = pCurrent->next;
	}

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

	free(list);
}

1.7.3 ListTest3.cpp

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include "LinkList.h"
#define _CRT_SECURE_NO_WARNINGS

typedef struct PERSON {
	LinkNode node;
	char name[64];
	int age;

}Person;

void MyPrint(LinkNode* data) {
	Person* p = (Person*)data;
	printf("Name:%s Age:%d\n",p->name,p->age);
}

int main()
{
    //创建链表
	LinkList* list = Init_LinkList();
	//创建数据
	Person p1, p2, p3, p4, p5;
	strcpy_s(p1.name, "aaa");
	strcpy_s(p2.name, "bbb");
	strcpy_s(p3.name, "ccc");
	strcpy_s(p4.name, "ddd");
	strcpy_s(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);

	//释放链表内存
	FreeSpace_LinkList(list);
}

2. linux内核链表

上面介绍的企业链表p_next是第一个成员变量,而linux内核链表中p_next是最后一个成员变量,这样与首地址存在一个偏移量才能找到LINKNODE* next的问题,企业链表也可以看做是linux内核链表的改进版。具体示意图如下所示

在这里插入图片描述
3. 学习视频地址:
企业链表思路企业链表实现_测试1企业链表实现_测试2

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十月旧城

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值