栈和队列操作

栈(先进后出)

实现栈

1、数组实现

java程序员面试笔试宝典实现:

package JBStack;

import java.util.Arrays;

public class MySqStack<E>{
	private Object[] stack; //声明数组
	private int size;//数组元素
	public MySqStack() {//构造函数
		// TODO Auto-generated constructor stub
		stack = new Object[10]; //默认大小
	}
	
	/**
	 * 判断是否为空
	 * @return
	 */
	private boolean isEmpty(){
		return size == 0;
	}
	
	/**
	 * 取出栈顶元素
	 * @return
	 */
	private E peek(){
		if (size==0) {
			return null;//空栈
		}
		return (E) stack[size-1];//返回数组最后一个元素,即栈顶元素
	}
	
	/**
	 * 出栈
	 * @return
	 */
	private E pop(){
		if (isEmpty()) {//判断是否为空
			return null;
		}
		E e = peek();//取出栈顶元素
		stack[size-1]=null;//栈顶元素置空
		size--;//长度递减
		return e;//返回栈顶元素值
	}
	
	/**
	 * 入栈
	 * @param item
	 * @return
	 */
	private E push(E item){
		ensureCapacity(size+1);//判断是否是满栈,如果栈满则扩充长度
		stack[size++]=item;//依次添加,下标从0开始
		return item;//返回入栈值
	}
	
	/**
	 * 判断是否是满栈,如果栈满则扩充长度
	 * @param i
	 */
	private void ensureCapacity(int i){
		int len = stack.length;
		if(size>len){
			int newLen = 10;
			stack = Arrays.copyOf(stack, newLen);//利用数组函数
		}
	}
	
	public static void main(String[] args) {
		MySqStack<Integer> ss = new MySqStack<Integer>();
		ss.push(1);
		ss.push(2);
		ss.push(3);
		System.out.println("栈元素个数"+ss.size);
		System.out.println("栈顶元素"+ss.pop());
		System.out.println("栈顶元素"+ss.pop());
	}

}

大话数据结构:

package Stack;

/**
 * 栈的顺序储存结构
 *
 * 问题:构造器中,泛型数组创建是否有更好的方法?
 * @author Yongh
 *
 */
public class SqStack<E> {
    private E[] data; //数据
    private int top;  //栈顶指针,top=-1时为空栈
    private int maxSize; //栈大小
    private static final int DEFAULT_SIZE= 10; //栈默认大小
     
    public SqStack() {
        this(DEFAULT_SIZE);
    }
    public SqStack(int maxSize) {
        //无法创建泛型数组 data=new E[maxSize];
        data=(E[]) new Object[maxSize];
        top=-1;
        this.maxSize=maxSize;
    }
     
    public void push(E e) {
        if(top==maxSize-1)
            throw new RuntimeException("栈已满,无法进栈!");
        top++;
        data[top]=e;//先赋值后运算,即T=top++:T=top; top=top+1;而T=++top:先运算后赋值:top=top+1;T=top;
    }
     
    public E pop() {
        if(top==-1)
            throw new RuntimeException("空栈,无法出栈!");
        E e=data[top];
        top--;
        return e;
    }
     
    public void printStack() {
        if(top==-1) {
            System.out.println("空栈");          
        }else {
            for(int i=0;i<=top;i++) {
                System.out.println(data[i]);
            }
        }      
    }
}

2、链表实现

java程序员面试笔试宝典实现(首选):

package JBStack;
/**
 * 链栈实现
 * @author Dan
 *
 * @param <E>
 */
public class MyStack<E> {
	Node<E> top = null;//头结点
	public class Node<E>{
		Node<E> next;
		E data;
		public Node(E data){
			this.data = data;
		}
	}
	
	/**
	 * 判断是否为空栈
	 */
	public boolean isEmpty(){
		return top==null;
	}
	
	/**
	 * 入栈
	 * @param data
	 */
	 public void push(E data){
		Node<E> newNode = new Node<E>(data);
		newNode.next = top;//在首部插入
		top = newNode;
	 }
	 
	 /**
	  * 出栈
	  * @return
	  */
	 public E pop(){
		 if (this.isEmpty()) {
			return null;
		}
		 E e = top.data;
		 top.next =top.next;
		 return e;
	 }
	 
	 /**
	  * 获取栈顶元素
	  * @return
	  */
	 public E peek(){
		 if (isEmpty()) {
			return null;
		}
		 return top.data;
	 }
	 

}

大话数据结构:

package Stack;

