首先先解释约瑟夫环问题,这个问题,背景其实挺残酷的,来自于一场自杀游戏,举个现实的例子,如果你有4个朋友,但是只能给一个人带饭,那么做这样的游戏,4个人围成一个环,你说从1开始数,数到2,就淘汰掉2,剩下的继续围成一个环,在继续这个游戏,直到剩下一个为止。
表达能力有限,直接百度百科!
约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。通常解决这类问题时我们把编号从0~n-1,最后结果+1即为原问题的解。
那么如何构建环以及如何进行删除操作是最重要的了!
构建之前,我们要有一个已经存在的tail,有无数据不重要,
首先是构建的问题:
//实现一个插入操作
void addElements(int value){
if(tail==nullptr){
//第一种情况是链表里面没有任何的结点,那么新建的结点有特殊的操作,指向自己,形成一个环
tail=new node(value);
//让tail指向自己,形成一个小环
tail->next=tail;
}else{
//新建结点
node * new_node=new node(value);
//让原来的结点的next指向变成此时新结点的指向
new_node->next=tail->next;
//让tail指向新结点,形成一个环
tail->next=new_node;
//让新结点成为tail,继续进行下一步的增加操作,循环往复
tail=new_node;
}
}
构建完约瑟夫之后,接下来是一个删除操作
/*index表示需要输入的数*/
void delete(index){
//设置临时变量
node*p=tail;
//避免程序抛出nullPointexception
if(p!=nullptr&&p->next!=p){
for(int i=0;i<index-1;i++){
p=p->next;
}
}
node * delete_element=p->next;
p->next=p->next->next;
if(delete_element==tail)
tail=p;
//C++实现,需要释放内存
delete delete_element;
}
如此就可以实现一个约瑟夫环的构建与删除的问题,总结一下:
1、在构建的时候,首先意识到这个是一个圆环,所以哪怕是一个元素,也要让它指向自己。
2、在构建新结点的时候,需要让tail原本的关系给新结点,然后再指向新结点,不可以颠倒顺序,不然会丢失原结点的关系
从约瑟夫环衍生到循环链表,其实约瑟夫环就是一个循环链表,哈哈哈