现在的位置: 首页 > 综合 > 正文

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

2018年04月06日 ⁄ 综合 ⁄ 共 9503字 ⁄ 字号 评论关闭

      约瑟夫问题,就是指n个人围成一圈,每个人都有一个1~n内唯一的编号。根据游戏规则,从第s号的人开始数1,2,3..,数到第m号的那个人将被淘汰出局,然后又从第m+1个人开始数1,2,3...,如此反复,直到最后只剩下一个人的时候游戏才结束。现在根据游戏人数n,号码间隔m和起始号码s,求游戏结束时那个人的号码。

     这个问题是数据结构中非常基础,也是很简单的一个问题:用一个不带附加头结点的循环链表即可实现。但是在用c++描述代码的过程中,虽然最后实现了问题的求解,但程序结束的时候却出现了内存不能read的现象,检查了一阵,仍不知道是什么原因,特将代码和结果图附上,希望能有同学加以指点。代码如下:

 

  

//CircLinkList.h

#ifndef CIRCLINKLIST_H

#define CIRCLINKLIST_H

#include<cstdlib>

//单向无附加头结点的循环链表类定义

template<class T>

struct CircLinkNode

{

         T data;

         CircLinkNode<T>* link;

         CircLinkNode(CircLinkNode<T>* ptr=NULL):link(ptr){}

         CircLinkNode(T item,CircLinkNode<T>* ptr=NULL):data(item),link(ptr){}

};

 

template<class T>

class CircLinkList

{

         CircLinkNode<T>* first;

public:

         CircLinkList(){first=new CircLinkNode<T>;first->link=first;}//默认构造函数

         CircLinkList(T value){first=new CircLinkNode<T>(value);first->link=first;}//构造函数

         CircLinkList(CircLinkList<T>& L);//拷贝构造函数

         ~CircLinkList(){makeEmpty();delete first;}

        

         CircLinkNode<T>* getHead(){return first;}//获取头结点

         int Length();//求循环链表长度

         void makeEmpty();

         void input(T& endTag);//创建链表

         void output();//显示链表

 

         CircLinkNode<T>* Locate(int i);//定位第i个元素

         bool Insert(int i,T& x);//i个元素后插入元素

         bool Remove(int i,T& x);//删除第i个元素

 

         bool Reverse();//逆转链表

         void Creat(int n);//创建1:n的有序链表

};

 

#endif

/*****************************************************************/

//CircLinkList.cpp

#include"CircLinkList.h"

 

/*****************************************************/

//拷贝构造函数,拷贝函数有点点问题,触发了assert机制,不知为何?

template<class T>

CircLinkList<T>::CircLinkList(CircLinkList<T>& L)

{

         CircLinkNode<T>*  srcptr=L.getHead(),

                                                 *destptr=first;

         int len=L.Length();

         T value;

 

         value=srcptr->data;

         destptr->data=/*new CircLinkNode<T>*/value;//赋值第一个节点

         for(int i=1;i<len;i++)

         {

                   value=srcptr->data;

                   destptr=new CircLinkNode<T>(value);

                   if(destptr==NULL)

                   {

                            cerr<<"内存分配失败!"<<endl;

                            exit(1);

                   }

                  

                   destptr=destptr->link;

                   srcptr=srcptr->link;

         }

         destptr->link=first;

}

 

/*****************************************************/

//求循环链表长度

template<class T>

int CircLinkList<T>::Length()

{

         CircLinkNode<T>*  current=first;

         int count=1;

         while(current->link!=first)

         {

                   current=current->link;

                   count++;

         }

         return count;

}

/*****************************************************/

//清空结点,仅剩下头结点

template<class T>

void CircLinkList<T>::makeEmpty()

{

         CircLinkNode<T>*  current;

         while(first->link!=first)

         {      

                   current=first->link;

                   first->link=current->link;

                   delete current;

        

                  

         }

}

/*****************************************************/

//创建链表

template<class T>

void CircLinkList<T>::input(T& endTag)

{

         CircLinkNode<T>*  newNode,*current;

         makeEmpty();

         current=first;

        

         T value;

         cin>>value;

         if(value!=endTag)

         {

                   //newNode=new CircLinkNode<T>(value);//此处不应该新开辟空间

                   first/*newNode*/->data=value;

                   current=/*newNode*/first;

         }

         cin>>value;

         while(value!=endTag)

         {

                   newNode=new CircLinkNode<T>(value);

                   if(newNode==NULL)

                   {

                            cerr<<"内存分配失败!"<<endl;

                            exit(1);

                   }

                   current->link=newNode;

                   current=current->link;

                   cin>>value;

         }

         current->link=first;

}

 

 

/*****************************************************/

//创建1:n的有序链表

template<class T>

void CircLinkList<T>::Creat(int n)

{

         CircLinkNode<T>*  newNode,*current;

         makeEmpty();

         current=first;

         first->data=1;

         current=first;

         int x=2;

         while(x<=n)

         {

                   newNode=new CircLinkNode<T>(x);

                   if(newNode==NULL)

                   {

                            cerr<<"内存分配失败!"<<endl;

                            exit(1);

                   }

                   current->link=newNode;

                   current=current->link;

                   x++;

         }

         current->link=first;

}

 

 

/*****************************************************/

//显示链表

template<class T>

void CircLinkList<T>::output()

{

         CircLinkNode<T>*  current=first;

         int len=Length();

         for(int i=0;i<len;i++)

         {

                   cout<<current->data<<" ";

                   current=current->link;

         }

         cout<<endl;

}

