1. 程式人生 > >佇列求解素數篩

佇列求解素數篩

這是我們資料結構的作業,先看要求吧:

程式設計實現佇列類,要求包括基本變數和基本操作,也沒啥。

佇列中兩個變數,頭節點和尾節點。每個節點不僅要有next節點值,還要有last節點。

然後insert函式和pop函式,一個插入一個刪除。不過這個要分幾種情況,當佇列為空,或者只有一個元素。

佇列實現:

class Link<T>{	
	Node<T> head;									//佇列頭節點
	Node<T> tail;									//佇列尾節點
	public void insert(T x) {						//插入函式
		Node<T> t=new Node<T>(x);
		if(head==null) {			//如果佇列為空
			head=t;
			tail=t;
		}
		else if(head==tail) {		//如果佇列只有一個元素
			tail=t;
			tail.last=head;
			head.next=tail;
		}
		else {						//其他情況
			tail.next=t;
			t.last=tail;
			tail=t;
		}
	}
	public T getFront() {							//得到頭節點
		return head.v;
	}
	public T pop() {								//刪除頭節點,三種情況,分類處理
		T t=head.v;
		if(head==null) {
			return null;
		}
		if(head==tail) {
			head=tail=null;
			return t;
		}
		head=head.next;
		head.last=null;
		return t;
	}
	public boolean isEmpty() {						//判斷是否為空
		return head==null;
	}
	private class Node<T>{
		Node<T> next;			//上一個節點
		Node<T> last;			//下一個節點
		T v;					//權值
		public Node(T x){
			this.v=x;
		}
		public Node() {}
	}
}

下面是實現素數環,原理我也不知道。

就是用一個順序表,一個佇列。

順序表Q先add(1),佇列L add(2-n);

然後下面操作重複:

1、取L首

2、看是否和Q尾和構成素數

3、如果是,插入Q尾,如果否入隊L,重複1直到佇列為空。

原理其實我也不清楚。不過好像就是能用。

然後加個區間篩優化一下判斷素數。

public class Main {
	static StreamTokenizer in=new StreamTokenizer (new BufferedReader(new InputStreamReader(System.in)));
    static boolean isPrime[];
    static int isP_Len=100;
    public static void main(String[] args) throws Exception {
    	int arr[]=getPrimeRing(20);
    	for(int i=0;i<20;i++) {
    		System.out.println(arr[i]);
    	}
    }
    ///==========================================得到素數環主函式
    /*
     * 我真的不知道為啥要用佇列實現素數環,也不知道原理,為啥是這樣。
     * 而且寫起來又這麼複雜。
     * bfs寫起來那麼簡便。
     * 這個時間複雜度不好算,也不知道那個複雜度高。
     * 結果環用陣列儲存
     */
    static int[] getPrimeRing(int n) {
    	int arr[]=new int[n];
    	getPrimeArrays();
    	Link<Integer> list=new Link<Integer>();
    	arr[0]=1;
    	int len=1;
    	for(int i=2;i<=n;i++) {
    		list.insert(i);
    	}
    	while(!list.isEmpty()) {
    		int t=list.pop();
    		if(isP(t+arr[len-1])) {
    			arr[len++]=t;
    		}
    		else {
    			list.insert(t);
    		}
    	}
    	return arr;
    }
    //=============================================
    static boolean isP(int x) {
    	return isPrime[x];
    }
    //篩法求素數,複雜度會低很多。n^3/2到幾乎線性的輔助度。
    static void getPrimeArrays() {
    	isPrime=new boolean[isP_Len];
    	for(int i=2;i<isP_Len;i++) {
    		isPrime[i]=true;
    	}
    	for(int i=2;i<isP_Len;i++) {
    		if(isPrime[i]) {
    			for(int j=i*2;j<isP_Len;j+=i) {
    				isPrime[j]=false;
    			}
    		}
    	}
    }
    static int getInt() throws Exception{
    	in.nextToken();
    	return (int)in.nval;
    	
    }
}