需求分析
一群小孩編號為1,2,…,n(n>0)圍成一圈,有一個剛出鍋的山芋在他們之間傳遞。假設剛開始由1號拿着山芋,然后依次計數把山芋交給下一個小孩,當數到某個特定的k時,拿着山芋的小孩退出游戲,然后從下一個小孩重新開始計數,如此不斷,最后剩下的那個孩子就是幸運者。要求設計一個程序模擬次過程,並給出不同的n,k組合下那個幸運者是誰?
1、 輸入的形式和輸入值的范圍:演示程序以用戶和計算機的對話方式執行,即在計算機終端上顯示“提示信息”之后,由用戶在鍵盤上輸入相應的數據,每個人的序號由程序自動分配。以int型輸入,范圍在-2147483648~2147483648;
2、 輸出的形式:int型;
3、 程序所能達到的功能:構造鏈表;輸入數據;執行報數;儲存出列人的序號,刪除出列人的信息以及把指向出列人的指針移到出列人的下一個人,然后重新開始執行報數;直到最后一個人報數完畢,程序結束。
4、 測試數據:n=9,9個人的序號分別為:1,2,3,4,5,6,7,8,9。然后b=1,從第一個開始報數。k=5,則確定輸出的序列為:5,1,7,4,3,6,9,2,8。
#include<stdio.h>
#include<stdlib.h>
//聲明循環鏈表結構體
typedef struct LNode
{
int num;//數據域
struct LNode *next;//結構體指針
}LNode;//結點類型
//創建結點
LNode *Create_node(int Lnum)
{
LNode *Lp;//創建結點指針
Lp=(LNode *)malloc(sizeof(LNode));//分配動態儲存空間
Lp->num=Lnum;//*Lp指向num,把num的值傳給Lnum
Lp->next=NULL;//*Lp指向下一個元素結點為空,確定*Lp是頭結點指針
return Lp;//返回頭結點指針
}
//創建循環鏈表
LNode *Create_Linklist(LNode *pHead, int Lsum)
{
int k;
LNode *p, *temp;//創建兩個指針
for(k=1;k<=Lsum;k++)//遍歷整個鏈表
{
p=Create_node(k);
//如果鏈表為空,創建鏈表第一個結點,其next指針指向自身
if(pHead==NULL)
{
temp=p; //把p的值傳給temp
pHead=p; //把p的值傳給pHead
temp->next=pHead; //讓*temp指向的下一個位置為pHead
}
//否則,執行插入節點操作
else
{
p->next=temp->next;//空白指針跟着*p后面,一個接一個插入
temp->next=p;
temp=p; //把p的值再傳給temp
}
}
//測試是否生成循環鏈表成功!
p=pHead;
k=1;//初始化k的值
while(p->next!=pHead)//用循環輸出鏈表中的元素
{
printf("第%d個小孩的編號為:%d\n",k,p->num);
p=p->next;//指針移向下一個位置
k++;
}
printf("第%d個小孩的編號為:%d\n\n",k,p->num);//確保最后一個元素能顯示出來
return pHead;//返回頭指針
}
//執行出列操作
void Delete_Linklist(LNode *pHead,int Lstart, int Ldel)
{
int i,count=1;//count為計數器
LNode *p, *temp;
p=pHead;
//找到第M個孩子所在的位置
for(i=1;i<Lstart;i++)
p=p->next;
//只剩1個結點時終止循環
while(p->next!=p)
{
//找到要出列的孩子的位置
for(i=1;i<Ldel;i++)
{
temp=p;
p=p->next;
}
//執行出列操作
temp->next=p->next;//讓*temp指向*p后面的結點
printf("第%d個出列的小孩的編號為:%d\n",count,p->num);
free(p);//釋放*p
count++;
//出列者的下一個孩子作為新的第一個報數者
p=temp->next;
}
printf("第%d個出列的小孩的編號為:%d\n",count,p->num);
free(p);
//所有人均出列,頭結點釋放后賦空值,避免出現懸垂指針
pHead=NULL;
}
/*主函數*/
int main()
{
int n,b,k;
LNode *pHead=NULL, *p;//執行初始化操作
//輸入字符的合法性驗證暫時忽略
printf("請輸入小孩的個數:\n");
scanf("%d",&n);
printf("請輸入開始報數的小孩編號:\n");
scanf("%d",&b);
printf("請輸入報數數目:\n");
scanf("%d",&k);
p=Create_Linklist(pHead,n);//調用創建鏈表函數
Delete_Linklist(p,b,k);//調用刪除鏈表函數
return 0;
}
