个人觉得用链表弄好弄多了,只是运行成本大,数组什么的想得头大,悲剧,楼主看下能用不
#include "stdio.h"
#include "conio.h"
typedef struct
NUM_P
{
struct NUM_P *p;
int num;
} no_p;
/*
**
分配n个链表,并把他们连成一个圈
*/
no_p *be_circle(int n)
{
no_p *rootp,*link,*temp;
int i = 1;
/*
**
保存根节点,用于程序返回
*/
rootp = (no_p *)malloc(sizeof(no_p));
if(rootp == NULL) return rootp;
/*
**
编号
*/
rootp -> num = i;
link = rootp;
for(i = 2;i <= n;i++)
{
temp = (no_p *)malloc(sizeof(no_p));
if(temp == NULL)
{
printf("ONLY %d no_p",i);
return rootp;
}
/*
**
编号,然后连接
*/
temp -> num = i;
link -> p = temp;
link = temp;
}
/*
**
首尾连一起
*/
link -> p = rootp;
return rootp;
}
/*
**
报数并删除
*/
no_p *del_link(no_p *root)
{
no_p *delp,*link;
while(root -> p != NULL)
{
/*
**
root平移一个单位,指向下一个,也就是报数2
*/
root = root -> p;
/*
**
把delp指向第三个,报数三,在把link指向第四个,然后用root连接link
**
释放delp
*/
delp = root -> p;
link = delp -> p;
root -> p = link;
printf("No.%d out of the circle\n",delp -> num);
free(delp);
/*
**
考虑到剩下最后三个的时候,第四个就是上一轮报数的第一个,循环该结束了
**
当然root此时已经指向第二个了,我们没有指向第一个的指针,不过可以换个角度
**
考虑第一个不就指向第二个的吗?于是只要link->p == root我们就可以知道循环结束
*/
if(link -> p == root) break;
/*
** root要重新指向没数过的数,也就是link,第四个没数,从第四个开始报数1
*/
root = link;
}
return root;
}
main()
{
int n;
no_p *root,*freep;
printf("How many people there are ?");
scanf("%d",&n);
if(n < 0) exit(1);
printf("%d no_p To be a circle !\n",n);
root = be_circle(n);
root = del_link(root);
printf("NO.%d remain\n",root -> num);
printf("NO.%d remain\n",root -> p -> num);
printf("free them !");
freep = root -> p;
free(root);
free(freep);
getch();
}