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

约瑟夫问题(有时也称为 约瑟夫斯置换,是一个出现在 计算机科学和 数学中的问题。在计算机 编程的算法中,类似问题又称为 约瑟夫环。又称“丢手绢问题”)
据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第 k个人。接着,再越过k-1个人,并杀掉第 k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

我写了一个循环链表来实现约瑟夫问题,其实没必要这么复杂,只需要用一个vector或者是数组即可,以下是我写的代码:

1.循环链表头文件:

#ifndef __CircleList_H__
#define __CircleList_H__

#include 
#include 
#include 
#include 
using namespace std;

#define LEN 20
#define RANLEN 100
typedef int ElemType;

typedef struct Lnode
{
	ElemType data;  //值域
	Lnode *next;    //next指针
}Lnode;

class CircleList
{
private:
	Lnode *head;//头指针
	Lnode *curr;//当前指针
	int count;  //循环链表中元素个数
public:
	CircleList();//构造函数,只有一个头结点
	~CircleList(){delete head;}//析构函数
	Lnode *CreateCircleList(const int& n,const int& mark);//创建循环链表,n表示的是循环链表中的元素个数,mark为1的时候表示升序,-1的时候表示降序,0的时候表示随机
	void TraverseCircleList();  //遍历整个循环链表
//	void InsertNode(const ElemType& item,int pos);  //向循环链表中指定位置插入节点
	bool IsEmpty(){ return head->next == head; } //判断链表是否为空
//	Lnode *Index(int pos);  //返回指定位置的Lnode指针
	ElemType GetElem(int pos);  //返回指定位置的data值
	Lnode *Next();  //返回下一个节点的指针
	Lnode *Reset(int pos);  //将curr指针指向指定的位置并返回
	ElemType DeleteNext();  //删除curr指针指向的下一个节点
	Lnode* GetCurrNode(); //返回curr指针
	ElemType DeletePosNode(int pos);  //删除指定位置的节点

};
#endif

2.循环链表.cpp文件

#include "stdafx.h"
#include "CircleList.h"


CircleList::CircleList()
{
	head = new Lnode;
	head->next = head;
	curr = NULL;
	count = 0;
}

Lnode *CircleList::CreateCircleList(const int& n,const int& mark)
{
	int i,j,min;
	ElemType temp;
	ElemType a[LEN];
	Lnode *tempNode = NULL;
	srand((unsigned)time(NULL));//用于产生随机数的种子
	count = n;
	for(i = 0; i < LEN; i++ )
	{
		a[i] = rand()%RANLEN;  //产生100以内的随机数,保存在a数组中,a数组的长度为LEN=20个,也即n不能超过20
		cout< a[j] ) 
				min = j;
		}
		if( min != i )
		{
			temp = a[min];
			a[min] = a[i];
			a[i] = temp;
		}
	}
	for( i = 0; i < LEN; i++ )
	{
		cout<next = curr = tempNode = new Lnode;
	switch(mark)
	{
	case -1://表示降序排列
		curr->data = a[0];
		curr->next = head;
		for(i = 1;i < n; i++ )
		{
			curr = new Lnode;
			curr->data = a[i];
			tempNode->next = curr;
			tempNode = tempNode->next;
			curr->next = head;
		}
		break;
	case 0://表示随机排列
		curr->data = rand()%RANLEN;
		curr->next = head;
		for( i = 1; i < n; ++i )
		{
			curr = new Lnode;
			curr->data = rand()%RANLEN;
			tempNode->next = curr;
			tempNode = tempNode->next;
			curr->next = head;
		}
		break;
	case 1://表示升序排列
		curr->data = a[LEN-1];
		curr->next = head;
		for( i = 2; i <= n; ++i )
		{
			curr = new Lnode;
			curr->data = a[LEN-i];
			tempNode->next = curr;
			tempNode = tempNode->next;
			curr->next = head;
		}
		break;
	default:cerr<<"mark error!"<next != head )
	{
		search = search->next;
		cout<data<next;
	}
	return search->data;
}

ElemType CircleList::DeletePosNode(int pos)
{
	assert( pos > 0 );
	int i = 0;
	ElemType data;
	Lnode *search = head->next;
	curr = head;
	for( i = 1; i < pos; i++ )
	{
		curr = curr->next;
		search = search->next;
	}
	curr->next = search->next;
	search->next = NULL;
	data = search->data;
	delete search;
	count--;
	return data;
}

Lnode *CircleList::Next()
{
	if( curr->next == head )
		curr = curr->next->next;
	else
		curr = curr->next;
	return curr;
}

Lnode *CircleList::Reset(int pos)
{
	int i;
	curr = head;
	for( i = 0; i < pos; i++ )
	{
		curr = curr->next;
	}
	return curr;
}

ElemType CircleList::DeleteNext()
{
	ElemType data;
	Lnode *search = NULL;
	if( curr->next != head )
	{
		search = curr->next;
		curr->next = curr->next->next;
		data = search->data;
		search->next = NULL;
		delete search;
	}
	else
	{
		search = curr->next->next;
		curr->next->next = search->next;
		data = search->data;
		search->next = NULL;
		delete search;
	}
	return data;
}

Lnode* CircleList::GetCurrNode()
{
	return curr;
}

3.约瑟夫函数以及主函数的.cpp文件

// CircleListAndJosephProblem.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "CircleList.h"

//约瑟夫问题,n表示人数,m表示数多少个数,x表示第一次从哪个人开始数数
void JosephProblem(int n,int m,int x)
{
	int i,j;
	CircleList cl;
	cl.CreateCircleList(n,1);
	cout<<"未报数之前人的编号顺序:"<data<

如果您那么细心的看完代码后,发现有什么问题,希望您能够给我留言提出,只有不断发现不足,才能一直前进!!!

你可能感兴趣的:(数据结构于算法,约瑟夫问题,c++,Visual,Studio,2010)