解题思路:
1:创建长度为n的循环链表(单链表的最后一个结点与首结点连接,不是头结点);
2:链表结点包括编号和next指针;
3:从首结点p开始报数(p=p->next),但是只报数到离开的结点的前一个结点,然后删除它后面的结点,更新报数的第一个结点(p=p—>next);用指针q指向要删除的结点;
4:重复上述过程,直到链表中只有一个结点结束(即:p->next=p);
5:如下图假设有6个结点(6个人),报数数为3;
把头结点free了,因为删除过程中,头结点的next被删除的话,头结点next指向不安全地方,就不要用它了;
以上就是链表的实现过程,要挑战自己可以弄一个单链表实现的,再厉害一点可以顺序表,但顺序表不推荐,
顺序表删除要移动大量元素
报数到最后一个之后,返回第一个的实现过程复杂,需要用下标关系,很容易晕;
注意事项:
每个结点删除后都要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*/ }
别忘点赞哦-.-
0.0分
48 人评分
没搞懂链表只是也不想用指针所以用循环写了一个 #include<stdio.h> #include<string.h> int main() { int n,a[50],b[50],i,j,m,q=0; scanf("%d",&n); for(i=0;i<n;i++)a[i]=i+1;a[i]=0;b[0]=1; for(m=0;b[0]!=0;m++) { j=0; for(i=0;a[i]!=0;i++) { q++; if(q%3!=0) {b[j]=a[i];j++;} else continue; }b[j]=0; memcpy(a,b,sizeof(b)); if(j==2){printf("%d",b[1]);break;} } return 0; }
大佬,你这个程序,当N=1(即所报数字为1时),就错了。
p->next = q->next; /* 采用后差法插入节点 */ q->next = p; q = p; 这段代码不是前插法吗??
今天你也学英语了嘛 2022-03-21 14:47:30 |
尾插法啊
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; }
我也利用大佬的思想,写了一下,把大佬说的第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
数列 (C++代码)浏览:707 |
C语言程序设计教程(第三版)课后习题10.5 (C语言代码)浏览:1485 |
求圆的面积 (C语言代码)浏览:1366 |
蛇行矩阵 (C语言代码)浏览:792 |
C语言程序设计教程(第三版)课后习题5.7 (C语言代码)浏览:606 |
【计算球体积】 (C语言代码)浏览:1158 |
蚂蚁感冒 (C语言代码)浏览:816 |
C二级辅导-同因查找 (C语言代码)浏览:618 |
简单的a+b (C语言代码)浏览:683 |
简单的a+b (C语言代码)浏览:491 |
QUchenchen 2024-04-26 22:23:06 |
牛!