"金箍"我的约瑟夫环算法设计



约瑟夫环的设计在百度知道另一贴131楼和133楼命名为"金箍"就是观音大士给孙悟空头上戴的金箍.MSDN示例代码

            List<int> 贝 = new List<int>(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<int> 贝 = new List<int>(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<int>::size_type 容量 = 量;
	int 数(1);
	list<int> 动态;
	list<int>::iterator 序头;
	do/*填充顺序数组*/
	{
		动态.push_back(数++);
	} while (量 >= 数);
	--序;
	--报;
	do
	{
		序 = ((序 + 报) % 量 == 0) ? 0 : (序 + 报) % 量;/*序 = (序 + 报) % 量;*/
		//list<int>::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<int> 动态;
	do
	{
		动态.push_back(数++);
	} while (量 >= 数);
	--序;
	--报;
	do
	{
		序 = ((序 + 报) % 量 == 0) ? 0 : (序 + 报) % 量;/*序 = (序 + 报) % 量;*/
		list<int>::iterator 序头 = 动态.begin();
		list<int>::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<int> 动态;
	do/*填充顺序数组*/
	{
		动态.push_back(数++);
	} while (量 >= 数);
	--序;
	--报;
	序 = 量 - 1 - 序;/*逆推*/
	do
	{
		序 = ((序 - 报) % 量 < 0) ? 量 + ((序 - 报) % 量) : (序 - 报) % 量;/*逆推*/
		list<int>::iterator 序头 = 动态.begin();
		数 = 0;
		while (数 < 序)/*序转换为元素*/
		{
			*序头++;
			数++;
		};
		std::cout << *序头 << endl;
		动态.erase(序头);
		量--;
		序 = 序 ? --序 : 量 - 1;/*逆推需移动向前因此序减一位,0序减位回到数组实际尾元素;在顺推中因为元素被删除后下位补上此时序等效于直接指向下位因此不需移位处理*/
	} while (量 > 止);
	list<int>::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("本次抓阄结束");
VB:请高手帮忙写一个VB的多人抽签代码,设置一个文本框输入抽签人数,一个文本框输入抽签范围,一个按钮开始,一个按钮抽签,一个按钮停止。
输入人数及范围,点击开始后,每按一次抽签,出现一个号数,抽签完毕后,按停止结束本次抽签。
要求:不会抽到在开始到结束这段抽签里面,不会抽到同样的号数。
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

vb
    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
        固定数组约瑟夫环(数组)



















猜你喜欢

转载自blog.csdn.net/xianfajushi/article/details/24846979