/**
*
* 栈的链式存储结构
* 栈顶放在单链表的头部
* 类似单链表
* @author Yongh
*/
public class LinkStack<E> {
   private StackNode<E> top; //栈顶相当于单链表头结点
   private int count;        //栈链的长度
    
   /**
    * 栈链的结点
    * @author Dan
    *
    * @param <E>
    */
   private class StackNode<E>{
       E data;
       StackNode<E> next;
       public StackNode(E data,StackNode<E> next) {
           this.data=data;
           this.next=next;
       }
   }
    /**
     * 初始化栈链
     */
   public LinkStack() {
       top=new StackNode<E>(null, null);
       count=0;
   }
   
   /**
    * 入栈
    * @param e
    */
    
   public void push(E e) {
       StackNode<E> node=new StackNode<E>(e, top);//一直是在栈顶操作即头结点出进行插入,初始化node(e,top)
       top=node;
       count++;
   }
    
   /**
    * 出栈
    * @return
    */
   public E pop() {
       if(count==0)
           throw new RuntimeException("空栈,无法出栈!");
       StackNode<E> node;            //新建结点   
       node=top;                     //存储要删除的栈顶结点
       E e=node.data;                //获取删除结点的数据   
       top=top.next;                 //栈顶指针后移一位
       node=null;                    //释放栈顶结点
       count--;                      //长度减一      
       return e;     
       //返回数据
   }
    
   public void printStack() {
       if(count==0) {
           System.out.println("空栈");          
       }else {
           StackNode<E> node=top;        //新建栈链点存放要打印的点
           for(int i=0;i<count;i++) {
               System.out.println(node.data); 
               node=node.next;           //依次从栈顶(链表头结点)向下遍历输出
           }
       }      
   }
    
   /*
    * 测试代码
    */
   public static void main(String[] args) {
       LinkStack<Student> linkStack=new LinkStack<Student>();     
       Student[] students= {new Student("小A",11),new Student("小B",12),new Student("小C",13),
               new Student("小D",14),new Student("小E",151)};
       for(int i=0;i<5;i++) {
           linkStack.push(students[i]);
       }
       linkStack.printStack();
       System.out.println("----");
       for(int i=0;i<5;i++) {
           System.out.println(linkStack.pop());//先入后出
       }
       linkStack.printStack();    
   }
}

如何用O(1)的时间复杂度求栈中最小元素

package JBStack;
/**
 * 如何用O(1)的时间复杂度求栈中最小元素
 * 1、使用elem 和 min两个栈结构,elem用来存储结构,min用来存储elem最小元素
 * 2、在入栈时,如果当前入栈元素比原来栈中元素要小,则把这个值压入min栈中
 * 3、在出栈时,先获取当前出栈元素恰好为当前栈中的最小值,则min栈的栈顶元素也出栈。
 *    使当前最小值变为其入栈之前的那个最小值。
 * @author Dan
 *
 */

public class MyStack1{ 
	
	MyStack<Integer> elem;
	MyStack<Integer> min;
	public MyStack1(){
		elem = new MyStack<Integer>();
		min = new MyStack<Integer>();	
	}
	
	public void push(int data ){
		elem.push(data);
		if(min.isEmpty()){
			min.push(data);
		}else{
			if (data<min.peek()) {
				min.push(data);
			}
		}
	}
	
	public int pop(){
		int topData = elem.peek();
		elem.pop();
		if (topData == this.min()) {
			min.pop();
		}
		return topData;
	}
	/**
	 * 求min中栈顶元素
	 * @return
	 */
	 public int min() {
	        if(min.isEmpty())
	            return Integer.MAX_VALUE;
	        else
	            return min.peek();
	    }

}

队列

实现队列

链表实现

java程序员面试笔试宝典(首选):

package JBQueue;

import org.w3c.dom.Node;

public class MyQueue<E> {
	
	Node<E> head = null;
	Node<E> tail = null;
	
	class Node<E> {
		Node<E> next;
		E data;
		public Node(E data){
			this.data = data;
		}
	}
	
	public boolean isEmpty(){
		return head==tail;
	}
	
	public void put(E data){
		Node<E> newNode = new Node<E>(data);
		if (head==null&&tail==null) {
			head = tail = newNode;
		}else {
			tail.next = newNode;
			tail = newNode;
		}
	}
	
	public E pop(){
		if (this.isEmpty()) {
			return null;
		}
		E data = head.data;
		head = head.next;
		return data;
	}
	
	public int size(){
		Node<E> node = head;
		int n = 0;
		while(node !=null){
			n++;
			node = node.next;
		}
		return n;
	}
	
	public static void main(String[] args) {
		MyQueue<Integer> queue = new MyQueue<Integer>();
		queue.put(1);
		queue.put(2);
		queue.put(3);
		System.out.println("队列长度:"+queue.size());
		System.out.println("队列首元素:"+queue.pop());
	}
	
	

}

大话数据结构:

package Queue;

/**
 * 链队列
 * 队尾指针指向终端结点
 *
 * 注意点:出队操作时,若队头是队尾(即队中仅有一个结点),
 * 则删除后要将rear指向头结点。
 *
 * @param <E>
 */
public class LinkQueue<E> {
    private QNode front,rear;
    private int count;
     
    /**
     * 结点
     */
    class QNode{ 
        E data;     
        QNode next; 
        public QNode(E data,QNode next) {
            this.data=data;
            this.next=next;
        }
    }
    /**
     * 链队列的初始化 
     */
    public LinkQueue() {
        front= new QNode(null, null); 
        rear = front;
        count = 0;
    }
     
    /*
     * 入队操作(尾结点插入)
     */
    public void enQueue(E e) {
        QNode node=new QNode(e, null); //将要插入的数据放进新的结点
        rear.next=node;                //从队尾插入,新的结点为队尾结点的后继
        rear=node;                     //新节点成为队尾结点.
        count++;                       //长度增加
    }
     
    /*
     * 出队操作
     */
    public E deQueue() {
        if(rear==front)                                 
            throw new RuntimeException("队列为空!");
        QNode node=front;                          //将欲删除的队头结点暂时存给node
        E e=node.data;                                  //将欲删除的队头结点的值赋值为e
        front = node.next;                         //将原对头结点后继赋值赋值给头结点后继
        if(rear==node)                                  //若队头是队尾,则删除后要将rear指向头结点。
            rear=front;
        node=null;                                      //置为null
        count--;
        //通过count来判断,可能更容易理解
        //if(count==0)
        //  rear=front;
        return e;
    }
     
    /*
     * 获取队列长度
     */
    public int getLength() {
        return count;
    }
     
    /*
     * 打印输出队列
     */
    public void printQueue() {
        if(count==0) {
            System.out.println("空队列"); 
        }else {
            QNode node=front;
            for(int i=0;i<count;i++) {
                node=node.next;
                System.out.print(node.data+" ");
            }
            System.out.println();
        }
    }
     
    /*
     * 测试代码
     */
    public static void main(String[] args) {
        LinkQueue<String> lQueue =new LinkQueue<>();
        lQueue.printQueue();
        lQueue.enQueue("A");
        lQueue.enQueue("B");
        lQueue.enQueue("c");
        lQueue.enQueue("D");
        lQueue.printQueue();    
        lQueue.deQueue();
        lQueue.deQueue();
        lQueue.enQueue("E");
        lQueue.printQueue();
    }
}

循环链表实现:
大话数据结构思路:

package Queue;

/**
 * <循环队列>
 *
 * 注意点:表长的表示、队列满的判断、front和rear的改变
 * 因为rear可能比front大,也可能比front小,
 * 所以队列满的条件应该为:(rear+1)%maxSize==front;
 * 同理,队列长度的计算公式为:maxSize-front + (rear+0)===>(rear-front+maxSize)
 * 通用计算队列长度公式为:(rear-front+maxSize)%maxSize
 * @author Lai
 *
 */
public class SqQueue<E> {
    private E[] data; //数据域
    private int front;//队头(删除)
    private int rear; //队尾(插入)
    private int maxSize;//队列最大长度
    private static final int DEFAULT_SIZE= 10;
     
    /*
     * 初始化
     */
    public SqQueue(){
        this(DEFAULT_SIZE);
    }
    public SqQueue(int maxSize){
        data=(E[]) new Object[maxSize];
        this.maxSize=maxSize;
        front=0;
        rear=0;
    }
     
    /*
     * 求循环队列长度
     */
    public int getLength() {
        return (rear-front+maxSize)%maxSize;
    }
     
    /*
     * 入队操作
     */
    public void enQueue(E e) {
        if((rear+1)%maxSize==front)
            throw new RuntimeException("队列已满,无法入队!");
        data[rear]=e; //队尾插入
        rear=(rear+1)%maxSize;
        //不是rear=rear+1,当rear在数组尾部时,后移一位会转到数组头部
    }
     
    /*
     * 出队操作
     */
    public E deQueue() {
        if(rear==front)
            throw new RuntimeException("队列为空!");
        E e=data[front];//队首插入
        front=(front+1)%maxSize;
        //不是front++,理由同rear
        return e;
    }
     
