约瑟夫环程序C++循环单链表实现。/
//当中的new和delete采用了重载函数。
//也采用了可利用空间表提高了系统分配和回收的速度。
// 题目:
// 编号为1,2,3。。。。N的N个人按顺时针方向坐成一圈。每个人有一个密码,一开始任选一个
// 整数作为报数上限值M,从第一个人开始按顺时针方向自1开始顺序报数。报到M时停止报数,报M
// 的人出列,将他的密码作为下一次报数的新值M,从他的顺时针方向上的下一个人开始重新从1
// 开始报数。如此下去直到所有人都出列为止。
#include <iostream>
using namespace std;
//每个人的号码和密码。
struct people
{
int NO;
int pass;
}node;
template <class Elem>
class Link
{
private:
static Link<Elem>* freelist;//静态数据成员的头接点。
public:
struct people element;
Link* next;
Link(people elemval,Link* nextval=NULL)
{
element.NO=elemval.NO;
element.pass=elemval.pass;
next=nextval;
}
Link(Link* nextval=NULL)
{
next=nextval;
}
void* operator new(size_t);// 重载new 函数。
void operator delete(void*);//重载delete函数。
};
template <class Elem>
class LList
{
private:
Link<Elem> *head;
Link<Elem> *tail;
Link<Elem> *fence;
void init()
{
head=tail=fence=new Link<Elem>;
tail->next=head->next; //生成链表是要把它的头接点和尾接点连接起来构成循环链表。
//因为有一个空的头接点。所以要把他的尾接点接到头接点的下一个指针。
}
void removeall()
{
while(head!=NULL)
{
fence=head;
fence=fence->next;
delete fence;
}
}
public:
LList()
{
init();
}
~LList()
{
removeall();
}
bool insert(const people& T);
bool remove(Elem&);
void getOut(int&,int&);
void prev();
bool append(const people& T);
};
template <class Elem>
Link<Elem>* Link<Elem>::freelist=NULL;//静态数据成员的初始化。
//重载的实现。
template <class Elem>
void* Link<Elem>::operator new(size_t)
{
if(freelist==NULL)
return ::new Link;
Link<Elem>* temp=freelist;
freelist=freelist->next;
return temp;
}
//重载的实现
template <class Elem>
void Link<Elem>::operator delete(void* ptr)
{
((Link<Elem>*)ptr)->next=freelist;
freelist=(Link<Elem>*)ptr;
}
//插入函数。此程序并没有用到次函数。
template <class Elem>
bool LList<Elem>::insert(const people& T)
{
fence->next=new Link<Elem>(T,fence->next);//通过调用构造函数的初始化。
if(tail==fence)
{
tail=fence->next;
tail->next=head->next;
}
return true;
}
//从链表的尾插入。
template <class Elem>
bool LList<Elem>::append(const people& T)
{
tail=tail->next=new Link<Elem>(T,head->next);//通过调用构造函数的初始化。
return true;
}
template <class Elem>
bool LList<Elem>::remove(Elem& it)
{
if(tail==head)
return false;
if(fence->next==NULL)
{
it=fence->element.pass;
cout<<fence->element.NO<<"-- ";
return true;
}
it=fence->next->element.pass;
cout<<fence->next->element.NO<<"-- ";
Link<Elem>* temp=fence->next;
fence->next=temp->next;
if(temp==tail)
{
tail=fence;//当是尾接点的时候要把他的尾指针指向标记指针
}
delete temp;
return true;
}
//找下一个接点。
template <class Elem>
void LList<Elem>::prev()
{
if(fence->next!=head)
fence=fence->next;
else
{
fence->next=head->next;
fence=fence->next;
}
}
//程序的主题//
template <class Elem>
void LList<Elem>::getOut(int &it,int& sum)
{
int sign,n=1;
fence=tail;//因为是从报到数的上一个人开始找到的删除点。所以要记得从head的上一个接点tail开始。
cout<<"Enter you want to first get out:";
cin>>sign;//报数值。
while(sum>0)
{
if(sign>sum&&sign>1) //为避免多次的循环找数通过取模可以节省时间。
sign=sign%sum;
if(sign==n||sum==1)
{
remove(it);
sign=it;
sum--;
n=0;//重新做标记从下一个人1开始。
}
else
prev();//找下个接点。
n++;
}
}
int main()
{
LList<int> A;
struct people T;
int item,it,sum;
cout<<"Enter you want to people:";
cin>>sum;
for(int i=1;i<=sum;i++)
{
cout<<"enter the--"<<i<<"--pass:";
cin>>item;
T.NO=i;
T.pass=item;
A.append(T);//我这里是从尾插入的。
cout<<endl;
}
A.getOut(it,sum);
return 0;
}
这是我学习数据结构和算法写的程序.我平时还可以看看自己写的程序.到以后自己有进步了.我在来看看自己的程序
是否是正确.合理的.