20200115数据结构和算法之循环链表,解决joesph问题!

                 **## 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值