面试总结:2个栈去实现一个队列

说明

博主我最近去面试,面试的公司问了很多问题,其中有2个和算法相关的题目,没回答上来,后来回来仔细看了下 其实也是很简单的,主要还是这些年 忽略了基础的一些算法,立下个Flag 这下半年 好好的 温习下算法,刷下leetcode.

话不多说,其中的一问题是这样的:

面试官:你知道栈结构么?栈和队列有啥区别?怎么用2个栈去实现一个队列?

栈??? 嗯嗯 知道这个结构 但是很少用呀~? 栈和队列的区别不就是 数据一个树先进先出,一个先进后出么!2个栈实现一个队列???

分析

其实这个题目,我很久之前就看过,当时也没注意,就是大概扫了一下,自己也没有用心去思考!导致了面试的时候 不知道怎么去实现~

首先我们看下这个栈的结构:

Java 中的栈是Stack

class Stack<E> extends Vector<E> {
      public E push(E item) {
        addElement(item);
        return item;
      }
    
    /**
     * 放入一个元素到栈的顶端
     */
     public E push(E item) {
        addElement(item);
        return item;
     }
    
     /**
     * 线程安全的方法 从栈顶取值  并做取出完移除操作
     */
     public synchronized E pop() {
        E  obj;
        int len = size();
        obj = peek();
        removeElementAt(len - 1);
        return obj;
    }
    
    /**
     * 线程安全的方法 从栈顶取值 如果空 抛出异常  
     */
     public synchronized E peek() {
        int  len = size();
        if (len == 0)
            throw new EmptyStackException();
        return elementAt(len - 1);
    }
}

从栈的源码上来看,内部得代码很少,基本都是调用的继承类Vector的方法

Vector

我们再看下 Vector的代码 是怎么做的:

public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
    
    protected Object[] elementData;//存储栈元素的容器   
    protected int elementCount;//栈元素的大小
    
    public Vector() {
        this(10);// 默认大小是10
    }
    
    public synchronized void addElement(E obj) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);//确认数组容量的大小,如果不够会去做数组扩容操作
        elementData[elementCount++] = obj;// 相当于栈顶放入元素
    }
    
    public synchronized E elementAt(int index) {
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
        }
        return elementData(index);//Stack 在调用此方法的时候,传的都是栈顶的原数的位置
    }
    
    E elementData(int index) {
        return (E) elementData[index];
    }
}

有兴趣的可以看下ensureCapacityHelper 这个方法 看名字 应该也能猜到 这个是一数组大小判断的,如果不够应该会做扩容操作,Vector的扩容 还可以设置每次扩容的时候增长的大小,如果不设置 就是默认的double!~

说了这么多和面试的题目一点儿关系都没有哈全是废话 哈哈~

现在步入正题,上面我也说过 栈是后入先出 队列是 先入先出,这个时候又2个栈,怎么去实现?

其实现在想想也简单的,一个栈是后入先出,如果我们把这个栈 倒入另外一个栈 这样另外一个栈数据的顺序 刚好从栈顶到栈底,然后再冲栈顶取出,这样不就是间接实现了先入先出的么!

嗯嗯应该是这样的~

代码

show code:

 /// 定义实现类
    static class StackToQueue<T> {
        public volatile boolean IsEmpty = true;//判断 元素是否为空
        private volatile Stack<T> stack1 = new Stack<>();// 栈1
        private volatile Stack<T> stack2 = new Stack<>();// 栈2

        public synchronized void push(T data) {
            stack1.push(data);
            IsEmpty = false;
        }

        public synchronized T pop() {
            if (stack1.isEmpty()) {
                return null;
            }
            while (stack1.isEmpty() == false) {
                stack2.push(stack1.pop());//将栈1元素倒入到栈2中
            }
            T popData = stack2.pop();// 从栈2的取出原数  此元素就是栈1的底部元素
            while (stack2.isEmpty() == false) {
                stack1.push(stack2.pop());
            }
            if (stack1.isEmpty()) {
                IsEmpty = true;
            }
            return popData;
        }
    }

测试方法:

/**
 * @ClassName StackForListTest
 * @Auther burgxun
 * @Description: 2个栈去实现一个队列
 * @Date 2020/09/07 11:16
 **/
public class StackToQueueTest {
    public static void main(String[] args) {
        Queue<Integer> queue;
        StackToQueue<Integer> stackToQueue = new StackToQueue<>();
        stackToQueue.push(1);
        stackToQueue.push(2);
        stackToQueue.push(3);
        stackToQueue.push(4);
        stackToQueue.push(5);
        while (stackToQueue.IsEmpty == false) {
            Integer integer = stackToQueue.pop();
            if (integer != null) {
                System.out.println("输出:" + integer);
            }
        }
    }
}

输入结果:

输出:1
输出:2
输出:3
输出:4
输出:5

总结

其实这个题目 真的不是很难的,我没有回答出来的原因有2个:

  • 2个面试官 问了大概40分钟后,出现的这个题目,当时已经很累了,加上这个面试已经是我当天下午第二场面试,个人确实有点困乏!
  • 没回答上来 也不能给自己找借口 还是自己对算法性的题目掌握不好,基础不扎实导致,后面继续加油吧~
  • 面试的时候 应该冷静一下,和面试官说 让思考一下,我相信 如果 冷静下来,这个题目还是很好回答的,其实当时心里已经有思路了,但是由于紧张和累,就懒得继续想下去了~

继续加油~!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值