java基礎:14.4 棧、隊列


可以使用數組線性表實現棧,使用鏈表實現隊列。

棧可以看做是一種特殊類型的線性表,訪問、插入和刪除其中的元素只能在棧尾進行。用數組線性表來實現棧比用鏈表來實現實現效率更高

這裏有兩種辦法可用來設計棧和隊列的類。

  • 使用繼承:可以通過繼承數組線性表類ArrayList 來定義棧類,通過繼承鏈表類LinkedList 來定義隊列類。
  • 使用組合:可以將數組線性表定義爲棧類中的數據域,將鏈表定義爲隊列類中的數據域,

在這裏插入圖片描述

這兩種設計方法都是可行的,但是相比之下,組合可能更好一些,因爲它可以定義一個全新的棧類和隊列類,而不需要繼承數組線性表類與鏈表類中不必要和不合適的方法。

1、棧

在這裏插入圖片描述
棧的典型應用

  1. 逆序輸出Conversion
    輸出次序與處理過程顛倒;遞歸深讀和輸出長度不易預知
  2. 遞歸嵌套 stack permutation + parenthesis
    具有自相似性的問題可遞歸描述,但分支位置和嵌套深度不固定
  3. 延遲緩衝 evaluation
    線性掃描算法模式中,在預讀足夠長之後,方能確定可處理的前綴
  4. 棧式計算 RPN
    基於棧結構的特定計算模式

1.1 myStack的實現

public class myStack<E> {

    private java.util.ArrayList<E> list = new java.util.ArrayList<E>();

    public void push(E e){
        list.add(e);
    }

    public E pop(){
        return list.remove(list.size()-1);
    }

    public E top(){
        return list.get(list.size()-1);
    }

    public int getSize(){
        return list.size();
    }
    
    public boolean empty(){       //if stack is empty, return true;
        if(list.size() == 0) return true;
        else return false;
    }
    @Override
    public String toString() {
        return "stack:" + list.toString();
    }
}

 

1.2 棧應用:進制轉換問題

逆序輸出Conversion :輸出次序與處理過程顛倒;遞歸深讀和輸出長度不易預知

進制轉換 輸入一個數,可以轉換成任意的n進制。

public class convert {

    public static void main(String []args){
        ConvertBase(-17,2);
    }

    static void ConvertBase (int num , int base){
        myStack s = new myStack();
        char digit [] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        boolean flag = false;

        if(num < 0){
            flag = true;
            num *= -1;
        }

        while (num > 0) {
            s.push(digit[num % base]);
            num /= base;
        }

        if(flag){
            s.push('-');
        }

        for(int i = s.getSize() ; i > 0 ; i--)
            System.out.print(s.pop());
    }
}

 

1.3 棧應用:括號匹配問題

