您的位置:首页 > 其它

算法----约瑟夫环的简易实现

2014-07-10 12:20 281 查看
题目:用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。

分析:该题目的通用解法是利用循环链表,当然也可以利用循环数组。易于扩展的做法是,定义循环链表的数据结构,并实现循环链表的基本操作,利用这些基本操作如插入、删除、初始化、构建链表等操作;简易的实现方法则是仅适合该题目的解法。

采用无头的循环链表,如果有头,则需要在每次遍历中跳过头节点。因为采用了无头的链表,因此在插入或者删除时,需要针对头节点特殊处理:

1、插入时,链表为空,则当前待插入的节点为链表头;

2、删除时,由于题目只要求输出删除节点,链表又是循环链表,因此可以不考虑删除节点为头节点的情况。不过,为了删除当前节点,我们需要保存其前驱结点的指针。

代码如下:

#include <iostream>
#include "joseph.h"

using namespace std;

void joseph()
{
int m = 0, n = 0;
cin >> n >> m;

Node head = NULL;
Node current = NULL;

for (int i = 1; i <= n; ++i) {
Node tempNode = new ListNode();
tempNode->data = i;

if (head == NULL) { //构建链表,特殊处理头节点
head = tempNode;
head->next = head;
current = head;
} else {
current->next = tempNode;
tempNode->next = head;
current = current->next;
}
}

Node prev = current; //此处有些取巧,我们从链表头开始遍历链表,其前驱应为表尾,链表构建完成过后current指针恰好为表尾,因此先保存该指针
current = head; //再给current赋值,指向表头
int cnt = 1; //初始化计数器,当前节点计数器为1

while (current != current->next) { //循环条件为直至链表剩余一个元素,此时current != current->next
if (cnt == m) {
cnt = 1; //当前节点需要删除,重置计数器
prev->next = current->next; //更改当前节点的前驱结点的后继结点为当前节点的后继
cout << current->data << '\t';
delete current;
current = prev->next; //重新赋值current
} else {
++cnt;
prev = current;
current = current->next;
}
}

cout << current->data << endl; //输出链表最后一个元素
delete current;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: