`
chentingk
  • 浏览: 19985 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

循环链表解决约瑟夫环问题

 
阅读更多

                                                                       问题描述

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

 

就问题来看,需要进行循环删除,在到达尾部后的下一个是头部,而每一次删除都会记录删除删除位置的下一个位置并且把队列给缩短。

因此,我们需要建立一个循环链表来进行解决这个问题。

循环链表简介:

循环链表是一种数据结构,由一些离散数据和连接数据的指针来构成,主要特点是队尾指针执行的是队头,形成一个环状的存储结构

功能:

(1)构造函数-----用于建立空表

(2)析构函数-----用于释放已经申请的内存

(3)添加-----尾插法建立链表,头指针不动,位指针向后移

(4)删除-----删除所输入位置的元素

(5)指向删除-----为了方便约瑟夫环问题解决而建立的

(6)遍历-----输出链表的元素

思路:

根据约瑟夫环游戏进行的过程,每次删除之后下一个开始数数的人为一,所以我建立了一个方法(Todelate())为了每次删除之后记录删除位置下一个位置为起始点。然后从起始点往后的传入参数个位置进行删除,然后再记录删除后一个位置,如此循环,直到表中只有一个元素为止。

/**循环链表解决约瑟夫环问题=========================>无头指针**/
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
class listnode;
class Link
{
	friend listnode;
private:
	int date;
	Link *link;
};
class listnode
{
private:
	Link *first,*last;
	Link *memorLink;
	int elementsCount;
public :
	//构造
	listnode()
	{
		elementsCount=0;
		first=last=0;
	}
	//析构
	~listnode()
	{
		Link *next=first->link;
		Link *front=first->link;
		do
		{
			front=next->link;
			delete next;
			next=front;
		}while(next!=first);
	}
	//信号设置
	void signSet()
	{
		if(first!=0)
			memorLink=first;
	}
	//加入元素
	void add(int x)
	{
		Link *p=new Link;
		p->date=x;
		if(!first)
		{
			first=last=p;
			last->link=first;
			
		}
		else
		{
			last->link=p;
			last=p;
			last->link=first;
		}
		elementsCount++;
	}

	//删除
	listnode &Delete(int location)
	{
		int index=1;
		Link *p=first;
		while(index<location-1)
		{
			index++;
			p=p->link;
		}
		if(index==1 || p->link==first)
		{
			Link *next=first;
			first=next->link;
			last->link=first;
			delete next;
			return *this;
		}
		else if(p->link==last)
		{
			Link *next=last;
			p->link=next->link;
			last=p;
			delete next;
			return *this;
		}
		else
		{
			Link *next=p->link;
			p->link=next->link;
			delete next;
			return *this;
		}
	}
	//约瑟夫删除
	void Todelete(int location)
	{
		
		Link *p=memorLink;
		int index=1;
		while(index<location-1)
		{
			index++;
			p=p->link;
		}
		if(memorLink==first&&p==first ||p->link==first)
		{
			Link* next=first;
			memorLink=last->link=next->link;
			first=next->link;
			delete next;
		}
		else if(memorLink==last&&p==last || p->link==last)
		{
			Link *next=last;
			Link *front=first;
			for(int i=1;i<elementsCount-1;i++)
			{
				front=front->link;
			}
			memorLink=front->link=next->link;
			last=front;
			delete next;
			
		}
		else
		{
			Link *next=p->link;
			memorLink=p->link=next->link;
			delete next;
			
		}
		elementsCount--;

		

	}
	//获取元素个数
	int getCount()
	{
		return elementsCount;
	}
	//遍历
	void print()
	{
		int count=0;
		Link* p=first;
		if(first->link==first)
		{
			cout<<first->date<<endl;
		}
		else{
			do
			{
				cout<<p->date<<" ";
				p=p->link;
				count++;
			}while(p!=first || count==0);
			cout<<endl;
		}
	}
};
void main()
{
	cout<<"==============================欢迎使用约瑟夫环程序=============================="<<endl;
	listnode list;
	int Juseph;
	int setNumber;
	cout<<"请输入你需要设置的环的大小:";
	cin>>setNumber;
	for(int i=0;i<setNumber;i++)
		list.add(i);
	list.signSet();//至关重要
	cout<<"您设置的环全貌是=======================================》"<<endl;
	list.print();
	cout<<"请输入你需要测试的数据:";
	cin>>Juseph;
	while(list.getCount()!=1)
	{
		list.Todelete(Juseph);
	}
	cout<<"=============================约瑟夫环问题算法结果是============================="<<endl;
	list.print();

	
}

 

分享到:
评论

相关推荐

    双向循环链表解决约瑟夫环问题

    用双向循环链表解决约瑟夫环问题的程序清单

    用循环链表实现约瑟夫环问题

    使用c语言中的循环链表及结构体实现约瑟夫环问题

    c++循环链表解决约瑟夫环问题

    通过上述C++代码实现了约瑟夫环问题的解决方案,该方案利用了单向循环链表来高效地模拟出题目的过程。不仅能够处理任意数量的参与者,而且能够根据不同的初始条件得出正确的出列顺序。这种实现方式简单明了,易于...

    java编写的循环链表来实现约瑟夫环

    循环链表 实现约瑟夫环 java 自己写的 测试通过 有注释

    利用循环链表解决约瑟夫环问题的C++实现

    问题描述:已经n个人(以编号1,2,3,…,n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部...

    [C&C++]利用循环链表解决约瑟夫环问题.rar

    分别基于C和C++利用循环链表的数据结构解决约瑟夫环问题 注释详细,包含了Visual Studio 2017 Professional的工程文件,可以直接运行 包含了C语言实现和C++实现两个文件

    循环链表实现约瑟夫环

    要利用循环链表解决约瑟夫环问题,我们首先需要创建链表节点。每个节点通常包含两个部分:一个是存储数据(如人编号),另一个是指向下一个节点的引用。在创建链表时,我们需要注意确保最后一个节点的指针正确地指向...

    用单循环链表实现约瑟夫环问题

    《使用单循环链表解决约瑟夫环问题》 约瑟夫环问题,作为一个经典的计算机科学问题,其核心在于模拟一种淘汰机制。在这个问题中,n个人按照顺时针方向围成一个圆圈,从第1号开始报数,每报到m就出圈,然后从下一个...

    C语言基于循环链表解决约瑟夫环问题的方法示例

    本文实例讲述了C语言基于循环链表解决约瑟夫环问题的方法。分享给大家供大家参考,具体如下: 概述: 约瑟夫环问题,是一个经典的循环链表问题,题意是:已知 n 个人(以编号1,2,3,…,n分别表示)围坐在一张圆桌...

    数组表示循环链表的约瑟夫环的实验报告

    这个实验报告展示了如何用数组模拟循环链表解决约瑟夫环问题,同时也体现了问题求解的算法设计和实现能力。通过此实验,可以学习到数组操作、循环控制以及动态更新数据结构的方法。在实际编程中,类似的思路可以应用...

    用链表表示循环链表的约瑟夫环的问题的源代码

    通过这个程序,我们可以理解如何利用链表和循环链表的概念解决约瑟夫环问题。循环链表使得我们能够方便地遍历整个链表,而剔除操作则通过移动指针实现了对链表节点的删除。这种编程方法展示了数据结构和算法在解决...

    单向循环链表实现约瑟夫环.zip

    约瑟夫环问题的解决方案通常采用模运算来确定剔除的顺序。假设初始时所有人在一个圈中,编号从1到n,每次剔除的间隔k是已知的。我们可以创建一个链表,节点代表人,节点的顺序表示人的编号。然后,我们从某个节点...

    单向循环链表解决约瑟夫问题

    用单向循环链表解决约瑟夫问题。使用c++语言,结构体,链表的操作。

    双向循环链表解决约瑟夫实验报告

    总结,双向循环链表在解决约瑟夫环问题中扮演了关键角色,它的特性使得在环形结构中高效地进行节点操作成为可能。通过链表操作与报数逻辑的结合,我们可以构建出一个完整的解决方案,有效地模拟并解决了这一经典问题...

    循环链表实现约瑟夫环问题

    循环链表实现约瑟夫环问题 约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又...

    用链表表示循环链表的约瑟夫环的问题的源代码的报告

    《用链表表示循环链表的约瑟夫环问题的源代码分析...通过以上步骤,我们可以构建一个循环链表来模拟约瑟夫环问题,从而解决这个问题。这个方法的关键在于递归思想的应用,以及链表操作的实现,使得复杂的问题得以简化。

Global site tag (gtag.js) - Google Analytics