一、栈
1、定义
栈是一种只能在表的一端(栈顶)操作的线性表结构,可以基于数组或链表实现。
2、特点
(1)只能访问栈顶元素(最后一个插入的数据项)。栈顶元素被移除出后(或称弹栈),才能访问倒数第二个数据项。
(2)访问结点必须遵循先进后出或后进先出原则。
3、用途介绍
基于栈后进先出的特点,我们可以用栈来实现字符串反转、匹配符验证(代码实现见5)以及表达式求值(计算器)等等。
4、Java代码实现( 基于数组):
/**
* 栈
* 时间复杂度:O(1)
* @author honyer
*
*/
public class DefStack {
private Object[] stackArray; //存储栈元素的数组
private int maxSize; //栈的容量
private int top; //指向栈顶
/**
* 初始化栈
*/
public DefStack(int size) {
this.maxSize = size;
this.stackArray = new Object[size];
this.top = -1;
}
/**
* 入栈
* @param obj
* @return true 入栈成功, false 入栈失败
*/
public boolean push(Object obj) {
if(isFull()) {
return false;
}
stackArray[++top] = obj;
return true;
}
/**
* 弹出栈顶元素(会删除栈顶元素)
* @return 返回栈顶元素,top到达栈底之后返回 null元素
*/
public Object pop() {
if(top < 0) {
return null;
}
return stackArray[top--];
}
/**
* 弹出栈顶元素(不会删除栈顶元素)
* @return 返回栈顶元素,top到达栈底之后返回 null元素
*/
public Object peek() {
if(top < 0) {
return null;
}
return stackArray[top];
}
/**
* 判断栈是否为空
* @return
*/
public boolean isEmpty() {
return top == -1;
}
/**
* 判断栈是否已满
* @return
*/
public boolean isFull() {
return top == maxSize - 1;
}
}
PS: 后期会补上链表的实现方式。
5、校验大、中、小括号匹配的代码实现:
public class BracketChecker {
private String input;
public BracketChecker(String input) {
this.input = input;
}
public boolean check() {
DefStack expressStack = new DefStack(input.length());
for(int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);
switch(ch) {
case '{':
case '[':
case '(':
expressStack.push(ch);
break;
case '}':
if('{' != ((char)expressStack.pop())) {
System.err.println("Error: char at " + i + " must be '}'");
return false;
}
break;
case ']':
if('[' != ((char)expressStack.pop())) {
System.err.println("Error: char at " + i + " must be ']'");
return false;
}
break;
case ')':
if('(' != ((char)expressStack.pop())) {
System.err.println("Error: char at " + i + " must be ')'");
return false;
}
break;
default:
break;
}
}
if(!expressStack.isEmpty()) {
System.err.println("Error: missing rigth delimiter !");
return false;
}
return true;
}
public static void main(String[] args) {
String input = "{{({} ";
BracketChecker bc = new BracketChecker(input);
bc.check();
}
}
运行结果:
Error: missing rigth delimiter !
二、队列
1、定义
一种只能在队尾插入元素和在队头删除元素的线性表,可以基于数组和链表实现。它和栈有点类似,不同是队列只能从尾部插入元素。
2、特点
(1)头删尾插。
(2)访问结点必须遵循先进先出原则。
3、分类
基于功能我们可以实现单端队列、双端队列、阻塞队列以及优先级队列等等。
4、Java代码实现( 基于数组):
/**
* 队列(非双端)
* 时间复杂度:O(1)
* 采用数组实现,并采用环绕式方式存储元素
*(即队尾指针到达数组索引length-1的位置后,开始从索引0的位置插入)
*/
public class DefQueue {
private Object[] queueArray;//实现queue的数组
private int maxSize; //队列的最大空间
private int head; //队头
private int count; //队列中元素的个数
private int tail; //队尾
public DefQueue(int size) {
this.maxSize = size;
this.queueArray = new Object[size];
this.head = 0;
this.count = 0;
this.tail = -1;
}
/**
* 入队
* 如果队尾指针已经指向数组最大索引位置,则开始从索引0的位置插入元素(即环绕式插入元素)。
* @param obj
* @throws IndexOutOfBoundsException 当队列已满,插入元素会抛出异常
*/
public void add (Object obj) throws IndexOutOfBoundsException{
if(count == maxSize) {
throw new IndexOutOfBoundsException("队列已满!");
}
if(tail == maxSize -1) {
tail = -1;
}
queueArray[++tail] = obj;
count++;
}
/**
* 删除
* 队列的删除是操作队列头部
* @return 队列头部元素
*/
public Object remove() {
if(count == 0) {
return null;
}
Object obj = queueArray[head++];
if(head >= maxSize) {
head = 0;
}
count--;
return obj;
}
/**
* 获取队列头部元素但不删除该元素
* @return
*/
public Object peekHead() {
return queueArray[head];
}
/**
* 获取队列尾部元素但不删除该元素
* @return
*/
public Object peekTail() {
return queueArray[tail];
}
/**
* 判断队列是否为空
* @return
*/
public boolean isEmpty() {
return count == 0;
}
/**
* 判断队列是否已满
* @return
*/
public boolean isFull() {
return count == maxSize;
}
/**
* 获取队列中的元素的个数
* @return
*/
public int size() {
return count;
}
}