1,栈的实现
1.1 栈-链表实现
//定义Node类 public class Node { public String data=""; Node next=null; public Node(){ data="THE-HEAD"; } public Node(String data){ this.data=data; } }
//基础 //空? //长度-用成员变量表示 //操作 //入栈 //出栈 //返回栈顶元素 //遍历 public class LinkedStack { private int length=0; private Node head=new Node(); //空? public boolean isEmpty(){ if(length==0) return true; else return false; } //入栈 public void push(String data){ Node newNode=new Node(data); newNode.next=head.next; head.next=newNode; length++; } //出栈 public String pop(){ if(length==0){ System.out.println("栈空,无法出栈"); return "ERROR-emptyStack"; }else{ Node p=head.next; head.next=p.next; length--; return p.data; } } //返回栈顶元素 public String getTop(){ if(length==0){ System.out.println("栈空,无法返回"); return null; }else{ return head.next.data; } } //遍历 public void print(){ if(length==0) System.out.println("栈空,无输出"); else{ System.out.print("栈: "); Node p=head; while(p.next!=null){ p=p.next; System.out.print(p.data+" "); } System.out.println(); } } public static void main(String[] asdf){ LinkedStack mystack=new LinkedStack(); System.out.println(mystack.isEmpty()); mystack.pop(); mystack.getTop(); mystack.push("123"); mystack.push("234"); mystack.push("345"); mystack.push("456"); mystack.print(); System.out.println(mystack.isEmpty()); System.out.println(mystack.pop()); mystack.pop(); mystack.print(); } }
1.2 栈-数组实现
public class ArrayStack { private final int SIZE=30; private int[] stackarray=new int[SIZE]; private int top=-1; public void push(int data){ stackarray[++top]=data; } public boolean isEmpty(){ if(top==-1) return true; else return false; } public int pop(){ if(top<0){ System.out.println("栈空,无法出栈"); return Integer.MAX_VALUE; } else{ int num=stackarray[top]; top--; return num; } } public int getTop(){ if(top<0){ System.out.println("栈空,返回失败"); return Integer.MAX_VALUE; } else{ return stackarray[top]; } } public void print(){ if(top==-1) System.out.println("栈空,无输出"); else{ System.out.print("栈: "); int num=top; while(num>=0){ System.out.print(stackarray[num--]+" "); } System.out.println(); } } public static void main(String args[]) { ArrayStack mystack=new ArrayStack(); System.out.println(mystack.isEmpty()); mystack.pop(); mystack.getTop(); mystack.push(1); mystack.push(2); mystack.push(3); mystack.push(4); mystack.print(); System.out.println(mystack.isEmpty()); mystack.pop(); mystack.pop(); mystack.print(); } }
2,队列
2.1队列-链表
1 //Node类 2 public class Node { 3 public String data=""; 4 Node next=null; 5 6 public Node(){ 7 data="THE-HEAD"; 8 } 9 public Node(String data){ 10 this.data=data; 11 } 12 } 13 14 //队列类 15 16 public class LinkedQueue { 17 private Node Head=new Node(); 18 private Node Tail=new Node(); 19 private int length=0; 20 21 public boolean isEmpty(){ 22 return Head.next==null&&Tail.next==null; 23 } 24 //入队 25 public void add(String data){ 26 Node newNode=new Node(data); 27 if(length==0){ 28 Head.next=newNode; 29 Tail.next=newNode; 30 length++; 31 }else{ 32 Tail.next.next=newNode; 33 Tail.next=newNode; 34 length++; 35 } 36 } 37 //出队 38 public String poll(){ 39 if(length<1){ 40 System.out.println("队列空,无法出队"); 41 return "ERROE-emptyQueue"; 42 }else if(length==1){ 43 String data=Head.next.data; 44 Head.next=null; 45 Tail.next=null; 46 length--; 47 return data; 48 } 49 else{ 50 Node p=Head.next; 51 String data=Head.next.data; 52 Head.next=p.next; 53 length--; 54 return data; 55 } 56 } 57 //返回队首 58 public String getHead(){ 59 if(length==0){ 60 System.out.println("队空,无队头"); 61 return null; 62 } 63 else{ 64 return Head.next.data; 65 } 66 } 67 68 //遍历队列 69 public void print(){ 70 if(length==0) 71 System.out.println("队空,无输出"); 72 else{ 73 System.out.print("队列: Head->"); 74 Node p=Head; 75 while(p.next!=null){ 76 p=p.next; 77 System.out.print(p.data+"->"); 78 } 79 System.out.println("(<-Tail) null"); 80 } 81 } 82 83 84 public static void main(String args[]) { 85 LinkedQueue myQueue=new LinkedQueue(); 86 System.out.println(myQueue.isEmpty()); 87 myQueue.getHead(); 88 myQueue.poll(); 89 90 myQueue.add("12"); 91 myQueue.add("23"); 92 myQueue.add("34"); 93 myQueue.add("45"); 94 95 myQueue.print(); 96 97 myQueue.poll(); 98 myQueue.poll(); 99 myQueue.print(); 100 101 } 102 103 }
2.2队列-数组
循环数组队列,头指向第一个元素,尾指向最后一个元素的下一个
1 //头指向第一个,尾指向最后一个的下一个 2 //队空:Head==Tail 3 //队满:(Tail+1)%SIZE==Head 4 5 public class ArrayQueue { 6 private int SIZE=10; 7 private int[] queueArray=new int[SIZE]; 8 private int Head=0; 9 private int Tail=0; 10 11 12 //空? 13 public boolean isEmpty(){ 14 if(Head==Tail){ 15 return true; 16 }else 17 return false; 18 } 19 //返回长度 20 public int length(){ 21 if(Head==Tail) 22 return 0; 23 else if(Head<Tail) 24 return Tail-Head; 25 else{ 26 return SIZE-(Head-Tail); 27 } 28 } 29 //入队 30 public void add(int data){ 31 if((Tail+1)%SIZE==Head) 32 System.out.println("队列已满,无法入队"); 33 else{ 34 queueArray[Tail]=data; 35 Tail=(Tail+1)%SIZE; 36 } 37 } 38 //出队 39 public int poll(){ 40 if(Head==Tail){ 41 System.out.println("队空,无法出栈"); 42 return Integer.MAX_VALUE; 43 } 44 else 45 return Head=(Head+1)%SIZE; 46 } 47 //返回队首 48 public int getHead(){ 49 if(Head==Tail){ 50 System.out.println("队空,无队首"); 51 return Integer.MAX_VALUE; 52 } 53 else 54 return queueArray[Head]; 55 } 56 57 //遍历 58 public void print(){ 59 if(Head==Tail) 60 System.out.println("队空,无输出"); 61 else{ 62 System.out.print("队: "); 63 int head=Head; 64 while(Tail!=head){ 65 System.out.print(queueArray[(head++)%SIZE]+" "); 66 } 67 System.out.println(); 68 } 69 } 70 71 public static void main(String args[]) { 72 ArrayQueue myQueue=new ArrayQueue(); 73 System.out.println(myQueue.isEmpty()); 74 myQueue.getHead(); 75 myQueue.poll(); 76 77 myQueue.add(12); 78 myQueue.add(23); 79 myQueue.add(34); 80 myQueue.add(45); 81 System.out.println("队长 "+myQueue.length()); 82 myQueue.add(45); 83 myQueue.add(45); 84 myQueue.add(45); 85 myQueue.add(45); 86 myQueue.add(45); 87 myQueue.add(45); 88 System.out.println("队首 "+myQueue.getHead()); 89 System.out.println("队长 "+myQueue.length()); 90 91 myQueue.print(); 92 93 myQueue.poll(); 94 myQueue.poll(); 95 myQueue.print(); 96 } 97 98 }
3,用栈表示队列,用队列表示栈
3.1 栈->队列
①用两个栈,将数据从一个栈的顺序弹出压入另一个栈,刚好顺序相反-----满足队列一端进一端出要求,队列倒序遍历的一种实现方式;
②一个记录stackin记录入队顺序,栈顶当作队尾,另一个stackout记录出队顺序,栈顶当中队首
③要入队时,让数据从stackout弹出,在压进stackin,
1 import java.util.Stack; 2 3 public class StackQueue { 4 private Stack<Integer> stackIn=new Stack<>(); 5 private Stack<Integer> stackOut=new Stack<>(); 6 7 public boolean isEmpty(){ 8 return stackIn.isEmpty()&&stackOut.isEmpty(); 9 } 10 public void add(int data){ 11 if(stackIn.isEmpty()){ 12 while (!stackOut.isEmpty()) 13 stackIn.push(stackOut.pop()); 14 stackIn.push(data); 15 }else{ 16 stackIn.push(data); 17 } 18 } 19 public int length(){ 20 if(stackIn.isEmpty()) 21 return stackOut.size(); 22 else 23 return stackIn.size(); 24 } 25 public int poll(){ 26 if(!isEmpty()){ 27 //stackin,stackOut都是专用的,不像queueStacck一样两个queue等价 28 //因为①用两个栈,将数据从一个栈的顺序弹出压入另一个栈,刚好顺序相反-----满足队列一端进一端出要求 29 //②用两个队列,因为把数据从一个队列移动到另一个队列顺序不变,所以这两个队列是等价, 30 if(stackOut.isEmpty()){ 31 //这里是用isempty判空,然后push最后一个,还是用size>1,直接返回popz最后一个,两者时间复杂度? 32 //https://blog.caoyu.info/is-empty-size-in-java.html 33 //ConcurrentLinkedQueue如类需要异步求当前size() 34 //isempty O(1) 35 //size() 通常O(1),有时O(n); 36 while (stackIn.size()>1) 37 stackOut.push(stackIn.pop()); 38 return stackIn.pop(); 39 }else{ 40 return stackOut.pop(); 41 } 42 }else{ 43 System.out.println("队空,无出队"); 44 return Integer.MAX_VALUE; 45 } 46 } 47 //遍历 48 //遍历 49 //可正序,也可倒叙 50 public void print(){ 51 if(!isEmpty()){ 52 if(stackIn.isEmpty()){ 53 System.out.print("倒序遍历: (队尾)"); 54 while(!stackOut.isEmpty()){ 55 int num=stackOut.pop(); 56 System.out.print(num+" "); 57 stackIn.push(num); 58 } 59 System.out.println(); 60 System.out.print("正序遍历: (队首)"); 61 while(!stackIn.isEmpty()){ 62 int num=stackIn.pop(); 63 System.out.print(num+" "); 64 stackOut.push(num); 65 } 66 System.out.println(); 67 }else{ 68 System.out.print("正序遍历: (队首)"); 69 while(!stackIn.isEmpty()){ 70 int num=stackIn.pop(); 71 System.out.print(num+" "); 72 stackOut.push(num); 73 } 74 System.out.println(); 75 System.out.print("倒序遍历: (队尾)"); 76 while(!stackOut.isEmpty()){ 77 int num=stackOut.pop(); 78 System.out.print(num+" "); 79 stackIn.push(num); 80 } 81 System.out.println(); 82 } 83 }else 84 System.out.println("队空,无输出"); 85 } 86 87 88 89 public static void main(String args[]) { 90 StackQueue myQueue=new StackQueue(); 91 System.out.println(myQueue.isEmpty()); 92 //myQueue.getHead(); 93 myQueue.poll(); 94 95 myQueue.add(12); 96 myQueue.add(23); 97 myQueue.add(34); 98 myQueue.add(45); 99 System.out.println("队长 "+myQueue.length()); 100 myQueue.print(); 101 myQueue.add(56); 102 myQueue.add(67); 103 myQueue.add(78); 104 myQueue.add(89); 105 myQueue.add(90); 106 myQueue.add(01); 107 System.out.println("队长 "+myQueue.length()); 108 myQueue.print(); 109 110 111 myQueue.poll(); 112 myQueue.poll(); 113 System.out.println("队长 "+myQueue.length()); 114 myQueue.print(); 115 } 116 117 }
3.2 队列表示栈
①用两个队列,因为把数据从一个队列移动到另一个队列顺序不变,所以这两个队列是等价,
②当要入栈时,将有数据的队列顺序出队进入另一个队列,留下最后一个数据,即栈顶数据,
③入栈直接进入有数据的队列队尾就行了
1 import java.util.LinkedList; 2 import java.util.Queue; 3 4 //始终保持辅助队列为空,不为空为数据队列 5 //只有两条队列都空才空 6 public class QueueStack { 7 private Queue<Integer> q1=new LinkedList<Integer>(); 8 private Queue<Integer> q2=new LinkedList<Integer>(); 9 public boolean isEmpty(){ 10 return (q1.isEmpty()&&q2.isEmpty()); 11 } 12 //入栈 13 public void push(int a){ 14 if(isEmpty()) 15 q1.add(a); 16 else{ 17 if(q1.isEmpty()) 18 q2.add(a); 19 if(q2.isEmpty()) 20 q1.add(a); 21 } 22 } 23 //出栈 24 public int pop(){ 25 if(!isEmpty()){ 26 if(q1.isEmpty()){ 27 while(q2.size()>1) 28 q1.add(q2.poll()); 29 return q2.poll(); 30 }else { 31 while(q1.size()>1) 32 q2.add(q1.poll()); 33 return q1.poll(); 34 } 35 }else { 36 System.out.println("栈空,无出栈"); 37 return Integer.MAX_VALUE; 38 } 39 } 40 //返回栈首 41 public int peek(){ 42 int num; 43 if(!isEmpty()){ 44 if(q1.isEmpty()){ 45 while(q2.size()>1) 46 q1.add(q2.poll()); 47 num=q2.poll(); 48 q1.add(num); 49 return num; 50 }else { 51 while(q1.size()>1) 52 q2.add(q1.poll()); 53 num=q1.poll(); 54 q2.add(num); 55 return num; 56 } 57 }else{ 58 System.out.println("栈空,无栈头"); 59 return Integer.MAX_VALUE; 60 } 61 } 62 //遍历 63 public void print(){ 64 if(!isEmpty()){ 65 System.out.print("栈: "); 66 if(q1.isEmpty()){ 67 while (!q2.isEmpty()){ 68 int num=q2.poll(); 69 System.out.print(num+" "); 70 q1.add(num); 71 } 72 System.out.println(); 73 }else{ 74 while (!q1.isEmpty()){ 75 int num=q1.poll(); 76 System.out.print(num+" "); 77 q2.add(num); 78 } 79 System.out.println(); 80 } 81 }else 82 System.out.println("栈空,无输出"); 83 } 84 85 86 public static void main(String args[]) { 87 QueueStack s=new QueueStack(); 88 s.isEmpty(); 89 s.peek(); 90 s.pop(); 91 92 s.push(5); 93 s.push(6); 94 s.push(7); 95 s.push(8); 96 s.print(); 97 98 System.out.println(s.peek()); 99 System.out.println(s.pop()); 100 System.out.println(s.pop()); 101 s.print(); 102 103 } 104 105 106 }
4,栈队列相关算法
参考网上帖子
转载:简书ID:@我没有三颗心脏
https://www.jianshu.com/p/5087c751cb42
4.1
①最小堆问题,数据栈+辅助栈,辅助栈负责记录每一个值入栈时,当前数据栈状态得最小值,即每一个数入栈时如果<=辅助栈栈顶值,同时进辅助栈,
②出队时一样与辅助栈栈顶比较,与辅助栈顶相同则辅助栈pop,
③,辅助栈保证栈顶始终是数据栈当前状态下的最小值,
1 import java.util.Stack; 2 3 //入栈 4 //空栈加入第一个元素,两个栈都push; 5 //栈非空,push时若小于min栈顶元素,min栈也入 6 //出栈 7 //若data栈顶==min栈顶,双栈出;!=min栈不出 8 public class MinStack { 9 private Stack<Integer> data=new Stack<>(); 10 private Stack<Integer> min=new Stack<>(); 11 12 public boolean isEmpty(){ 13 return data.isEmpty(); 14 } 15 16 public void push(int a){ 17 if(isEmpty()){ 18 data.push(a); 19 min.push(a); 20 }else{ 21 data.push(a); 22 if(a<=min.peek()) 23 min.push(a); 24 } 25 } 26 public void pop(){ 27 if(!isEmpty()){ 28 int a=data.pop(); 29 if(a==min.peek()) 30 min.pop(); 31 }else{ 32 System.out.println("栈空,出栈失败"); 33 } 34 } 35 public int peek(){ 36 if(!isEmpty()) 37 return data.peek(); 38 else 39 return Integer.MAX_VALUE; 40 } 41 public int getMind(){ 42 if(!isEmpty()) 43 return min.peek(); 44 else return Integer.MAX_VALUE; 45 } 46 47 public static void main(String args[]) { 48 MinStack m=new MinStack(); 49 m.push(-1); 50 m.push(3); 51 m.push(-3); 52 m.push(5); 53 m.push(-2); 54 m.push(8); 55 56 System.out.println("最小 "+m.getMind()); 57 58 m.pop(); 59 System.out.println("最小 "+m.getMind()); 60 m.pop(); 61 System.out.println("最小 "+m.getMind()); 62 m.pop(); 63 System.out.println("最小 "+m.getMind()); 64 m.pop(); 65 System.out.println("最小 "+m.getMind()); 66 } 67 68 69 }
4.2 括号匹配问题,{} []()<>
左括号直接入栈,遇到右括号,栈顶一定是与之匹配的左括号,是-出栈,不是-直接返回错误
1 //转载:简书ID:@我没有三颗心脏 2 //https://www.jianshu.com/p/5087c751cb42 3 import java.util.Scanner; 4 import java.util.Stack; 5 6 public class Stack_Use_For { 7 8 //LeetCode 相关题目整理 9 //20.有效的括号 10 public boolean isRight(String s){ 11 12 Stack<Character> stack=new Stack<>(); 13 if(s.length()==0) 14 return false; 15 else{ 16 for(int i=0;i<s.length();i++){ 17 char c=s.charAt(i); 18 if(c=='('||c=='['||c=='<'||c=='{') 19 stack.push(c); 20 else{ 21 if(c==']'&&stack.pop()!='['){ 22 return false; 23 } 24 if(c=='}'&&stack.pop()!='{'){ 25 return false; 26 } 27 if(c=='>'&&stack.pop()!='<'){ 28 return false; 29 } 30 if(c==')'&&stack.pop()!='('){ 31 return false; 32 } 33 } 34 } 35 } 36 if(stack.empty()){ 37 return true; 38 }else{ 39 return false; 40 } 41 42 43 } 44 45 public static void main(String args[]) { 46 Stack_Use_For stack=new Stack_Use_For(); 47 48 System.out.println("请输入包含{}[]()<>的字符串"); 49 Scanner sc=new Scanner(System.in); 50 String s=sc.nextLine(); 51 52 53 System.out.println(stack.isRight(s)); 54 55 56 } 57 58 59 }
4.3 某给定顺序序列入栈的出栈序列问题,比如1234567入栈,5436721是否是出栈序列问题
唉,自己的方法太蠢,233,,思路没问题,实现起来太容易出错,下标很乱
1 //https://www.jianshu.com/p/5087c751cb42 2 3 /* 4 * 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假 5 * 设压入栈的所有数字均不相等。例如,序列{1,2,3,4,5}是某栈的压栈序列,序列{4,5,3,2,1}是该压 6 * 栈序列对应的一个弹出序列,但{4,3,5,1,2}就不可能是该压栈序列的弹出序列。 7 8 */ 9 10 /** 11 * 思路1:从前往后遍历弹出序列,求出弹出值入序的下标x,在求出入序列表中在x之前的元素的出序下标数组 12 * ,这个数组是降序的,不是降序的则错误,因为靠近X 的先弹出。 13 * 14 * 前提:序列元素不能重复 15 */ 16 17 /** 18 * 更正思路1 19 * 思路1错了一部分,求出第一个值后,若没返回false则证明x之前的元素顺序都对,则就不用考虑这些元素了,即把1-x之间的元素从out 20 * 中删除(in也要删除),不是从前往后遍历,而是跳着遍历, 21 * 22 * 23 * 不能删除,删除后后面的下标就乱了2333,,还是得用特殊字符代替, 24 * 25 * 26 * * (我们拿到输出序列往外很关注第一个值,比如1234567入栈,如果出栈序列第一个是5,那么4321的出栈顺序就限制住了, 27 * * 4要在321前面中间肯有其他值比如67,只要是4在出序中的位置下标比3小,3比2小,以此类推,如果4有差错,直接返回错误 28 * * ,如果没错,出栈序列中54321(5是第一个,下标肯定比4321小)就不用遍历了,已经确认没问题了,可以标记一下如替换“-”,接着拿 29 * * 下一个非“-”当作“第一个”继续,) 30 * 31 * 32 33 */ 34 import java.util.Stack; 35 public class Stack_Out_Order { 36 //工地英语,是否是in序的out 37 //这里用String返回值,方便定位哪里出了问题,到底是哪里下标设计会溢出, 38 public String isOutOfIn(String in,String out){ 39 if(out.length()!=in.length()) 40 return "false1"; 41 else{ 42 //遍历出序的值 43 for(int i=0;i<out.length();i++){ 44 char curChar=out.charAt(i); 45 //找出curChar在入序中的下标, 46 int index=findIndex(curChar,in); 47 //curChar不在入序 48 if(index==Integer.MAX_VALUE) 49 return "false2"; 50 //找出入序中在index之前的元素,并求他们在出序中的位置 51 int indexarry=Integer.MAX_VALUE;//保证其比下一个index大即可,不需要存数组 52 for(int j=0;j<index;j++){ 53 if(in.charAt(j)=='_') 54 ; 55 else{ 56 char curChar2=in.charAt(j); 57 int index2=findIndex(curChar2,out); 58 if (index2>indexarry){ 59 return "false3"; 60 } 61 else { 62 indexarry=index2; 63 64 //删除ste指定index上的char; 65 out=out.substring(0,index2)+"_"+out.substring(index2+1,out.length()); 66 int index3=findIndex(curChar2,in); 67 in=in.substring(0,index3)+"_"+in.substring(index3+1,in.length()); 68 69 } 70 } 71 } 72 //把第一个也删掉才对 73 out=out.substring(0,i)+"_"+out.substring(i+1,out.length()); 74 in=in.substring(0,index)+"_"+in.substring(index+1,in.length()); 75 76 } 77 //遍历完无返回false,即true; 78 return "true"; 79 } 80 81 } 82 //假设序列中无重复值, 83 public int findIndex(char c,String in){ 84 for(int i=0;i<in.length();i++){ 85 if(c==in.charAt(i)) 86 return i; 87 } 88 return Integer.MAX_VALUE; 89 //若不在入序中返回标记,直接非出序 90 } 91 92 93 94 95 //看了原博主的方法,还标准方法简单,啊啊啊 96 public boolean isOutOfIn2(String in,String out){ 97 Stack<Character> stack=new Stack<>(); 98 int indexin=0; 99 int indexout=0; 100 101 while (indexout<out.length()){ 102 while(indexin<in.length()&&(stack.isEmpty()||stack.peek()!=out.charAt(indexout))){ 103 stack.push(in.charAt(indexin++)); 104 } 105 if(out.charAt(indexout)==stack.peek()){ 106 stack.pop(); 107 indexout++; 108 }else{ 109 return false; 110 } 111 } 112 return true; 113 } 114 115 public static void main(String args[]) { 116 String in="1234567"; 117 String out1="5432167"; 118 String out2="5431267"; 119 String out3="1234567"; 120 String out4="2367541"; 121 String out5="7654321"; 122 String out6="7564321"; 123 Stack_Out_Order s=new Stack_Out_Order(); 124 System.out.println(in+" "+out1+" "+s.isOutOfIn(in,out1)); 125 System.out.println(in+" "+out2+" "+s.isOutOfIn(in,out2)); 126 System.out.println(in+" "+out3+" "+s.isOutOfIn(in,out3)); 127 System.out.println(in+" "+out4+" "+s.isOutOfIn(in,out4)); 128 System.out.println(in+" "+out5+" "+s.isOutOfIn(in,out5)); 129 System.out.println(in+" "+out6+" "+s.isOutOfIn(in,out6)); 130 System.out.println(); 131 132 System.out.println(in+" "+out1+" "+s.isOutOfIn2(in,out1)); 133 System.out.println(in+" "+out2+" "+s.isOutOfIn2(in,out2)); 134 System.out.println(in+" "+out3+" "+s.isOutOfIn2(in,out3)); 135 System.out.println(in+" "+out4+" "+s.isOutOfIn2(in,out4)); 136 System.out.println(in+" "+out5+" "+s.isOutOfIn2(in,out5)); 137 System.out.println(in+" "+out5+" "+s.isOutOfIn2(in,out6)); 138 } 139 140 }