1. 栈


实现自己的栈
public class MyStack {
public int[] elem;
public int usedSized;//当前栈中存储有效数据的个数,也是当前存放数据元素的下标
public static final int DEFAULE_SIZE = 10;
public MyStack(){
elem = new int[DEFAULE_SIZE];
}
//压栈
public boolean empty(){
if(usedSized == elem.length){
return true;
}
return false;
}
public void push(int val){
//判断是否栈满
if(empty()){
elem = Arrays.copyOf(elem,2*elem.length);
}
//存放当前的下标,同时usedSized需要自增
elem[usedSized] = val;
usedSized++;
}
//删除栈顶元素
public boolean isEmpty(){
return usedSized==0;
}
public int pop(){
if(isEmpty()){
throw new EmptyStackException("栈为空了!");
}
int oldVal = elem[usedSized-1];
usedSized--;
return oldVal;
}
//获取栈顶元素,但是不删除
public int peek(){
if(isEmpty()){
throw new EmptyStackException("栈为空了!");
}
return elem[usedSized-1];
}
//大小
public int getUsedSized(){
return usedSized;
}
}

2. 队列

即Queue<Integer> q = new LinkedList<>();

实现队列:
public class MyQueue {
static class Node{
public int val;
public Node next;
public Node(int val) {
this.val = val;
}
}
public Node head;//队列的头
public Node tail;//队列的尾
//************************************************入队***********************************************
public void offer(int val){
Node node = new Node(val);
if(head == null){
head = node;
tail = node;
}else{
tail.next = node;
tail = tail.next;
}
}
//************************************************出队***********************************************
public int poll(){
if(head == null){
return -1;
}
int oldVal = head.val;
if(head.next==null){
head = tail =null;
}else{
head = head.next;
}
return oldVal;
}
//************************************************查看对头元素***********************************************
public int peek(){
if(head==null){
return -1;
}
return head.val;
}
}3. 由栈实现到队列
注意:需要创建两个栈:如果stack2中不为空则出栈stack2里面的,如果为空则把stack1里的全部倒到stack2中再去出栈
class MyQueue {
Stack<Integer> stack1;
Stack<Integer> stack2;
public MyQueue() {
stack1 = new Stack<>();
stack2 = new Stack<>();
}
public void push(int x) {
stack1.push(x);
}
public int pop() {
if(empty()){
return -1;
}
if (stack2.empty()){
//需要把stack1的元素全部倒出来
while (!stack1.empty()){
stack2.push(stack1.pop());
}
}
//如果stack2中不为空则出栈stack2里面的,如果为空则把stack1里的全部倒到stack2中再去出栈
return stack2.pop();
}
public int peek() {
if(empty()){
return -1;
}
if (stack2.empty()){
//需要把stack1的元素全部倒出来
while (!stack1.empty()){
stack2.push(stack1.pop());
}
}
//如果stack2中不为空则出栈stack2里面的,如果为空则把stack1里的全部倒到stack2中再去出栈
return stack2.peek();
}
public boolean empty() {
return stack1.empty() && stack2.empty();
}
}
4. 由队列实现到栈
class MyStack {
Queue<Integer> qu1;
Queue<Integer> qu2;
int useSizes;
public MyStack() {
qu1 = new LinkedList<>();
qu2 = new LinkedList<>();
}
public void push(int x) {
if(!qu1.isEmpty()){
qu1.offer(x);
}else if(!qu2.isEmpty()){
qu2.offer(x);
}else{
qu1.offer(x);
}
useSizes++;
}
public int pop() {
if(empty()){
return -1;
}
if(!qu1.isEmpty()){
int curSize=qu1.size();
for (int i = 0; i < curSize-1; i++) {
qu2.offer(qu1.poll());
}
useSizes--;
return qu1.poll();
}else{
int curSize=qu2.size();
for (int i = 0; i < curSize-1; i++) {
qu1.offer(qu2.poll());
}
useSizes--;
return qu2.poll();
}
}
//就是peek()显示对尾元素
public int top() {
if(empty()){
return -1;
}
if(!qu1.isEmpty()){
int curSize=qu1.size();
int ret = -1;
for (int i = 0; i < curSize; i++) {
ret = qu1.poll();
qu2.offer(ret);
}
return ret;
}else{
int curSize=qu2.size();
int ret=-1;
for (int i = 0; i < curSize; i++) {
ret = qu2.poll();
qu1.offer(ret);
}
return ret;
}
}
public boolean empty() {
return useSizes==0;
}
}
5. 设计一个支持 push ,pop ,top 操作,并能在常数时间(即时间复杂度为O(1))内检索到最小元素的栈。
所以需要借助一个辅助栈,即这里的minstack
class MinStack {
Stack<Integer> stack;
Stack<Integer> minstack;
public MinStack() {
stack = new Stack<>();
minstack = new Stack<>();
}
public void push(int val) {
stack.push(val);
if(minstack.empty()){
//minstack为空的时候,存一下
minstack.push(val);
}else{
int peekVal = minstack.peek();
if(val <= peekVal){
minstack.push(val);
}
}
}
public void pop() {
if(!stack.empty()){
int popVal = stack.pop();
if(popVal == minstack.peek()){
minstack.pop();
}
}
}
public int top() {
if(!stack.empty()){
return stack.peek();
}else{
return -1;
}
}
public int getMin() {
if(!minstack.empty()){
return minstack.peek();
}else{
return -1;
}
}
}6.栈的一些练习
public class test {
public static void main(String[] args) {
String s1= "{[]}";
System.out.println(isValid(s1));
String[] s2= {"2","1","+","3","*"};
System.out.println(evalRPN(s2));
int[] pushA ={1,2,3,4,5};
int[] popA={4,3,5,1,2};
System.out.println(IsPopOrder(pushA,popA));
}
//给定一个只包括 '(',')','{','}','[',']'的字符串 s ,判断字符串是否有效。
//有效字符串需满足:
//左括号必须用相同类型的右括号闭合。
//左括号必须以正确的顺序闭合。
public static boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for(int i=0;i<s.length();i++){
char ch=s.charAt(i);
if(ch=='(' || ch=='[' || ch=='{'){
stack.push(ch);
}else{
//右括号多
if(stack.empty()){
return false;
}
char top = stack.peek();//获取栈顶元素但不删除
if(ch==')'&&top=='(' || ch=='}'&&top=='{' || ch==']'&&top=='['){
//说明当前字符是匹配的
stack.pop();
}else{
//不匹配
return false;
}
}
}
if(stack.empty()){
return true;
}else{
//左括号多
return false;
}
}
//根据 逆波兰表示法,求表达式的值。
//有效的算符包括+、-、*、/。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
//注意两个整数之间的除法只保留整数部分
public static int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>();
for(String x:tokens){
if(!isOperation(x)){
stack.push(Integer.parseInt(x));
}else{
int num2 = stack.pop();
int num1 = stack.pop();
switch(x){
case "+":
stack.push(num1+num2);
break;
case "-":
stack.push(num1-num2);
break;
case "*":
stack.push(num1*num2);
break;
case "/":
stack.push(num1/num2);
break;
}
}
}
return stack.pop();
}
public static boolean isOperation(String x){
//字符串相比较不能直接用“==”,而是用equals()函数
if(x.equals("+")||x.equals("-")||x.equals("*")||x.equals("/")){
return true;
}else{
return false;
}
}
//输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。
// 假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,
// 但4,3,5,1,2就不可能是该压栈序列的弹出序列。
public static boolean IsPopOrder(int [] pushA,int [] popA) {
if(pushA.length == 0 || popA.length == 0){
return false;
}
Stack<Integer> stack = new Stack<>();
int j= 0;
for(int i=0;i<pushA.length;i++){
stack.push(pushA[i]);
while(j<popA.length && !stack.empty() && stack.peek().equals(popA[j])){
//如果pushA和popA是分开的两个栈,则它们相比较不能直接用“==”,而是用equals()函数
stack.pop();
j++;
}
}
return stack.empty();
}
}
版权声明:本文为weixin_46772722原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。