码迷,mamicode.com
首页 > 其他好文 > 详细

循环链表和约瑟夫环

时间:2015-05-21 19:41:55      阅读:148      评论:0      收藏:0      [点我收藏+]

标签:

循环链表时另一种形式的链式存储结构,把单链表中指向最后一个结点的指针指向单链表的表头结点,就形成了一个循环链表。循环链表无论从链表中的任意出发点出发均可找到表中的其他结点。

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

用循环链表来实现约瑟夫问题是一个很好的选择,第一,链表插入和删除元素的操作非常简单,第二,循环链表时一个环,可以持续进行计数杀人。然后我就花了一整天的时间来搞循环链表和约瑟夫问题。

头文件:(CirLinkList.h)

//CirLinkList循环链表
#ifndef CIRLINKLIST_H_
#define CIRLINKLIST_H_
#include <iostream>
using std::cout;
using std::endl;
template<typename T>
struct Node
{
	T data;
	Node<T> *next;
	//构造函数
	Node();
	Node(T item, Node<T> *link=NULL);
};
template <typename T>
Node<T>::Node()
{
	next=NULL;
}
template<typename T>
Node<T>::Node(T item, Node<T> *link=NULL)
{
	data=item;
	next=link;
}
template <typename T>
class SimpleCirLinkList
{
protected:
	Node<T> *head;
	
	void Init();
public:
	Node<T> *GetElemPtr(int position) const;
	SimpleCirLinkList();//构造函数
	virtual ~SimpleCirLinkList();//析构函数
	bool IsEmpty();
	int Length() const;
	void Clear();
	void GetElem(int position, T &e);
	SimpleCirLinkList<T> &SetElem(int position, const T e);
	SimpleCirLinkList<T> &DeleteElem(int position, T &e);
	SimpleCirLinkList<T> &DeleteNode(Node<T> *tempPtr);
	SimpleCirLinkList<T> &InsertElem(int position, const T e);
	SimpleCirLinkList(const SimpleCirLinkList<T> &copy);
	SimpleCirLinkList<T> &operator =(const SimpleCirLinkList<T> &copy);
};
//初始化
template<typename T>
void SimpleCirLinkList<T>::Init()
{
	head=new Node<T>;
	head->next=head;
}
template<typename T>
Node<T> *SimpleCirLinkList<T>::GetElemPtr(int position) const
{
	int curPosition=1;
	Node<T> *tempPtr=head->next;
	if(position==0)
	{
		return head;
	}
	while(tempPtr->next!=head && curPosition<position)
	{
		tempPtr=tempPtr->next;
		++curPosition;
	}
	if(tempPtr!=head && curPosition==position)
	{
		return tempPtr;
	}
	else
	{
		return NULL;
	}

}
//构造函数
template<typename T>
SimpleCirLinkList<T>::SimpleCirLinkList()
{
	Init();
}
template <typename T>
SimpleCirLinkList<T>::~SimpleCirLinkList()
//析构函数
{
	Clear();
	delete head;
}
template <typename T>
int SimpleCirLinkList<T>::Length() const
{
	int count=0;
	Node<T> *tempPtr;
	for(tempPtr=head->next; tempPtr!=head; tempPtr=tempPtr->next)
	{
		++count;
	}
	return count;
}
template <typename T>
bool SimpleCirLinkList<T>::IsEmpty()
{
	if(head->next==head)
	{
		return true;
	}
	else 
	{
		return false;
	}
}
template <typename T>
void SimpleCirLinkList<T>::Clear()
{
	T temp;
	while(Length()>0)
	{
		DeleteElem(1,temp);
	}
}
template <typename T>
void SimpleCirLinkList<T>::GetElem(int position, T &e)
{
	Node<T> *tempPtr;
	if(position<1 || position>Length())
	{
		cout<<"获取元素时超出范围!"<<endl;
	}
	else
	{
		tempPtr=GetElemPtr(position);
		e=tempPtr->data;
	}
}
template <typename T>
SimpleCirLinkList<T> &SimpleCirLinkList<T>::SetElem(int position, const T e)
{
	Node<T> *tempPtr;
	if(position<1 || position>Length())
	{
		cout<<"获取元素时超出范围!"<<endl;
	}
	else
	{
		tempPtr=GetElemPtr(position);
		tempPtr->data=e;
	}
	return *this;
}
template <typename T>
SimpleCirLinkList<T> &SimpleCirLinkList<T>::DeleteElem(int position, T &e)
{
	Node<T> *tempPtr;
	Node<T> *dePtr;
	if(position<1 || position>Length())
	{
		cout<<"获取元素时超出范围!"<<endl;
	}
	else
	{
		tempPtr=GetElemPtr(position-1);
		Node<T> *newPtr=tempPtr->next;
		dePtr=newPtr->next;
		e=newPtr->data;
		tempPtr->next=dePtr;
		delete newPtr;
	}
	return *this;
}
template<typename T>
SimpleCirLinkList<T> &SimpleCirLinkList<T>::DeleteNode(Node<T> *tempPtr)
{
	Node<T> *newPtr=head;//=GetElemPtr(tempPtr->data-1);
	while(newPtr->next!=tempPtr)
	{
		newPtr=newPtr->next;
	}
	newPtr->next=tempPtr->next;
	delete tempPtr;
	return *this;
}
template <typename T>
SimpleCirLinkList<T> &SimpleCirLinkList<T>::InsertElem(int position, const T e)
{
	if(position<1 || position>(Length()+1))
	{
		cout<<"获取元素时超出范围!"<<endl;
	}
	else
	{
		Node<T> *tempPtr;
		Node<T> *newPtr=new Node<T>;
		newPtr->data=e;
		tempPtr=GetElemPtr(position-1);
		newPtr->next=tempPtr->next;
		tempPtr->next=newPtr;
	}
	return *this;
}
template <typename T>
SimpleCirLinkList<T>::SimpleCirLinkList(const SimpleCirLinkList<T> &copy)
{
	//构造函数拷贝类参数必须为const的引用
	int copyLength=copy.Length();
	Init();
	Node<T> *tempPtr=head->next;
	for(int curPosition=1; curPosition<=copyLength; curPosition++)
	{
		tempPtr=copy.GetElemPtr(curPosition);
		InsertElem(curPosition,tempPtr->data);
	}
}
template <typename T>
SimpleCirLinkList<T> &SimpleCirLinkList<T>::operator =(const SimpleCirLinkList<T> &copy)
{
	if(copy!=this)
	{
		int copyLength=copy.Length();
		Init();
		Node<T> *tempPtr=head->next;
		for(int curPosition=1; curPosition<=copyLength; curPosition++)
		{
			tempPtr=copy.GetElemPtr(curPosition);
			InsertElem(curPosition,tempPtr->data);
		}
	}
	return *this;
}
template <typename T>
std::ostream &operator <<(std::ostream &os, SimpleCirLinkList<T> &CirLinkList)
{
	T e;
	for(int curPosition=1; curPosition<=CirLinkList.Length(); curPosition++)
	{
		CirLinkList.GetElem(curPosition,e);
		cout<<e<<" ";
	}
	return os;
}
#endif

