正文

我所理解的队列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);     /*释放节点*/ }

阅读(4947) | 评论(0)


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

评论

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