循环链表时另一种形式的链式存储结构,把单链表中指向最后一个结点的指针指向单链表的表头结点,就形成了一个循环链表。循环链表无论从链表中的任意出发点出发均可找到表中的其他结点。
约瑟夫问题是犹太历史学家约瑟夫的一个故事:在罗马人占领乔塔帕特后,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> ©);
SimpleCirLinkList<T> &operator =(const SimpleCirLinkList<T> ©);
};
//初始化
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> ©)
{
//构造函数拷贝类参数必须为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> ©)
{
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;
}
结果: