正文

我所理解的队列022005-12-18 15:47:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/goal00001111/8488.html

分享到:

举个简单的例子,围圈问题的详细算法和程序

17人围成一圈,编号为1,2,3,……,17,从1开始报数,报到3的倍数的人离开,

一直下去,直到最后剩下1人,求此人的编号。

这个题目的解法很多,我原来就总结了5种,但都不如用数组队列来的简明。算法如下:

/*求围圈问题的详细算法和程序*/

/*17人围成一圈,编号为1,2,3,……,17,从1开始报数,报到3的倍数的人离开,

一直下去,直到最后剩下1人,求此人的编号  */

#include <stdio.h>

#include <stdlib.h>

int main(void)

{

       int a[17]={0};

       int front=0, rear=16;  //因为数据较小,可令队头元素也占一个实用(有数据域)的空间

       int i, count=0; //计数器               

       for (i = 0;i < 17;i++)

              a[i] = i + 1;    /* 填空数组,编号是下标加一,注意C语言中的数组下标从0开始 */ 

       while((front%17) != (rear%17))//当队列元素还有一个,注意这里不需要队列为空,而是留一个元素

       {

              if(++count <  3)//若元素非3的倍数,往前移

                     a[++rear%17] = a[front++%17];

              else    //否则将该元素从队列中删除,并打印

              {

                     printf("%d\n",a[front++%17]);    /* 把这个家伙打印出来 */

                     count = 0;

              }           

       }

       printf("最后一个是:%d\n",a[rear%17]);                     

        system("pause");

    return 0;                

}

另,附上几个不同的算法:(多数是我自己写的,部分是收集别人的 )

一:

int main(void)

{

    int a[17]={0};

       int i, count, s;

        

         for (i = 0;i < 17;i++)

    {

        a[i] = i + 1;    /* 填空数组,编号是下标加一,注意C语言中的数组下标从0开始 */

    } 

    i=0;

    s=17;  //用来记录退出圈外的人的数目

    count=0;  //计数器

    while(s > 1)

    {

                     for(i=0; i<17; i++)

                            if(a[i] != 0)

                            {

                                   count++;    //报一次数

                                   if(count == 3)  //每报到一次3,该人退出

                                   {

                                          printf("%d\n",a[i]);    /* 把这个家伙打印出来 */

                                          a[i] = 0;

                                          count = 0;  //计数器归零

                                          s--;

                                   }

                            }

        }       

        for(i=0; i<17; i++)

               if(a[i] != 0)

                     printf("最后一个是:%d\n",a[i]);

                     

        system("pause");

    return 0;                

}

二:

int main(void)

{

    int* arr;    /* 用于存储“那些人” */

    int n;        /* “那些人”的总数 */

    int s;        /* 开始的编号 */

    int m;        /* 间隔多少个人出列一个 */

    int i,j;  

    printf("请输入多少个人:\n");

    scanf("%d",&n); 

    printf("请输入开始的序号:\n");

    scanf("%d",&s);   

    printf("请输入间隔的人数:\n");

    scanf("%d",&m); 

    arr = (int*)(malloc(sizeof(int) * n));    /* 申请一个数组,以存储“那些人” */   

    if (arr == NULL)    /* 并非一定分配成功的 */

    {

        printf("空间不足,程序退出。\n");

        return 1;

    }   

    for (i = 0;i < n;i++)

    {

        arr[i] = i + 1;    /* 填空数组,编号是下标加一,注意C语言中的数组下标从0开始 */

    } 

    printf("出列顺序:\n");   

    j = s + m - 2;    /* 这是第一个要出列的人的下标 */  

    while (n > 1)    /* 当队列中还有不止一个人的时候,要就进行出列的动作 */

    {

        printf("%d\n",arr[j]);    /* 把这个家伙打印出来 */       

        /* 这个家伙走了以后,后面的人应该依次顶上来 */

        for (i = j;i < n - 1;i++)

        {

            arr[i] = arr[i + 1];

        }

        n--;    /* 并且整个队列的人少了一个,也就是长度要减掉一 */

        /* 这是下一个要出列的人 */

        j = (j + m - 1) % n;

    }

     /* 现在只有一个人了,就是arr[0] */

    printf("最后一个是:%d\n",arr[0]);   

    free(arr);    /* 记得要释放申请的空间 */   

        system("pause");

    return 0;

}

三: 

int main(void)

{

    int a[17]={0};

        int i, j, s;        

         for (i = 0;i < 17;i++)

    {

        a[i] = i + 1;    /* 填空数组,编号是下标加一,注意C语言中的数组下标从0开始 */

    } 

    i=0;

    s=17;

    j=0;

    while(s > 1)

    {

                     if(a[i%17] != 0)

                     {

                            if((i+1-j)%3 == 0)

                            { 

                                   printf("%d\n",a[i%17]);    /* 把这个家伙打印出来 */

                                  a[i%17] = 0;

                                   s--;

                            }

                     }

                     else

                            j++;              

                     i++;

        }        

        for(i=0; i<17; i++)

               if(a[i] != 0)

                     printf("最后一个是:%d\n",a[i]);

        system("pause");

    return 0;                

}

四: 

int main(void)

{

       int n, m;   

       int* a;    /* 用于存储“那些人” */

       int i, j, s; 

      

       printf("请输入多少个人:\n");

   scanf("%d",&n);

   printf("请输入是哪个数字的倍数:\n");

   scanf("%d",&m); 

   a = (int*)(malloc(sizeof(int) * n));    /* 申请一个数组,以存储“那些人” */   

   if (a == NULL)    /* 并非一定分配成功的 */

   {

      printf("空间不足,程序退出。\n");

      return 1;

   }   

   for (i = 0; i < n; i++)

   {

      a[i] = i + 1;    /* 填空数组,编号是下标加一,注意C语言中的数组下标从0开始 */

   }

       i = 0;   //从下标为 i%n 的元素开始数数

       j = 0;   //记录已经退出的元素的个数

       s = n;   //记录尚未退出的元素的个数

       while(s > 1)

   {

              if(a[i%n] != 0) //如果元素值不为0,则表示其尚未退出

              {

                     if((i+1-j)%m == 0) //判断当前报数(i+1-j)是否为m的倍数,(-j)表示跳过j个元素

                     { 

                            printf("第%d号出列\n",a[i%n]);    /* 把这个家伙打印出来 */

                            a[i%n] = 0;   //已经退出的元素赋值为0

                            s--;    //退出一个元素

                     }

              }

              else   //如果元素值为0,则表示其已经退出

                     j++; //此时i值仍然会累加,但我们记下这个已经退出的元素 ,以便报数时跳过它          

              i++;

       }

        

      for(i=0; i<n; i++)

              if(a[i] != 0)

                    printf("最后一个是:%d\n",a[i]);

                   

       free(a);    /* 记得要释放申请的空间 */

       system("pause");

   return 0;                

}

 五:

 /*此算法我看不懂*/

void fun(int m, int n);

 

int main(void)

{

       int n, m;  

       int* a;    /* 用于存储“那些人” */

       int i, j, s; 

      

       printf("请输入多少个人:\n");

   scanf("%d",&n);

   printf("请输入是哪个数字的倍数:\n");

   scanf("%d",&m);

   fun(n, m);

   system("pause");

   return 0;                

}  

void fun(int m, int n)

{

    int *pos;

    int i, p = m-1;  

    pos = (int*)malloc(m*sizeof(int));

    pos[m-1] = 0;    

    for (i=0; i<m-1; i++)

        {  

        pos[i] = i+1;

    }      

    do{

        //  printf("\np=%d\t", p);

      for (i=0; i<n-1; i++)

         p = pos[p]; 

     // printf("%d ",pos[p]+1);

      pos[p] = pos[pos[p]];

    }       while(p != pos[p]);  

    printf("%d", p+1); 

}

六: 

int main(void)

