栈
- 先进后出
- 为栈中的每一个元素定义一个结点Node,这个结点包括元素本身和下一个结点的引用,栈底结点的下一个为null。
- 只有一个栈顶指针
实现出栈、入栈和迭代等操作。
public class Stack<T> implements Iterable<T> { //栈顶元素 private Node<T> first; //栈长度 private int n; //栈的存储单位:一个存放当前元素和下一个结点的结点 private static class Node<T>{ private T item; private Node<T> next; } /** * @Author haien * @Description 初始化一个空栈 * @Date 19:56 2018/10/25 **/ public Stack(){ first = null; n=0; } public boolean isEmpty(){ return first==null; } public int size(){ return n; } public void push(T item){ Node<T> oldfirst=first; first=new Node<T>(); first.item=item; first.next=oldfirst; n++; } public T pop(){ if(isEmpty()) throw new NoSuchElementException(); T item=first.item; first=first.next; n--; return item; } /** * @Author haien * @Description 出栈但不删除元素 * @Date 2018/10/25 * @Param [] * @return void **/ public T peek(){ if(isEmpty()) throw new NoSuchElementException(); return first.item; } /** * @Author haien * @Description 把所有元素都连成一个字符串 * @Date 2018/10/25 * @Param [] * @return java.lang.String **/ @Override public String toString() { StringBuilder s=new StringBuilder(); //适用于处理大量字符串 for(T item:this){ s.append(item); s.append(' '); } return s.toString(); } @Override public Iterator<T> iterator(){ return new ListIterator<T>(first); } private class ListIterator<T> implements Iterator<T>{ private Node<T> current; public ListIterator(Node<T> current) { this.current = current; } @Override public boolean hasNext() { return current!=null; } @Override public T next() { if(!hasNext()) throw new NoSuchElementException(); T item=current.item; current=current.next; return item; } @Override public void remove(){ throw new UnsupportedOperationException(); } } }
应用:用两个栈实现四则运算
/** * @Author haien * @Description 用栈实现四则运算 * @Date 2018/10/29 **/ public class Evaluate { //设置优先级 public static int priority(String s) throws ValidationException { switch(s){ case "(": return 4; case "*": case "/": return 3; case "+": case "-": return 2; case ")": return 1; default: throw new ValidationException("算术表达式格式错误!"); } } public static void main(String[] args) throws ValidationException { //数字栈 Stack<Double> s1=new Stack<>(); //符号栈 Stack<String> s2=new Stack<>(); StringBuilder num=new StringBuilder(""); int i=0; double a=0.0; System.out.println("请输入表达式:"); //读取表达式 while(!StdIn.isEmpty()){ //获取表达式 String s=StdIn.readLine().replaceAll("\\s*",""); //获取一行字符串;去空白符 //遍历表达式 while(i<=s.length()){ //数字(支持多位数、小数) if(i<s.length()&&(s.charAt(i)>='0'&&s.charAt(i)<='9'||s.charAt(i)=='.')){ num.append(s.charAt(i)); i++; if(i==s.length()||((s.charAt(i)<'0'||s.charAt(i)>'9')&&s.charAt(i)!='.')){ if(!ValidatorUtil.isNumeric(num)){ //是否整数或小数 throw new ValidationException("算术表达式格式错误!"); } s1.push(Double.parseDouble(num.toString())); num=new StringBuilder(""); } } //运算符 //无效括号 else if(i<s.length()&&s.charAt(i)==')'&&!s2.isEmpty()&&s2.peek().equals("(")) { s2.pop(); //记得把栈里没用的左括号弹掉 i++; } //进栈(栈为空||运算符优先级大于栈顶||栈顶为左括号) else if(i<s.length() &&(s2.isEmpty() ||priority(String.valueOf(s.charAt(i))) > priority(s2.peek()) ||s2.peek().equals("(")) ){ s2.push(String.valueOf(s.charAt(i))); i++; } //表达式只有一个数字 else if(s1.size()==1) break; //弹栈(i>=字符串长度时就已经读取完了,但是符号栈还有就还要进行运算||符号优先级低于栈顶) else if((i>=s.length() && !s2.isEmpty()) || (priority(String.valueOf(s.charAt(i))) <= priority(s2.peek()))){ //- / 记得颠倒过来 switch (s2.pop()){ case "+": s1.push(s1.pop()+s1.pop()); break; case "-": a=s1.pop();s1.push(s1.pop()-a); break; case "*": s1.push(s1.pop()*s1.pop()); break; case "/": a=s1.pop();s1.push(s1.pop()/a); break; } } else{ throw new ValidationException("算术表达式格式错误!"); } } System.out.println("结果为:"+s1.pop()); System.out.println("请输入表达式:"); i=0; } } }
队列
- 先进先出
- 相当于在栈的基础上加上一个队头指针,指向最早加入的成员,别新成员一来老成员就不见了
如果是数组的话很少用循环数组,而是超出容量重新创建一个新数组并把旧元素移过去
/** * @Author haien * @Description 基于链表的队列 * @Date 2018/10/26 **/ public class Queue<T> implements Iterable<T>{ //队头,用于出队 private Node first; //队尾,用于入队 private Node last; //长度 private int n; //结点 private class Node{ private T item; private Node next; } public boolean isEmpty(){ return first==null; } public int size(){ return n; } public void enQueue(T item){ Node oldlast=last; last=new Node(); //必须要new,防止栈为空时下一行出现NPE last.item=item; //为什么私有属性也能访问??? last.next=null; if(isEmpty()) first=last; else oldlast.next=last; n++; //放最后,方便前面判空 } public T deQueue(){ if(isEmpty()) throw new NoSuchElementException(); n--; T item=first.item; first=first.next; //防止游离,否则last还指着已经出队的那个元素 if(isEmpty()) last=null; return item; } public T peek(){ if(isEmpty()) throw new NoSuchElementException(); return first.item; } @Override public String toString() { StringBuilder s=new StringBuilder(); for(T item:this){ //调用的是this的迭代器 s.append(item); s.append(' '); } return s.toString(); } @Override public Iterator<T> iterator() { return new ListIterator(); } private class ListIterator implements Iterator{ //不能定义为MyIterator<T>,此T与外部类的T会被视为另一类 private Node currrent; public ListIterator() { this.currrent = first; } @Override public boolean hasNext() { return currrent!=null; } @Override public T next() { if(!hasNext()) throw new NoSuchElementException(); T item=currrent.item; currrent=currrent.next; return item; } @Override public void remove() { throw new UnsupportedOperationException(); } } public static void main(String[] args) { Queue<String> queue=new Queue<>(); //输入字符串,回车,进栈,输入-,回车,出栈 while (!StdIn.isEmpty()){ //底层是scanner.hasNext(),请求输入并获取输入流判断是否为空 //底层是scanner.next(),从输入流中读取字符串,遇到空格结束一次读取,直到读到输入流末尾再重新请求输入 String item=StdIn.readString(); if(!item.equals("-")) queue.enQueue(item); else if(!queue.isEmpty()) StdOut.print(queue.deQueue()+" "); } StdOut.println("("+queue.size()+" left on queue)"); } }
背包
- 其实就是不能出栈的栈,只能往里add元素
代码实例
- DataStructure/dataStructure