数据结构(一)线性表循环链表之约瑟夫环
(一)前提
41个人报数,1-3,当谁报数为3,谁就去嗝屁。现在获取他们嗝屁的顺序
(二)实现结构
顺序:3->1->5->2->4
(三)代码实现
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <time.h> #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 typedef int ElemType; typedef int Status; typedef struct Node { ElemType data; struct Node* next; }Node; typedef struct Node* CLinkList; //四个基本操作,初始,清空,判断是否为空,获取长度 Status InitList(CLinkList* L, int n); //指定开始位置来打印数据 void PrintListByIndex(CLinkList rear, int index); //用来打印链表 void PrintList(CLinkList rear);
int main() { CLinkList L = NULL; CLinkList p; ElemType e; int n = 41; int m = 3; int i; InitList(&L,n); //现在L指向第一个结点 PrintList(L); while (L!=L->next) //判断头尾指针是否指向相同,相同则元素都不存在 { for (i = 1; i < m-1; i++) L = L->next; //找到要删除的那个结点的前一个 printf("%d->", L->next->data); //获取被杀死的人的数据 p = L->next; //获取被杀死的人 L->next = p->next; free(p); L = L->next;//指向新的下一个元素 } printf("%d", L->data); //输出最后一个 free(L); system("pause"); return 0; } //四个基本操作,初始,清空,判断是否为空,获取长度 //初始化不带头结点的链表 Status InitList(CLinkList* L,int n) { CLinkList rear, q; //rear是尾结点 ElemType item; rear = q = NULL; srand(time(0)); for (int i = 0; i < n;i++) { item = rand() % 100; if (*L==NULL) { *L = (CLinkList)malloc(sizeof(Node)); if (!(*L)) return ERROR; (*L)->data = item; (*L)->next = *L; //自己指向自己 rear = *L; //设置尾指针位置 } else { //生成新的节点,根据尾指针添加节点,并实时更新尾指针。注意这里数据插入是尾插法 q = (CLinkList)malloc(sizeof(Node)); q->data = item; q->next = rear->next; rear->next = q; rear = q; } } return OK; }
//用来打印链表 void PrintList(CLinkList L) { CLinkList q = L; //获取头指针 while (q->next != L) { printf("%d ", q->data); q = q->next; } printf("%d\n", q->data); }
(四)扩展提升
1-N个人,按顺时针一圈,每个人手中有一个密码(一个正整数),
我们(裁判)定义第一个开始值为M,从第一个人开始自1开始报数,直到报数为M,那么这个人就退出,将他手中的密码值作为新的开始值,
一直循环直到所有的人都退出
情景演示
修改代码
int main() { CLinkList L = NULL; CLinkList p; ElemType e; int n = 19; int m; int i; InitList(&L, n); //现在L指向第一个结点 PrintList(L); scanf("%d", &m); //初始密码值我们输入 m--; //下面while循环都是由前一结点开始计算距离的,而我们这里是从第一个结点直接开始的,需要找到他的前一个节点,或者将走的步数减一即可 while (L != L->next) //判断头尾指针是否指向相同,相同则元素都不存在 { for (i = 1; i <= m - 1; i++) L = L->next; //找到要退出的那个人的前一个人 printf("%d->", L->next->data); //获取将要退出的人的密码 p = L->next; //获取即将退出的人 L->next = p->next; m = p->data; //更新密码值 free(p); //每次返回的都是退出结点的前一个节点,方便计算当密码为1的情况(重点)
} printf("%d\n", L->data); //输出最后一个人 free(L); system("pause"); return 0; }