1. 程式人生 > >帶密碼的約瑟夫環的解題思路

帶密碼的約瑟夫環的解題思路

題目:

編號為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 如有錯誤,歡迎指出。