栈(stack):是一种只允许在表的一端进行插入或删除操作的线性表。
栈顶:表尾端,即表中允许进行插入和删除操作的一端称为栈顶。栈顶是动态的,它由一个称为栈顶指针的位置指示器指示。
栈底:表头端,即栈的最下面的那一端称为栈底。
空栈:没有元素的栈
进栈或入栈:堆栈的插入操作
出栈或退栈:堆栈的删除操作
“后进先出”,因此,栈又被称为后进先出(last in first out,LIFO)表。它的实现方式主要有顺序栈、链栈两种。
数据关系:数据元素建是线性关系
数据操作:入栈、出栈、取栈顶元素、返回栈中元素个数、判断栈是否为空
我们定义抽象数据类型如下:
package codingTest2;
public interface IStack {
E push(E item);//入栈
E pop();//出栈
E peek();//取栈顶元素
int size();//返回栈中元素个数
boolean empty();//判断栈是否为空
}
顺序栈是利用顺序存储结构实现的栈,即利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素。
类似于顺序表,它使用一维数组来存放顺序栈中的数据元素。
栈顶指示器top设在数组下标为最大的那一端,top随着插入或删除而变化。
当栈为空时,top=-1;其他时候,top为栈顶元素的索引号。
优点:相比于链栈,顺序栈在实现以及操作上均比链栈要容易许多
缺点:相比链栈,顺序栈只能在事先进行预申请,所以在存放较大数据量的数据时会存在栈满或则说时栈溢出的情况,在用顺序栈时需提前注意。
import java.lang.reflect.Array;
//用数组实现顺序栈
class arraysSequentialStack {
public class SeqStack implements IStack{
private int maxSize;
private E[] data;
private int top;
//初始化栈
public SeqStack(Class type, int size) {
data = (E[])Array.newInstance(type, size);//初始化一个类型为type,大小为size的数组
maxSize = size;//容量最大为size
top = -1;
}
@Override
//将数据压入栈中
public E push(E item) {
if(!isFull()) {
data[++top] = item;
return item;
}else {
return null;
}
}
private boolean isFull() {
if(top == maxSize - 1) {
return true;
}else {
return false;
}
}
//元素出栈
@Override
public E pop() {
E item = null;
if(!empty()) {
item = data[top--];
}
return item;
}
@Override
//取栈顶元素
public E peek() {
E item = null;
if(!empty()) {
return data[top];
}
return item;
}
@Override
//返回元素的大小
public int size() {
return top + 1;
}
@Override
//判断顺序栈是否为空
public boolean empty() {
if(top == -1) {
return true;
}else {
return false;
}
}
}
}
采用链式存储结构实现的栈,通常用单链表来表示链栈。
它的结点结构与单链表的结构一样,都是由数据域data和引用域next两部分组成。
由于链栈的操作只在一段进行(栈顶),为了操作方便,我们将栈顶设在链表的头部,即将栈顶指示器指向链表的头部,所有对栈的数据元素的增加和删除操作都在链表头部进行。
优点:相比于顺序栈,链栈在计算机内存允许的情况下可以存放不限个数的数据单元,也无需考虑栈满的情况
缺点:相比顺序栈,链栈在实现过程中较为复杂一些
package codingTest2;
public class StackNode{
private E data;
private StackNode next;
public StackNode(){}
public StackNode(E data) {
this.data = data;
}
public StackNode(E data, StackNode next) {
this.data = data;
this.next = next;
}
public E getData() {
return data;
}
public void setData(E data) {
this.data = data;
}
public StackNode getNext() {
return next;
}
public void setNext(StackNode next) {
this.next = next;
}
}
package codingTest2;
public class arraysLinkedStack implements IStack{
private StackNode top;//栈顶指示器
private int size;//栈中节点个数
//初始化栈
public void LinkStack() {
top = null;
size = 0;
}
//将数据压入栈中
@Override
public E push(E item) {
StackNode newNode = new StackNode(item);
if(!empty()) {
newNode.setNext(top);
}
top = newNode;
++size;
return item;
}
//出栈操作
@Override
public E pop() {
E item = null;
if(!empty()) {
item = top.getData();
top = top.getNext();
size --;
}
return item;
}
//取栈顶元素
@Override
public E peek() {
E item = null;
if(!empty()) {
item = top.getData();
}
return item;
}
//求栈的长度
@Override
public int size() {
return size;
}
//判断栈是否为空
@Override
public boolean empty() {
if((top == null) && (size == 0)) {
return true;
}else {
return false;
}
}
}
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串,判断字符串是否有效。
有效字符串需满足:
注意空字符串可被认为是有效字符串。
示例 1:
输入: "()"
输出: true
示例 2:
输入: "()[]{}"
输出: true
示例 3:
输入: "(]"
输出: false
示例 4:
输入: "([)]"
输出: false
示例 5:
输入: "{[]}"
输出: true
package codingTest2;
import java.util.Stack;
public class ValidParentheses {
public static boolean isValid(String str) {
//将字符串转换为字符数组
char[] chs = str.toCharArray();
Stack s= new Stack<>();
//对于字符数组中的每一个字符元素有;
for(char ch : chs) {
if(ch == '(' || ch == '[' || ch == '{') {
s.push(ch);
}else {
if(s.size() == 0) {
return false;
}
if(ch == '}' && s.peek() == '{') {
s.pop();
}else if(ch == ')' && s.peek() == '(') {
s.pop();
}else if(ch == ']' && s.peek() == '[') {
s.pop();
}else {
return false;
}
}
}
return s.size() == 0;
}
public static void main(String[] args) {
System.out.println(isValid("[][]"));
System.out.println(isValid("[]["));
}
}
https://blog.csdn.net/volcano1995/article/details/88092631
https://blog.csdn.net/volcano1995/article/details/88090188
本文主要参考了以下两篇文章:
https://blog.csdn.net/qq_38410730/article/details/79587711
https://blog.csdn.net/qq_36441169/article/details/80760372