| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1648 人关注过本帖
标题:求高手解决一条很难的指针问题
只看楼主 加入收藏
EricZhan
Rank: 1
等 级:新手上路
帖 子:39
专家分:0
注 册:2010-7-9
结帖率:86.67%
收藏
已结贴  问题点数:15 回复次数:16 
求高手解决一条很难的指针问题
有n人围成一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来的第几号的那位。(最好可以用指针做,如果已经是顶尖高手还可以用结构体链表做一下,帮帮小弟.)
搜索更多相关主题的帖子: 指针 
2010-08-02 20:13
sd2930357
Rank: 2
等 级:论坛游民
帖 子:19
专家分:28
注 册:2010-7-25
收藏
得分:5 
哈哈,,这个问题是我刚做过的,,楼主参考下。。
check (int nub[],int n)
{ int *pt,i,j,k;
for(k=0,i=1;n-k>1;)
  {for(pt=nub;pt<(nub+n);pt++,i++)
   {if(*pt==0)
    {i--;}
   else if(i%3==0)
     {*pt=0;
      k++;
     }
   }
  }
}
main()
{  int a[100],*p,n,i;
   printf("input the unmber of people.\n");
   scanf("%d",&n);
   for(p=a,i=1;p<a+n;p++)
    *p=i++;
    p=a;
    check(p,n);

   for(p=a;p<a+n;p++)
   { if(*p==0) continue;
    printf("%d,",*p);
   }
getch();
}
2010-08-02 21:46
uppermore
Rank: 2
等 级:论坛游民
帖 子:33
专家分:26
注 册:2010-7-20
收藏
得分:0 
为什么我觉得除了前面两个,后面的都会被删除?数1,2,第三个删除,然后原来的四变成第三个,又删除......后来就全部删完后面的,最后剩下最初的两个,编号1和编号2
突然懂了,上面的想错了,应该是不断地数123

[ 本帖最后由 uppermore 于 2010-8-2 22:25 编辑 ]
2010-08-02 22:23
ggyy4k
Rank: 5Rank: 5
等 级:职业侠客
帖 子:111
专家分:334
注 册:2010-6-28
收藏
得分:0 
回复 楼主 EricZhan
按照楼主题目的意思,最后应该剩下两个人啊。比如这个圈子有3个人,只数一轮就结束了,结果剩下两个人。
2010-08-02 22:45
uppermore
Rank: 2
等 级:论坛游民
帖 子:33
专家分:26
注 册:2010-7-20
收藏
得分:3 
个人觉得用链表弄好弄多了,只是运行成本大,数组什么的想得头大,悲剧,楼主看下能用不
#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();
}
2010-08-02 23:34
EricZhan
Rank: 1
等 级:新手上路
帖 子:39
专家分:0
注 册:2010-7-9
收藏
得分:0 
题意不是只留下一个人吗?即还有两个的时候再报数,报到3的退出.
2010-08-03 19:28
sd2930357
Rank: 2
等 级:论坛游民
帖 子:19
专家分:28
注 册:2010-7-25
收藏
得分:0 
是留一个人啊,,楼主可以实际编译下看结果。。
2010-08-03 19:47
zisefengye
Rank: 5Rank: 5
等 级:职业侠客
帖 子:167
专家分:386
注 册:2010-6-27
收藏
得分:3 
我用数组做了一个,指针楼主自己试着改改看
#include <stdio.h>
#include <stdlib.h>
#define MAX 10
int main(int argc, char **argv)
{
    //int n = 10;改良,引入order记录退出次序
    int order = 1;
    int count = 1;
    int people[MAX] = {0};
    //while(n > 1)
    while(order < MAX)
    {
        for(int index = 0; index < MAX; index++)
        {
            //while(people[index] == 3)
            //{
            //    index++;
            //}
            while(people[index] != 0)
            {
                index++;
            }
            if(index >= MAX)
            {
                break;
            }
            //people[index] = count;
            //count++;
            //if(count > 3)
            //{
            //    count = 1;
            //    n--;
            //}
            if(count % 3 == 0)
            {
                people[index] = order;
                order++;
            }
            count++;
        }
    }
    printf("显示退出次序")
    for(int index = 0; index < MAX; index++)
    {
        if(people[index] != 0)
        {
            printf("people[%d] : %d\n", index, people[index]);
        }
    }
    printf("显示未退出的元素\n");
    for(int index = 0; index < MAX; index++)
    {
        if(people[index] == 0)
        {
            printf("people[%d] : %d\n", index, people[index]);
            break;
        }
    }
    system("pause");
    return 0;
}
楼主可以自己调试一下,我没一一测试数据。


[ 本帖最后由 zisefengye 于 2010-8-4 22:05 编辑 ]
2010-08-03 21:30
conquerorbzm
Rank: 2
等 级:论坛游民
帖 子:35
专家分:33
注 册:2010-7-23
收藏
得分:4 
/*这道题叫做约瑟夫问题,我们考过,当时我编的只能输出最后剩下的人,但就是不能正确输入退出人的顺序。所以看到你出了,我就顺便再做一遍。
我认为这道题仅用数组就可解决,指针也很方便,但看到有人用链表做,我觉得太麻烦了,你看看我。*/
#include"stdio.h"
int main()
{
    int i,j,k,n;
    int a[4000]={0};                        //定义个数组,把所有人存进去。
    while(scanf("%d",&n)!=EOF)                //k用来记推出人的个数,j用来数数。
    {    k=0;j=1;
        for(i=0;i<n;i++)
            a[i]=i+1;
        for(i=0;i<n;i++)
        a[-1]=a[n-1];                        //这个地方有点难理解,因为调试了许多遍才发现这里错了,先别管这,继续看。
        for(i=0;;i++)                        
        {        
            if(i>=n-1)                        //当数到n-1时,i又要重新归零,这里是-1,因为每循环完会加1,所以最后变成0;
                i=-1;                        //所以会出现个特例按我的程序,就是a[-1]时,自己想想吧。
            if(a[i]==-1)                    //a[i]=-1说明这人已退出,所以不计数,继续下次循环。
                continue;
            if(j%3==0)                        //这里是凡数到3,我就把这个人赋值为-1;并且输出已退出人的序号。
            {
                printf("%d ",a[i]);
                a[i]=-1;
                k++;
            }
            j++;
            if(k==n-1)                        //当有n-1退出时,循环就结束。
                break;
        }
        for(i=0;i<n;i++)                    //输出最后剩下的人。
            if(a[i]!=-1)
            {printf("\n%d\n",a[i]);
                break;
            }
    }
    return 0;
}

 //我调试了下,这程序应该是对的,你试试。希望你能满意。
2010-08-04 10:08
uppermore
Rank: 2
等 级:论坛游民
帖 子:33
专家分:26
注 册:2010-7-20
收藏
得分:0 
这个就是剩下一个的版本,其实都差不多,加一条语句,修改一下显示,就OK了
#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-1);
             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)
         {
             /*
             ** 剩下两个人的时候,数一的人将出局
             */
             free(link);
             break;
         }
         /*
         ** root要重新指向没数过的数,也就是link,第四个没数,从第四个开始报数1
         */
         root = link;
    }
    return root;
}
main()
{
    int n;
    no_p *root;
    printf("How many people are there ?");
    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("\nNO.%d left\n",root -> num);
    printf("free !");
    free(root);
    getch();
}

[ 本帖最后由 uppermore 于 2010-8-4 10:30 编辑 ]
2010-08-04 10:15
快速回复:求高手解决一条很难的指针问题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.027863 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved