1. 程式人生 > >約瑟夫環問題的連結串列實現

約瑟夫環問題的連結串列實現



       據說著名猶太曆史學家 Josephus有過以下的故事:在羅馬人佔領喬塔帕特後,39 個猶太人與Josephus及他的朋友躲到一個洞中,39個猶太人決定寧願死也不要被敵人抓到,於是決定了一個自殺方式,41個人排成一個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,然後再由下一個重新報數,直到所有人都自殺身亡為止。然而Josephus 和他的朋友並不想遵從。首先從一個人開始,越過k-2個人(因為第一個人已經被越過),並殺掉第k個人。接著,再越過k-1個人,並殺掉第k個人。這個過程沿著圓圈一直進行,直到最終只剩下一個人留下,這個人就可以繼續活著。問題是,給定了和,一開始要站在什麼地方才能避免被處決?Josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,於是逃過了這場死亡遊戲。

       後來人們把這個問題進行了簡化:N個人圍成一圈,從第1個人開始報數,將報第M個數的人殺掉,然後從第M+1個人又從1開始報數,報第M個數的人殺掉,如此迴圈······  最後剩下一個,其餘人都將被殺掉。例如N=6,M=5,被殺掉的順序是:5,4,6,2,3。最後能活下來的人是 1。這個問題就是經典的約瑟夫環問題,有時也稱約瑟夫置換或丟手絹問題。是一個經常出現在電腦科學和數學中的問題。

       約瑟夫問題並不難,但求解的方法很多;題目的變化形式也很多。這裡給出一種用連結串列實現的方法

我們用一個單迴圈連結串列來模擬圍成一圈的N個人,用結構體來構成人員資訊,結構體中儲存兩個成員,其中一個為指向下一個人的指標,已構成環形鏈,另一個成員記錄人員所處的位置序號。殺掉一個人就刪除一個節點的資訊。如此迴圈,直到只剩下一個人,即活下來的那個人。

具體實現程式碼如下,希望和大家一起交流學習。

#define  _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
#include<stdlib.h>

typedef int DataType;

typedef struct Node
{
	DataType data;
	struct Node * next;
}Node, *pNode;

pNode cur = NULL;//當前節點
pNode pre = NULL;//當前結點的前一個節點
pNode head = NULL;//頭節點

pNode CreateNode( DataType n)//用單迴圈連結串列建立約瑟夫環
{
	int i = 0;
	for (i = 1; i <= n;i++)
	{
		pNode tmp = (pNode)malloc(sizeof(Node));
		if (NULL == tmp)
		{
			printf("out of memory !\n");
			exit(EXIT_FAILURE);
		}
		else
		{
			cur = tmp;
			cur->data = i;
			cur->next = NULL;
		}
		if (head == NULL)
		{
			head = cur;
		}
		else
		{
			pre->next = cur;
		}
		pre = cur;	
	}
	cur ->next = head;//連結串列尾節點指向頭節點形成環
	return head;
}

void JosephCircle(DataType num, DataType count)
{
	int i = 0;
	int j = 0;
	cur =CreateNode(num);
	while (cur->next != cur)//判斷連結串列中是否只剩下一個人
	{
		for (i = 1; i <num ;i++)
		{
			for (j = 1;j < count ; j++)
			{
				pre = cur;
				cur = cur->next;
			}
			
			printf("第%d個出局的人是第%d 位\n", i, cur->data);
			pre->next = cur->next;
			free(cur);
			cur = pre->next;
		}
	}
	printf("最終活下來的人是第 %d 位\n", cur->data);
}

int main()
{
	int num;//約瑟夫環總人數
	int count;//出局的人所報的數
	printf("請輸入約瑟夫環問題的總人數num-> ");
	scanf("%d", &num);
	printf("請輸入約瑟夫環問題中第幾個報數的人出局-> ");
	scanf("%d", &count);
	JosephCircle( num,  count);
	system("pause");
	return 0;
}

執行結果:

相關推薦

連結串列實現

寫的蠻繁瑣的,而且中間還出現了些問題 #include <iostream> #include <stdio.h> #include <cstring> using namespace std; typedef struct node { i

雙向連結串列實現

#include<stdio.h> #include<stdlib.h> const int N = 1000; int m, n, k; struct people { int id; people *last, *ne

--連結串列實現

# include <stdio.h> # include <malloc.h> typedef struct Node { int data; struct Node * next; }NODE,*pnode; typedef struc

問題——連結串列實現

據說著名猶太曆史學家 Josephus有過以下的故事:在羅馬人佔領喬塔帕特後,39 個猶太人與Josephus及他的朋友躲到一個洞中,39個猶太人決定寧願死也不要被敵人抓到,於是決定了一個自殺方式,41個人排成一個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,

-順序表實現

題目: 約瑟夫環的一種描述為 編號為1,2,…,n的n個人按順時針方向圍坐一圈,每人持有一個密碼(正整數)。 一開始任選一個正整數作為報數上限值m,從第一個人開始按順時針方向自1開始順序報數,報到m時停止報數。 報m的人出列,將他的密碼作為新的m值,從他在

