2、栈&队列&链表

在java中,常见于集合如List这种写法,就是确保一个集合内的所有对象是属于一个类型的。

算术表达式的存储

如何让一个算术表达式正确的执行?

5 +2*3 +4/2

E.W.Dijkstra在上世纪60年代发明了一种简单的存储方法,使用2个栈,一个用来保存数字,一个用来保存运算符号;

1、将数字压入 数字栈
2、将运算符号压入 符号栈
3、忽略左括弧
4、遇到右括弧时,取出 前面的 数字栈 和 符号栈进行计算 并压入数字栈
public class Evaluate {
    public static void main(String[] args) {
        Stack<String> ops = new Stack<>();
        Stack<Double> nums = new Stack<>() ;

        String str = "(2+(5*2) ) + (2*4)" ; //这里需要做括弧分割!!
        str = "(" +str+")" ;  //格式化输入

        for(int i=0;i<str.length();i++){
            String subStr = str.substring(i, i+1) ;
            System.out.println(subStr);
            if(subStr.equals(" ")) ;
            else if(subStr.equals("(")) ;
            else if(subStr.equals("+")) ops.push(subStr) ;
            else if(subStr.equals("-")) ops.push(subStr) ;
            else if(subStr.equals("*")) ops.push(subStr) ;
            else if(subStr.equals("/")) ops.push(subStr) ;
            else if(subStr.equals("sqrt")) ops.push(subStr) ;
            else if(subStr.equals(")")) {  //输出标识
                System.out.println("-------");
                String op = ops.pop();
                double var = nums.pop() ;
                if(op.equals("+")) var = nums.pop() + var ;
                else if(op.equals("-")) var = nums.pop() - var ;
                else if(op.equals("*")) var = nums.pop() * var ;
                else if(op.equals("/")) var = nums.pop() / var ;
                else if(op.equals("sqrt")) var = Math.sqrt(var) ;
                nums.push(var) ;
            }
            else {
                nums.push(Double.parseDouble(subStr)) ;
            }
        }
        System.out.println(nums.pop());
        //System.out.println(nums.pop());
    }
}

20.0

调整数组大小

private void resize(int max){
    Object[] objs = new Object[max] ;
    for(int i =0 ;i<exsited.length ;i++){
        objs[i] = exsited[i];
    }
    exsited = objs ;
}

对象的游离

从stack的源码得知:

class Stack<E> extends Vector<E>
public synchronized void addElement(E obj) {
    modCount++;
    ensureCapacityHelper(elementCount + 1);
    elementData[elementCount++] = obj;
}

对象的管理实际是用一个下标和一个数组定义的,如果stack超出了设定的大小(初始为10)则进行扩容,见上。
但当使用一个pop方法时,被弹出的元素的引用仍然存在于数组中。这个元素实际上就是个孤儿了,没有谁会再访问它,但Java编译器没法知道这一点,除非该引用被覆盖。这种情况(保存一个不需要的对象的引用)成为游离。在这里,避免对象游离很简单,只需将被弹出的数组元素的值设为null即可,这将覆盖无用的引用,并使系统在使用完被弹出的元素后回收它的内存。

public Item pop(){//删除栈顶元素
    Item item = a[--N];
    a[N] = null;//**避免对象游离**
    ...
    return item;
}

在stack代码中已经实现:

    public synchronized E pop() {
        E      obj;
        int     len = size();
        obj = peek();
        removeElementAt(len - 1);
        return obj;
    }
    public synchronized void removeElementAt(int index) {
        modCount++;
        elementCount--;
        elementData[elementCount] = null; /* to let gc do its work */
    }

stack是一种能够实现动态调整数组大小,支持任意数据类型,支持foreach的后进先出(LIFO)的数据结构。

LinkedBlockingQueue的数据结构

private class Node<E>{
    E e; //任意数据类型
    Node next ;//指向下一引用
}
private final ReentrantLock takeLock = new ReentrantLock();
private final ReentrantLock putLock = new ReentrantLock();

ArrayList的数据结构

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

LinkedList的数据结构

private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;

    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}

为什么stack&queue&list可以pull一个null对象?

在LinkedBlockingQueue中是不可以的,if (e == null) throw new NullPointerException();
stack和list是可以的。

offer,add区别:

区别:两者都是往队列尾部插入元素,不同的时候,当超出队列界限的时候,add()方法是抛出异常让你处理,而offer()方法是直接返回false
offer还提供了 long timeout 阻塞方法。

-抛出异常返回值阻塞超时
插入add(e)offer(e)put(e)offer(e, time, unit)
移除remove()poll()take()poll(time, unit)
检查element()peek()

element() 和 peek() 用于在队列的头部查询元素。与 remove() 方法类似,在队列为空时, element() 抛出一个异常,而 peek() 返回 null。

Deque & Queue
1.stack堆栈,没有迭代器,支持push()方法。后进先出,top()返回最顶端的元素,pop()剔除最顶元素,后进先出(LIFO);

2.deque双端队列,支持迭代器,有push_back()方法,跟vector差不多,比vector多了个pop_front,push_front方法;

3.queue队列,先进先出,不支持迭代器。队列通常(但并非一定)以 FIFO(先进先出)的方式排序各个元素。Queue使用时要尽量避免Collection的add()和remove()方法,而是要使用offer()来加入元素,使用poll()来获取并移出元素。它们的优点是通过返回值可以判断成功与否,add()和remove()方法在失败的时候会抛出异常。 如果要使用前端而不移出该元素,使用element()或者peek()方法。

public interface Deque<E>   extends Queue<E>  

一个线性 collection,支持在两端插入和移除元素。

名称 deque 是“double ended queue(双端队列)”的缩写,通常读为“deck”。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值