數據結構之棧與隊列


 

1.棧與隊列

  棧與隊列是程序設計中廣泛使用的兩種重要的線性數據結構。

  棧是LIFO(Last In First Out),先存進去的數據只能最后被取出來,進出順序逆序,即先進后出,后進先出。

       隊列是FIFO(First In First Out),它保持進出順序一致,即先進先出,后進后出。

2.如何實現棧

  

兩種方式實現,數組和鏈表

 1 public class MyStack<E> {
 2 
 3     /*
 4      * 用數組實現棧  先進后出,后進先出
 5      * 思路:定義一個數組,用來保存入棧的數據,數組初始化大小為10
 6      *     用size表示入棧數據的個數 而size-1則是對應的數組下標
 7      *     (由於是數組,需要考慮擴容的問題)
 8      *     入棧時,需要判斷數據個數是否超出數組大小,如果超出 使用Arrays.copyOf(,)來擴容
 9      *     
10      *     出棧時,則直接獲取棧頂數據,即根據size-1獲取后進的數據元素的數組下標,然后將對應出棧
11      *     的數據元素的數組下標處置空。
12      *     
13      */
14     private Object[] stack;
15     private int size; //初始化為0
16     private int newLen;
17     
18     public MyStack(){
19         stack = new Object[10];
20     }
21     //判讀是否棧為空
22     public boolean isEmpty(){
23         return size==0;
24     }
25     //查看堆棧頂部的對象,而不將其從堆棧中移除。
26     public E peek(){
27         if(isEmpty())
28         {
29             return null;
30         }
31         return (E)stack[size-1];
32     }
33     //棧頂元素 出棧
34     public E pop(){
35         E e = peek();
36         stack[size-1]=null;
37         size--;
38         return e;
39     }
40     
41     //入棧
42     public E push(E item){
43         ensureCapacity(size+1);
44         stack[size++] = item;
45         return item;
46     }
47     //
48     private void ensureCapacity(int size) {
49         int len = stack.length;
50         if(size>len)
51         {    
52             int newLen = 10;
53             //copy stack to newLen+len of length ’s array
54             stack = Arrays.copyOf(stack, newLen+len);
55         }    
56     }
57 
58     
59       public static void main(String[] args) {
60         MyStack<Integer> ms = new MyStack<>();
61         System.out.println(ms.size);
62         ms.push(1);
63         ms.push(2);
64 
65         System.out.println(ms.size);
66         System.out.println("棧頂元素:"+ms.pop());
67         System.out.println("棧頂元素:"+ms.pop());
68 
69 }

 

 1 /*
 2  * 使用鏈表實現棧  先進后出  后進先出
 3  * 思路: 棧頂位置top  根據鏈表 進行前插法 將入棧的元素放在鏈表頭部
 4  *      出棧的時候,就直接可以從鏈表頭部取出
 5  */
 6 class Node<E>{
 7     Node<E> next = null;
 8     E data;
 9     Node(E data){
10         this.data = data;
11     }
12 }
13 class Stack<E>{
14     Node<E> top = null;
15     
16     //判讀是否棧空
17     public boolean isEmpty(){
18         return top==null;
19     }
20     //讀棧頂元素
21     public E peek(){
22         if(isEmpty()){
23             return null;
24         }
25         return top.data;
26     }
27     
28     //取出棧頂元素
29     public E pop(){
30         if(isEmpty()){
31             return null;
32         }
33         E data = top.data;
34         top = top.next;
35         return data;
36     }
37     
38     
39     
40     //元素入棧
41     public void push(E data){
42         Node<E> newNode = new Node<E>(data);
43         newNode.next = top;
44         top = newNode;
45     }
46 }

 

3.如何實現隊列

Java中是實現了Queue隊列的接口,具體實例化的時候需要用到LinkedList等其他實例化類

使用LinkedList和鏈表

 1 public class MyQueue<E> {
 2     /*
 3      * 使用(list)實現隊列 先進先出 后進后出
 4      * 思路使用LinkedList  本質是雙向鏈表
 5      * 入隊 鏈表后插入
 6      * 出隊 獲取鏈表頭部元素 並remove掉
 7      */
 8     private LinkedList<E> list = new LinkedList<E>();
 9     private int size ;
10     public synchronized void push(E e){
11         list.add(e);
12         //list.addLast(e);
13         size++;
14     }
15     public synchronized E pop(){
16         E e = list.removeFirst();
17         size--;
18         return e;
19     }
20     
21     public synchronized boolean empty(){
22         return size==0;
23     }
24     
25     public synchronized int size(){
26         return size;
27     }
28     
29     
30     public static void main(String[] args) {
31         
32         
33         MyQueue<Integer> mq = new MyQueue<>();
34         mq.push(4);//
35         mq.push(2);
36         
37         System.out.println(mq.size);
38         System.out.println(mq.pop());
39         System.out.println(mq.size);
40     }
41 
42 }
class Queue<E>{
    Node<E> head = null;
    Node<E> tail = null;
    //判讀是否隊空
    public boolean isEmpty(){
        if(head == null && tail==null){
            return true;
        }
        else
            return false;
    }
    //讀隊頭
    public E peek(){
        if(isEmpty())
            return null;
        return head.data;
    }
    //從隊頭 出隊
    public E pop(){
        if(isEmpty())
            return null;
        E e = head.data;
        head= head.next;
        return e;
    }
    //進隊尾
    public void push(E data){
        Node<E>  newNode = new Node<E>(data);
        if(head==null && tail == null)
        {
            head = newNode;
            tail = newNode; 
        }else{
            tail.next = newNode;
            tail = newNode;
        }
    }
    
    //隊長
    public int size(){
        if(head == null)
            return 0;
        int len = 1 ;
        Node<E> l = head;
        while(l.next!=null){
            len++;
            l = l.next;
        }
        return len;
    }
        public static void main(String[] args) {
        
        
        //使用鏈表實現隊列
        Queue<Integer> q = new Queue();
        q.push(1);
        q.push(2);
        q.push(3);
        System.out.println(q.size());
        System.out.println(q.pop());
        System.out.println(q.peek());
    }
}
class Node<E>{
    Node<E> next = null;
    E data;
    Node(E data){
        this.data = data;
    }
}

 

4.如何使用兩個棧模擬隊列操作

 1 public class TwoStackForQueue<E> {
 2 
 3     /*
 4      * 用法兩個stack 實現隊列操作   隊列是先進先出的
 5      * 思想:設置兩個stack A,B, stackA為入隊的棧,stackB為出隊的棧
 6      *         入隊直接進棧A,出棧需要判斷棧B是否為空,如果為空,需要將棧A中的元素放入棧B中
 7      *         如果不為空 直接獲取棧B的棧頂元素
 8      */
 9     Stack<E> A = new Stack<>();
10     Stack<E> B = new Stack<>();
11     public static void main(String[] args) {
12         TwoStackForQueue<Integer> queue = new TwoStackForQueue<>();
13         queue.put(1);
14         queue.put(2);
15         queue.put(3);
16 //        int i = queue.pop();
17 //        System.out.println(i);
18 //        i = queue.pop();
19 //        System.out.println(i);
20 //        i = queue.pop();
21 //        System.out.println(i);
22         while(!queue.empty()){
23             int i = queue.pop();
24             System.out.println(i);
25         }
26         
27     }
28     //判斷是否隊空
29     public boolean empty(){
30         return A.isEmpty() && B.isEmpty();
31     }
32     
33     //出隊
34     public synchronized E pop(){
35         /*if(B.isEmpty()){
36             if(A.isEmpty())
37                 return null;
38             while(!A.isEmpty())
39             {
40                 B.push(A.pop());
41             }
42             return B.pop();
43         }
44         return B.pop();*/
45         //優化
46         if(B.isEmpty()){
47             while(!A.isEmpty())
48             {
49                 B.push(A.pop());
50             }
51         }
52         return B.pop();
53     }
54     //入隊
55     public synchronized void put(E e){
56         A.push(e);
57     }
58     
59     
60     
61 
62 }

 

5.如果使用兩個隊列模擬棧操作

 1 public class TwoQueueForStack<E> {
 2     
 3     /*
 4      * 使用兩個隊列實現棧  棧的特點是先進后出,后進先出
 5      * 思路:兩個Queue 使用LinkedList實例化  LinkedList實際上是一個雙向鏈表
 6      *         q1作為入棧的隊列  即直接將入棧的數據放入q1
 7      *         q2作為出棧的隊列  即需要出棧時,如果q1只有一個元素 直接出棧
 8      *         如果q1不止一個元素,即可以將q1隊列中的數據依次放入q2,最后一個不放入,最后一個元素輸出
 9      *         再將q2中的元素依次放回q1
10      */
11     private Queue<E> q1 = new LinkedList<E>();
12     private Queue<E> q2 = new LinkedList<E>();;
13     public static void main(String[] args) {
14         TwoQueueForStack<Integer> stack = new TwoQueueForStack<>();
15         stack.put(1);
16         stack.put(2);
17         stack.put(3);
18         while(!stack.empty()){
19             int i = stack.pop();
20             System.out.println(i);
21         }
22 
23     }
24     
25     //判斷是否棧空
26         public boolean empty(){
27             return q1.isEmpty() && q2.isEmpty();
28         }
29         
30         //出棧
31         public synchronized E pop(){
32             int size = q1.size();
33             if(size==1)
34                 return q1.poll();
35             
36             int i=1;
37             while(!(i==size)){
38                 q2.add(q1.poll());
39                 i++;
40             }
41             E e = q1.poll();
42             
43             while(!q2.isEmpty()){
44                 q1.add(q2.poll());
45             }
46             return e;
47         }
48         //入棧
49         public synchronized void put(E e){
50             q1.add(e);
51         }
52 
53 }

 


免責聲明!

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



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