c++数据结构算法复习基础-- 4 -- 线性表-单向循环链表-常用操作接口-复杂度分析

1、单向循环链表一

1)特点

每一个节点除了数据域,还有一个next指针域指向下一个节点(存储了下一个节点的地址)
末尾节点的指针域指向了头节点

在这里插入图片描述

析构函数思路图

在这里插入图片描述

2)代码实现

//定义结点
//单向循环链表
class CircleLink
{
public:
	//构造函数
	CircleLink()//这里是生成一个带头节点的
	{
		head_ = new Node();
		tail_ = head_;
		head_->next_ = head_;
	}
	//析构函数
	~CircleLink()//析构函数
	{
		Node* p = head_->next_;
		while(p != head_)
		{
			head_->next_ = p->next_;
			delete p;
			p = head_->next_;
		}
		delete head_;
	}
//共有方法区域
public:
	//尾插法  O(1)
	void InsertTail(int val)
	{
		Node* node = new Node(val);
		node->next_ = head_; //node->next_ = tail_->next_;
		tail_->next_ = node;
		tail_ = node; //更新tail_ 指针 指向新的尾节点
	}

	//头插法
	void InsertHead(int val)
	{
		Node* node = new Node(val);
		node->next_ = head_->next_;
		head_->next_ = node;

		//万一是空链表,要处理tail_
		if(node->next_ == head_)
			tail_ = node;
	}

	//删除节点
	void Remove(int val)
	{
		Node* q = head_;
		Node* p = head_->next_;

		while( p != head_ )
		{
			if( p->data_ == val )
			{
				//找到删除节点
				//if(p == tail_)
				//	tail_ = q;
				q->next_ = p->next_;
				delete p;

				//防止所删除的数据为尾节点,重置尾节点
				if(q->next_ == head_)
				{
					tail_ = q;
				}
				
				return ;
			}
			else
			{
				p = p->next_;
				q = q->next_;
			}
		}
	}
		
	//查询
	bool Find(int val) const
	{
		Node* p = head_->next_;
		while(p != head_)
		{
			if(p->data_ == val)
			{
				return true;
			}
			else
			{
				p = p->next_;
			}
		}

		return false;
	}
	
	//打印链表
	void Show() const
	{
		Node* p =head_->next_;
		while (p != head_)
		{
			cout<<p->data_<< " " ;
			p = p->next_;
		}
		cout<< endl;
	}

private:
	struct Node
	{
		Node(int date = 0):data_(date),next_(nullptr){}
		int data_;
		Node* next_;
	};

	Node* head_; // 指向头节点
	Node* tail_; //指向末尾节点
};

代码测试

int main()
{
	CircleLink clink;
	srand((time(NULL)));

	//尾插
	for(int i = 0; i <10;i++)
	{
		clink.InsertTail(rand() % 100);
	}
	clink.Show();

	//头插
	for(int i = 0; i <5;i++)
	{
		clink.InsertHead(i);
	}
	clink.Show();

	//删除
	clink.InsertTail(0);
	clink.Show();
	clink.Remove(0);
	clink.Show();
	clink.Remove(0);
	clink.Show();

}

测试结果:

在这里插入图片描述

2、约瑟夫环问题

约瑟夫环是一个数学的应用问题: 已知n个人 (以编号1,2,3…n分别表示)围坐在一张圆桌周围,从编号为k的人开始报数,数到m的那个人出列,它的下一个人又从1开始报数,数到m的那个人又出列,依此规律重复下去,直到圆桌周围的人全部出列,输出人的出列顺序。

代码实现1 – 不带头节点

#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <string.h>
using namespace std;

struct Node
{
	Node(int date = 0):data_(date),next_(nullptr){}
	int data_;
	Node* next_;
};

//约瑟夫环问题
void Joseph(Node* head,int k,int m)//这里指针指向的是第一个节点,该算法为不带头节点的单向循环链表应用
{
	Node* p = head;
	Node* q = head;

	//q指向最后一个节点,防止m==1 的特殊情况
	while(q->next_ != head)
	{
		q = q->next_;
	}

	//从第k个人开始报数的
	for(int i = 1; i < k; i++)
	{
		q = p;
		p = p->next_;
	}

	//走到地m个人
	for(;;)
	{
		for(int i = 1; i<m; i++)
		{
			q = p;
			p=p->next_;
		}

		//打印符合条件的节点数据
		cout<<p->data_ << " ";

		//删除p指向的节点
		if(p == q)//剩余最后一个节点
		{
			delete p;
			break;
		}
		/*if(p == head)//所删除节点为头节点
		{
			head = q->next_;
		}*/
		
		q->next_ = p->next_;
		delete p;
		p=q->next_;
	}
	cout<<endl;
}

测试代码

int main()
{
	Node *head = new Node(1);
	Node *n2 = new Node(2);
	Node *n3 = new Node(3);
	Node *n4 = new Node(4);
	Node *n5 = new Node(5);
	Node *n6 = new Node(6);
	Node *n7 = new Node(7);
	Node *n8 = new Node(8);

	head->next_ = n2;
	n2->next_ = n3;
	n3->next_ = n4;
	n4->next_ = n5;
	n5->next_ = n6;
	n6->next_ = n7;
	n7->next_ = n8;
	n8->next_ = head;

	Joseph(head,1,3);
	//Joseph(head,1,1);

	return 0;
}

运行结果

Joseph(head,1,3);

在这里插入图片描述

Joseph(head,1,1);

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值