天天看点

使用单链表求解约瑟夫环问题 (自定义单链表)

约瑟夫环(Josephus)问题:古代某法官要判决n个犯人的死刑,他有一条荒唐的法律,将犯人站成一个圆圈,从第s个人开始数起,每数到第d个犯人,就拉出来处决,然后再数d个,数到的人再处决……直到剩下的最后一个可赦免。当n=5,s=1,d=2,时:

第一步:定义节点Node

public class Node<T> {

	public T data;
	public Node<T> next;
	public Node(T data,Node<T> next){
		this.data=data;
		this.next=next;
	}
	public Node(){
		this(null,null);
	}
}
           

第二步:定义单链表SingleLinkedList<T>

public class SingleLinkedList<T> implements LList<T> {
    private Node<T> head;
    public SingleLinkedList(){
    	this.head=new Node<T>();
    }
    public SingleLinkedList(SingleLinkedList<T> list){
    	Node<T> p=list.head.next;
    	Node<T> rear=this.head;
    	while(p!=null){
    		rear.next=new Node<T>(p.data,null);
    		rear=rear.next;
    		p=p.next;	
    	}
    }
    public SingleLinkedList(T[] element){
    	this();
    	Node<T> rear=this.head;
    	for(int i=0;i<element.length;i++){
    		rear.next=new Node<T>(element[i],null);
    		rear=rear.next;
    	}
    }
    public boolean isEmpty(){
    	return this.head.next==null;
    }
    public int length(){
    	int i=0;
    	Node<T> p=this.head.next;
    	while(p!=null){
    		i++;
    		p=p.next;
    	}
    	return i;
    }
    public T get(int i){
    	if(i>=0){
    		Node<T> p=this.head.next;
        	for(int j=0;p!=null&&j<i;j++){
        		p=p.next;
        	}
        	if(p!=null)
        		return p.data;
    	}
    	return null;
    }
    public void set(int i,T x){
    	if(x==null){
    		return;
    	}
    	if(i>=0){
    		Node<T> p=this.head.next;
    		for(int j=0;p!=null&&j<i;j++){
    			p=p.next;
    		}
    		if(p!=null)
    			p.data=x;
    	}else{
    		throw new IndexOutOfBoundsException();
    	}
    }
    public void insert(int i,T x){
    	if(x==null)
    		return;
    	Node<T> p=this.head;
    	for(int j=0;p.next!=null&&j<i;j++){
    		p=p.next;
    	}
    	p.next=new Node<T>(x,p.next);
    }
    public void append(T x){
    	insert(Integer.MAX_VALUE,x);
    }
    public T remove(int i){
    	if(i>=0){
    		Node<T> p=this.head;
    		for(int j=0;p.next!=null&&j<i;j++){
    			p=p.next;
    		}
    		if(p.next!=null){
    			T old =p.next.data;
    			p.next=p.next.next;
    			return old;
    		}
    	}
    	return null;
    }
    public void removeAll(){
    	this.head.next=null;
    }
    public T search(T key){
    	int index=this.indexOf(key);
    	Node<T> p=this.head.next;
    	if(index>=0){
    		for(int j=0;p!=null&&j<index;j++){
    			p=p.next;
    		}
    		if(p!=null){
    		    return p.data;
    		}
    	}
    	return null;
    }
    public int indexOf(T key){
    	Node<T> p=this.head.next;
    	int i=-1;
    	while(p!=null){
    		i++;
    		if(p.data.equals(key)){
    			return i;
    		}
    	}
    	return -1;
    }
    public String toString(){
    	String str="(";
    	Node<T> p=this.head.next;
    	while(p!=null){
    		str+=p.data.toString();
    		if(p.next!=null)
    			str+=",";
    		p=p.next;
    	}
    	str+=")";
    	return str;
    }
    public static<T> void reverse(SingleLinkedList<T> list){
    	Node<T> p=list.head.next,succ=null,font=null;
    	while(p!=null){
    		succ=p.next;
    		p.next=font;
    		font=p;
    		p=succ;
    	}
    	list.head.next=font;
    }
    
    public boolean isEquals(Object o){
    	if(this==o)
    		return true;
    	if(!(o instanceof SingleLinkedList)){
    		return false;
    	}else{
    		Node<T> p=this.head.next;
    		Node<T> q=((SingleLinkedList<T>)o).head.next;
    		while(p!=null&&q!=null&&p.data.equals(q.data)){
    			p=p.next;
    			q=q.next;
    		}
    		return p==null&&q==null;
    	}
    	
    }
}
           

第三步定义约瑟夫环并求解:

public class Josephus {

	public Josephus2(int number,int start,int distance){
		
		SingleLinkedList<String> list=new SingleLinkedList<String>();//自定义的单链表 
		for(int i=0;i<number;i++){
			list.append((char)('A'+i)+"");
		}
		//list.reverse(list);//单链表逆转
		System.out.print("约瑟夫环("+number+","+start+","+distance+"),");
		System.out.println(list.toString());
		int i=start;
		while(list.length()>1){
			i=(i+distance-1)%list.length();
			System.out.print("删除的元素:"+list.remove(i).toString()+",");
			System.out.println(list.toString());
		}
		System.out.println("被赦免的罪犯是:"+list.get(0).toString());
	}
	
	public static void main(String[] args) {
		new Josephus2(5,0,2);
	
		

	}

}
           

第四步:输出结果如下

约瑟夫环(5,0,2),(A,B,C,D,E)

删除的元素:B,(A,C,D,E)

删除的元素:D,(A,C,E)

删除的元素:A,(C,E)

删除的元素:E,(C)

被赦免的罪犯是:C