約瑟夫環的三種解法(循環鏈表、數組、遞歸)


約瑟夫環

問題描述:

m個人圍成一個圈,指定一個數字n,從第一個人開始報數,每輪報到n的選手出局,由下一個人接着從頭開始報,最后一個人是贏家。其中m>1,n>2。

鏈表法

用循環鏈表能完美契合本題

#include<iostream>
using namespace std;
struct Node{
    int data;
    Node* next;
    Node(int value){this->data = value;};
};
//創建一個約瑟夫環的類
class JosephCircle{
private:
    Node* tail;	//尾結點
    //Node* eliminate;	//淘汰結點
public:
    JosephCircle():tail(NULL){}
    ~JosephCircle(){delete tail;}
    void Add(int num);
    void Eliminate(int step);
    void Print();
};
void JosephCircle::Add(int num){
    if(tail == NULL){
        tail = new Node(num);
        tail->next = tail;
    }
    else{
        Node* new_node = new Node(num);
        new_node->next = tail->next;
        tail->next = new_node;
        tail = new_node;
    }
}
void JosephCircle::Eliminate(int step){
    Node* p = tail;
    while(p != NULL && p != p->next){
        for(int i = 0;i < step-1;i++){
            p = p->next;
        }
        Node* eliminate = p->next;
        p->next = eliminate->next;
        if(eliminate == tail){
            tail = p;
        }
        cout<<"deleting"<<eliminate->data<<endl;
        delete eliminate;
        Print();
    }
}
void JosephCircle::Print(){		//這打印還是有點說法的
    Node* cur = tail;
    while(cur != NULL){
        cur = cur->next;
        cout<<cur->data<<"  ";
        if(cur == tail)
            break;
    }
    cout<<endl;
}
int main(){
    JosephCircle jc;
    for(int i = 1;i <= 6;i++){
        jc.Add(i);
    }
    jc.Eliminate(3);
    jc.Print();
    return 0;
}

數組

數組倒是也能完成,代碼量好像還要少一丟丟,但是要注意的邊界條件太多了,debug的時間都夠我寫個鏈表解決的了T_T

#include <iostream>
using namespace std;
int JCArr(int num,int step){
	int arr[num];
	for (int i = 1; i <= num; ++i){
		arr[i-1] = i;
	}
	int n = num,i = 0,curOut = 1;
	while(num != 1){
		if(arr[i] == -1){
			i++;
		}
		else{
			i++;
			curOut++;
		}
		if(i == n){ 	//超過末尾從頭開始
			i = 0;
		}
		if(curOut == step && arr[i] != -1){
			cout<<"deleting "<<arr[i]<<endl;
			arr[i] = -1;
			i++;
			if(i == n){		//這里也有可能發生越界,小心呀!
				i = 0;
			}
			curOut = 1;
			num--;	//別忘了總人數減一 
		}
	}
	int k = 0;
	for(;k < n;k++){
		if(arr[k] != -1)
			return arr[k];
	}
	
}
int main(int argc, char const *argv[])
{
	cout<<JCArr(6,3)<<endl;
	return 0;
}

遞歸

//TO DO

參考鏈接:

  1. 約瑟夫環-遞歸分析數學解法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM