約瑟夫環--C語言
阿新 • • 發佈:2019-01-08
約瑟夫(Joseph)問題的一種描述是:編號為1,2,3,…,n的n個人按順時針方向圍坐一圈。每人持有一個密碼(正整數)。一開始任選一個正整數作為報數上限值m,從第一個人開始按順時針方向自1開始順序報數,報到m時停止報數,令其出列,將他的密碼作為新的m值,從他在順時針方向上的下一個人開始重新報數,如此下去,直到所有人全部出列為止。
試設計一個程式求出出列順序。
測試資料:m的初值為20;n=7,7個人的密碼依次為:3,1,7,2,4,8,4(對應於節點的密碼),首先m值為20,則正確的出列順序應為6,1,4,7,2,3,5(對應於節點的編號)
在設計程式時要特別注意第一個插入的節點和最後一個刪除的節點的處理;還有就是密碼為1的節點出列後的下一個節點的處理(因為密碼為1的節點出列後下一個出列的節點即為該節點出列之前的下一個節點)。
程式碼:
#include <stdio.h>
#include <stdlib.h>
typedef struct JoseCycleNode
{
int pwd;//密碼
int num;//節點編號
struct JoseCycleNode *next;//指向連結串列下一個節點的指標
}JoseCycleNode;//連結串列結構體
//建立約瑟夫環
JoseCycleNode *createLinkList(int num)
{
int i = 0;
JoseCycleNode *p = NULL;
JoseCycleNode * last = NULL;//指向連結串列中最後插入的節點的指標
while(i < num)
{
p = (JoseCycleNode *)malloc(sizeof(JoseCycleNode));
printf("Please input %ds node's password!\n",i + 1);
scanf("%d",&p->pwd);
p->num = i + 1;
if(0 == i)
{
p->next = p;//i = 0代表是第一個插入的節點,迴圈連結串列的第一個節點的next指標指向節點本身
}
else
{
p->next = last->next;
last->next = p;
}
last = p;
i ++;
}
last = last->next;//將指標指向第一個插入的節點
return last;
}
//按照刪除節點的順序輸出節點編號
void putNum(JoseCycleNode *List,int pwd)
{
int i = 0;
JoseCycleNode *p = List;
while(List->next != List)
{
for(i = 1;i < pwd - 1;i++)
{
p = p->next;
}
List = p;
p = p->next;
pwd = p->pwd;
List->next = p->next;
printf("%d ",p->num);
free(p);
if(pwd == 1)
{
p = List;//當密碼為1時,只需要刪除List節點的下一個節點即可
}
else
{
p = List->next;//因為計數是從被刪除節點的下一個節點開始
}
}
printf("%d\n",p->num);//輸出最後一個節點的節點編號
free(p);//刪除最後一個節點
}
int main()
{
JoseCycleNode *List = NULL;
int num = 0;//連結串列節點個數
int pwd = 0;
printf("Please input node number:");
scanf("%d",&num);
List = createLinkList(num);
printf("Please input first limit cycle num!\n");
scanf("%d",&pwd);
putNum(List,pwd);
return 0;
}
這個是當時上大學時沒有實現的程式碼,好像當時沒有處理好只有一個節點的情況。今天突然想到了就寫了一下,用的時間不算很少,但也還好~堅持下去吧~自己會越來越強大的!