問題C++實現

題目就不說了,學過演算法或者看過一些程式設計思維故事的人應該都有了解這個經典的問題。這裡直接看程式碼和執行結果。 #include <bits/stdc++.h> using namespace std; int n,m; int main() { while(c

資料結構之C語言實現

資料結構,是很重要的一門學科,每年考研,資料結構是各大院校必考的科目。當然,資料結構,最令人頭疼的就是演算法設計題了。為了幫助大家理解和掌握資料結構常見的演算法,學長推出系列文章,為大家分享這些重要演算法的C語言完成實現,大家有條件的話,可以在電腦上除錯執行,加深

】Java實現:100個人開始從1開始報數,每當報數到3,報數3的人離開,求最後留下來人的位置。

問題背景:約瑟夫環問題  在這裡寫一個簡單的約瑟夫環的問題:100個人坐成一圈開始從1開始報數,每個報數為3的人離開座位,直到座位上只剩下一個人,求這個人的位置。 解決問題使用的工具&程式語言:  工具:Eclipse  程式設計:Java 程式碼如下: public class Yuesef

問題(迴圈連結串列實現

約瑟夫環問題,n個人圍成一圈,報數到m的人出列,直至n個人全部出列,問出列人的順序 手寫迴圈連結串列模擬實現 #include<stdio.h> #include<stdlib.h> typedef struct SingleNode {

問題連結串列實現

問題描述:約瑟夫環問題是,編號為1,2,3,…,n的n個人按順時針方向圍坐一圈,每人持有一個密碼。開始時任選一個正整數作為報數上限值m,從第一個人開始順時針方向自1開始順序報數,報到m時停止報數。報m的人出列,將他的密碼作為新的m值,從他在順時針方向上的下一個人開始重新從1報

遊戲->連結串列和順序表實現

#include<cstdio> #include<cstdlib> #include<iostream> using namespace std; typedef struct Staff { int number; struct Staff

Problem E: 用連結串列實現

Description 你聽說過約瑟夫問題嗎?問題大致如下:首先n個人圍成一個圈,標記為1到n號。接著,從1號開始報數(從1開始),然後2號報數,然後3號。。。當有人報到到m時,這個人就要踢出比賽,然後從被踢出的人的下一個人開始,重新報數(從1開始)。這樣經過n-1次後,就只剩下了一個人,問最後剩下的

迴圈連結串列的遞迴實現

約瑟夫(Joseph)問題的一種描述是:編號為1,2,…,n的n個人按順時針方向圍坐一圈,每人持有一個密碼(正整數)。一開始任選一個正整數作為報數上限值m,從第一個人開始按順時針方向自1開始順序報數,報到m時停止報數。報m的人出列,將他的密碼作為新的m值,從他在順時針方向上的下一個人開始重新

單向迴圈連結串列實現

約瑟夫環 已知n個人(以編號1,2,3...n分別表示)圍坐在一張圓桌周圍。從編號為k的人開始報數,數到m的那個人出列;他的下一個人又從1開始報數,數到m的那個人又出列;依此規律重複下去,直到圓桌周圍的人全部出列。 ///迴圈連結串列實現 #include<bits/stdc++.h>

問題的連結串列實現

        據說著名猶太曆史學家 Josephus有過以下的故事:在羅馬人佔領喬塔帕特後,39 個猶太人與Josephus及他的朋友躲到一個洞中,39個猶太人決定寧願死也不要被敵人抓到,於是決定了一個自殺方式,41個人排成一個圓圈,由第1個人開始報數,每報數到第3

問題(迴圈連結串列實現C)

約瑟夫環(約瑟夫問題)是一個數學的應用問題:已知n個人(以編號1,2,3...n分別表示)圍坐在一張圓桌周圍。從編號為k的人開始報數,數到m的那個人出列;他的下一個人又從1開始報數,數到m的那個人又出列;依此規律重複下去,直到圓桌周圍的人全部出列。 以下是程式碼實現(c語

迴圈連結串列 實現

【約瑟夫環問題】 已知 n 個人(n>=1)圍坐一圓桌周圍,從 1 開始順序編號,從序號為 1 的人開始報數,順時針數到 m 的那個人出列。下一個人又從 1 開始報數,數到m 的那個人又出列

問題迴圈連結串列實現

//n個人圍圈報數,報m出列,模擬出列的過程 #include <cstdio> #include <cstdlib> typedef struct node { int data; struct node *next; }node; nod

迴圈連結串列()的建立及C語言實現

連結串列的使用,還可以把連結串列的兩頭連線,形成了一個環狀連結串列,稱為迴圈連結串列。和它名字的表意一樣,只需要將表中最後一個結點的指標指向頭結點,就形成了一個環。 圖1 迴圈連結串列 迴圈連結串列和動態連結串列相比,唯一的不同就是迴圈連結串列首尾相連,其他都完全一

單向迴圈連結串列實現以及實現

/* * single.h * * Created on: 2012-7-21 * Author: root */ #ifndef SINGLE_H_ #define SINGLE_H_ #include<stdio.h> #includ