{

       int n, m;  

       int* a;    /* 用于存储“那些人” */

       int i, j, s; 

      

       printf("请输入多少个人:\n");

   scanf("%d",&n);

   printf("请输入是哪个数字的倍数:\n");

   scanf("%d",&m);

   a = (int*)(malloc(sizeof(int) * n));    /* 申请一个数组,以存储“那些人” */   

   if (a == NULL)    /* 并非一定分配成功的 */

   {

      printf("空间不足,程序退出。\n");

      return 1;

   }  

   for (i = 0; i < n; i++)

   {

      a[i] = i + 1;    /* 填空数组,编号是下标加一,注意C语言中的数组下标从0开始 */

   }

       i = 0;   

       j = 0;   //报数

       s = n;   //记录尚未退出的元素的个数

       while(s > 1)

   {

              if(a[i%n] != 0) //如果元素值不为0,则表示其尚未退出

              {

                     j++;

                    if(j%m == 0) //判断当前报数是否为m的倍数

                     { 

                            printf("第%d号出列\n",a[i%n]);    /* 把这个家伙打印出来 */

                            a[i%n] = 0;   //已经退出的元素赋值为0

                            s--;    //退出一个元素

                     }

              }    

              i++;

       }        

      for(i=0; i<n; i++)

              if(a[i] != 0)

                    printf("最后一个是:%d\n",a[i]);                   

       free(a);    /* 记得要释放申请的空间 */  

       system("pause");

   return 0;                

}

七:

typedef struct List

{

    int Number;

    struct List *Next;

}Node,*Link;

 

Link Create_List(int n) ;   /*建立循环链表*/

void Print_List(Link Head)  ;     /*遍历打印链表*/

void Kick(Link Head, int m, int s);       /*设置函数,将数据逐个踢出队列*/

int main(void)

{

    Link ysf;   /* 用于存储“那些人” */

    int n;        /* “那些人”的总数 */

    int s;        /* 开始的编号 */

    int m;        /* 间隔多少个人出列一个 */   

    printf("请输入多少个人:\n");

    scanf("%d",&n); 

    ysf = Create_List(n);

    Print_List(ysf);   

    printf("请输入开始的序号:\n");

    scanf("%d",&s);  

    printf("请输入间隔的人数:\n");

    scanf("%d",&m);

 

    Kick(ysf,m,s);

    printf ("\n");

    system("pause");

    return 0;

Link Create_List(int n)    /*建立循环链表*/

{

    Link Head;

    Link New;

    Link Pointer;

 

    Head=(Link)malloc(sizeof(Node));    /*申请头节点*/

    if( Head == NULL)    /* 并非一定分配成功的 */

    {

        printf("空间不足,程序退出。\n");

        exit(1);

    }

    Head->Number = 1;

    Head->Next = NULL;

    Pointer = Head; 

    for (int i=1;i<n;i++)           /*对中点节点进行赋值并连接链表*/

    {

           New=(Link)malloc(sizeof(Node));

      if (New == NULL)    /* 并非一定分配成功的 */

          {

             printf("空间不足,程序退出。\n");

             exit(1);

          }

      New->Number = i+1;    

      New->Next = NULL;

              Pointer->Next = New;

      Pointer = New;

       }

      Pointer->Next = Head;       

    return Head;

}

void Print_List(Link Head)       /*遍历打印链表*/

{

    Link Pointer; 

    Pointer = Head;

    while (Pointer->Next != Head)

    {

        printf ("%d ",Pointer->Number);

        Pointer=Pointer->Next;

    }

    printf ("%d ",Pointer->Number);

    printf ("\n");

}

void Kick(Link Head, int m, int s)       /*设置函数,将数据逐个踢出队列*/

{

        Link NEW_HEAD;     /*被踢出节点的直接前驱*/

    Link PrePointer;     /*被踢出节点的直接前驱*/

    Link Pointer;     /*被踢出队列的节点*/

    int j=1;

 

    NEW_HEAD = Head;

    while(NEW_HEAD->Number != s)

                NEW_HEAD = NEW_HEAD->Next;

        PrePointer = NEW_HEAD;  

    while (1)

    {

               j = 1;  printf ("\nj=%d \n",j);

        while (j++ < m)

            PrePointer = PrePointer->Next; 

        Pointer = PrePointer->Next;

        PrePointer->Next = Pointer->Next;    /*前驱与后继相连,将节点踢出*/

        PrePointer = PrePointer->Next;      

        printf ("tizou %d ",Pointer->Number); 

        free(Pointer);

        if (PrePointer->Next==PrePointer)

            break;

    }

    printf ("shengxia %d",PrePointer->Number);

    free (PrePointer);     /*释放节点*/

}

阅读(2482) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册