码迷,mamicode.com
首页 > 其他好文 > 详细

线性表、栈、队列和优先队列

时间:2020-07-29 17:53:03      阅读:74      评论:0      收藏:0      [点我收藏+]

标签:面向对象思想   注意   operation   empty   lan   private   row   for   ++   

  为一个特定的任务选择最好的数据结构和算法是开发高性能软件的一个关键。

  数据结构是以某种形式将数据组织在一起的集合(collection)。数据结构不仅存储数据,还支持访问和处理数据的操作。

  在面向对象思想里,一种数据结构也被认为是一个容器(container)或者容器对象(container object),它是一个能存储其他对象(常称为数据或元素)的对象。定义一种数据结构从本质上讲就是定义一个类。数据结构应该使用数据域存储数据,并提供方法支持查找,插入和删除等操作。因此,创建一个数据结构就是创建这个类的一个实例。然后可以使用这个实例上的方法来操作这个数据结构,例如,向该数据结构中插入一个元素,或者从这个数据结构中删除一个元素。

  java提供了很多能有效组织和操作数据的数据结构。这些数据结构 通常称为java集合框架(Java Conllections Framework)。

collection接口为线性表、向量、栈、队列,优先队列以及集合定义了共同的操作。

Java集合框架支持以下两种类型的容器:

  一种是为了存储一个元素集合,简称为集合(collection)

  另一种是为了存储键/值对,称为映射表(map)

现在我们把注意力集中在以下集合上,键值对后续再做介绍

List用于存储一个有序元素集合。

Set用于存储一组不重复的元素。

Stack用于存储采用后进先出方式处理的对象。

Queue用于存储采用先进先出方式处理的对象。

Priority Queue用于存储按照优先级顺序处理的对象。

这些集合的通用特性再接口中定义,而实现在具体类中提供。

技术图片

Collection接口是处理对象集合的根接口,公共方法如下

技术图片

 

 

注:方法addAll、removeAll、retainAll类似于集合上的并、差、交运算。

注:Collection接口中的有些方法是不能再具体子类中实现的。再这种情况下,这些方法会抛出异常java.lang.UnsupportedOperationException,它是RuntimeException异常类的一个子类。这样设计很好,可以在自己的项目中使用。如果一个方法在子类中没有意义,可以按如下方式实现它:

pub1ic void someMethod() {
    throw new UnsupportedOperationException("Method not supported");
}

  迭代器

每种集合都是可迭代的(Iterable)。可以获得集合的Iterator对象来遍历集合中的所有元素。

Iterator是一种经典的设计模式,用于在不需要暴露数据是如何保存在数据结构的细节的情况下,来遍历一种数据结构。

线性表

List接口继承自Collection,定义了一个用于顺序存储元素的集合。可以使用它的两个具体类ArrayList和LinkedList来创建一个线性表

 

Comparator接口

线性表和集合的静态方法

向量类和栈类

队列和优先队列

示例:表达式求值

技术图片

/**
 * 使用两个栈(operandStack,operatorStack)分别存放操作数和操作符
 * 阶段1:扫描表达式 ,(15+2)*5-23,从左到右扫描表达式,提取出操作数和操作符以及括号
 *         1.如果提取的是操作数,则将其压入operandStack。
 *         2.如果提取的是+或者-号运算符,处理operatorStack栈顶所有的运算符,并将提取到的运算符压入到operatorStack
 *         3.如果提取的是*或者/号运算符,处理operatorStack栈顶所有的*和/运算符,并将提取到的运算符压入到operatorStack
 *         4.如果提取的是(,将提取到的运算符压入到operatorStack。
 *         5.如果提取的是),重复处理来自operatorStack栈顶的运算符,直到遇到(为止。
 * 阶段2:清除栈
 *         重复处理来自operatorStack栈顶的运算符,直到operatorStack栈为空
 * 
 *
 */
