栈和队列都是特殊的线性表,它们的插入和删除操作都是事先规定好的。
第一节 栈
1 定义
栈(Stack):只允许在一端进行插入和删除操作的线性表。
栈顶(Top):允许进行插入和删除的那一端。
栈底(Bottom):不允许进行插入和删除的那一端。
其操作的特性是后进先出(Last In First Out, LIFO)。
2 顺序栈
采用顺序存储的栈称为顺序栈,它利用一组地址连续的存储单元存放自栈底到栈顶的数据元素,同时设一个指针(top)指示当前栈顶的位置。
public class MyArrayStack<T> {
private T[] data; // 存放元素的数组
private int top = -1; // 栈顶,初始值为-1
private int maxSize; // 栈容量
/**
* 初始化栈
* @param maxSize
*/
public MyArrayStack(int maxSize) {
this.maxSize = maxSize;
data = (T[]) new Object[this.maxSize];
}
/**
* 判栈空
* @return
*/
public boolean isEmpty() {
return top == -1;
}
/**
* 判栈满
* @return
*/
public boolean isFull() {
return top == this.maxSize - 1;
}
/**
* 入栈
* @param data
* @return
*/
public boolean push(T data) {
if (this.isFull()) {
throw new RuntimeException("栈满");
}
this.data[++this.top] = data;
return true;
}
/**
* 出栈
* @return
*/
public T pop() {
if (this.isEmpty()) {
throw new RuntimeException("栈空");
}
return this.data[this.top--];
}
/**
* 查看栈顶元素
* @return
*/
public T peek() {
if (this.isEmpty()) {
throw new RuntimeException("栈空");
}
return this.data[this.top];
}
}
3 链栈
采用链式存储的栈称为链栈。
链栈的优点是便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况。
通常采用单链表实现,并规定所有操作都是在单链表的表头进行的。
public class MyLinkedStack<T> {
private Node<T> head; // 栈头
private int length; // 栈长度
/**
* 初始化
*/
public MyLinkedStack() {
this.head = new Node<>();
this.length = 0;
}
/**
* 判栈空
* @return
*/
public boolean isEmpty() {
return this.head == null;
}
/**
* 获取栈长度
* @return
*/
public int size() {
return this.length;
}
/**
* 进栈
* @param data
* @return
*/
public boolean push(T data) {
Node<T> node = new Node<>(data);
boolean flag = false;
if (this.isEmpty()) {
this.head.next = node;
this.length++;
flag = true;
} else {
node.next = this.head.next;
this.head.next = node;
this.length++;
flag = true;
}
return flag;
}
/**
* 出栈
* @return
*/
public T pop() {
T data = null;
if (this.isEmpty()) {
throw new RuntimeException("栈空");
} else if (this.length == 1) {
data = (T) this.head.next.data;
this.head.next = null;
} else {
data = (T) this.head.next.data;
this.head.next = this.head.next.next;
}
return data;
}
/**
* 查看栈顶元素
* @return
*/
public T peek() {
T data = null;
if (this.isEmpty()) {
throw new RuntimeException("栈空");
} else {
data = (T) this.head.next.data;
}
return data;
}
public void print() {
if (this.isEmpty()) {
System.out.println("栈空");
} else {
Node<T> cur = this.head;
while (cur.next != null) {
cur = cur.next;
System.out.println(cur.data);
}
}
}
/**
* 栈元素
* @param <T>
*/
private class Node<T> {
private T data;
private Node next;
public Node() {
}
public Node(T data) {
this.data = data;
}
}
public static void main(String[] args) {
MyLinkedStack<String> list = new MyLinkedStack<>();
list.push("a");
list.push("b");
list.push("c");
list.print();
System.out.println("========");
System.out.println(list.pop());
System.out.println("=======");
list.print();
}
}
第二节 队列
1 定义
队列(Queue)也是一种操作受限的线性表,它只允许在表的一端进行插入,而在表的另一端进行删除。
向队列中插入元素称为入队;删除元素称为出队。其操作的特性是先进先出(First In First Out, FIFO)。
队头(Front):允许删除的一端。
队尾(Rear):允许插入的一端。
2 顺序存储的队列
队列的顺序实现是指分配一块连续的存储单元存放队列中的元素,并附设两个指针front和rear分别指示队列头元素和队尾元素的位置。将数组想象成一个环状的空间,可以充分利用数组的空间,称之为循环队列。
public class MyArrayQueue<T> {
private T[] arr; // 存放元素的数组
private int front; // 队头索引
private int rear; // 队尾索引
private int maxSize; // 队列容量
private int length; // 队长
/**
* 初始化队列
* @param maxSize
*/
public MyArrayQueue(int maxSize) {
this.maxSize = maxSize;
this.arr = (T[]) new Object[this.maxSize]; // 初始化数组
this.front = -1; // 初始化队头索引
this.rear = -1; // 初始化队尾索引
this.length = 0; // 初始化队长
}
/**
* 判队空
* @return
*/
public boolean isEmpty() {
return this.length == 0;
}
/**
* 判队满
* @return
*/
public boolean isFull() {
return this.length == this.maxSize;
}
/**
* 入队
* @param data
* @return
*/
public boolean enQueue(T data) {
if (this.isFull()) {
throw new RuntimeException("队满");
}
boolean flag = false;
if (isEmpty()) {
arr[this.rear + 1] = data;
this.rear = (this.rear + 1) % this.maxSize;
this.front = (this.front + 1) % this.maxSize;
this.length++;
flag = true;
} else {
arr[this.rear + 1] = data;
this.rear = (this.rear + 1) % this.maxSize;
this.length++;
flag = true;
}
return flag;
}
/**
* 出队
* @return
*/
public T deQueue() {
if (this.isEmpty()) {
throw new RuntimeException("队空");
}
T data = arr[this.front];
this.front = (this.front + 1) % this.maxSize;
this.length--;
return data;
}
public void print() {
if (this.isEmpty()) {
System.out.println("队空");
} else {
if (this.front < this.rear) {
for (int i = this.front; i <= this.rear; i++) {
System.out.println(arr[i]);
}
} else {
for (int i = this.front; i < this.maxSize; i++) {
System.out.println(arr[i]);
}
for (int i = 0; i <= this.rear; i++) {
System.out.println(arr[i]);
}
}
}
}
public static void main(String[] args) {
MyArrayQueue<String> queue = new MyArrayQueue<>(10);
queue.print();
queue.enQueue("a");
queue.enQueue("b");
queue.enQueue("c");
queue.enQueue("d");
System.out.println("===========");
queue.print();
System.out.println("===========");
System.out.println("出队:"+queue.deQueue());
queue.print();
System.out.println("===========");
System.out.println("出队:"+queue.deQueue());
queue.print();
}
}

京公网安备 11010502036488号