#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; }
|