1. 程式人生 > >迴圈連結串列和約瑟夫環

迴圈連結串列和約瑟夫環

迴圈連結串列時另一種形式的鏈式儲存結構,把單鏈表中指向最後一個結點的指標指向單鏈表的表頭結點,就形成了一個迴圈連結串列。迴圈連結串列無論從連結串列中的任意出發點出發均可找到表中的其他結點。

約瑟夫問題是猶太曆史學家約瑟夫的一個故事:在羅馬人佔領喬塔帕特後,39 個猶太人與Josephus及他的朋友躲到一個洞中,39個猶太人決定寧願死也不要被敵人抓到,於是決定了一個自殺方式,41個人排成一個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,然後再由下一個重新報數,直到所有人都自殺身亡為止。然而Josephus 和他的朋友並不想遵從。首先從一個人開始,越過k-2個人(因為第一個人已經被越過),並殺掉第

k個人。接著,再越過k-1個人,並殺掉第k個人。這個過程沿著圓圈一直進行,直到最終只剩下一個人留下,這個人就可以繼續活著。問題是,給定了和,一開始要站在什麼地方才能避免被處決?Josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,於是逃過了這場死亡遊戲。

用迴圈連結串列來實現約瑟夫問題是一個很好的選擇,第一,連結串列插入和刪除元素的操作非常簡單,第二,迴圈連結串列時一個環,可以持續進行計數殺人。然後我就花了一整天的時間來搞迴圈連結串列和約瑟夫問題。

標頭檔案:(CirLinkList.h)

//CirLinkList迴圈連結串列
#ifndef CIRLINKLIST_H_
#define CIRLINKLIST_H_
#include <iostream>
using std::cout;
using std::endl;
template<typename T>
struct Node
{
	T data;
	Node<T> *next;
	//建構函式
	Node();
	Node(T item, Node<T> *link=NULL);
};
template <typename T>
Node<T>::Node()
{
	next=NULL;
}
template<typename T>
Node<T>::Node(T item, Node<T> *link=NULL)
{
	data=item;
	next=link;
}
template <typename T>
class SimpleCirLinkList
{
protected:
	Node<T> *head;
	
	void Init();
public:
	Node<T> *GetElemPtr(int position) const;
	SimpleCirLinkList();//建構函式
	virtual ~SimpleCirLinkList();//解構函式
	bool IsEmpty();
	int Length() const;
	void Clear();
	void GetElem(int position, T &e);
	SimpleCirLinkList<T> &SetElem(int position, const T e);
	SimpleCirLinkList<T> &DeleteElem(int position, T &e);
	SimpleCirLinkList<T> &DeleteNode(Node<T> *tempPtr);
	SimpleCirLinkList<T> &InsertElem(int position, const T e);
	SimpleCirLinkList(const SimpleCirLinkList<T> &copy);
	SimpleCirLinkList<T> &operator =(const SimpleCirLinkList<T> &copy);
};
//初始化
template<typename T>
void SimpleCirLinkList<T>::Init()
{
	head=new Node<T>;
	head->next=head;
}
template<typename T>
Node<T> *SimpleCirLinkList<T>::GetElemPtr(int position) const
{
	int curPosition=1;
	Node<T> *tempPtr=head->next;
	if(position==0)
	{
		return head;
	}
	while(tempPtr->next!=head && curPosition<position)
	{
		tempPtr=tempPtr->next;
		++curPosition;
	}
	if(tempPtr!=head && curPosition==position)
	{
		return tempPtr;
	}
	else
	{
		return NULL;
	}

}
//建構函式
template<typename T>
SimpleCirLinkList<T>::SimpleCirLinkList()
{
	Init();
}
template <typename T>
SimpleCirLinkList<T>::~SimpleCirLinkList()
//解構函式
{
	Clear();
	delete head;
}
template <typename T>
int SimpleCirLinkList<T>::Length() const
{
	int count=0;
	Node<T> *tempPtr;
	for(tempPtr=head->next; tempPtr!=head; tempPtr=tempPtr->next)
	{
		++count;
	}
	return count;
}
template <typename T>
bool SimpleCirLinkList<T>::IsEmpty()
{
	if(head->next==head)
	{
		return true;
	}
	else 
	{
		return false;
	}
}
template <typename T>
void SimpleCirLinkList<T>::Clear()
{
	T temp;
	while(Length()>0)
	{
		DeleteElem(1,temp);
	}
}
template <typename T>
void SimpleCirLinkList<T>::GetElem(int position, T &e)
{
	Node<T> *tempPtr;
	if(position<1 || position>Length())
	{
		cout<<"獲取元素時超出範圍!"<<endl;
	}
	else
	{
		tempPtr=GetElemPtr(position);
		e=tempPtr->data;
	}
}
template <typename T>
SimpleCirLinkList<T> &SimpleCirLinkList<T>::SetElem(int position, const T e)
{
	Node<T> *tempPtr;
	if(position<1 || position>Length())
	{
		cout<<"獲取元素時超出範圍!"<<endl;
	}
	else
	{
		tempPtr=GetElemPtr(position);
		tempPtr->data=e;
	}
	return *this;
}
template <typename T>
SimpleCirLinkList<T> &SimpleCirLinkList<T>::DeleteElem(int position, T &e)
{
	Node<T> *tempPtr;
	Node<T> *dePtr;
	if(position<1 || position>Length())
	{
		cout<<"獲取元素時超出範圍!"<<endl;
	}
	else
	{
		tempPtr=GetElemPtr(position-1);
		Node<T> *newPtr=tempPtr->next;
		dePtr=newPtr->next;
		e=newPtr->data;
		tempPtr->next=dePtr;
		delete newPtr;
	}
	return *this;
}
template<typename T>
SimpleCirLinkList<T> &SimpleCirLinkList<T>::DeleteNode(Node<T> *tempPtr)
{
	Node<T> *newPtr=head;//=GetElemPtr(tempPtr->data-1);
	while(newPtr->next!=tempPtr)
	{
		newPtr=newPtr->next;
	}
	newPtr->next=tempPtr->next;
	delete tempPtr;
	return *this;
}
template <typename T>
SimpleCirLinkList<T> &SimpleCirLinkList<T>::InsertElem(int position, const T e)
{
	if(position<1 || position>(Length()+1))
	{
		cout<<"獲取元素時超出範圍!"<<endl;
	}
	else
	{
		Node<T> *tempPtr;
		Node<T> *newPtr=new Node<T>;
		newPtr->data=e;
		tempPtr=GetElemPtr(position-1);
		newPtr->next=tempPtr->next;
		tempPtr->next=newPtr;
	}
	return *this;
}
template <typename T>
SimpleCirLinkList<T>::SimpleCirLinkList(const SimpleCirLinkList<T> &copy)
{
	//建構函式拷貝類引數必須為const的引用
	int copyLength=copy.Length();
	Init();
	Node<T> *tempPtr=head->next;
	for(int curPosition=1; curPosition<=copyLength; curPosition++)
	{
		tempPtr=copy.GetElemPtr(curPosition);
		InsertElem(curPosition,tempPtr->data);
	}
}
template <typename T>
SimpleCirLinkList<T> &SimpleCirLinkList<T>::operator =(const SimpleCirLinkList<T> &copy)
{
	if(copy!=this)
	{
		int copyLength=copy.Length();
		Init();
		Node<T> *tempPtr=head->next;
		for(int curPosition=1; curPosition<=copyLength; curPosition++)
		{
			tempPtr=copy.GetElemPtr(curPosition);
			InsertElem(curPosition,tempPtr->data);
		}
	}
	return *this;
}
template <typename T>
std::ostream &operator <<(std::ostream &os, SimpleCirLinkList<T> &CirLinkList)
{
	T e;
	for(int curPosition=1; curPosition<=CirLinkList.Length(); curPosition++)
	{
		CirLinkList.GetElem(curPosition,e);
		cout<<e<<" ";
	}
	return os;
}
#endif

原始檔:(CirLinkList.cpp)

// CirLinkList.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include "CirLinkList.h"
#include <iostream>

