赞
踩
jdk1.8
**
**
LIFO,可动态调整大小的栈实现
下压栈(或简称栈): 是一种基于后进先出策略的集合类型。
场景:
1.存放电子邮件——在收信时将邮件压入最顶端,在取信时从最顶端将它们弹出。第一封一定是最新的邮件。好处是可以及时看到感兴趣的邮件,但不把栈清空,较早的邮件可能不会被读到。
2.网上冲浪——点击一个超链接,浏览器会显示一个新的页面(并将其压入一个栈)。不断点击超链接进入新的页面,但总可以通过“回退”按钮重新访问以前的页面。
public static void main(String[] args) {
Stack<Integer> stack;
stack = new Stack<>();
int [] arr = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };
for (int x : arr){
stack.push(x);
}
while ( !stack.isEmpty() )
{
System.out.print(stack.pop()+"\t");
}
}
import java.util.Iterator; /** * @Auther: Charherogit * @Package: DataStructure.basic */ public class ResizingArrayStack<Item> implements Iterable<Item> { private Item[] a = (Item[]) new Object[1]; //栈元素 private int N = 0; //元素数量 public boolean isEmpty(){ return N == 0; } public int size(){ return N; } //将栈移动到一个大小为max的新数组 private void resize(int max) { Item[] temp = (Item[]) new Object[max]; for (int i = 0; i < N ; i++) temp[i] = a[i]; a = temp; } //将元素添加到栈顶 public void push(Item item) { if (N == a.length) resize(2*a.length); a[N++] = item; } //从栈顶删除元素 public Item pop() { Item item = a[--N]; a[N] = null; if (N > 0 && N == a.length/4 ) resize(a.length/2); return item; } @Override public Iterator<Item> iterator() { return new ReverseArrayIterator(); } //支持后进先出的迭代 private class ReverseArrayIterator implements Iterator<Item>{ private int i = N; @Override public boolean hasNext() { return i > 0 ; } @Override public Item next() { return a[--i]; } public void remove(){} } }
import java.util.Iterator; /** * @Auther: Charherogit * @Package: DataStructure.basic */ public class ListStack<Item> implements Iterable<Item> { //节点嵌套类 private class Node{ Item item; Node next; } private Node first; //栈顶(最近添加的元素) private int N; //元素数量 public boolean isEmpty(){ return N == 0; } public int size(){ return N; } //向栈顶添加元素 public void push(Item item) { Node oldfirst = first; first = new Node(); first.item = item; first.next = oldfirst; N++; } //从栈顶删除元素 public Item pop(){ Item item = first.item; first = first.next; N--; return item; } @Override public Iterator<Item> iterator() { return new ListIterator(); } private class ListIterator implements Iterator<Item>{ private Node current = first; @Override public boolean hasNext() { return current != null; } public void remove(){} @Override public Item next() { Item item = current.item; current = current.next; return item; } } }
四则运算
针对一个字符串(算术表达式 eg:(1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) )。 这个算术表达式可能是一个数字,可能是由数字和运算符或者加上括号组成的表达式。
针对这种由括号、运算符和数字组成的字符串,并按照正确的顺序完成各种初级算术运算操作。可以使用两个栈来完成。
分4中情况从左到右逐个将其入栈处理
1.将操作数压入操作数栈
2.将运算符压入运算符栈
3.忽略左括号
4.遇到右括号,弹出一个操作符,弹出所需数量的操作数,并将运算符和操作数的运算结果压入操作数栈
具体实现
public static void main(String[] args) { Stack<String> ops = new Stack<>(); Stack<Double> vals = new Stack<>(); //以下为两个测试用例 // ( 1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) ) 101.0 // ( ( 1 + sqrt ( 5.0 ) ) / 2.0 ) 1.618033988749895 String str = new Scanner(System.in).nextLine(); int i = 0; int j = -1; Deque<String> deque = new LinkedList<>(); for (char x : str.toCharArray()){ if (x == ' '){ deque.offer(str.substring(j+1,i)); j = i; } i++; } deque.offer(str.substring(j+1,i)); while ( !deque.isEmpty() ) { String s = deque.pop(); if (s.equals("(")) ; else if (s.equals("+")) ops.push(s); else if (s.equals("-")) ops.push(s); else if (s.equals("*")) ops.push(s); else if (s.equals("/")) ops.push(s); else if (s.equals("sqrt")) ops.push(s); else if (s.equals(")")) { String op = ops.pop(); double v = vals.pop(); if (op.equals("+")) v = vals.pop() + v; else if (op.equals("-")) v = vals.pop() - v; else if (op.equals("*")) v = vals.pop() * v; else if (op.equals("/")) v = vals.pop() / v; else if (op.equals("sqrt")) v = Math.sqrt(v); vals.push(v); } else vals.push(Double.parseDouble(s)); } System.out.println(vals.pop()); }
DFS深度优先遍历
栈在算法中另一个应用则是深度优先遍历的应用。在各种树的模型中,进行树的深度遍历,使用栈是最好的选择。
在二叉树中,针对于前中后序遍历,我们一般使用递归算法,非常简单。在使用非递归算法中,我们则需要借用栈的特性来进行迭代遍历。
除此之外,包括各种树的变形题,二叉树的左右视图、N叉树遍历等。
当然有些问题使用队列来进行广度优先遍历更方便。
深度优先遍历在一点程度上比较类似于回溯算法。在各种问题中,DFS和回溯使用的解题策略是差不多的。
有兴趣的关注我的公众号,一起学习交流啊
转到 》深度优先遍历
上一篇 》数组与链表
下一篇 》队列
返回 》数据结构
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。