解题思路:
1:创建长度为n的循环链表(单链表的最后一个结点与首结点连接,不是头结点);

2:链表结点包括编号和next指针;

3:从首结点p开始报数(p=p->next),但是只报数到离开的结点的前一个结点,然后删除它后面的结点,更新报数的第一个结点(p=p—>next);用指针q指向要删除的结点;

4:重复上述过程,直到链表中只有一个结点结束(即:p->next=p);

5:如下图假设有6个结点(6个人),报数数为3;

2017-12-22 22-10-34屏幕截图.png

把头结点free了,因为删除过程中,头结点的next被删除的话,头结点next指向不安全地方,就不要用它了;

2017-12-22 22-11-03屏幕截图.png

2017-12-22 22-11-27屏幕截图.png

2017-12-22 22-19-26屏幕截图.png

2017-12-22 22-11-54屏幕截图.png

以上就是链表的实现过程,要挑战自己可以弄一个单链表实现的,再厉害一点可以顺序表,但顺序表不推荐,

  1. 顺序表删除要移动大量元素

  2. 报数到最后一个之后,返回第一个的实现过程复杂,需要用下标关系,很容易晕;



注意事项:
每个结点删除后都要free了,输出留下来的那个人之后也要把它的free了;


参考代码:

#include <malloc.h>
#include <iostream>
using namespace std;

typedef struct student {
    int        number;
    struct student    * next;
}*node, Node;                           /* 结点 */

node creat( int n );                    /* 创建链表函数 */

void function( node l1, int baoshu );   /* 运行函数 */


int main()
{
    int    n;                      /* 人数 */
    node    head1;                  /* 链表的头结点 */
    int    baoshu = 3;
    cin >> n;
    /* cin >> baoshu; */          /*加上这句,实现n个人,报数数为baoshu */
    head1 = creat( n );             /* 创建链表*/

    function( head1, baoshu );

    return(0);
}


/*-------------------------------------------------------------*/

node creat( int n )
{
    node h;                                         /* 头结点指针 */
    h    = (node) malloc( sizeof(Node) );        /* 创建头结点 */
    h->next = NULL;                                 /* next指针域赋空 */
    node    q = h;                                  /* 定义指针q,指向头结点 */
    node    p;

    for ( int i = 1; i <= n; i++ )                  /* 创建n个结点 */
    {
        p        = (node) malloc( sizeof(Node) );
        (*p).number    = i;                    /* 输入编号 */

        p->next = q->next;                      /* 采用后差法插入节点 */
        q->next = p;
        q    = p;
    }
    q->next = h->next;                              /* 尾结点和首结点链接 */

    return(h);                                      /* 返回头结点 */
}


/*-------------------------------------------------------------*/
void function( node l1, int baoshu )              /* 移除实现 */
{
    node p = l1->next;                        /* 指向首结点 */
    free( l1 );                               /* free头结点 */
    node q = NULL;                             /* 指向被移除结点,用于释放移除的人的结点 */
    while ( p->next != p )
    {
        for ( int i = 1; i <= baoshu - 2; i++ ) /* 移动到离开的人的结点的前一个,只需要移动baoshu-2次; */
            p = p->next;

        q    = p->next;              /* 记录删去的人的结点 */
        p->next = q->next;           /* 把q结点从链表移除 */

        p = p->next;                 /* 移动到下一个开始报数的人,很重要这一步 */
        free( q );             /*释放q结点*/
    }

    cout << p->number;
    free( p );      /* 把最后一个结点free*/
}

别忘点赞哦-.-

点赞(95)
 

0.0分

43 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 23 条评论

z能 5年前 回复TA
r(int i=1;i<=n;i++)
 	{
 		p=(Linklist)malloc(sizeof(Lnode));
 		p->data=i;
 		p->next=NULL;
 		r->next=p;
 		r=p;
	 }
	 p->next=L->next;
	 return L; 
 }
 void selection(Linklist h,int x)
 {
 	Linklist p=h;
 	while(p->next!=p)
 	{
 		for(int i=1;i<=x-1;i++)
 	   {
 		p=p->next;
	   }
 	   Linklist q=p->next;
       p->next=q->next;
       delete q;
	 }
    std::cout<<p->data;
 }
z能 5年前 回复TA
我也利用大佬的思想,写了一下,把大佬说的第69行代码 /* 移动到下一个开始报数的人,很重要这一步 */这一步骤,改成每次直接移动两位。还有大佬写的45行,虽然我也理解大佬那样写的意思,但是把 p->next = q->next;直接改成p->next=NULL,也就是把链表尾部的next域每次都赋予NULL值,是不是更容易理解一点?代码如下:
#include<iostream>
#include<stdlib.h> 
typedef struct Lnode
{
	int data;
	struct Lnode *next;
} Lnode,*Linklist;
 Linklist creat(Linklist L,int n);
 void selection(Linklist h,int x);
int main()
{
	int n,x=3;
	
	Linklist L=(Linklist)malloc(sizeof(Lnode));//这样传参?? 
 	L->next=NULL;
 	std::cin>>n;
 	Linklist h=creat(L,n);
 	selection(h,x);
	return 0;
 } 
 
 Linklist creat(Linklist L,int n)
 {
 	Linklist p;
 	Linklist r=L;
 	fo
编程cxk 5年前 回复TA
循环链表啥的没复习看不懂,可以试试这个
#include <stdio.h>
void turn(int a[],int n,int m);
int main(int argc,const char *argv[])
{
	int a[100]={0},b[100];
	int i,j,n;
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		a[i]=1;
	}
	int sum=0,cnt=0;
	for(i=1,j=0;i<=n;i++){
		sum+=a[i];
		cnt++;
		if(sum==3){
			a[i]=0;
			sum=0;
			cnt=0;
			b[j]=i;
//			printf("b[%d]=%d\n",j,b[j]);
			j++;
		}
		if(i==n)i=0;
		if(cnt>3*n)break;
	}
	printf("%d\n",b[j-1]);
	return 0;
}

其实意思也差不多了
楚之棠 5年前 回复TA
为什么我经常打开网页图片无法显示,今天又碰到了⊙∀⊙!
氟先森 5年前 回复TA
只有我一个人来看题目是什么意思的吗?
juzi 5年前 回复TA
q->next = h->next;                              /* 尾结点和首结点链接 */
这是什么意思?对吗?没明白
juzi 5年前 回复TA
能AC吗
居外先生 6年前 回复TA
怎么看的有点头疼
我有个喵喵酱 6年前 回复TA
神TM简单易懂,大佬的世界我果然不懂
c晨光 6年前 回复TA
厉害,循环链表想到了,就是没勇气去写,哎,学到了不少东西,感谢