欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

双向循环链表

程序员文章站 2022-03-15 20:25:14
...

在上一篇双向链表的基础上增加了循环,有不小的改动,特别是一些核心的地方。

例如,如何在插入结点的过程中,确保时刻都在首位相连; 遍历循环条件怎么写 等等。

双向链表:https://blog.csdn.net/hpu2022/article/details/83146619

双向循环链表:

#include <iostream>
#include <string>
using namespace std;
typedef long long LL;

typedef struct List{
	int num;		// 编号
	string name;	// 姓名
	LL tel;			// 电话
	struct List *prior;
	struct List *next;
} List, *LinkList;		// List 定义结构体变量, LinkList 定义结构体指针

LinkList Insert(LinkList &head, LinkList &tmp);
LinkList Create()
{
	LinkList head, p;
	int num;
	string name;
	LL tel;
	head = NULL;
	cout << "input num, name and tel: \n";
	cin >> num >> name >> tel;
	while(num)
	{
		p = new List;
		p->num = num;
		p->name = name;
		p->tel = tel;
		head = Insert(head, p);
		cin >> num >> name >> tel;
	}
	return head;
}
LinkList Insert(LinkList &head, LinkList &tmp)	// 引用参数
{
	LinkList ptr, ptr1, ptr2;	// 辅助指针
	ptr = tmp;
	ptr2 = head;
	if(head == NULL)	// 插入的结点是唯一一个结点的情况
	{
		head = ptr;
		head->prior = head;
		head->next = head;
	}
	else
	{
		while((ptr->num > ptr2->num) && (ptr2->next != head))	// 寻找插入的有序位置
		{
			ptr1 = ptr2;
			ptr2 = ptr2->next;
		}
		if(ptr->num <= ptr2->num)
		{
			if(head == ptr2)	// 要插入的结点在头结点之前,是新的头结点
			{
				head = ptr;
				head->prior = ptr2->prior;	// 新的头结点的前驱仍然是原来头结点的前驱,指向最后一个节点
				head->next = ptr2;			// 新的头结点的后继结点是原来的头结点
				ptr2->prior = head;			// 原来头结点的前驱是新的头结点
//				ptr2->next = NULL;
			}
			else	// 插入在两个结点的中间
			{
				ptr1->next = ptr;
				ptr->prior = ptr1;
				ptr->next = ptr2;
				ptr2->prior = ptr;
			}
		}
		else	// 插入在末尾
		{
			ptr2->next = ptr;
			ptr->prior = ptr2;
			head->prior = ptr;	// 头结点的前驱是末尾结点
			ptr->next = head;	// 末尾结点的后继是头结点
		}
	}
	return head;
}
LinkList Delete(LinkList head, int num)		// 删除指定编号的结点
{
	LinkList ptr1, ptr2;	// 辅助指针
	while(head != NULL && head->num == num)	// 要删除的结点是头结点
	{
		ptr2 = head;
		head = head->next;
		head->prior = ptr2->prior;
		delete ptr2;	// 删除结点
	}
	if(head == NULL)	// 头结点为空等价于链表为空
		return NULL;
	ptr1 = head;
	ptr2 = head->next;
	while(ptr2 != head)
	{
		if(ptr2->num == num)
		{
			ptr1->next = ptr2->next;
			ptr2->next->prior = ptr1;
			delete ptr2;
		}
		else
			ptr1 = ptr2;
		ptr2 = ptr1->next;
	}
	return head;
}
void Print(LinkList head)	// 遍历输出
{
	if(head == NULL)
	{
		cout << "No Records" << endl;
		return;
	}
	cout << "num\t name\t tel\n";

	LinkList ptr = head;
	do{
		cout << ptr->num << "\t ";
		cout << ptr->name << "\t ";
		cout <<ptr->tel << endl;
		ptr = ptr->next;
	}while(ptr != head);

	//for(LinkList ptr = head; ptr->next != head; ptr = ptr->next)
}
LinkList Find(List *head, int num)
{
	LinkList flag = NULL;
	if(head->num == num)
		return head;
	for(LinkList ptr = head->next; ptr != head; ptr = ptr->next)
	{
		if(ptr->num == num)
		{
			flag = ptr;
		}
	}
	return flag;
}

int main()
{
	List *head, *p;
	int num;
	string name;
	LL tel;
	int choice;

	do{
		cout << "1: create\n2: insert\n3: delete\n4: print\n5: Find\n0: exit\n";
		cin >> choice;
		switch(choice)
		{
			case 1:
				head = Create();
				break;
			case 2:
				cout << "input num, name and tel: \n";
				cin >> num >> name >> tel;
				p = new List;
				p->num = num;
				p->name = name;
				p->tel = tel;
				head = Insert(head, p);
				break;
			case 3:
				cout << "input name" << endl;
				cin >> num;
				head = Delete(head, num);
				break;
			case 4:
				Print(head);
				break;
			case 5:
				cout << "input num \n";
				cin >> num;
				LinkList tmp1 = Find(head, num);
				if(tmp1 != NULL)
				{
					cout << "Find: ";
					cout << tmp1->name << " " << tmp1->tel << endl;
					cout << "Find->prior ";
					cout << tmp1->prior->name << " " << tmp1->prior->tel << endl;
					cout << "Find->next ";
					cout << tmp1->next->name << " " << tmp1->next->tel << endl;
				}
				else
					cout << "Not Find" << endl;

				break;
		}
	}while(choice != 0);




	return 0;
}