zoukankan      html  css  js  c++  java
  • 数据结构之栈与队列

    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 }
  • 相关阅读:
    软件工程概论(课堂作业01)
    java小程序(课堂作业06)
    动手动脑(课堂作业06)
    动手动脑(课堂作业05)
    java小程序(课堂作业04)
    动手动脑(课堂作业04)
    java小程序(课堂作业03)
    动手动脑(课堂作业03)
    动手动脑(课堂作业02)
    Codeforces 178B1-B3 Greedy Merchants
  • 原文地址:https://www.cnblogs.com/weiziqiang/p/8998081.html
Copyright © 2011-2022 走看看