读书人

约瑟夫有关问题

发布时间: 2012-04-14 17:14:21 作者: rapoo

约瑟夫问题——求助
约瑟夫问题——假设有n个人围圈而坐,现在从第k人开始数数,数到m的人出列,紧接着的后续人又从1开始数数,到m出列,如此重复下去,直到全体人员出列。编程实现新出列的数字序号输出。
我使用了循环链表,以下是我的代码(为了调试,加了一些printf语句):

#include<stdio.h>
#include<stdlib.h>
typedef struct CLNode{
int data;
struct CLNode *next;
}Node;//定义单循环链表结构体及指针
Node* Creat(Node* head,int n);
int Search(Node* head,int m);
int main()
{
int m,n,i,k,j;
int *ret=NULL;//动态增长的数组,用来存放出列人员的号码
Node *head=NULL;
printf("How many person?");
scanf("%d",&n);
if(n<=0){
printf("Can't be zero!\n");
exit(0);
}
head=Creat(head,n);//建立链表,测试成功!
ret=(int*)malloc(n*sizeof(int));
if(ret==NULL){//动态增长的数组
printf("Allocate memory error!\n");
exit(1);
}
printf("Which number should be out:");
scanf("%d",&m);
printf("Which number do you want to start:");
scanf("%d",&k);
for(j=1;j<k;j++){//测试成功!
head=head->next;
}
printf("now head data is %d\n",head->data);
printf("\n");
i=0;
while(head->next!=head){
printf("at first head data is %d\n",head->data);//test
ret[i]=Search(head,m);//返回找到的值
printf("************output data is %d\n",ret[i]);//输出
i++;
printf("\n");
}
free(head);
return 0;
}
/*Create函数:参数为Linklist型结点指针和数量n
-建立单循环链表,如果成功,返回该链表的头指针*/
Node* Creat(Node *head,int n)
{
Node *p=NULL;
Node *pr=head;
inti;
for (i=1; i<=n;i++){
if (head==NULL)
{
head=(Node*)malloc(sizeof(Node));
if(head==NULL){
printf("Allcate memory error!\n");
exit(1);
}
head->next=head;
head->data=i;
pr=head;
}
else
{
p=(Node*)malloc(sizeof(Node));
if(p==NULL){
printf("Allcate memory error!\n");
exit(1);
}
pr->next=p;
p->data=i;
p->next=head;
pr=p;

}
}
return head;
}
/*Search函数:返回data域为m的结点,删除它,
-并令此节点之后的结点为头结点,数据域从它开始*/
int Search(Node *head,int m)
{
int i=1;
int data;
Node *cur_p=head,*pre=NULL;//head为开始数1的人
printf("**now head data ** is %d\n",head->data);
if(head->next==head){
return head->data;
}
while(i<m){
pre=cur_p;
cur_p=cur_p->next;
i++;
}
data=cur_p->data;
printf("pre number is %d\n",pre->data);//test
printf("current number is %d\n",data);//test
printf("before delete,head data is %d\n",head->data);//test
pre->next=cur_p->next;
free(cur_p);
head=pre->next;//改变头指针!!!没有成功!
printf("after delete,head data is %d\n",head->data);//test
return data;
}

这里会出现一个问题,问题的原因应该是:删除一个节点之后,我会改变头指针,但修改没有成功。比如,我设定
共有5个人,然后数到第4的人会出列,从原本编号为1的人开始数,这样输出结果应该为:
4,3,5,2,1(原本编号为1,2,3,4,5)
按理说,编号为4的人出列后,应该从编号为5的人开始数。但这里仍是从编号为1的人开始数,让我很是奇怪。
希望哪位高手能帮助我看一下


[解决办法]
[code=C/C++][/code]
/*Search函数:返回data域为m的结点之后的结点,
另其为头结点,数据域从它开始再次循环*/
Node* Search(Node *head,int m)
{
int i=1;
int data;
Node *cur_p=head,*pre=NULL;//head为开始数1的人
while(i<m){//数数,移动指针
pre=cur_p;
cur_p=cur_p->next;
i++;
}
data=cur_p->data;
printf("output number is:%d\n",data);
pre->next=cur_p->next;
free(cur_p);
head=pre->next;
return head;
}

读书人网 >软件架构设计

热点推荐