约瑟夫环的设计在百度知道和另一贴131楼和133楼命名为"金箍"就是观音大士给孙悟空头上戴的金箍.MSDN示例代码
List 贝 = new List(Enumerable.Range(1, 1000000));/*生成元素加入约瑟夫环*/
int 序 = 2 - 1, 报 = 8 - 1, 量 = 贝.Count();/*报数减去自身报1因此要-1,元素序从0开始因此要-1*/
do/*这是真实逐个排除的设计环算法:10000运行1.7秒,10万运行14.7秒,*/
{/*顺环计算,当序=数组量时,因为序应是-1的,那么,等于数组量的序就要转到序0处*/
序 = (序 + 报) % 量;
Console.WriteLine("出局数: {0}", 贝[序]);
贝.RemoveAt(序);
量 = 贝.Count();
} while (量 > 1);
Console.WriteLine("\n胜出数: {0}", 贝[0]);
c++版的代码,等有空闲心情再说了
int 序 = 2 - 1, 报 = 8 - 1, 量 = 40, 止 = 1;/*报数减去自身报1因此要-1,元素序从0开始因此要-1*/
List 贝 = new List(Enumerable.Range(1, 量));/*生成1-10元素加入约瑟夫环*/
do/*这是真实逐个排除的设计环算法:10000运行1.7秒,10万运行14.7秒,*/
{/*顺环计算,当序=数组量时,因为序应是-1的,那么,等于数组量的序就要转到序0处*/
序 = (序 + 报) % 量;
Console.WriteLine("出局数: {0}", 贝[序]);
贝.RemoveAt(序);
量--;
} while (量 > 止);
Console.WriteLine("\n胜出数: {0}", 贝[0]);
c++:
void 金箍环(int 序, int 报, int 止, int 量)
{
//const list::size_type 容量 = 量;
int 数(1);
list 动态;
list::iterator 序头;
do/*填充顺序数组*/
{
动态.push_back(数++);
} while (量 >= 数);
--序;
--报;
do
{
序 = ((序 + 报) % 量 == 0) ? 0 : (序 + 报) % 量;/*序 = (序 + 报) % 量;*/
//list::iterator 动态序 = find(动态.begin(), 动态.end(), 序);
序头 = 动态.begin();
数 = 0;
while (数 < 序)/*序转换为元素*/
{
*序头++;
数++;
};
cout << *序头 << endl;
动态.erase(序头);
} while (--量 > 止);
//cout << *动态.begin() << endl;
序头 = 动态.begin();
do/*如果[止]大于1循环剩余元素*/
{
std::cout << *序头++ << endl;
} while (--量);/*非零值做逻辑等效“真”*/
};
之下把数组对分处理以减少循环量:
void 金箍环(int 序, int 报, int 止, int 量)
{
int 数(1); list 动态;
do
{
动态.push_back(数++);
} while (量 >= 数);
--序;
--报;
do
{
序 = ((序 + 报) % 量 == 0) ? 0 : (序 + 报) % 量;/*序 = (序 + 报) % 量;*/
list::iterator 序头 = 动态.begin();
list::iterator 序尾 = 动态.end();
if (量 / 2 >= 序)
{
数 = 0;
while (数 < 序)/*序转换为元素*/
{
*序头++;
数++;
};
cout << *序头 << endl;
动态.erase(序头);
}
else
{
数 = 0;
do/*因为指向数组尾后一位故需先行执行一次以指向实际尾元素*/
{
*--序尾;
数++;
}
while (数 < 量 - 序);
cout << *序尾 << endl;
动态.erase(序尾);
}
} while (--量 > 止);
cout << *动态.begin() << endl;
};
主函数中调用:
金箍环(2, 8, 1, 40);
cout << "金箍环:" << endl;
金箍环(9, 9, 1, 81);
运行结果与上图一样.
之下逆推金箍环算法,对数组分半减少循环量处理就不写了,参考上例原理,依然以调用:金箍环逆推(2, 8, 1, 40);为例:
void 金箍环逆推(int 序 = 2, int 报 = 2, const int 止 = 4, int 量 = 9)
{
int 数(1); list 动态;
do/*填充顺序数组*/
{
动态.push_back(数++);
} while (量 >= 数);
--序;
--报;
序 = 量 - 1 - 序;/*逆推*/
do
{
序 = ((序 - 报) % 量 < 0) ? 量 + ((序 - 报) % 量) : (序 - 报) % 量;/*逆推*/
list::iterator 序头 = 动态.begin();
数 = 0;
while (数 < 序)/*序转换为元素*/
{
*序头++;
数++;
};
std::cout << *序头 << endl;
动态.erase(序头);
量--;
序 = 序 ? --序 : 量 - 1;/*逆推需移动向前因此序减一位,0序减位回到数组实际尾元素;在顺推中因为元素被删除后下位补上此时序等效于直接指向下位因此不需移位处理*/
} while (量 > 止);
list::iterator 序头 = 动态.begin();
do/*如果[止]大于1循环剩余元素*/
{
std::cout << *序头++ << endl;
} while (--量);/*非零值做逻辑等效“真”*/
};
void 固定数组约瑟夫环(int *数组, bool 顺逆 = true, int 止 = 0, const int 人数 = 9, const int 报数 = 3, int 序位 = 2)
{
int 减 = 人数, 找位(1), 选(0);
序位--;/*[序位]如果输入从第2人开始报数减1指向数组实际对象,数组不含0编号的元素*/
do
{
选 = 顺逆 ? 序位 % 人数 : 人数 - 1 - 序位 % 人数;/*在数组大小中求标记序位,选择顺逆转换*/
if (数组[选])/*跳过已标记*/
if (!(找位++ % 报数)/*||(减 - 止 <= 0)*/)/*非标记内,报数开关,顺推环算法, [找位]自增准备进入下循环*/
{
std::cout << 数组[选] << endl;
数组[选] = 0;/*标记*/
减--;/*标记后减*/
/*if(减 - 止 <= 0)
止--;*/
}
序位++;/*不停随循环移动*/
} while (减 - 止);/*while (止 >= 0);*/
do/*按选定顺序输出剩余元素*/
{
选 = 顺逆 ? 序位 % 人数 : 人数 - 1 - 序位 % 人数;
if (数组[选])/*跳过已标记*/
{
std::cout << 数组[选] << endl;
止--;
}
序位++;
} while (止);
};
int 圈顺[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
固定数组约瑟夫环(圈顺, false, 2, 10);
cout << endl;
int 顺圈[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
固定数组约瑟夫环(顺圈, true, 2, 10);
cout << endl;
string[] baijie = new string[10] { "李欢", "龚丽", "谭显亮", "王涛", "徐荣辉", "刘烨", "郑权恒", "廖伟", "郭威", "李襑" };
bool 控制 = true;
Console.WriteLine("国信安百杰47部抓阄程序");
Console.WriteLine("显示全体成员姓名");
for (int i = 0; i < baijie.Length; i++)
{
Console.Write(baijie[i] + "\t");
}
Console.WriteLine("开始抓阄");
Console.WriteLine("请按下回车键");
for (int j = 0; j < baijie.Length; /*j++*/)
{
if (控制) Console.ReadLine();
Random rand = new Random();
int num = rand.Next(10);
if (baijie[num] != "")
{
Console.WriteLine(baijie[num]);
baijie[num] = "";
j++;/*如果不想用变形,则采用控制j的方式效果一样*/
控制 = true;
}
else { 控制 = false; /*j--;*/ }
}
Console.WriteLine();
Console.WriteLine("本次抓阄结束");
Public Class Form1
Dim 数组()
Dim 计数
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
数组 = {"李欢", "龚丽", "谭显亮", "王涛", "徐荣辉", "刘烨", "郑权恒", "廖伟", "郭威", "李襑"}
计数 = 数组.Count
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim 随机 = New Random().Next(数组.Count)
Do
If 数组(随机) <> "" Then
计数 -= 1
Me.Text = 数组(随机) & 计数
数组(随机) = ""
Exit Do
Else
随机 = New Random().Next(数组.Count)
End If
Loop While (计数 > 1)
End Sub
End Class
Sub 固定数组约瑟夫环(ByRef 数组() As Integer, Optional ByVal 顺逆 As Boolean = True, Optional ByVal 止 As Integer = 0, Optional ByVal 人数 As Integer = 10, Optional ByVal 报数 As Integer = 1, Optional ByVal 序位 As Integer = 10)
Dim 减 = 人数, 找位 = 1, 选 = 0
序位 -= 1
Do
选 = IIf(顺逆, 序位 Mod 人数, 人数 - 1 - 序位 Mod 人数)
If 数组(选) > 0 Then
找位 += 1
If 找位 Mod 报数 = 0 Then
Console.WriteLine(数组(选))
数组(选) = 0
减 -= 1
报数 += 1 '变数
End If
End If
序位 += 1
Loop Until (减 - 止 = 0)
Do
选 = IIf(顺逆, 序位 Mod 人数, 人数 - 1 - 序位 Mod 人数)
If 数组(选) > 0 Then
Console.WriteLine(数组(选))
止 -= 1
End If
序位 += 1
Loop Until (止 = 0)
End Sub
Dim 数组 = Enumerable.Range(1, 10).ToArray
固定数组约瑟夫环(数组)