stack permutation + parenthesis
具有自相似性的問題可遞歸描述,但分支位置和嵌套深度不固定
括號匹配問題 :判斷一個類似於“(())()()()))(((()” 是否左括號和右括號可以一一正確匹配上。

    static boolean paren(String s){
        myStack stack = new myStack();
        for(int i=0; i < s.length(); i++){
            if(s.charAt(i) == '(')  stack.push(1);
            else if(!stack.empty())  stack.pop();
            else return false;
        }
        return stack.empty();
    }

這個題在學有限自動機課程時也遇到過,同樣的思路~~
 

1.4 棧應用:棧混洗問題

/*
描述
輸入兩個整數序列,第一個序列表示棧的壓入順序,請判斷第二個序列是否可能爲該棧的彈出順序。
假設壓入棧的所有數字均不相等。例如序列1,2,3,4,5是某棧的壓入順序,序列4,5,3,2,1是該壓棧序列對應的一個彈出序列,
但4,3,5,1,2就不可能是該壓棧序列的彈出序列。(注意:這兩個序列的長度是相等的)

輸入
第一行:輸入N個整數,空格隔開,按先後順序入棧
第二行:輸入N個整數,空格隔開,表示一種出棧順序
輸出
True 或者 False ,意思是第二行數據是否是一個合法的彈出序列
樣例輸入
1 2 3 4 5
4 5 3 2 1
樣例輸出
True
*/
在這裏插入圖片描述

    static boolean sp(){
        Scanner in = new Scanner(System.in);
        System.out.println("enter your number");
        String s1 = in.nextLine();
        String s2 = in.nextLine();
        String a1[] = s1.split(" ");
        String a2[] = s2.split(" ");
        Stack<Integer> s = new Stack<>();

        int a[] = new int[a1.length];    //a 是壓入棧的順序 從 0--a.length
        int b[] = new int[a1.length];     // b 是彈出的順序 從 0--b.length
        for(int i = 0;i < a.length;i++){
            a[i] = Integer.valueOf(a1[i]);
            b[i] = Integer.valueOf(a2[i]);
        }

        int k = 0;
        for(int i = 0; i < a.length; i++){
            s.push(a[i]);
            while( s.empty()==false && b[k] == s.peek()  )
            {
                s.pop();
                k++;
            }
        }
        if( k == a.length && s.empty())
            return true;
        else
            return false;
    }

 

2、隊列的實現

隊列,元素只能從隊列的末端插入,從開始端訪問和刪除。由於刪除是在線性表的起始位置進行的,所以用鏈表實現隊列比用數組線性表實現效率更高。

package ReWrite;
public class GenericQueue<E> {
	
	// 隊列:尾進前出
	private java.util.LinkedList<E> list = new java.util.LinkedList<E>();
	
	/**
	 * 添加一個元素到隊列
	 * @param e
	 */
	public void enqueue(E e) { 
		list.addLast(e);
	}
	
	/**
	 * 從隊列刪除一個元素
	 */
	public E dequeue() {
		return list.removeLast();
	}
	
	
	public int getSize() {
		return list.size();
	}
	
	@Override
	public String toString() {
		return "Queue:" + list.toString();
	}
}

2、棧的實現

package ReWrite;

public class GenericStack<E> {
	
	private java.util.ArrayList<E> list = new java.util.ArrayList<E>();
	
	/**
	 * 添加一個元素到隊列
	 * @param e
	 */
	public void push(E e) { 
		list.add(e);
	}
	
	/**
	 * 從隊列刪除一個元素
	 */
	public E pop() {
		return list.remove(list.size()-1);
	}
	
	
	public int getSize() {
		return list.size();
	}
	
	@Override
	public String toString() {
		return "stack:" + list.toString();
	}
}

3、測試

package ReWrite;

public class Test {
	public static void main(String[] args) {
		
	/*	
		GenericQueue<String> queue = new GenericQueue<String>();
		queue.enqueue("tom");
		queue.enqueue("Ali");
		queue.enqueue("Sua");
		System.out.println("(1)" + queue);
		System.out.println("(1)" + queue.dequeue());
		
	*/
		
		GenericStack<String> stack = new GenericStack<String>();
		stack.push("apple");
		stack.push("orange");
		stack.push("megon");
		System.out.println("(1)" + stack);
		System.out.println("(2)" + stack.pop());
		System.out.println("(3)" + stack.pop());
		System.out.println("(4)" + stack);

	}
}

4、優先隊列

普通的隊列是一種先進先出的數據結構,元素在隊列尾追加,而從隊列頭刪除。在優先隊列( priority queue) 中,元素被賦予優先級。當訪問元素時,具有最高優先級的元素最先刪除。例如,醫院的急救室爲病人賦予優先級,具有最高優先級的病人最先得到治療。

可以使用堆實現優先隊列,其中根結點是隊列中具有最高優先級的對象。

package ReWrite;

import Sort.Heap;

public class MyPriorityQueue<E extends Comparable<E>> {
	
	private Heap<E> heap = new Heap<>();
	
	public void enqueue(E newObject) {
		heap.add(newObject);
	}
	
	public E dequeue() {
		return heap.remove();
	}
	
	public int getSize() {
		return heap.getSize();
	}
}

測試:

package ReWrite;

public class Test {
	public static void main(String[] args) {
		Patient p1 = new Patient("John",2);
		Patient p2 = new Patient("Jim",1);
		Patient p3 = new Patient("Tim",5);
		Patient p4 = new Patient("Cindy",7);
		
		MyPriorityQueue<Patient> priorityQueue = new MyPriorityQueue<>();
		priorityQueue.enqueue(p1);
		priorityQueue.enqueue(p2);
		priorityQueue.enqueue(p3);
		priorityQueue.enqueue(p4);
		
		while(priorityQueue.getSize()>0)
			System.out.println(priorityQueue.dequeue());
		

	}
	
	static class Patient implements Comparable<Patient>{
		private String name;
		private int priority;
		
		public Patient(String name, int priority) {
			this.name = name;
			this.priority = priority;
		}
		
		@Override
		public String toString() {
			return name + "(priority:" + priority + ")";
		}
		


		@Override
		public int compareTo(Patient o) {
			return this.priority - o.priority;
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章