題目要求:編號為1,2,...n的n個人按順時針的方向圍坐一個圈,每個人持有一個密碼.一開始任選一個正整數作為報數的上限值m,從第一個人開始按順時針方向自1開始順序報數,報到m時停止報數.報到m的人出列,將他的密碼作為新的m的值,從他的順時針方向的下一個人開始重新從1報數,如此下去,直至所有人全部出列為止.
測試要求:m的初值為20,n=7,7個人的密碼依次為:3 1 7 2 4 8 4.出列順序應為6 1 4 7 2 3 5
#include<stdio.h>
#include<stdlib.h>
struct node{
int num;
struct node *next;
}a;
struct node * creat(int n); //返回頭指標
int excute(int m,struct node *head);//返回最後剩下的人的編號
main()
{
int n;
int m;
struct node *h = NULL;
printf("input how many people\n");
scanf("%d",&n);
printf("input which people been delete\n");
scanf("%d",&m);
if(n < 1 || m < 1){ /*對特殊情況的討論*/
printf("wrong input!\n");
return -1;
}else if( n == 1 ){
printf("nobady left!\n");
return 0;
}else if( m == 1 ){
printf("the last number is %d\n",n);
return 0;
}else{
h = creat(n);
printf("\nthe last number is %d\n",excute(m,h));
return 0;
}
}
struct node * creat(int n) //構造迴圈鏈表
{
struct node * p = NULL;
struct node * h = NULL;
struct node * q = NULL;
int num = 0;
p = (struct node *)malloc( sizeof(a) );
p->num = ++num;
p->next = NULL;
h = p;
while( --n !=0 ){
q= (struct node *)malloc( sizeof(a) );
q->num = ++num;
p->next = q;
p = q;
}
if(p != NULL)
p->next = h;
return h;
}
int excute(int m,struct node *h)
{
struct node *current=NULL;
struct node * p=NULL;
int i;
current = h;
printf("the out order is:");
while (current->next != current){
for (i = 1; i < m; i++){ /* 尋找報數為m的小孩結點 */
p = current;
current = current->next;
}
p->next = current->next; /* 刪除報數為m的小孩結點 */
printf("%5d",current->num); //列印出被淘汰的順序
free(current); /* 釋放報數為m的小孩結點空間 */
current = p->next;
}
return current->num;
}
1,先確定資料結構為迴圈鏈表,每一個元素為一個結構,包括兩個變數。再畫一個圖,找到解題的思路,寫出大致的演算法。
2,根據畫的圖,先不考慮特殊的情況,寫出代碼。
3,編譯,連結,確保無錯。
4,加入安全方面的考慮,如非法輸入等。
5,加入易用性方面的代碼。
6,編譯,連結,確保無錯。
之後可以參考一下別人的代碼,可能會發現很多新的方法和思路。
比如,這個題目也可以這樣做:
#include <stdio.h>
#include <stdlib.h>
#include <string.h> //沒有使用鏈表
int main(int argc, char *argv[])
{
int m, n, step=0, index=0, cir=0;
char *out=NULL;
scanf("%d%d", &m, &n);
out = (char*)malloc(m);//可以看作是數組的動態分配,好!!。與memset函數聯合使用
if(out == NULL)
return -1;
memset(out, 0, m); //因為malloc不對分配的記憶體進行初始化,所以這裡用memset進行初始化
while(1){
if(step==m)
break;
while(cir<n) {
if(!out[index])
++cir;
index=(index+1)%m;
}
cir=0;
++step;
out[(index+m-1)%m]=1;
printf("\nNo.%d out.", !index?m:index);
}
free(out);
system("PAUSE"); //當有非法輸入時,如0,5或4,0時,在螢幕上顯示“請按任意鍵繼續”
return 0;
}
也可以這樣做:
/**********************************************
********* Josephus problem ************
*********************************************/ //和我的方法差不多
#include <malloc.h>
#include <stdio.h>
struct boy /* struct of boy*/
{
int num;
struct boy *next;
};
int main()
{
int i;
int number; /* 小孩的數目 */
int interval; /* 即報數從1- interval */
struct boy *head, *p, *current;
printf("please input the number of boys:");
scanf("%d", &number);
printf("please input the interval:");
scanf("%d", &interval);
if(number < interval || number <= 0 || interval <= 0)
{
printf("input error!!!\n");
return 0;
}
head = (struct boy *) malloc(sizeof(struct boy));
head->num = 1;
head->next = NULL;
current = head;
printf("Boy numbers:%d,", head->num);
for (i = 2; i <= number; i++)/* 建立單向迴圈鏈表 */
{
p = (struct boy *) malloc(sizeof(struct boy));
p->num = i;
p->next = NULL;
current->next = p;
current = p;
printf(" %d,", p->num);
}
printf("\n");
current->next = head;
current = head;
printf("Out queue order:");
while (current->next != current) /*loop to find the winner */
{
for (i = 1; i < interval; i++) /* 尋找報數為interval的小孩結點 */
{
p = current;
current = current->next;
}
p->next = current->next; /* 刪除報數為interval的小孩結點 */
printf(" %d,", current->num);
free(current); /* 釋放報數為interval的小孩結點空間 */
current = p->next;
}
printf("\n");
printf("No.%d boy's won!\n", current->num);
getch();
return 0;
}
From:
http://www.80diy.com/home/20050410/23/3924954.html
http://dev.csdn.net/article/71/71711.shtm
http://www.programfan.com/club/showpost.asp?id=21255&t=o
http://tieba.baidu.com/f?kz=158638008
http://baike.baidu.com/view/717633.htm
http://blog.sina.com.cn/s/blog_4e5a13ad01009ccb.html