源文件:(CirLinkList.cpp)

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

#include "stdafx.h"
#include "CirLinkList.h"
#include <iostream>

using namespace std;
//n为共有多少人,m为数到几自杀。(41,3)
void Josephus(int n, int m)
{
	SimpleCirLinkList<int> CirLink;
	for(int i=1; i<=n; i++)
	{
		CirLink.InsertElem(i,i);
	}
	cout<<"约瑟夫链表为:"<<CirLink<<endl;
	Node<int> *deadmanPtr;
	Node<int> *tempPtr=CirLink.GetElemPtr(1);
	int e,s;
	cout<<"杀人顺序为:";
	for(int i=1; i<=n; i++)
	{
		for(int j=1; j<=2; j++)
		{
			if(tempPtr==CirLink.GetElemPtr(0))
			{
				tempPtr=tempPtr->next;
			}
			tempPtr=tempPtr->next;
			if(tempPtr==CirLink.GetElemPtr(0))
			{
				tempPtr=tempPtr->next;
			}
		}
		e=tempPtr->data;
		cout<<e<<" ";
		deadmanPtr=tempPtr->next;
		CirLink.DeleteNode(tempPtr);
		tempPtr=deadmanPtr;
		/*CirLink.DeleteElem(e,s);*/
	}
	cout<<endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
	SimpleCirLinkList<int> CirLinkList;
	cout<<"链表的长度为:"<<CirLinkList.Length()<<endl;
	cout<<"链表是否为空? ";
	if(CirLinkList.IsEmpty()==1)
	{
		cout<<"Yes!"<<endl;
	}
	else
	{
		cout<<"No!"<<endl;
	}
	//CirLinkList.InsertElem(0,1);
	CirLinkList.InsertElem(1,2);
	CirLinkList.InsertElem(2,3).InsertElem(3,4).InsertElem(4,5).InsertElem(5,6);
	cout<<"链表的长度为:"<<CirLinkList.Length()<<endl;
	cout<<"链表是否为空? ";
	if(CirLinkList.IsEmpty()==1)
	{
		cout<<"Yes!"<<endl;
	}
	else
	{
		cout<<"No!"<<endl;
	}
	cout<<"循环链表为:"<<CirLinkList<<endl;
	//复制链表
	//SimpleLinkList<int> copy(LinkList);
	SimpleCirLinkList<int> copy=CirLinkList;
	copy.InsertElem(2,0).InsertElem(3,0);
	cout<<"链表的长度为:"<<copy.Length()<<endl;
	cout<<"链表是否为空? ";
	if(copy.IsEmpty()==1)
	{
		cout<<"Yes!"<<endl;
	}
	else
	{
		cout<<"No!"<<endl;
	}
	cout<<"循环链表为:"<<copy<<endl;
	cout<<"设置值之后:"<<endl;
	copy.SetElem(1,100);
	cout<<"循环链表为:"<<copy<<endl;
	//清除链表
	cout<<"清空链表"<<endl;
	copy.Clear();
	cout<<"链表的长度为:"<<copy.Length()<<endl;
	cout<<"链表是否为空? ";
	if(copy.IsEmpty()==1)
	{
		cout<<"Yes!"<<endl;
	}
	else
	{
		cout<<"No!"<<endl;
	}
	Josephus(41, 3);
	system("pause");
	return 0;
}


结果:
技术分享


循环链表和约瑟夫环

标签:

原文地址:http://blog.csdn.net/jiang111_111shan/article/details/45894107

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!