栈的实现和括号匹配问题和逆波兰表达式的处理笔记

26 篇文章 3 订阅

目录

代码实现

 括号匹配问题

代码实现

 逆波兰表达式求值问题

代码实现


 

是一种基于先进后出的数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读取的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)

代码实现

import java.util.Iterator;

public class Stack<T> implements Iterable <T>{
	//记录首结点
	private Node head;
	//记录栈中的元素个数
	private int N;
	private class Node{
		public T item;
		public Node next;
		public Node(T item,Node next)
		{
			this.item=item;
			this.next=next;
		}
	}
	public Stack() {
		this.head=new Node(null,null);
		this.N=0;
		
	}
	//判断当前栈中的元素个数是否为0
	public boolean isEmpty()
	{
		return N==0;
	}
	//获取栈中元素个数
	public int size()
	{
		return N;
	}
	//将元素压入栈,与链表中插入结点的处理几乎一样,只不过一只从头结点插入
	public void push(T t)
	{
		//找到首结点指向的第一个结点
		Node oldFirst=head.next;
		//创建新结点
		Node newNode =new Node(t,null);
		//让首结点指向新结点
		head.next=newNode;
		//让新结点指向原来的第一个结点
		newNode.next=oldFirst;
		N++;//压入了元素,元素肯定变多啦
	}
	//弹出元素,其实就是首结点越过第一个结点,与第二个结点相连(指向原来第一个结点的下一个结点)
	public T pop()
	{
	//找到首结点指向的第一个结点
		Node oldFirst=head.next;//可能是空的链表,所以要安全处理一下下
		if(oldFirst==null)
		{
			return null;
		}
		//让首结点指向原来第一个结点的下一个结点
		head.next=oldFirst.next;
		//弹出元素,肯定元素个数变少了
		N--;
		return oldFirst.item;
	}	
	public Iterator<T> iterator()
	{
		return new Literator();
	}
	private class Literator implements Iterator{
		private Node n;
		public Literator()
		{
			this.n=head;
		}
		public boolean hasNext()
		{
			return n.next!=null;
		}
		public Object next()
		{
			n=n.next;
			return n.item;
		}	
	}	
}
public class test {
public static void main(String[] args)
{
//创建栈对象
	
	Stack<String>stack=new Stack<>();

	//测试压栈
	stack.push("a");
    stack.push("b");
	stack.push("c");
	stack.push("d");
	for(String i:stack)
	{
		System.out.println(i);
	}
	System.out.println("————————————————————————————————————————————————");
	//测试弹栈
	String result=stack.pop();
	System.out.println("弹出的元素是"+result);
	System.out.println("剩余的元素的个数是:"+stack.size());
	
}	
}

 括号匹配问题

问题描述:给定一个字符串,里面可能包含"()"小括号和其他字符,请编写程序检查该字符串中的小括号是否成对出现。

例如:

"(小无)(小北)":正确

"小无((小北))":正确

"小无(小北(小明)(小南)小丽)":正确

"((小北)小无":错误

注意:这个括号成对出现,不是指“()”的数量,而是让左括号(和右括号)一一对应.

处理这道题的技巧主要就是当我们遍历字符串的时候,如果遇到左括号,将其压入栈,遇到右括号弹出栈的元素,如果没有对应的左括号,弹出的元素是null,可以判断。

到最后到达字符串的末尾,我们得判断栈中是否还有左括号,有的话说明右括号少了,返回false,没有的话满足题意,返回true。

代码实现

public class test {
public static void main(String[] args)
{
String str="(小无(小北)())";
boolean isf=isf(str);
System.out.println(str+"中的括号是否匹配:"+isf);

}	
public static boolean isf(String str)
{
	//创建栈对象,存储左括号
	  Stack<String> chars=new Stack<>();
	//从左往右遍历字符串
	  for(int i=0;i<str.length();i++)
	  {
		  //字符型的话返回不方便,定义成字符串型
		  String currchar=str.charAt(i)+"";
		  //判断是否为左括号,如果是,压入栈
		  if(currchar.equals("("))
				  {
			  chars.push(currchar);
				  }
		  else if(currchar.equals(")"))
		  {//判断是否是右括号,如果是,从栈中弹出元素(左括号)
			  String p= chars.pop();
			  if(p==null)
			  {
				  return false;
			  }
			  
		  }
			  
	  }
	//上面的遍历已经把所有右括号对应是否有左括号并进行操作处理完毕
	//最后我们检查栈中是否还有左括号即可
	  if(chars.size()==0)
	  {
		  return true;
	  }
	  else
	  {
		  return false;
	  }

}

}
import java.util.Iterator;

