一、基本概念
1.数据:数据是描述客观事物的数值、字符以及能输入机器且能被处理的各种符号集合。
2.数据元素:数据元素是组成数据的基本单位,是数据集合的个体。
3.数据对象:具有相同性质的数据元素的集合,是数据的一个子集。
4.数据结构:是相互之间存在一种或多种特定关系的数据元素的集合。
5.数据类型:是一个值的集合和定义在该值上的一组操作的总称。
6.抽象数据类型:由用户定义的一个数学模型与定义在该模型上的一组操作,它由基本的数据类型构成。
二、算法的定义及五个特征。
算法:是对特定问题求解步骤的一种描述,它是指令的有限序列,是一系列输入转换为输出的计算步骤。
算法的基本特性:输入、输出、有穷性、确定性、可行性
算法设计要求。
1正确性、2可读性、3健壮性、4效率与低存储量需求
算法分析。
三、时间复杂度
在计算机科学中,时间复杂性,又称时间复杂度,算法的时间复杂度是一个函数,它定性描述该算法的运行时间。这是一个代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号表述,不包括这个函数的低阶项和首项系数。使用这种方式时,时间复杂度可被称为是渐近的,亦即考察输入值大小趋近无穷时的情况。
常数阶O(1):无循环、无递归、与问题输入规模N无关的、逐行执行的代码。
线性阶O(n):与问题规模有关的,主要是一层循环的代码,多个一层循环可以并列但不能包含
线性O(n+m):和线性阶O(n)一样,只不过有两种数据的输入规模。
平方阶O(n²):与问题输入规模有关的,主要是二层嵌套循环的代码。
对数阶O(log^n):与问题输入规模有关的,主要是一层循环迭代或递归的代码。
四、中缀表达式
1.概念:是一个通用的算数或逻辑公式表示方法,操作符是以中缀表达式处于操作数的中间(如:3 + 4);与前缀表达式(如:+3 4)或者后缀表达式(例:3 4 +)相比,中缀表达式不容易被计算机解析,但仍被许多程序语言使用,因为它符合人们的普遍用法;与前缀或后缀记法不同的是,中缀记法中括号是必需的。
2.代码实现:
package p2.线性结构; //中缀表达式计算器 public class InfixCalculator { public static void main(String[] args) { String expression = "(10+20/2*3)/2+8"; try { int result = evaluateExpression(expression); System.out.println(result); } catch (Exception e) { e.printStackTrace(); System.out.println("Wrong expression :" + expression); } } private static int evaluateExpression(String expression) { //需要两个辅助栈 ArrayStack<Character> operatorStack = new ArrayStack<>(); ArrayStack<Integer> numberStack = new ArrayStack<>(); //格式化表达式 expression = insertBlanks(expression); String[] tokens = expression.split(" "); for (String token : tokens) { //token == tokens[i] //过滤空串 if (token.length() == 0) { continue; //遍历到 + - 号 } else if (token.equals("+") || token.equals("-")) { while (!operatorStack.isEmpty() && (operatorStack.peek() == '+' || operatorStack.peek() == '-' || operatorStack.peek() == '*' || operatorStack.peek() == '/')) { //如果之前是别的+ - * / 则需要弹栈 并计算 processAnOperator(numberStack, operatorStack); } //如果操作符栈为空 或者 不为空但栈顶为( operatorStack.push(token.charAt(0)); //遍历到 * / 号 } else if (token.equals("*") || token.equals("/")) { while (!operatorStack.isEmpty() && (operatorStack.peek() == '*' || operatorStack.peek() == '/')) { //如果之前是别的* / 则需要弹栈 并计算 processAnOperator(numberStack, operatorStack); } //如果操作符栈为空 或者 不为空但栈顶为( operatorStack.push(token.charAt(0)); //遍历到 ( } else if (token.equals("(")) { operatorStack.push(token.charAt(0)); //遍历到 ) } else if (token.equals(")")) { //只要操作符栈的栈顶不是左括号( 就挨个弹栈计算即可 while (operatorStack.peek() != '(') { processAnOperator(numberStack, operatorStack); } //最后 清掉左括号 operatorStack.pop(); //遍历到数字 } else { numberStack.push(new Integer(token)); } } //处理最后面的操作符 while (!operatorStack.isEmpty()) { processAnOperator(numberStack, operatorStack); } return numberStack.pop(); } //操作符栈弹栈一个元素 数字栈弹栈两个数字 进行计算 并将新的结果进栈到数字栈 private static void processAnOperator(ArrayStack<Integer> numberStack, ArrayStack<Character> operatorStack) { char op = operatorStack.pop(); int num1 = numberStack.pop(); int num2 = numberStack.pop(); //num2 op num1 if (op == '+') { numberStack.push(num2 + num1); } else if (op == '-') { numberStack.push(num2 - num1); } else if (op == '*') { numberStack.push(num2 * num1); } else { numberStack.push(num2 / num1); } } //对原表达式进行格式化处理 给所有的非数字字符两边添加空格 private static String insertBlanks(String expression) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < expression.length(); i++) { char c = expression.charAt(i); if (c == '(' || c == ')' || c == '+' || c == '-' || c == '*' || c == '/') { sb.append(' '); sb.append(c); sb.append(' '); } else { sb.append(c); } } return sb.toString(); } }