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;
}
发布了48 篇原创文章 · 获赞 0 · 访问量 367

猜你喜欢

转载自blog.csdn.net/weixin_40071289/article/details/103996206
今日推荐