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

来源:互联网 发布:佳成餐饮软件 编辑:程序博客网 时间:2024/05/22 17:30
约瑟夫问题(有时也称为约瑟夫斯置换,是一个出现在计算机科学和数学中的问题。在计算机编程的算法中,类似问题又称为约瑟夫环。又称“丢手绢问题”)
据说著名犹太历史学家 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 <iomanip>#include <iostream>#include <ctime>#include <cassert>using namespace std;#define LEN 20#define RANLEN 100typedef 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不能超过20cout<<a[i]<<setw(3);if( i == LEN -1 )cout<<endl;}//选择排序for( i = 0; i < LEN-1; i++){min = i;for( j = i+1; j < LEN;j++ ){if( a[min] > a[j] ) min = j;}if( min != i ){temp = a[min];a[min] = a[i];a[i] = temp;}}for( i = 0; i < LEN; i++ ){cout<<a[i]<<setw(3);if( i == LEN - 1)cout<<endl;}head->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!"<<endl;}return head;}void CircleList::TraverseCircleList(){Lnode *search = head;cout<<"遍历链表结果:"<<endl;while( search->next != head ){search = search->next;cout<<search->data<<setw(3);}}ElemType CircleList::GetElem(int pos){int i = 0;Lnode *search = head;for( i = 0; i < pos; i++ ){search = search->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;elsecurr = 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<<"未报数之前人的编号顺序:"<<endl;cl.TraverseCircleList();cout<<endl;cl.Reset(x-1);for( i = 0; i < n-1; i++ ){for( j = 0; j < m-1; j++ )cl.Next();cout<<cl.DeleteNext()<<"元素被删除!"<<endl;}cout<<"最后剩下的元素为:"<<cl.GetCurrNode()->data<<endl;}int _tmain(int argc, _TCHAR* argv[]){/*CircleList cl;cl.CreateCircleList(10,1);cl.TraverseCircleList();cl.DeletePosNode(2);cout<<"删除后的链表为:"<<endl;cl.TraverseCircleList();*/JosephProblem(10,3,1);return 0;}

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

原创粉丝点击