Chinaunix首页 | 论坛 | 博客
  • 博客访问: 949506
  • 博文数量: 214
  • 博客积分: 10173
  • 博客等级: 上将
  • 技术积分: 1867
  • 用 户 组: 普通用户
  • 注册时间: 2007-06-18 13:48
文章分类

全部博文(214)

文章存档

2012年(1)

2010年(13)

2009年(5)

2008年(98)

2007年(97)

分类: LINUX

2007-11-14 18:33:09

出圈问题的链表解法(经典之作)
      出圈问题是上级考试中最难的题之一,可以说如果能独立解决这个问题那么其他的题自然不在话下。
      传统的解法使用了一种桥难理解的复杂算法,在这里我提供一种相对来说更易理解的算法“环链表模拟法”
   题目57:设有n个人围坐一圈并按顺时针方向从1到n编号,从第s个人开始进行1到m的报数,报数到第个m人,此人出圈,再从他的下一个人重新开始1到m的报数,如此进行下去直到所有的人都出圈为止。现要求按出圈次序,每10人一组,给出这n个人的顺序表。请考生编制函数Josegh()实现此功能并调用函数WriteDat()把结果p输出到文件OUT.DAT中。
设n=100,s=1,m=10.
(1)将1到n个人的序号存入一维数组p中;
(2)若第i个人报数后出圈,则将p[i]置于数组的倒数第i个位置上,而原来第i+1个至倒数第i个元素依次向前移动一个位置;
(3)重复第(2)步直至圈中只剩下p[1]为止。
部分源程序已给出。
请勿改动主函数main()和输出数据函数writeDat()的内容。
       下面是原题答案:
-------------------
void Josegh(void) /*标准答案*/
{int I,j,k,s1,w;
s1=s;
for(I=1;I<=n;I++) p[I-1]=I;
for(I=n;I>=2;I--)
{s1=(s1+m-1)%I;     “原题中采用的算法关键”
if (s1==0) s1=I;
w=p[s1-1];
for(j=s1;j<=I-1;j++) p[j-1]=p[j];
p[I-1]=w;}
}
注:题中第一个for()循环是先对数组p赋初值。在第二个for()中用i来控制没出圈的
总人数,s1=(s1+m-1)%i的作用是找出报数后出圈人的下标,其中对i求余的作用是使报
数按圈进行(即报到尾后又从头报),该算法在很多题目中都用到。由于求余的作用当
报数正好到最后一个时s1为0,故而要进行if(s1==0)的判断。内嵌的for()循环是将出圈
以后的人依次往前移。
     环链表模拟法
void Josegh(void)
{  typedef struct p { int n;
                     struct p *next;} m; /*定义结构体*/
   typedef m  *link;
   m  *h,*s,*r;             /*定义指针*/
   int i,j,a[100]={0};      
   h=malloc(sizeof(m));
   h->n=1;

   r=h;

   for(i=2;i<=100;i++)            /*赋初值*/
   {  r=(r->next=malloc(sizeof(m)));

      r->n=i;
             }

    r->next=h;
    r=r->next;

    for(i=0;i<100;i++)
    {  j=1;

       while(j<9)           /*模拟报数*/
       {  r=r->next;
       j++;}

       a[i]=r->next->n;
       h=r->next;
       r=r->next=h->next;
       free(h);
       printf("%d\t",a[i]);}
}

阅读(1370) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~