泛型双向循环链表的创建及其方法

前言

上次给大家展示了泛型单项循环链表的创建及其方法,接下来,让我们在学完双向链表后,进行双向循环链表的学习。

泛型单向循环链表:泛型循环链表-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/xiawubushangban/article/details/136350085?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170929507916800211580920%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=170929507916800211580920&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-5-136350085-null-null.142^v99^pc_search_result_base8&utm_term=%E6%B3%9B%E5%9E%8B%E5%BE%AA%E7%8E%AF%E9%93%BE%E8%A1%A8&spm=1018.2226.3001.4187

 创建节点类

template<typename T>
class LNode
{
public:
	T data;
	LNode* next;
	LNode* prev;
};

 在节点类中,由于是双向链表,有两个指针分别指向节点的前驱和后继

创建链表类由于管理节点

template<typename T>
class Link_list
{
public:
	LNode<T>* Head;
	int size;
};

泛型双向循环链表的方法 

1.初始化链表 

template<typename T>
Link_list<T>* init_List()
{
	Link_list<T>* L;
	L = new Link_list<T>;
	L->Head = new LNode<T>;
	if (L == NULL)
	{
		printf("创建泛型双向循环链表失败\n");
	}
	L->Head->data = NULL;
	L->Head->next = new LNode<T>;
	L->Head->prev = new LNode<T>;
	L->Head->next = L->Head;
	L->Head->prev = L->Head;
	printf("创建泛型双向循环链表成功\n");
	return L;
}

这里先将两个指针分别指回头Head,数据域为空

2.增加节点 

template<typename T>
void insert_list(Link_list<T>* L, int pos)
{
	LNode<T>* new_Node = new LNode<T>;
	LNode<T>* pcurrent = new LNode<T>;
	new_Node->data = 0;
	new_Node->next = NULL;
	new_Node->prev = NULL;
	T data;
	cout << "请输入要插入的数据" << endl;
	cin >> data;
	new_Node->data = data;
	pcurrent = L->Head;
	for (int i = 1; i < pos; i++)
	{
		pcurrent = pcurrent->next;
	}
	new_Node->next = pcurrent->next;
	pcurrent->next->prev = new_Node;
	pcurrent->next = new_Node;
	new_Node->prev = pcurrent;
	
	return;
}

 在这段代码中,分别初始化两个节点对象,new_Node:用于插入的新节点,pcurrent:用于遍历链表锁定位置

注意:一定要对新节点进行完整的初始化,以便后续插入

 

 3.删除,销毁节点

template<typename T>
void delete_list(Link_list<T>* L,int pos)
{
	LNode<T>* pcurrent = new LNode<T>;
	LNode<T>* curr = new LNode<T>;
	curr->data = 0;
	curr->next = NULL;
	curr->prev = NULL;
	pcurrent = L->Head;
	for (int i = 0; i < pos; i++)
	{
		if (pos < 1)
		{
			printf("请重新输入:\n");
			continue;
		}
		curr = pcurrent;
		pcurrent = pcurrent->next;
	}
	curr->next = pcurrent->next;
	pcurrent->next->prev = curr;
	delete pcurrent;
	printf("删除成功\n");
	return;
}

 这里的两个节点对象

1.curr始终在pcurrent前方,用于锁定目标的前驱和为后续连接链表

2.pcurrent用于遍历整条链表,找到目标节点并销毁

3,更改,查询,打印链表

与链式存储的其他数据结构相同,这几种方法只是按照指令访问对应的数据域即可。

template<typename T>
void Change_list(Link_list<T>* L, int pos)
{
	LNode<T>* pcurrent = L->Head;
	for (int i = 0; i < pos; i++)
	{
		if (pcurrent == L->Head)
		{
			pcurrent = L->Head->next;
		}
		pcurrent = pcurrent->next;
	}
	T data;
	printf("请输入更改后的数据\n");
	cin >> data;
	pcurrent->data = data;
	return;
}

template<typename T>
void search_list(Link_list<T>* L, int pos)
{
	LNode<T>* pcurrent = L->Head;
	for (int i = 0; i < pos; i++)
	{
		if (pcurrent == L->Head)
		{
			pcurrent = L->Head->next;
		}
		pcurrent = pcurrent->next;
	}
	cout << pcurrent->data << endl;
}

 

template<typename T>
void print_list(Link_list<T>* L, int pos)
{
	LNode<T>* pcurrent = L->Head->next;
	for (int i = 0; i < pos; i++)
	{
		if (pcurrent == L->Head)
		{
			pcurrent = L->Head->next;
		}
		cout << pcurrent->data << "\t";
		pcurrent = pcurrent->next;
	}
	cout << endl;
	return;
}

几种方法基本相同 ,都是通过pcurrent指针遍历链表,找到目标后访问其数据域

主函数测试

int main1()
{
	Link_list<int>* L = init_List<int>();
	while (true)
	{
		printf("1.增 2.删 3.改 4.查 5.打印\n");
		int point;
		cin >> point;
		switch (point)
		{
		case 1:
			int round;
			printf("请输入你要添加的次数:\n");
			cin >> round;
			for (int i = 0; i < round; i++)
			{
				int address;
				printf("请输入你要插入的位置:\n");
				cin >> address;
				insert_list<int>(L, address);
			}
			break;
		case 2:
			printf("请输入你要删除的位置:\n");
			int pos;
			cin >> pos;
			delete_list<int>(L, pos);
			break;
		case 3:
			printf("请输入你要更改的数据的位置:\n");
			int pose;
			cin >> pose;
			Change_list<int>(L, pose-1);
			print_list<int>(L, 9);
			break;
		case 4:
			printf("请输入你要查询的数据的位置:\n");
			int add;
			cin >> add;
			search_list<int>(L, add-1);
			break;
		case 5:
			printf("请输入你要打印的数:\n");
			int num;
			cin >> num;
			print_list<int>(L, num);
			break;
		}
	}
	return 0;
}
int main2()
{
	Link_list<float>* L = init_List<float>();
	while (true)
	{
		printf("1.增 2.删 3.改 4.查 5.打印\n");
		int point;
		cin >> point;
		switch (point)
		{
		case 1:
			int round;
			printf("请输入你要添加的次数:\n");
			cin >> round;
			for (int i = 0; i < round; i++)
			{
				int address;
				printf("请输入你要插入的位置:\n");
				cin >> address;
				insert_list<float>(L, address);
			}
			break;
		case 2:
			printf("请输入你要删除的位置:\n");
			int pos;
			cin >> pos;
			delete_list<float>(L, pos);
			break;
		case 3:
			printf("请输入你要更改的数据的位置:\n");
			int pose;
			cin >> pose;
			Change_list<float>(L, pose - 1);
			print_list<float>(L, 9);
			break;
		case 4:
			printf("请输入你要查询的数据的位置:\n");
			int add;
			cin >> add;
			search_list<float>(L, add - 1);
			break;
		case 5:
			printf("请输入你要打印的数:\n");
			int num;
			cin >> num;
			print_list<float>(L, num);
			break;
		}
	}
	return 0;
}
int main()
{
	int x;
	printf("请输入你要操作的链表类型:\n");
	printf("1.整形  2.浮点型\n");
	cin >> x;
	switch (x)
	{
	case 1:main1();
	case 2:main2();
	}
	
}

 可以看到由于是泛型循环链表,操作可以涵盖多种数据类型,甚至自定义类型(不过可能需要运算符重载等操作)

运行结果:

这里我只展示了整形的例子

注意:由于是循环链表的一种,在输入的之后如果访问的值的位置大于链表长度,则会循环的访问

,可以更改循环条件控制访问。

  • 21
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值