    /*
     * 打印操作
     */
    public void printQueue() {
        int k=front;
        for(int i=0;i<getLength();i++) {
            System.out.print(data[k]+" ");
            k=(k+1)%maxSize;
        }
        System.out.println();
    }
     
    /*
     * 测试代码
     */
    public static void main(String[] args) {
        SqQueue<String> aQueue=new SqQueue<>(5);   
        aQueue.enQueue("a");
        aQueue.enQueue("b");
        aQueue.enQueue("c");
        aQueue.enQueue("d");
        aQueue.printQueue();
        System.out.println("-----");
        aQueue.getLength();
        aQueue.deQueue();
        aQueue.deQueue();
        aQueue.enQueue("e");
        aQueue.printQueue();
    }
     
}

两个栈实现队列

package JBQueue;

/**
 * 两个栈实现队列
 * 1、利用java内置的stack:import java.util.Stack;
 * 2、栈S1用来提供入队列功能,栈s2用来提供出队列的功能
 * 3、入队列入栈s1就可以
 * 4、出队列分两种情况:
 *    4.1 栈s2不为空,直接弹出s2中的数据
 *    4.2 栈s2为空,依次弹出栈s1的数据放入到栈s2中,再弹出S2的数据。
 * 
 */
import java.util.Stack;


public class SSQueue<E> {
	Stack<E> s1 = new Stack<E>();
	Stack<E> s2 = new Stack<E>();
	public boolean Empty(){
		return s1.isEmpty() && s2.isEmpty();
	}
	public synchronized  void put(E e){
		s1.push(e);
	}
	public synchronized  E pop(){
		if(s2.isEmpty()){
			while(!s1.isEmpty()){
				s2.push(s1.pop());
			}
		}
		return s2.pop();
	}
	
	public static void main(String[] args) {
		SSQueue<Integer> ssq = new SSQueue<Integer>();
		ssq.put(1);
		ssq.put(2);
		System.out.println("队列首元素:"+ssq.pop());
		System.out.println("队列首元素:"+ssq.pop());
		
	} 

}

两个队列实现栈

package JBQueue;

import java.util.ArrayDeque;
import java.util.Queue;

/**
 * 两个队列实现一个栈
 * 1、两个队列q1 q2,q1提供压栈功能  q2提供弹栈功能
 * 2、若队列q1只有一个元素,则让q1中的元素出队列并输出即可
 * 3、若队列q1中不止一个元素,则队列q1中的所有元素出队列,入队列q2,
 *    最后一个元素不入队列q2,
 *    输出该元素,然后将队列q2所有入队列q1
 * @author Dan
 *
 */

public class QQStack {
	Queue<Integer> queue1 = new ArrayDeque<Integer>();
	Queue<Integer> queue2 = new ArrayDeque<Integer>();
	
	/*
	 * 向栈中压入数据
	 */
	public void push(Integer element){
		//两个队列都为空时,优先考虑 queue1
		if(queue1.isEmpty() && queue2.isEmpty()){
			queue1.add(element);
			return;
		}
		
		//如果queue1为空,queue2有数据,直接放入queue2
		if(queue1.isEmpty()){
			queue2.add(element);
			return;
		}
		
		//如果queue2为空,queue1有数据,直接放入queue1中
		if(queue2.isEmpty()){
			queue1.add(element);
			return;
		}
	}
	
	/*
	 * 从栈中弹出一个数据
	 */
	public Integer pop(){
		//如果两个栈都为空,则没有元素可以弹出,异常
		if(queue1.isEmpty() && queue2.isEmpty()){
			try{
				throw new Exception("satck is empty!");
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		
		//如果queue1中没有元素,queue2中有元素,将其queue2中的元素依次放入queue1中,直到最后一个元素,弹出即可
		if(queue1.isEmpty()){
			while(queue2.size() > 1){
				queue1.add(queue2.poll());
			}
			return queue2.poll();
		}
		
		//如果queue2中没有元素,queue1中有元素,将其queue1中的元素依次放入queue2中,直到最后一个元素,弹出即可
		if(queue2.isEmpty()){
			while(queue1.size() > 1){
				queue2.add(queue1.poll());
			}
			return queue1.poll();
		}
		
		return (Integer)null;
	}
	
	public static void main(String[] args) {
		QQStack qs = new QQStack();
		qs.push(2);
		qs.push(4);
		qs.push(7);
		qs.push(5);
		System.out.println(qs.pop());
		System.out.println(qs.pop());
		
		qs.push(1);
		System.out.println(qs.pop());
	}
}

猜你喜欢

转载自blog.csdn.net/hd12370/article/details/82215747