public class Stack<T> implements Iterable <T>{
	//记录首结点
	private Node head;
	//记录栈中的元素个数
	private int N;
	private class Node{
		public T item;
		public Node next;
		public Node(T item,Node next)
		{
			this.item=item;
			this.next=next;
		}
	}
	public Stack() {
		this.head=new Node(null,null);
		this.N=0;
		
	}
	//判断当前栈中的元素个数是否为0
	public boolean isEmpty()
	{
		return N==0;
	}
	//获取栈中元素个数
	public int size()
	{
		return N;
	}
	//将元素压入栈,与链表中插入结点的处理几乎一样,只不过一只从头结点插入
	public void push(T t)
	{
		//找到首结点指向的第一个结点
		Node oldFirst=head.next;
		//创建新结点
		Node newNode =new Node(t,null);
		//让首结点指向新结点
		head.next=newNode;
		//让新结点指向原来的第一个结点
		newNode.next=oldFirst;
		N++;//压入了元素,元素肯定变多啦
	}
	//弹出元素,其实就是首结点越过第一个结点,与第二个结点相连(指向原来第一个结点的下一个结点)
	public T pop()
	{
	//找到首结点指向的第一个结点
		Node oldFirst=head.next;//可能是空的链表,所以要安全处理一下下
		if(oldFirst==null)
		{
			return null;
		}
		//让首结点指向原来第一个结点的下一个结点
		head.next=oldFirst.next;
		//弹出元素,肯定元素个数变少了
		N--;
		return oldFirst.item;
	}	
	public Iterator<T> iterator()
	{
		return new Literator();
	}
	private class Literator implements Iterator{
		private Node n;
		public Literator()
		{
			this.n=head;
		}
		public boolean hasNext()
		{
			return n.next!=null;
		}
		public Object next()
		{
			n=n.next;
			return n.item;
		}	
	}	
}

 逆波兰表达式求值问题

波兰表达式就是我们平常写的a+b这种式子变成了ab+,运算符号在后面

a+(b-c)变成 abc-+

a+(b-c)*d变为abc-d*+

代码处理的思想和上一个括号匹配问题原理类似,我们遍历字符串的时候判断字符是否是运算符,如果不是,将数字放入栈,如果是操作符,则弹出两个数字使用该运算符计算即可

在把结果放入栈,以便于和其他数字使用运算符计算。主要利用我们栈的原理,放入数先进后出.最后再检查是否到达字符串的末尾,返回最终结果

代码实现

public class test {
public static void main(String[] args)
{
//4*(20-18)+9/3的波兰表达式如下
	String[] notation= {"4","20","18","-","*","9","3","/","+"};
	int result =caculate(notation);
	System.out.println("逆波兰表达式的计算结果为:"+result);
}

public static int caculate(String[] notation)
{
	//定义一个栈,存储操作数
	Stack<Integer>  ap=new Stack<>();
	//从左往右遍历逆波兰表达式,判断当前元素是运算符还是操作数、
	如果是运算符,从栈中弹出2个操作数
	//如果是操作数,将其放入栈中
	for(int i =0;i<notation.length;i++)
	{
		String curr=notation[i];
		Integer b1,b2,result;
		switch(curr) 
		{//此时要注意应该是第二个弹出的元素减去(操作)第一个弹出的元素
		case"+":
			   b1=ap.pop();
			   b2=ap.pop();
			  result=b2+b1;
			ap.push(result);
			break;
		case"-":
	            b1=ap.pop();
	            b2=ap.pop();
	            result=b2-b1;
		        ap.push(result);
		        break;
		case"*": 
			b1=ap.pop();
            b2=ap.pop();
            result=b2*b1;
            ap.push(result);
			break;
		case"/":
			    b1=ap.pop();
	            b2=ap.pop();
	            result=b2/b1;
		        ap.push(result);
			break;
		default:
			ap.push(Integer.parseInt(curr));
			  break;
		}
	}
	//得到栈中的末尾元素,返回结果
	int result=ap.pop();
    return result;	
  }

}
	
import java.util.Iterator;

public class Stack<T> implements Iterable <T>{
	//记录首结点
	private Node head;
	//记录栈中的元素个数
	private int N;
	private class Node{
		public T item;
		public Node next;
		public Node(T item,Node next)
		{
			this.item=item;
			this.next=next;
		}
	}
	public Stack() {
		this.head=new Node(null,null);
		this.N=0;
		
	}
	//判断当前栈中的元素个数是否为0
	public boolean isEmpty()
	{
		return N==0;
	}
	//获取栈中元素个数
	public int size()
	{
		return N;
	}
	//将元素压入栈,与链表中插入结点的处理几乎一样,只不过一只从头结点插入
	public void push(T t)
	{
		//找到首结点指向的第一个结点
		Node oldFirst=head.next;
		//创建新结点
		Node newNode =new Node(t,null);
		//让首结点指向新结点
		head.next=newNode;
		//让新结点指向原来的第一个结点
		newNode.next=oldFirst;
		N++;//压入了元素,元素肯定变多啦
	}
	//弹出元素,其实就是首结点越过第一个结点,与第二个结点相连(指向原来第一个结点的下一个结点)
	public T pop()
	{
	//找到首结点指向的第一个结点
		Node oldFirst=head.next;//可能是空的链表,所以要安全处理一下下
		if(oldFirst==null)
		{
			return null;
		}
		//让首结点指向原来第一个结点的下一个结点
		head.next=oldFirst.next;
		//弹出元素,肯定元素个数变少了
		N--;
		return oldFirst.item;
	}	
	public Iterator<T> iterator()
	{
		return new Literator();
	}
	private class Literator implements Iterator{
		private Node n;
		public Literator()
		{
			this.n=head;
		}
		public boolean hasNext()
		{
			return n.next!=null;
		}
		public Object next()
		{
			n=n.next;
			return n.item;
		}	
	}	
}

 栈——先进后出,万变不离其宗

学习如逆水行舟,不进则退。和小吴一起加油吧!

评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小吴有想法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值