using namespace std;
//n為共有多少人,m為數到幾自殺。(41,3)
void Josephus(int n, int m)
{
	SimpleCirLinkList<int> CirLink;
	for(int i=1; i<=n; i++)
	{
		CirLink.InsertElem(i,i);
	}
	cout<<"約瑟夫連結串列為:"<<CirLink<<endl;
	Node<int> *deadmanPtr;
	Node<int> *tempPtr=CirLink.GetElemPtr(1);
	int e,s;
	cout<<"殺人順序為:";
	for(int i=1; i<=n; i++)
	{
		for(int j=1; j<=2; j++)
		{
			if(tempPtr==CirLink.GetElemPtr(0))
			{
				tempPtr=tempPtr->next;
			}
			tempPtr=tempPtr->next;
			if(tempPtr==CirLink.GetElemPtr(0))
			{
				tempPtr=tempPtr->next;
			}
		}
		e=tempPtr->data;
		cout<<e<<" ";
		deadmanPtr=tempPtr->next;
		CirLink.DeleteNode(tempPtr);
		tempPtr=deadmanPtr;
		/*CirLink.DeleteElem(e,s);*/
	}
	cout<<endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
	SimpleCirLinkList<int> CirLinkList;
	cout<<"連結串列的長度為:"<<CirLinkList.Length()<<endl;
	cout<<"連結串列是否為空? ";
	if(CirLinkList.IsEmpty()==1)
	{
		cout<<"Yes!"<<endl;
	}
	else
	{
		cout<<"No!"<<endl;
	}
	//CirLinkList.InsertElem(0,1);
	CirLinkList.InsertElem(1,2);
	CirLinkList.InsertElem(2,3).InsertElem(3,4).InsertElem(4,5).InsertElem(5,6);
	cout<<"連結串列的長度為:"<<CirLinkList.Length()<<endl;
	cout<<"連結串列是否為空? ";
	if(CirLinkList.IsEmpty()==1)
	{
		cout<<"Yes!"<<endl;
	}
	else
	{
		cout<<"No!"<<endl;
	}
	cout<<"迴圈連結串列為:"<<CirLinkList<<endl;
	//複製連結串列
	//SimpleLinkList<int> copy(LinkList);
	SimpleCirLinkList<int> copy=CirLinkList;
	copy.InsertElem(2,0).InsertElem(3,0);
	cout<<"連結串列的長度為:"<<copy.Length()<<endl;
	cout<<"連結串列是否為空? ";
	if(copy.IsEmpty()==1)
	{
		cout<<"Yes!"<<endl;
	}
	else
	{
		cout<<"No!"<<endl;
	}
	cout<<"迴圈連結串列為:"<<copy<<endl;
	cout<<"設定值之後:"<<endl;
	copy.SetElem(1,100);
	cout<<"迴圈連結串列為:"<<copy<<endl;
	//清除連結串列
	cout<<"清空連結串列"<<endl;
	copy.Clear();
	cout<<"連結串列的長度為:"<<copy.Length()<<endl;
	cout<<"連結串列是否為空? ";
	if(copy.IsEmpty()==1)
	{
		cout<<"Yes!"<<endl;
	}
	else
	{
		cout<<"No!"<<endl;
	}
	Josephus(41, 3);
	system("pause");
	return 0;
}


結果:

相關推薦

迴圈連結串列和約

迴圈連結串列時另一種形式的鏈式儲存結構,把單鏈表中指向最後一個結點的指標指向單鏈表的表頭結點,就形成了一個迴圈連結串列。迴圈連結串列無論從連結串列中的任意出發點出發均可找到表中的其他結點。 約瑟夫問題是猶太曆史學家約瑟夫的一個故事:在羅馬人佔領喬塔帕特後,39 個猶太人與J

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

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

演算法-迴圈連結串列[約問題之進階]

1.問題描述: 約瑟夫問題:進階 有 n 個人,初始時按照順序圍成一圈而坐,每個人都有一個密碼。 從任意一個人開始,制定報數上線M,當有人報數為M時,該人死亡,從下一個人開始報數,該人報數前指定報數上限M為該人的密碼。 至到所有人都死亡結束遊戲,輸出死亡順序編號。 2.程式碼

演算法-迴圈連結串列[約問題]

連結串列屬於線性表的一種,資料邏輯記憶體相鄰,實體記憶體不相鄰。 常見連結串列有:單向連結串列,雙向連結串列,迴圈連結串列。 約瑟夫問題:有n個人圍在一起,初始化時編號相鄰,例如:1~41;從任何一個人開始報數為1,當有人報數為3時,該人死亡,從下一個人開始報數為1,

連結串列--約

