15.第20章:线性表、栈、队列、优先队列

java框架支持两种类型的容器:

  • 为了存储一个元素集合,简称合集
  • 为了存储键/值对,称为映射表

1.集合

  • Set用于存储一组不重复的元素
  • List用于存储一个有序元素集合
  • Stack用于存储后进先出方式处理的对象
  • Queue用于存储采用先进先出方式处理的对象
  • Priority Queue用于存储按照优先级顺序处理的对象


    15.第20章:线性表、栈、队列、优先队列_第1张图片

collection接口:

15.第20章:线性表、栈、队列、优先队列_第2张图片
collection接口

2.迭代器

Iterator是一种经典的设计模式,用于在不需要暴露数据是如何保存在数据结构的细节的情况下,来遍历一个数据结构。
Collection接口继承自Iterator接口,Iterator接口中Iterator()方法返回一个Iterator的实例。


15.第20章:线性表、栈、队列、优先队列_第3张图片

3.线性表 List

List接口继承自Collection接口,定义了一个用于顺序存储元素的集合。可以使用ArrayList(数组线性表)和LinkedList(链表)来创建一个线性表。

  • List接口通用方法
15.第20章:线性表、栈、队列、优先队列_第4张图片

方法listIterator()会返回ListIterator的一个实例。ListIterator接口继承了Iterator接口,以增加对线性表的双向遍历能力。


15.第20章:线性表、栈、队列、优先队列_第5张图片
ListIterator接口可以双向遍历线性表
  • 数组线性表类ArrayList和链表类LinkedList

ArrayList和LinkedList是实现List接口的两个具体类。
1)ArrayList
ArrayList用数组存储元素,这个数组是动态创建的。如果元素个数超过了数组的容量,就创建一个更大的新数组,并将当前数组中所有元素都复制到新数组中。


15.第20章:线性表、栈、队列、优先队列_第6张图片

2)LinkedList
LinkedList在一个链表中存储元素。


15.第20章:线性表、栈、队列、优先队列_第7张图片

比较:
如果需要通过下标随机访问元素,而不会在线性表起始末尾位置插入或删除,使用ArrayList效率高。
如果需要在线性表起始末尾位置插入删除元素,选用LinkedList效率高。
public class text1_线性表 {
    public static void main(String[] args ){
        //ArrayList
        List arrayList=new ArrayList();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(0,10);
        arrayList.add(3,30);
        System.out.println(arrayList);




        //linkedList
        LinkedList linkedList=new LinkedList();
        linkedList.add("red");
        linkedList.add(1);
        linkedList.add(2);
        linkedList.add(3);
        linkedList.addFirst("yellow");
        linkedList.removeLast();
        System.out.println(linkedList);
        //从前向后遍历
        ListIterator listIterator=linkedList.listIterator();
        while (listIterator.hasNext()){
            System.out.print(listIterator.next()+" ");
        }
        System.out.println();
        //从后向前遍历
        listIterator=linkedList.listIterator(linkedList.size());
        while (listIterator.hasPrevious()){
            System.out.print(listIterator.previous()+" ");
        }
    }
}

 
 
15.第20章:线性表、栈、队列、优先队列_第8张图片

4.Collections类

Collections类包含了执行合集和线性表中通用操作的静态方法。


15.第20章:线性表、栈、队列、优先队列_第9张图片

5.Vector和栈

  • Vector

Vector是AbstractList的子类,Stack是Vector的子类。
Vector是同步的,如果不需要同步,建议使用ArrayList效率高


15.第20章:线性表、栈、队列、优先队列_第10张图片
图片.png
  • stack类

15.第20章:线性表、栈、队列、优先队列_第11张图片

6.队列和优先队列

15.第20章:线性表、栈、队列、优先队列_第12张图片
  • 队列(queue)是一种先进先出的数据结构。元素被追加到队列末尾,然后从队列头部出去。


    15.第20章:线性表、栈、队列、优先队列_第13张图片
  • 双端队列(Deque),继承自Queue接口,增加了如下方法:addFirst(e)、removeFirst()、addLast(e)、removeLast()、getFirst()和getLast()这些从队列两端插入和删除的方法。
  • 可以使用LinkedList创建一个队列。
