使用循环链表实现 “猴子选大王”

本文解析猴子选大王问题的编程实现,通过计数和淘汰规则追踪每个猴子的命运,直至剩下一猴成为大王。涉及链表操作和淘汰条件判断。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:猴子选大王,现有n个猴子,一开始从第k个猴子开始从1开始报数,报到t的猴子会被淘汰,然后又从它的下一个猴子从1开始报数,如此循环,一直到只剩下一个猴子,这个猴子就是大王了,求得每次被淘汰猴子的编号及最后选出的猴大王编号。

#include<stdio.h>
#include<stdlib.h>

typedef struct ListNode node;

struct ListNode{
	  int data;//编号 
	  node* next;  
}; 

typedef struct LinkQueue{
	node* front;
	node* rear;
} Queue;

Queue* Build(Queue* S, int Data)//构建结构 
{
	if(S->rear == NULL){
	    node* p = (node* )malloc(sizeof(node));
		S->front->next = p; 
		S->rear = p;
		p->next = NULL;
		p->data = Data; 	
	    return S;
	}else{
        node* p = (node* )malloc(sizeof(node));
        S->rear->next = p; 
		S->rear = p;
	    p->data = Data;
	    p->next = NULL;
	    return S;
	}
}

void Solution(Queue* S, int k, int t, int n)//解决问题 
{//从第K个猴子开始  报到 t的猴子会被淘汰 
	node* p= S->front->next;//空节点的下一个
	node* p2 = S->front;//作用是跟在P的后面,便于删除节点 
	/*因为p2永远跟在p后,而消除的永远是p指向的节点,因此
	最后剩下的只有p2指向的节点*/ 
	int frist = k; 
	int death = t;
	int num = 1;
    
    if(frist==1&&death==1){
    	while(p!=S->rear){
	    	printf("\n被淘汰猴子的编号为:%5d\n", p->data);
			p = p->next; 
	    }
		printf("\n\n\n猴子大王的编号为:%5d\t", p->data);
    }
	for(int i=2; i<=frist; i++){
		 p = p->next;
		 p2 = p2->next;
	}//此时P到了第K个 
	//因为p2必须进入循环体,所以frist,death两者不能都为1 

	while(p!=p2&&p&&(frist!=1||death!=1)){
	    while(num==death&&p&&n!=1){
            node* h = p;
            printf("\n被淘汰猴子的编号为:%5d\n", h->data);
			p2->next =  p2->next->next;
			p = p2->next;
			h->next = NULL;
			free(h); 
			num = 1;
			--n;
  		}
        p = p->next;
        p2 = p2->next;
        ++num;//继续报数   
	} 
	if(p2&&(frist!=1||death!=1)){
      printf("\n\n\n猴子大王的编号为:%5d\t", p2->data);	
	}
    
}

int main()
{
	 //构建循环结构 
	 Queue* S = (Queue* )malloc(sizeof(Queue));//存放头尾指针 
	 node* head = (node* )malloc(sizeof(node));//头节点 
	 head->next = NULL; 
	 S->front = head;
	 S->rear = NULL;
     /*如果只有1个猴子,那么没有选择的必要
	   因此一定大于1*/
	 int n, i, Data;//n个猴子且n不为1 
     printf("n = \t");
     scanf("%d" ,&n);
 	 while(n <= 1){
 	 	 printf("输入猴子数过小,请重新选择:\n");
 		 printf("n = \t");
         scanf("%d" ,&n);
 	 } 
	 
	 i = n; 
     while(i--){
    	 printf("\n输入编号:\t");
     	 scanf("%d" ,&Data);
     	 S = Build(S, Data);
     }
	 S->rear->next = S->front->next;//首尾相连
	 //循环结构建立完成
	 //接下来到了计算阶段
	 int k, t; 
	 printf("\n从第几个猴子开始?:\t");
	 scanf("%d", &k); 
	 printf("\n报到几的猴子会被淘汰?:\t");
	 scanf("%d", &t); 
	 
 	 if(k <= n&&t >= 1){
 		Solution( S, k, t, n);
 	 }else{
 	 	printf("\n输 入 错 误 !\n");
 	 }
	 
	 
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值