链队列约瑟夫环c++代码_约瑟夫环问题详解 (c++)

本文介绍了约瑟夫环问题,详细讲解了问题的历史背景和解决思路,提供了两种C++实现方案:递归方法和循环链表法。通过递归方式和循环链表数据结构,演示了如何找到约瑟夫环中的最后生存者。并附带了完整的C++代码示例,展示如何模拟和删除节点的过程。
摘要由CSDN通过智能技术生成

问题描述:

已知n个人(以编号0,2,3...n-1分别表示)围坐在一起。从编号为0的人开始报数,数到k的那个人出列;他的下一个人又从1开始报数,数到k的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列,最后一个出列的人为胜利者。求胜利者编号.

历史背景:

Wikipedia: 这个问题是以弗拉维奥·约瑟夫斯命名的,它是1世纪的一名犹太历史学家。

他在自己的日记中写道,他和他的40个战友被罗马军队包围在洞中。

他们讨论是自杀还是被俘,最终决定自杀,并以抽签的方式决定谁杀掉谁。约瑟夫斯和另外一个人是最后两个留下的人。

约瑟夫斯说服了那个人,他们将向罗马军队投降,不再自杀。约瑟夫斯把他的存活归因于运气或天意,他不知道是哪一个.

问题分析:解决该问题有两种思路,第一种:通过建立循环链表来模拟这个过程

第二种:通过递归方式(数学归纳将问题转化为数学问题)

由于递归方式,代码更简洁,下面首先以递归方式来解决问题

——————递归实现:

例如对 m= 10,k=3

0  1  2  3  4  5  6  7  8  9  (*)

0  1  3  4  5  6  7  8  9    (* 循环下去)

转化为:       3  4  5  6  7  8  9  0  1  (* 循环下去)

0  1  2  3  4  5  6  7  8

m=10,k=3 去掉一个元素之后,变成了一个m=9,k=3的约瑟夫环问题

并且有如下关系

3 = (0+3)%10   4 = (1+3)%10   ... 0 = (3+7)%10

即 3 = (0+k)% m    4 =  (1+k) % m       ... 0  = (3+k) % m

m =10,k =3 设约瑟夫环最后一个出列的人为 Joseph(10,3),那么存在如下关系

Joseph(10,3) = (Joseph(9,3)+k) %m;

...

Joseph(n,k) = (Joseph(n-1,k)+k) % n (n>1);

C++实现如下:

递归方法一:

1 int Joseph(int m,intk)2 {3 if(m<=0||k<=0)4 {5 cout<

8 {9 if(m==1)10 {11 return 0;12 }else

13 {14 return ((Joseph(m-1,k)+k)%m);15 }16 }17 }

递归方法二:如果输出整个出队的顺序

int Joseph(int m,int k,inti)

{if(m<=0||k<=0||m

{

cout<

}else{if(i==1)

{return (m+k-1)%m;

}else{return ((Joseph(m-1,k,i-1)+k)%m);

}

}

}

程序运行结果如下:

intmain()

{

cout<

cout<< Joseph(6,3) <

cout<

{

cout<

}

getchar();return 0;

}

结果:

——————循环链表实现:

建立节点数据结构:循环链表

structNode

{intdata;

Node*next;

};structLinkedList

{

Node*pHead;

Node*pTail;intlen;

};

建立循环链表

//建立个节点

Node * GetNode(inti)

{

Node* p = (Node *)malloc(sizeof(Node));if(p!=NULL&&i>=0)

{

p->data =i;

p->next =NULL;returnp;

}else{

cout<

exit(-1);returnNULL;

}

}//建立链表

LinkedList* CreateLinkedList(inti)

{

Node* node = GetNode(0);

LinkedList*head = (LinkedList*)malloc(sizeof(LinkedList));if(head ==NULL)

{

cout<

exit(-1);returnNULL;

}if(i<=0)

{

cout<

exit(-1);returnNULL;

}

head->pHead =node;

head->pTail =node;

head->len = 1;if(i==1)

{

node->next =node;

}else{

Node*p = head->pHead;for(int j=1;j<=i-1;j++)

{

Node* node =GetNode(j);

node->data =j;

p->next =node;

p=p->next;

head->len++;

}

head->pTail =p;

p->next = head->pHead;

}returnhead;

}

删除节点:

//删除节点

void RemoveNode(LinkedList*head,Node *deleNode)

{

Node* p = head->pHead;

cout<data<len>1){do{if(p->data==deleNode->data)

{if(p==head->pHead)

{

head->pHead = p->next;

}if(p==head->pTail)

{

head->pTail = p->next;

}

p->data = p->next->data;

p->next = p->next->next;

head->len--;return;

}else{

p=p->next;

}

}while(p!=head->pHead);

}else{

cout<

exit(-1);return;

}

}else{return;

}

}

约瑟夫模拟:

int Joseph(int m,intk)

{if(m<=0||k<=0)

{

cout<

}

LinkedList* list =CreateLinkedList(m);//Print_List(list);

Node * p = list->pHead;for(int i=1;i<=k;i++)

{if(list->len ==1)

{return p->data;

}if(i==k)

{

RemoveNode(list,p);

i= 1;

}

p=p->next;

}return 0;

}

程序运行结果如下:

int _tmain(int argc, _TCHAR*argv[])

{

cout<

cout<

getchar();return 0;

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值