**## joseph问题**
需求:10个小朋友围成一圈,从1开始数数,数到9的小朋友出圈,再从1开始,直到所有的小朋友出列。
问第5次出圈的小朋友编号是多少?最后一个出圈的的小朋友编号是多少?
实现:用循环链表来解决
接口函数都可以直接调用,方便得很,而且joesph问题数的数也可以随便更改。
辛苦了一晚上,画了N多图,终于用自己的实现了 ,凯森ing!
常规操作:初始化、增加元素的尾部插入、打印循环链表信息、删除指定位置的元素,最后的销毁链表。
核心函数:解决问题的最重要函数是 自定义的joseph函数。循环遍历整个循环链表,数数到指定数时,出圈一个小朋友,直到链表为空(也即小朋友出局的个数达到最大数)结束循环。过程中要跳过头结点,同时加判断防止上一个出圈者是最后一个结点,下一次读取首结点而出现误判。
用一个整型数组来记录出局者的数据。
void joseph(linkLoopList*& link,int* iNum,int num) {
if (!link || link->next==link) return;
linkLoopList* p = link;
linkLoopList* tmp;
int cout=0;//记录数过的次数,循环累加,cout%9==0即出局
int outnum=0;//记录出局的小朋友个数
while (outnum<10) {
tmp = p;//记录前一个结点
p = p->next;
cout++;
if (link==p) {
cout--;
}
if (p!=link && cout % num == 0) {
//要加上p!=link,防止上一个出圈的小朋友是最后一个结点时,下一次读取首结点而出现误判!
iNum[outnum] =p->data ;
outnum++;
tmp->next = p->next;
delete p;
p = tmp;
}
}
}`
其余的代码如下,亲测无误,立字为证!
#include<Windows.h>
#include<iostream>
#include <assert.h>
using namespace std;
typedef struct _linkLoopList {
int data;
_linkLoopList* next;
}linkLoopList,linkLoopNode;
bool initLoopList(linkLoopList* &link);
bool linkLoopListInsertBack(linkLoopList* &link, linkLoopList* &e);
void linkLoopListPrint(linkLoopList* &link);
bool linkLoopListDelete(linkLoopList*& link, int i);//删除循环链表第i个位置的元素
void linkLoopListDestroy(linkLoopList* &link);//销毁循环链表
void joseph(linkLoopList* &link,int* iNum,int num);//num为报的数,小朋友的编号存于数组iNum中
int main() {
linkLoopList* link;
linkLoopList* node;
//01 初始化
if (initLoopList(link)) {
cout << "初始化循环链表成功!" << endl;
}
else {
cout << "初始化循环链表失败!" << endl;
}
//02 尾插法加入元素
cout << "*************采用尾插法加入元素***************" << endl;
for (int i = 0; i < 10; i++) {
node = new linkLoopList;
node->data = i + 1;
linkLoopListInsertBack(link, node);
}
linkLoopListPrint(link);
03 删除指定位置的结点
//cout << "*************删除指定位置的结点***************" << endl;
//if (linkLoopListDelete(link, 4)) {
// std::cout << "删除成功!" << std::endl;
// linkLoopListPrint(link);
//}
//else {
// std::cout << "删除失败!" << std::endl;
//}
//04--完成joseph的需求
int iNum[10] = { 0 };
joseph(link,iNum,3);
for (int i = 0; i < 10; i++) {
std::cout << iNum[i] <<" ";
}
std::cout<<std::endl;
system("pause");
linkLoopListDestroy(link);
return 0;
}
bool initLoopList(linkLoopList*& list) {
list = new linkLoopList;
list->data = -1;
list->next = list;
return true;
}
bool linkLoopListInsertBack(linkLoopList*& link, linkLoopList*& e) {
linkLoopList* node;
if (!link || !e) return false;
node = link->next;
while (node->next!=link) {
node = node->next;
}
node->next = e;
e->next = link;
return true;
}
void linkLoopListPrint(linkLoopList* &link) {
if (!link || link == link->next) return;
linkLoopList* p = link->next;
while (p != link) {
std::cout << p->data << " ";
p = p->next;
}
std::cout << std::endl;
}
void linkLoopListDestroy(linkLoopList*& link) {
if (!link) return;
linkLoopList* front = link;//记录首结点
linkLoopList* p = link->next;
while (p!= front) {
link=p->next;
delete p;
p = link;
}
delete front;
}
bool linkLoopListDelete(linkLoopList*& link, int i) {
if (!link) return false;
linkLoopList* p = link;
int pos = 0;
while ( pos < i - 1 && p->next!=link) {//先找到删除结点前的第i-1个位置
p = p->next;
pos++;
}
if (p->next==link || pos > i - 1) return false;
linkLoopList* q=p->next;
//assert(q->next);
p->next = q->next;
delete q;
return true;
}