- 博客主页小吴_小吴有想法_CSDN博客-leetcode,笔记,java领域博主
- 欢迎关注点赞收藏和留言
- 天道酬勤,勤能补拙,和小吴一起加油吧
- 17岁大一新生,水平有限,恳请各位大佬指点,不胜感激!
- 参考书籍:《算法4》,学习视频:黑马程序员Java数据结构与java算法,全网资料最全数据结构+算法教程,154张java数据结构图_哔哩哔哩_bilibili
目录
栈
栈是一种基于先进后出的数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读取的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)
代码实现
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;
}
}
}
栈——先进后出,万变不离其宗
学习如逆水行舟,不进则退。和小吴一起加油吧!