/*****************************************************/

//定位第i个元素

template<class T>

CircLinkNode<T>* CircLinkList<T>::Locate(int i)

{

         int len=Length();

         if(i<1 || i>len)

                   return NULL;

         CircLinkNode<T>*  current=first;

         int k=1;

         while(k<i)

         {

                   current=current->link;

                   k++;

         }

         return current;

}

/*****************************************************/

//i个元素后插入元素

template<class T>

bool CircLinkList<T>::Insert(int i,T& x)

{

         CircLinkNode<T>*  current=Locate(i),*newNode;

         newNode=new CircLinkNode<T>(x);

         if(newNode==NULL)

         {

                   cerr<<"内存分配失败!"<<endl;

                   exit(1);

         }

         newNode->link=current->link;

         current->link=newNode;

         return true;

}

 

/*****************************************************/

//删除第i个元素

template<class T>

bool CircLinkList<T>::Remove(int i,T& x)

{

         CircLinkNode<T>*  current=Locate(i-1),*del;

         del=current->link;

         current->link=del->link;

         x=del->data;

         delete del;

         return true;

}

/*****************************************************/

//逆转链表

template<class T>

bool CircLinkList<T>::Reverse()

{

         int len=Length();

         CircLinkNode<T>*  rear=Locate(len);

        

         CircLinkNode<T>*  p=first,*q,*r;

         q=p->link;

         if(q==p)

                   return false;

         else

         {

                   p->link=rear;

                   while(q!=/*p*/first)

                   {

                            r=q->link;

                            q->link=p;

                            p=q;

                            q=r;

 

                   }

                   first/*->link*/=p;//最后一个节点就是头结点

                   return true;

         }

}

/***************************************************************/

//Josephus.h

#ifndef JOSEPHUS_H

#define JOSEPHUS_H

#include"CircLinkList.h"

template<class T>

void Josephus(CircLinkList<T>& js,int n,int m,int s)

{

         CircLinkNode<T>* current=js.Locate(s),*pre;

         for(int i=0;i<n-1;i++)

         {

                   for(int j=s;j<s+m-1;j++)

                   {

                            pre=current;

                            current=current->link;

                   }

                   cout<<"出列的人是: "<<current->data<<endl;

                   pre->link=current->link;

                   delete current;

                   current=pre->link;

         }

         cout<<"最后剩下: "<<current->data<<endl;

}

 

#endif

 

/***************************************************************/

//JosephusTest.h

#ifndef JOSEPHUSTEST_H

#define JOSEPHUSTEST_H

#include"CircLinkList.h"

#include"Josephus.h"

#include<iostream>

using namespace std;

void JosephusTest()

{

         CircLinkList<int>js;

         /********************************************

         约瑟夫问题求解

   *********************************************/

 

         cout<<"输入参与游戏的总人数:"<<endl;

         int n;

         cin>>n;

         cout<<"输入报数的间隔:"<<endl;

         int m;

         cin>>m;

         cout<<"输入报数的起始号码:"<<endl;

         int s;

         cin>>s;

 

         js.Creat(n);

         cout<<"有序链表元素为: "<<endl;

    js.output();

         Josephus(js,n,m,s);      

}

 

#endif

 

 

/***************************************************************/

//cllTest.h

#ifndef CLLTEST_H

#define CLLTEST_H

 

void cllTest()

{

         CircLinkList<int>cll;

         /********************************************/

         int endTag=-1;

         cout<<"创建单向循环链表,输入元素(-1结束)"<<endl;

         cll.input(endTag);

         cout<<"链表长度是: "<<cll.Length()<<endl;

         cout<<"显示链表元素: "<<endl;

         cll.output();

//定位元素

         cout<<"输入需要定位的元素序号: "<<endl;

         int index;

         cin>>index;

         CircLinkNode<int>* loc=cll.Locate(index);

         cout<<""<<index<<"元素是: "<<loc->data<<endl;

 

         //插入元素

         cout<<"输入需要插入的元素: "<<endl;

         int inx;

         cin>>inx;

         cout<<"输入需要插入的位置: "<<endl;

         int ini;

         cin>>ini;

         cll.Insert(ini,inx);

         cout<<"插入元素后的链表是: "<<endl;

         cll.output();

         //删除元素

         cout<<"输入需要删除元素的序号: "<<endl;

         int oi;

         cin>>oi;

         int ox;

         cll.Remove(oi,ox);

         cout<<"删除的元素是: "<<ox<<endl;

         cout<<"删除元素后的链表是:"<<endl;

         cll.output();

         //逆转链表

 

         bool reyn=cll.Reverse();

         if(reyn)

                   cout<<"逆转成功!"<<endl;

         else

                   cout<<"逆转失败!"<<endl;

         cout<<"逆转链表后为:"<<endl;

         cll.output();

}

 

#endif

 

/***************************************************************/

//main.cpp

#include"CircLinkList.h"

#include"CircLinkList.cpp"

#include"Josephus.h"

#include"JosephusTest.h"

#include"cllTest.h"

 

int main()

{

         cout<<"***********************************************/n"

                   <<"************基本功能的测试*********************"<<endl;

         cllTest();//基本测试

         cout<<"***********************************************/n"

                   <<"************约瑟夫问题的测试********************"<<endl;

         JosephusTest();//约瑟夫问题测试

         return 0;

}

 

结果图如下:

 

 

 

 

 

抱歉!评论已关闭.