public class text2_队列 {
    public static void main(String[] args){
        //LinkedList实现了List和Deque接口,Deque接口继承了Queue接口,使用LinkedList()创建队列
        Queue queue=new LinkedList();
        queue.offer("hello");
        queue.offer("Queue");
        queue.offer("Deque");
        while (queue.size()>0){
            System.out.print(queue.remove()+" ");
        }
    }
}
  • 优先队列PriorityQueue


    15.第20章:线性表、栈、队列、优先队列_第14张图片

    优先队列默认字符串以升序从队列删除


    15.第20章:线性表、栈、队列、优先队列_第15张图片
    图片.png

7.示例:算数表达式求值

分析:
准备两个栈,一个用于准备放符号operatorStack,一个用于准备放数字operandStack。
准备:为得到的字符串表达式的()+-/左右两边添加空格,方便将多位数区分出来。以空格隔开。
1)如果遇到的是数字,将其push到operandStack中
2)如果遇到的符号是+或-:
operatorStack不为空,并且栈顶元素是+-
/,循环pop得到操作符,同时operandStack弹出两个操作数,将计算结果push进operandStack。直到 operatorStack为空
operatorStack为空,直接将操作符push进operatorStack。
3)如果遇到的是或/,栈顶元素是/,就弹出计算,循环直到operatorStack为空。
operatorStack为空,直接将操作符push进operatorStack。
4)如果遇到的是(,直接压入符号栈;
如果遇到),取出操作符计算,直到栈顶元素是(,最后弹出(。
5)如果 operatorStack不为空,就循环,弹出 operatorStack操作符,弹出operandStack中两个数据,计算结果push进operandStack。
6)返回operandStack的值就是结果

public class text3_算数表达式求值 {
    public static void main(String[] args){
        System.out.println("输入算数表达式");
        Scanner input=new Scanner(System.in);
        String caculate=input.nextLine();
        try {
            System.out.println(evaluateExpression(caculate));
        }catch (Exception e){
            System.out.println("Wrong expression");
        }

    }

    private static Double evaluateExpression(String caculate) {
        //定义了操作符的栈
        Stack operatorStack=new Stack();
        //定义了操作数的栈
        Stack operandStack=new Stack();
        //需要在所有符号前后加上空格,来分割数字,多位数才能正确读取
        caculate=insertBlanks(caculate);
        String[] tokens=caculate.split(" ");
        for(String token:tokens){
            //分割后token,第一个是空格,可能分割后是第一个是空串
            if(token.length()==0)
                continue;
            //如果遇到的是+ -
            if(token.charAt(0)=='+'||token.charAt(0)=='-'){
                while(!operatorStack.isEmpty()&&(operatorStack.peek()=='+'||operatorStack.peek()=='-'||operatorStack.peek()=='*'||operatorStack.peek()=='/')){
                    processAnOperator(operandStack,operatorStack);
                }
                operatorStack.push(token.charAt(0));
            }
            //如果遇到的是* /
            else if(token.charAt(0)=='*'||token.charAt(0)=='/'){
                while (!operatorStack.isEmpty()&&(operatorStack.peek()=='*'||operatorStack.peek()=='/')){
                    processAnOperator(operandStack,operatorStack);
                }
                operatorStack.push(token.charAt(0));
            }
            //如果是(
            else if(token.charAt(0)=='('){
                operatorStack.push(token.charAt(0));
            }
            //如果是)
            else if(token.charAt(0)==')'){
                while (operatorStack.peek()!='('){
                    processAnOperator(operandStack,operatorStack);
                }
                operatorStack.pop();//把(弹出
            }
            //是数字
            else{

               operandStack.push(new Double(token));
            }
        }

        while (!operatorStack.isEmpty()){
            processAnOperator(operandStack,operatorStack);
        }

       //返回最后在数字栈內的值就是结果
        return operandStack.pop();


    }

    private static String insertBlanks(String caculate) {
        String result="";
        for(int i=0;i operandStack, Stack operatorStack) {
        char op=operatorStack.pop();
        double num2=operandStack.pop();
        double num1=operandStack.pop();
        switch (op){
            case '+':operandStack.push(num1+num2);break;
            case '-':operandStack.push(num1-num2);break;
            case '*':operandStack.push(num1*num2);break;
            case '/':operandStack.push(num1/num2);break;
        }

    }
}

你可能感兴趣的:(15.第20章:线性表、栈、队列、优先队列)