public class EvaluateExpression {
    public static void main(String[] args) {
        System.out.println("请输入一个整数的简单运算表达式,比如:( 15 + 2 ) * 5 - 23");
        Scanner input = new Scanner(System.in);
        String expression = input.nextLine();
        int ret = evaluateExpression(expression);
        System.out.println(expression + " = " + ret);
        input.close();
    }
    /**
     * 计算表达式
     * @param expression 表达式
     * @return 结果
     */
    public static int evaluateExpression(String expression) {
        //创建operandStack存储操作数
        Stack<Integer> operandStack = new Stack<>();
        //创建operatorStack存储操作符
        Stack<Character> operatorStack = new Stack<>();
        //在表达式的操作符前后 添加空格,以便于提取操作数和操作符
        expression = insertBlanks(expression);
        //提取操作数及操作符
        String[] tokens = expression.split(" ");
        //阶段1:扫描表达式
        for(String token : tokens) {
            if(token.length() == 0) continue;//如果为
            else if(token.charAt(0) == ‘+‘ || token.charAt(0) == ‘-‘ ) {
                //处理运算符栈顶的所有+,-,*,/
                while(!operatorStack.isEmpty() && (
                        operatorStack.peek() == ‘+‘ ||
                        operatorStack.peek() == ‘-‘ || 
                        operatorStack.peek() == ‘*‘ || 
                        operatorStack.peek() == ‘/‘)) {
                    processAnOperator(operandStack,operatorStack);
                }
                //将+或者-压入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.trim().charAt(0) == ‘(‘) 
                operatorStack.push(‘(‘);
            else if(token.trim().charAt(0) == ‘)‘) {
                while(!operatorStack.isEmpty() && (
                        operatorStack.peek() != ‘(‘)) {
                    processAnOperator(operandStack,operatorStack);
                }
                operatorStack.pop();//弹出(
            }else 
                operandStack.push(Integer.valueOf(token));
        }
        //阶段2:清空栈
        while(!operatorStack.isEmpty()) {
            processAnOperator(operandStack,operatorStack);
        }
        return operandStack.pop();
    }
    /**
     * 在表达式的操作符前后 添加空格,以便于提取操作数和操作符
     * @param expression 表达式
     * @return 添加空格后的表达式
     */
    private static String insertBlanks(String expression) {
        String result = "";
        for(int i = 0; i < expression.length(); i++) {
            if(expression.charAt(i) == ‘(‘ || expression.charAt(i) == ‘)‘ || expression.charAt(i) == ‘+‘ ||
                    expression.charAt(i) == ‘-‘ || expression.charAt(i) == ‘*‘ || expression.charAt(i) == ‘/‘) 
                result += " " + expression.charAt(i) + " ";
            else
                result += expression.charAt(i) ;
        }
        return result;
    }
    
    private static void processAnOperator(Stack<Integer> operandStack,Stack<Character> operatorStack) {
        char op = operatorStack.pop();
        int num1 = operandStack.pop();
        int num2 = operandStack.pop();
        if(op == ‘+‘) operandStack.push(num2 + num1);
        else if(op == ‘-‘) operandStack.push(num2 - num1);
        else if(op == ‘*‘) operandStack.push(num2 * num1);
        else if(op == ‘/‘) operandStack.push(num2 / num1);
    }
}

编程练习题:

1.(按字母升序显示单词)编写一个程序,从文本文件读取单词,并按字母的升序显示所有的单词(可重复)。单词必须以字母开始。

2.编写一个测试程序,在一个链表上存储500万个整数,分别使用iterator和get(index)的遍历时间。

3.编程实现编组符号对

  圆括号:(和)

  花括号:{和}

  方括号:[和]

注意:符号不能交错,编写程序检测编组符号是否正确匹配。

4

线性表、栈、队列和优先队列

标签:面向对象思想   注意   operation   empty   lan   private   row   for   ++   

原文地址:https://www.cnblogs.com/adan-chiu/p/13182610.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!