学习数据结构笔记=====>栈
Posted 小智RE0
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习数据结构笔记=====>栈相关的知识,希望对你有一定的参考价值。
学习来源–>传送门–>尚硅谷Java数据结构与java算法(Java数据结构与算法)
案例引入;
一个计算器的运算原理
比如说 输入 5*6+3-2 ;计算器收到的是一个字符串,他就得一个一个分隔这些字符;然后计算;
栈(Stack) 先进后出的有序列表结构;(FILO)
最先放入的元素在栈底,最后放入的在栈顶;
1.栈的基本实现
自定义实现的话,这里直接用数组作为底层存储数据结构;
初始化栈时,定义栈顶的指针为 -1 ;入栈一个,就让栈顶加+1;然后数组存入一个元素;出栈一个,就让栈顶减1;取出元素;
//用数组实现栈;
class StackByArray{
//栈的容量;
private int capacity;
//栈顶指针; 默认指向 -1
private int top = -1;
//栈存储数据; 使用数组;
private int[] data;
//初始化;
public StackByArray(int capacity) {
this.capacity = capacity;
data = new int[capacity];
}
//空栈判断;
public boolean isEmpty(){
return top == -1;
}
//判断满栈;
public boolean isFull(){
return top == capacity - 1;
}
//入栈方法;
public void push(int ele){
//先判断是否栈满;
if(isFull()){
System.out.println("栈满,不可入栈");
return;
}
//指针上移;添加元素;
top++;
data[top] = ele;
}
//出栈方法;
public int pop(){
//先判断空栈;
if(isEmpty()){
throw new RuntimeException("空栈,无法取出元素.");
}
//先把要出栈的元素值存起来;
int temp = data[top];
//指针下移;
top--;
System.out.println("出栈的是-->"+temp);
return temp;
}
//遍历此栈;
public void getAll(){
//先去除空栈的情况;
if(isEmpty()){
System.out.println("空栈,不遍历");
}
for (int i = top; i >=0 ; i--) {
System.out.println("栈内元素->"+data[i]);
}
}
//获取查看的栈顶;
public int getHead() {
if (isEmpty()) {
throw new RuntimeException("空栈,不用看栈顶");
}
System.out.println("当前栈顶为->" + data[top]);
return data[top];
}
}
测试
public class TestStack01 {
//测试;
public static void main(String[] args) {
StackByArray stack = new StackByArray(6);
//入栈;
stack.push(3);
stack.push(2);
stack.push(1);
stack.push(3);
stack.push(6);
stack.push(9);
//栈满,不可入栈;
stack.push(10);
//遍历;
stack.getAll();
//看看栈顶;
stack.getHead();
System.out.println("---出栈-----");
stack.pop();
//看栈顶;
stack.getHead();
//遍历;
stack.getAll();
}
}
栈满,不可入栈
元素->9
元素->6
元素->3
元素->1
元素->2
元素->3
当前栈顶为->9
---出栈-----
出栈的是-->9
当前栈顶为->6
元素->6
元素->3
元素->1
元素->2
元素->3
2.使用栈实现一个基础的计算器(中缀表达式)
这里不考虑小括号
拿到一个表达式,数字直接就进左边的数字栈,
符号入栈时要分情况若符号栈为空栈,这个符号直接入栈即可;
若符号栈不是空栈–>1)待入栈的符号,优先级要是大于符号栈的
栈顶优先级
;直接入栈;
2)待入栈的符号,优先级小于或者说等于栈里的栈顶优先级
,就让左边的数字栈出栈两个数字;符号栈出来一个栈顶符号;计算的结果存入数字栈; 然后 这个待入栈的元素才能入栈;然后,表达式的数字和符号都分配结束后,分别出栈计算,最后数字栈的元素就是结果;
比如说计算 3 + 2 * 6 - 2
3
进入数字栈 ;
+
进入符号栈;
2
进入数字栈;
*
进入符号栈时,先比较优先级; *
优先级高于+
;
*
直接进入符号栈;
然后6
进入数字栈;
这时-
要准备进入符号栈,但是-
优先级小于栈顶*
的优先级;
在数字栈抛出6
和2
,在符号栈抛出*
,2 * 6
运算得到12
;这个计算得到的12
放入数字栈;
然后再把-
放入符号栈
然后把2
放入符号栈
弹出12
-
2
,计算得到10
; 这时栈顶指针指向了+
;
然后让10
+
3
计算 得到 13
即可
注意在存放数字时,字符对应的ascall码不一样;
相差48
(1)初步实现
还是在之前的数组实现的栈基础上进行实现;
public class CalculatorTest01 {
public static void main(String[] args) {
//测试;
//输入计算的式子;
String str = "2+9*8-1";
//创建两个栈,一个放数字,一个放符号;
StackByArray numStack = new StackByArray(15);
StackByArray symbolStack = new StackByArray(15);
//index,作为字符串的索引指针; 辅助作用;
int index =0;
//返回的结果;
int result =0;
//需要计算时的数字和符号;
int num1 =0;
int num2 =0;
int symbol =0;
//从公式中取出的字符
char character = ' ';
//现在要去遍历公式;取出单个字符;
do {
//注意取出单个字符时,这个index的值也在先向后移动;
character = str.substring(index, index + 1).charAt(0);
//判断运算符号;
if (symbolStack.isSymbol(character)) {
//里面还要分为两种情况; 空栈 ; 不是空栈的情况;
if (!symbolStack.isEmpty()) {
//1.运算字符栈不是空栈;那就继续分析这个栈的 栈顶元素优先级;
if (symbolStack.getPriority(character) <= symbolStack.getPriority(symbolStack.getHead())) {
//数字栈出两个数字;符号栈出一个符号;运算
num1 = numStack.pop();
num2 = numStack.pop();
symbol = symbolStack.pop();
result = numStack.getRes(num1, num2, symbol);
//运算结果先放入数字栈;
numStack.push(result);
//然后再把符号放入符号栈;
symbolStack.push(character);
}
//2.优先级大于运算符号栈的栈顶元素;
else {
symbolStack.push(character);
}
} else {
//运算字符栈是空栈,直接入栈即可;
symbolStack.push(character);
}
}
//计算数字的;注意数字的字符 ascall吗实际差距为48;
else {
numStack.push(character - 48);
}
//终止条件;
index++;
} while (index < str.length());
//以符号栈为空作为结束条件;
while (!symbolStack.isEmpty()) {
//计算;
num1 = numStack.pop();
num2 = numStack.pop();
symbol = symbolStack.pop();
result = numStack.getRes(num1, num2, symbol);
//运算结果先放入数字栈;
numStack.push(result);
}
System.out.println("-----计算结果为----->"+result);
}
}
//用数组实现的栈;
class StackByArray {
//栈的容量;
private int capacity;
//栈顶指针; 默认指向 -1
private int top = -1;
//栈存储数据; 使用数组;
private int[] data;
//初始化;
public StackByArray(int capacity) {
this.capacity = capacity;
data = new int[capacity];
}
//空栈判断;
public boolean isEmpty() {
return top == -1;
}
//判断满栈;
public boolean isFull() {
return top == capacity - 1;
}
//入栈方法;
public void push(int ele) {
//先判断是否栈满;
if (isFull()) {
System.out.println("栈满,不可入栈");
return;
}
//指针上移;添加元素;
top++;
data[top] = ele;
}
//出栈方法;
public int pop() {
//先判断空栈;
if (isEmpty()) {
throw new RuntimeException("空栈,无法取出元素.");
}
//先把要出栈的元素值存起来;
int temp = data[top];
//指针下移;
top--;
System.out.println("出栈的是-->" + temp);
return temp;
}
//遍历此栈;
public void getAll() {
//先去除空栈的情况;
if (isEmpty()) {
System.out.println("空栈,不遍历");
}
for (int i = top; i >= 0; i--) {
System.out.println("栈内元素->" + data[i]);
}
}
//获取查看的栈顶;
public int getHead() {
if (isEmpty()) {
throw new RuntimeException("空栈,不用看栈顶");
}
System.out.println("当前栈顶为->" + data[top]);
return data[top];
}
//首先是判断是否为符号;
public boolean isSymbol(char symbol){
return symbol=='+' || symbol=='-' || symbol=='*' || symbol=='/';
}
//给符号自定义优先级;越大优先级越高;
public int getPriority(int symbol){
if(symbol == '*' || symbol == '/'){
return 1;
}else if(symbol == '+' || symbol == '-'){
return 0;
} else {
return -1;
}
}
//计算的方法;
public int getRes(int num1, int num2, int symbol){
//得到的结果;
int result =0;
//判断计算的符号; 进行计算;
switch (symbol){
case '+':
result = num2 + num1;
break;
case '-':
result = num2 - num1;
break;
case '*':
result = num2 * num1;
break;
case '/':
result = num2 / num1;
break;
default:
break;
}
return result;
}
}
测试结果
当前栈顶为->43
当前栈顶为->42
出栈的是-->8
出栈的是-->9
出栈的是-->42
出栈的是-->1
出栈的是-->72
出栈的是-->45
出栈的是-->71
出栈的是-->2
出栈的是-->43
-----计算结果为----->73
这个计算的实现有基础功能,但是并不是很准确;
还有用字符表示数字;超过两位数字即无法计算;
(2)优化实现
在对字符进行判断时,要考虑到最后一个数字的情况,避免出现越界的异常错误
public class CalculatorTest02 {
public static void main(String[] args) {
//测试;
//输入计算的式子;
String str = "21+9/3-1*2-3";
//创建两个栈,一个放数字,一个放符号;
StackByArray numStack = new StackByArray(15);
StackByArray symbolStack = new StackByArray(15);
//index,作为字符串的索引指针; 辅助作用;
int index =0;
//返回的结果;
int result =0;
//需要计算时的数字和符号;
int num1 =0;
int num2 =0;
int symbol =0;
//从公式中取出的字符
char character = ' ';
//优化位置----------------------------------------->
//优化时;这里多定义一个字符串;把两位数以上的数字字符拼接起来;
String multipleStr = "";
//现在要去遍历公式;取出单个字符;
do {
//注意取出单个字符时,这个index的值也在先向后移动;
character = str.substring(index, index + 1).charAt(0);
//判断运算符号;
if (symbolStack.isSymbol(character)) {
//里面还要分为两种情况; 空栈 ; 不是空栈的情况;
if (!symbolStack.isEmpty()) {
//1.运算字符栈不是空栈;那就继续分析这个栈的 栈顶元素优先级;
if (symbolStack.getPriority(character) <= symbolStack.getPriority(symbolStack.getHead())) {
//数字栈出两个数字;符号栈出一个符号;运算
num1 = numStack.pop();
num2 = numStack.pop();
symbol = symbolStack.pop();
result = numStack.getRes(num1, num2, symbol);
//运算结果先放入数字栈;
numStack.push(result);
//然后再把符号放入符号栈;
symbolStack.push(character);
}
//2.优先级大于运算符号栈的栈顶元素;
else {
symbolStack.push(character);
}
} else {
//运算字符栈是空栈,直接入栈即可;
symbolStack.push(character);
}
}
//计算数字的;注意数字的字符 ascall吗实际差距为48;
else {
//numStack.push(character - 48);
//优化位置----------------------------------------->
//用定义的字符串拼接字符;
multipleStr += character;
//考虑最后一位字符的情况;
if(index == str.length()-1){
numStack.push(Integer.parseInt(multipleStr));
}
else {
//截取字符是判断后面是否还有数字;
if(symbolStack.isSymbol(str.substring(index+1,index+2).charAt(0))){
numStack.python学习笔记012——pdb调试