重寫Stack與Queue以及瀏覽器前進和後退的本質

一、棧的經典應用—瀏覽器的前進和後退

       瀏覽器前進和後退底層就是用兩個棧來實現的。


       前提:同一瀏覽器的一個窗口

       每訪問某個網址的時候瀏覽器都會將這個網址壓入棧1,用戶看到的實際就是棧1頂部的網址

       當用戶點擊後退的時候,會將棧1頂部的網址彈出並壓入棧2,此時瀏覽器又會將棧1頂部的網址呈現給用戶。

       當你按下前進按鈕的時候,本質是從棧2彈出一個網址壓到棧1裏面,不過如果棧2是空的話就無法點擊前進按鈕。

當棧2不爲空,此時用戶又訪問了一個新的網址,則這時候瀏覽器會將棧2中的所有內容都清空。



       舉例子:依次訪問京東、百度、淘寶,點擊兩次後退按鈕,點擊前進按鈕,再訪問騰訊。

       點擊兩次後退按鈕棧情況:
Alt
       點擊前進按鈕棧情況:
Alt
       再訪問騰訊棧情況:
Alt




二、Stack

1、棧明細

       棧是一種特殊的線性表,只能在棧頂插入和刪除元素(入棧和出棧),相當於只有棧頂一端纔對用戶可見。遵循後進先出LIFO原則(Last In First Out)與FILO原則(First In Last Out)。

       考慮到棧只在一端操作數據的時間複雜度,底層可以用動態數組或者雙向鏈表實現,jdk源碼用的是動態數組實現的棧,只不過繼承的是Vector<E>這個泛型,和動態數組唯一不同就是線程安全


Alt


	public class Stack<E> {
	    private ArrayList<E> list;  //組合優於繼承
	
	    public Stack() {
	        list = new ArrayList<>();
	    }
	
	    public boolean isEmpty() {
	        return list.size() == 0;
	    }
	
	    public void push(E element) {
	        list.add(element);
	    }
	
	    public E pop() {
	        E element = list.get(list.size() - 1);
	        list.remove(list.size() - 1);
	        return element;
	    }
	
	    /**
	     * 返回棧頂元素
	     *
	     * @return
	     */
	    public E peek() {
	        return list.get(list.size() - 1);
	    }
	    
	 	public static void main(String[] args) {
	        Stack<Integer> stack = new Stack<>();
	        stack.push(11);
	        stack.push(22);
	        stack.push(33);
	        stack.pop();
	        stack.push(44);
	        System.out.println(stack.peek());
	        while (!stack.isEmpty()) {
	            System.out.println(stack.pop());
	        }
	    }
	}



2、測試結果

Alt



三、Queue

1、普通隊列明細

       普通隊列也是特殊的線性表,只能在隊尾插入元素(入隊),在隊頭刪除元素(出隊),但是隻有隊頭爲用戶可見。遵循後進先出LILO原則(Last In Last Out)與FIFO原則(First In First Out)。

       考慮到隊列需要在兩端操作數據的時間複雜度,底層最適用雙向鏈表實現,jdk源碼用的也是LinkedList實現的隊列,LinkedList底層還是雙向鏈表啦。

       其實普通隊列完全可以用兩個棧來模擬

Alt


	public class Queue<E> {
	    private DoubleLinkedList<E> list;
	
	    public Queue() {
	        list = new DoubleLinkedList<>();
	    }
	
	    public boolean isEmpty() {
	        return list.size() == 0;
	    }
	
	    public void offer(E element) {
	        list.add(element);
	    }
	
	    public E remove() {
	        E element = list.get(0);
	        list.remove(0);
	        return element;
	    }
	
	    /**
	     * 返回隊列頭元素
	     *
	     * @return
	     */
	    public E peek() {
	        return list.get(0);
	    }
	
	    public static void main(String[] args) {
	        Queue<Integer> queue = new Queue<>();
	        queue.offer(11);
	        queue.offer(22);
	        queue.offer(33);
	        queue.remove();
	        queue.offer(44);
	        System.out.println(queue.peek());
	        while (!queue.isEmpty()) {
	            System.out.println(queue.remove());
	        }
	    }
	}



2、測試結果

Alt


3、雙端隊列明細

       雙端隊列不僅可以在隊列頭刪除元素還可以在隊列尾刪除元素(頭尾都可出隊),同時添加元素既可以在隊列尾也可以在隊列頭(頭尾都可入隊)。隊頭和隊尾都爲用戶可見

       jdk源碼用的也是LinkedList實現的隊列,LinkedList底層還是雙向鏈表啦。

Alt

	public class Deque<E> {
	    private DoubleLinkedList<E> list;   //組合優於繼承
	
	    public Deque() {
	        list = new DoubleLinkedList<>();
	    }
	
	    public boolean isEmpty() {
	        return list.size() == 0;
	    }
	
	    public void offerFirst(E element) {
	        list.add(0, element);
	    }
	
	    public void offerLast(E element) {
	        list.add(element);
	    }
	
	    public E removeFirst() {
	        E element = list.get(0);
	        list.remove(0);
	        return element;
	    }
	
	    public E removeLast() {
	        E element = list.get(list.size() - 1);
	        list.remove(list.size() - 1);
	        return element;
	    }
	
	    public E peekFirst() {
	        return list.get(0);
	    }
	
	    public E peekLast() {
	        return list.get(list.size() - 1);
	    }
	
	    public static void main(String[] args) {
	        Deque<Integer> deque = new Deque<>();
	        deque.offerFirst(22);
	        deque.offerFirst(11);
	        deque.offerLast(33);
	        deque.offerLast(44);
	        deque.offerFirst(0);
	        deque.removeFirst();
	        while (!deque.isEmpty()) {
	            System.out.println(deque.removeLast());
	        }
	    }
	}



4、測試結果

Alt

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章