//使用单向循环链表实现
约瑟夫双向生死游戏是在约瑟夫生者死者游戏的基础上,正向计数后反向计数,然后再正向计数。具体描述如下:30(NumofPeople)个旅客同乘一条船,因为严重超载,加上风高浪大,危险万分;因此船长告诉乘客,只有将全船一半(NumofKilled)的旅客投入海中,其余人才能幸免遇难。无奈,大家只得同意这种办法,并议定30个人围成一圈,由第一个人开始,顺时针依次报数,数到第9(ForwardCount)人,便把他投入大海中,然后从他的下一个人数起,逆时针数到第5(ReverseCount)人,将他投入大海,然后从他逆时针的下一个人数起,顺时针数到第9人,再将他投入大海,如此循环,直到剩下15个乘客为止。问哪些位置是将被扔下大海的位置。
#include<iostream>
#define elementtype int
using namespace std;
struct node *p=NULL;
static int q=0;
struct node {
elementtype data;
node *next;
};
enum error_cod { arrange_error, success };
class list {
public:
list();
int length()const;
~list();
error_cod insert(const int i, const elementtype x);
error_cod delete_data(int pos);
elementtype get_data(const int i);
void add(elementtype data);
node* get_node(const int i);
void output(ostream& out) const;
int Location(int data);
node *returnhead(){
return head;
}
private:
int count;
node *head;
node *tail;
};
int list::Location(int data){
node *q=head;
for(int i=1;i<=this->length();i++){
if(data==q->data){
return i;
}
q=q->next;
}
}
list::list() {
head = tail = NULL;
count = 0;
}
node* list::get_node(const int i) {
node *p = head;
for (int j = 1; j < i - 1; j++) {
p = p->next;
}
return p;
}
void list::add(elementtype data) {//添加data到链表中去
//默认添加到表尾
node *dcl = new node;
dcl->data = data;
if (head != NULL) {
node *temp = tail->next;
tail->next = dcl;
dcl->next = temp;
}
else {
head = dcl;//新加节点成为头结点
head->data = data;
head->next = head;//指向自身
}//已经添加完毕,新增节点成为当前节点
tail = dcl;
count++;//长度+1
}
int list::length() const {
return count;
}
error_cod list::insert(const int pos, const elementtype data) {
if (0 == count && 1 == pos) {
this->add(data);//直接调用add函数
return success;
}
if (count >= pos && pos > 0) {//有数据并且没有越界才显示
int k = 1;//计数
node *dcl = new node;
dcl->data = data;
node *temp = head;
while (pos != k) {
temp = temp->next;//直到到达指定的位置
k++;
}//先到达指定位置
//分情况是因为如果插入到第一个节点会改变head的状态
if (count == pos) {
if (1 == count) {//只有一个节点的时候
head = dcl;//当前结点成为头结点
head->next = temp;
temp->next = head;//旧头结点的后继和新结点相连
}
else {//插入到尾结点的前面
node *p = this->get_node(pos);
dcl->next = p->next;
p->next = dcl;
}
count++;
return success;
}
else {
if (1 == pos) {//插入到第一个位置
head = dcl;//当前结点成为头结点
head->next = temp;
tail->next = head;
}
else {//插入到中间的其它位置
node *p = this->get_node(pos);
dcl->next = p->next;
p->next = dcl;
}
count++;
return success;
}
}
return arrange_error;
}
error_cod list::delete_data(int pos) {//删除指定位置的数据
if (count >= pos && pos > 0) {//有数据并且没有越界才显示
int k = 1;//计数
node *temp = head;
while (pos != k) {
temp = temp->next;//直到到达指定的位置
k++;
}//先到达指定位置
//分情况是因为如果删除最后一个节点会改变cur的状态,挂空指针
if (count == pos) {
if (1 == count) {//只有一个节点的时候
delete temp;
head = tail = NULL;//置空
}
else {//删除最后一个节点
node *p = this->get_node(pos);
node *s = p->next;
tail = p;
tail->next = s->next;
delete s;
}
count--;
return success;
}
else {//如果删除第一个节点head会改变
if (1 == pos) {
head = temp->next;
tail->next = temp->next;
delete temp;
}
else {
node *p = this->get_node(pos);
node *s = p->next;
p->next = s->next;
delete s;
}
count--;//长度-1
return success;//成功返回0
}
return arrange_error;//无数据或者越界返回-1
}
}
elementtype list::get_data(const int i) {
node *p = head;
for (int k = 1; k < i; k++) {
p = p->next;
}
return p->data;
}
list::~list() {
while (0 != count) {//用size来控制析构的次数
node *temp = head->next;
delete head;
head = temp;
count--;
}
}
void list::output(ostream &out)const {
int k = 1;
node *p = head;
while (k <= count) {
cout << p->data << " ";
p = p->next;
k++;
}
}
ostream& operator<<(ostream& out, const list&x) {
x.output(out);
return out;
}
int main() {
list dcl;
for (int i = 1;i<=30; i++) {
dcl.add(i);
}
p=dcl.returnhead();
while(dcl.length()>16){
for(int i=1;i<9;i++){
p=p->next;
}
cout<<p->data<<" ";
q=p->data;
p=p->next;
dcl.delete_data(dcl.Location(q));
for(int j=1;j<dcl.length()-3;j++){
p=p->next;
}
cout<<p->data<<" ";
q=p->data;
for(int m=1;m<dcl.length();m++){
p=p->next;
}
dcl.delete_data(dcl.Location(q));
}
for(int n=1;n<9;n++){
p=p->next;
}
cout<<p->data<<" ";
q=p->data;
p=p->next;
dcl.delete_data(dcl.Location(q));
system("pause");
return 0;
}