今日一言:
謝謝你,成為我前進的理由。
——《言葉之庭》
數據結構 —— 約瑟夫環
這是用鏈表實現的,
約瑟夫環的規則是:
總數為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
請按任意鍵繼續. . .