/* * 雙向連結串列:在連結串列的基礎上進行改進 * 特徵:首尾相連,即最後一個節點指向第一個節點 * 另外:新增一個length屬性 * * */ /* * 定義一個node節點 * element 節點名稱 * nex

陣列迴圈右移和約問題

1. 把陣列中的每個數迴圈右移n位,要求時間複雜度O(n),空間複雜度O(1) package cn.lifx.test; public class RightMove { public static void main(String[] args) { int

迴圈佇列之約

此問題的要求為:n個人圍坐一圈,從第一個人開始數,每數到k,這個人就出列,圈中的下一個人重新從1開始計數,直到剩餘人數不足k人 下面我畫圖來加深理解(抱歉目前還不會用電腦繪製動畫,只好手動繪製,比較粗糙,之後有時間我改進下!!(看起來像個效果器上面的一堆旋鈕哈哈哈 下面附上完整

JavaScript實現迴圈佇列與約問題的解決

function MyCircularQueue(){ var items = []; //向佇列插入元素 this.enQueue = function(value){ return items

php通過迴圈鏈解決約

本想著用php寫些資料結構提升一下,寫到鏈的時候看到約瑟夫環問題,嘗試用迴圈鏈寫了一下 約瑟夫環: 約瑟夫環(約瑟夫問題)是一個數學的應用問題:已知n個人(以編號1,2,3...n分別表示)圍坐在一張圓桌周圍。從編號為k的人開始報數,數到m的那個人出列;他的下一個人又

迴圈連結串列解決約的問題

約瑟夫環問題簡介  約瑟夫環問題的原來描述為,設有編號為1,2,……,n的n(n>0)個人圍成一個圈,從第1個人開始報數,報到m時停止報數,報m的人出圈,再從他的下一個人起重新報數,報到m時停止報數,報m的出圈,……,如此下去,直到所有人全部出圈為止。當任意給定n和m後,設計演算法求n個人出

,魯智深吃饅頭之類的問題總結c++(不用迴圈連結串列

今天看見這一類的題,覺得用迴圈連結串列太麻煩了,就想用某一種方法來代替迴圈連結串列,總結如下。 大致題意 n 個人圍城一圈,從第一個人開始順序編號為1到n。從第1個人從1開始報數,數到3的人出圈。再由下一個人從1開始報數,數到3的人出圈,如此迴圈數下去,直到最後一個人出圈。(題意都差不多

(使用C語言單向迴圈連結串列來解決)

題目描述 編號為1,2,…,n的n個人按順時針方向圍坐在一張圓桌周圍,每人持有一個密碼(正整數)。一 開始任選一個正整數m作為報數上限值,從第一個人開始按順時針方向自1開始報數,報到m時停止報數,報m的那 個人出列,將他的密碼作為新的m值,從他順時針方向的下一個人開始重新從1報數,

--迴圈連結串列的應用

     通過迴圈連結串列實現約瑟夫環 要求:1)要求設計一個程式模擬次過程,輸入總的人數n,所報的出列的數字k,計數開始的位置p; 程式所能達到的功能:構造連結串列;輸入資料;執行報數;儲存出列人的序號,刪除出列人的資訊以及把指向出列人的指標移到出列人的下一個人,然後重

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

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

資料結構——約迴圈連結串列

n個數據元素構成一個環,從環中任意位置開始計數,計到m將該元素從表中取出,重複上述過程,直至表中只剩下一個元素。 提示:用一個無頭結點的迴圈單鏈表來實現n個元素的儲存。 樣例: 輸入: 10 3 1 //分別為總數,出列的人數到的數字,開始數的人的編號。 輸出:

(Josephus)迴圈連結串列解決

關於約瑟夫環的簡單思路技巧 題目要求: 分析題目: 設編號為1,2,3,4…n的n個人順時針坐一圈,約定編號為K的人按順時針從1開始報數,數到m的人出列,他的下一位從1開始 報數… 預設第一次輸入剛開始的序號,之後選擇到誰就用誰的密碼,並把它刪掉。 思路分析:正

迴圈連結串列的遞迴實現

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

資料結構——迴圈連結串列、僅設尾指標的迴圈連結串列、約

1 //迴圈連結串列,連結串列的尾結點的link域中不是NULL,而是存放了指標連結串列開始結點的指標 2 ////設p是在迴圈連結串列中逐個結點檢測指標,則在判斷p是否達到連結串列的鏈尾時p->link == first 3 4 5 //迴圈

問題(迴圈連結串列

這是一道比較經典的迴圈連結串列問題,在華為上機筆試中也出現過。 約瑟夫環是一個數學的應用問題:已知n個人(以編號1,2,3...n分別表示)圍坐在一張圓桌周圍。從編號為k的人開始報數,數到m的那個人出列;他的下一個人又從1開始報數,數到m的那個人又出列;依此規律重複下去,直

單向迴圈連結串列實現

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