帶密碼的約瑟夫環的解題思路
阿新 • • 發佈:2018-12-16
題目:
編號為1,2,…,n的n個人按順時針方向圍坐一圈,每個人持有一個密碼(正整數)。一開始任選一個正整數作為報數上限值m,從第一個人開始按順時針方向自1開始順序報數,報到m時停止報數。報m的人出列,將他的密碼作為新的m 值,從他在順時針方向上的下一個人開始重新從1報數,如此下去,直到所有人全部出列為止。
學完連結串列後面的題目,最後一題就是要求用連結串列實現約瑟夫環帶密碼的問題。 很明顯建立一個迴圈連結串列可以實現我們想要的結果。
單迴圈連結串列的建立與單鏈表的建立一樣,只是將尾結點的指標域指向頭指標所在的地址。
宣告一個人的結構體,每個人有自己的編號和所攜帶的密碼,所以:
struct node
{
int position; //位置
int m; //所持密碼
struct node *next;
};
建立單迴圈連結串列:
void CreateList(node **head, int n) //資料錄入與單迴圈連結串列的建立
{
node *p1, *p2;
int i = 1;
p1 = p2 = (node *)malloc(sizeof(node));
(*head)->next = p1; //頭指標的指標域指向第一個結點
while(n--)
{
scanf("%d",&p1-> m);
p1->position = i;
p2->next = p1; //指向新的
p2 = p1;
p1 = (node *)malloc(sizeof(node)); //新的節點
i++; //人數
}
p2->next = *head; //尾結點指向頭結點
}
錄入資料後,建立好了一個單迴圈連結串列。 接下來是主函式:
int main()
{
int n, M;
int i, k = 1;
node *head;
node *p1, *p2, *pf = NULL ;
if( (head = (node *)malloc(sizeof(node))) == NULL)
exit(1);
printf("n = ");
scanf("%d", &n);
CreateList(&head, n); //迴圈連結串列資料錄入
printf("第一次報數上限 m = ");
scanf("%d",&M);
printf("出列順序為: ");
p1 = head;
while(n != 0)
{
for(i = 1; i <= M; i++) //經過這一步,p1指向了即將要被踢出的那個人
{
p1 = p1->next; //結點移動
if(p1 == head)
p1 = p1->next; //迴圈了一遍之後,下個人從1開始數
if(i == M - 1) //記錄被踢出的結點左邊結點
p2 = p1;
}
free(pf);//釋放被踢出的那個人所在的位置
M = p1->m; //密碼值的更換
printf("%d ",p1->position); //輸出被提出的那個人的位置
p2->next = p1->next; //重新連線連結串列
n--;
}puts("");
system("pause");
return 0;
}
實現的過程: 通過for迴圈,使得連結串列指標指到將要被踢出人所在的位置,踢出可以理解為釋放掉那個人在的位置,並且把被釋放的結點左右結點接合起來,再次形成鏈式結構。
測試情況:
編譯環境:vs2010 如有錯誤,歡迎指出。