数据结构 —— 约瑟夫环
今日一言:
谢谢你,成为我前进的理由。
——《言叶之庭》
数据结构 —— 约瑟夫环
这是用链表实现的,
约瑟夫环的规则是:
总数为N的同学围成一个圆环,并将这些同学从1开始编号,
游戏开始时,约定好一个数字K,从1号同学开始轮着叫号,
当叫到K号时,该同学淘汰,下一位同学从1开始重新叫号,
只要叫到K号即淘汰,留下来的最后一位同学赢得游戏。
C语言实现
/*********************************************************************************
*
* 约瑟夫环
* create: 2020年5月24日 22点22分
* author: LOS(小鱼)
*
* *******************************************************************************/
#include<stdio.h>
#include<stdlib.h>
/*********************************************************************************
* 链表需要
********************************************************************************/
typedef struct Elem{
int value;
struct Elem *prev,*next;
}Elem;
struct{
Elem elems[200];
int size;
} Elems; // 全部的链表数据存储在这里 ( 不销毁, 但会覆盖 )
// 定义链表结构
typedef struct {
struct Elem *first;
struct Elem *last;
int size;
} LinkList;
// 初始化链表
void initLinkList( LinkList *list ){
list->size = 0;
}
// 获取表长
int getSizeL(LinkList *list){
return list->size;
}
void addFirst(LinkList *list,Elem *elem){
if( !getSizeL(list) ){
list->first = elem;
list->last = elem;
}
else {
elem->prev = list->last;
elem->next = list->first;
list->last->next = elem;
list->first->prev = elem;
list->first = elem;
}
list->size++;
}
// 添加元素
void addLast(LinkList *list,Elem *elem){
if( !getSizeL(list) ){
list->first = elem;
list->last = elem;
} else {
elem->prev = list->last;
elem->next = list->first;
list->last->next = elem;
list->first->prev = elem;
list->last = elem;
}
list->size++;
}
Elem * getElem(LinkList *list, int index){
int i ;
Elem *elem;
// 逐项访问
if ( index > list->size/2 ){
elem = list->last;
for ( i = list->size-1 ; i >= index ; i-- ){
if( i == index ){
return elem;
}
elem = elem->prev;
}
} else {
elem = list->first;
for ( i = 0 ; i <= index ; i++ ){
if( i == index ){
return elem;
}
elem = elem->next;
}
}
}
// 移除元素
void removeIndexL(LinkList *list, int index){
int i;
Elem *elem = list->first;
int flag = 0;
for ( i = 0 ; i <= index ; i++ ){
if( i == index ){
elem->prev->next = elem->next;
elem->next->prev = elem->prev;
if( list->first == elem ){
list->first = elem->next;
}
if( list->last == elem ){
list->last = elem->prev;
}
flag = 1;
}
elem = elem->next;
}
if(!flag) printf("没能完成任务!!!\n");
list->size--;
}
void removeElemL(LinkList *list, Elem *e){
int i;
Elem *elem = list->first;
int flag = 0;
for ( i = 0 ; i < list->size ; i++ ){
if( elem == e ){
elem->prev->next = elem->next;
elem->next->prev = elem->prev;
if( list->first == elem ){
list->first = elem->next;
}
if( list->last == elem ){
list->last = elem->prev;
}
flag = 1;
}
elem = elem->next;
}
if(!flag) printf("没能完成任务!!!\n");
list->size--;
}
/*********************************************************************************
* 链表需要
********************************************************************************/
Elem *createElem( int value ){
Elem *p = Elems.elems+Elems.size;
p->value = value;
Elems.size++;
if( Elems.size == 200 ) Elems.size = 0; // 注意不能超过200,否则数据错误
return p;
}
void main(){
LinkList list;
int n,k,i,count;
printf("请输入参与游戏的总人数:");
scanf("%d",&n);
fflush(stdin);
printf("请输入淘汰的间隔数:");
scanf("%d",&k);
fflush(stdin);
initLinkList(&list);
for ( i = 0 ; i < n ; i++ ){
Elem *elem = createElem(i+1);
addLast(&list,elem);
}
printf("游戏开始......\n");
count = 0;
while(list.size>1){
count = (count+k-1)%list.size;
printf("%d号同学被淘汰.\n",getElem(&list,count)->value);
removeIndexL(&list,count);
}
printf("最后的赢家是 --> %d号同学!\n",list.last->value);
}
运行结果
请输入参与游戏的总人数:10
请输入淘汰的间隔数:3
游戏开始......
3号同学被淘汰.
6号同学被淘汰.
9号同学被淘汰.
2号同学被淘汰.
7号同学被淘汰.
1号同学被淘汰.
8号同学被淘汰.
5号同学被淘汰.
10号同学被淘汰.
最后的赢家是 --> 4号同学!
--------------------------------
Process exited after 2.205 seconds with return value 27
请按任意键继续. . .