相较于前面几篇,本篇总结的栈与队列可能会相对简单一点。
所谓栈,即一种特殊的线性表,其只允许在固定的一端进行插入和删除元素的操作。并且遵循先进后出的规则。就像一个瓶子,先进去的在底部,后进去的在顶部。
而栈作为一种数据结构,当然也有着各种方法,但是相比与其他数据结构,由于其构造较为简单,相对应的方法也不算特别多,如push入栈,peek获取栈顶元素,pop出栈等,也可以进行模拟实现:
import java.util.Arrays;
public class MyStack {
int[] array;
int usedSize;
public MyStack(){
this.array = new int[10];
}
public boolean isFull(){
return usedSize == array.length;
}
//压栈
public void push(int val){
if (isFull()){
array = Arrays.copyOf(array, 2*array.length);
}
array[usedSize] = val;
usedSize++;
}
public boolean isEmpty(){
if (usedSize == 0){
return true;
}
else {
return false;
}
}
//出栈
public int pop(){
if (isEmpty()){
System.out.println("栈已为空");
}
int ret = array[usedSize - 1];
usedSize--;
return ret;
}
//偷看
public int peek(){
if (isEmpty()){
System.out.println("栈已为空");
}
return array[usedSize - 1];
}
public static void main(String[] args) {
MyStack myStack = new MyStack();
myStack.push(5);
myStack.push(8);
System.out.println(myStack.peek());
System.out.println(myStack.pop());
System.out.println(myStack.peek());
}
}
但要注意,进栈与出栈的顺序并非是无限制的。假如有一个集合有四个元素分别是1234,要依次将其放入栈中并且中途可以出栈,那其出栈顺序并非是无限制的,如3142的出栈顺序就不可能实现。因为当3入栈再出栈以后,下一个是2而非1。
再比如,要逆序打印一个链表。可以使用递归的方式:
public void funDisplay(ListNode head){
if (head != null){
funDisplay(head.next);
System.out.println(head.val);
}
}
除此以外也可以使用栈。将数据一个个放进去,出来的时候正好就是逆序的,这是对栈的简单应用:
public void funcDisplay(ListNode head){
Stack<Integer> stack = new Stack<>();
ListNode cur = head;
while (cur != null){
stack.push(cur.val);
cur = cur.next;
}
while (!stack.empty()){
System.out.print(stack.pop() + " ");
}
}
然后是队列。队列,即只允许在一端进行插入数据操作,而在另一端进行删除操作的特殊线性表。一般来说插入的是队尾,删除的是队头。其方法也并不算多,并且也可以进行简单的实现:
public class MyQueue {
class ListNode{
int val;
ListNode next;
public ListNode(int val) {
this.val = val;
}
}
ListNode head;
ListNode last;
int usedSize;
//入队
public void offer(int val){
ListNode cur = new ListNode(val);
if (head == null){
head = cur;
last = cur;
}
else {
last.next = cur;
last = cur;
}
usedSize++;
}
//出队
public int pop() {
if (head != null) {
int ch = head.val;
head = head.next;
usedSize--;
return ch;
}
else {
return -1;
}
}
//偷看
public int peek(){
if (head != null){
return head.val;
}
else {
return -1;
}
}
}
但是队列存在一些特殊结构。如环形队列。这种队列进行实现时就会出现一部分特殊情况需要考虑:
public class MyCircularQueue {
int[] array;
int front;
int rear;
public MyCircularQueue(int k) {
this.array = new int[k + 1];
}
public boolean enQueue(int value) {
if (isFull()){
return false;
}
else{
array[rear] = value;
rear = (rear + 1) % array.length;
return true;
}
}
public boolean deQueue() {
if(isEmpty()){
return false;
}
else {
front = (front + 1) % array.length;
return true;
}
}
public int Front() {
if (isEmpty()){
return -1;
}
else {
return array[front];
}
}
public int Rear() {
if (isEmpty()){
return -1;
}
else {
int index = (rear == 0) ? array.length - 1 : rear - 1;
return array[index];
}
}
public boolean isEmpty() {
return front == rear;
}
public boolean isFull() {
return (rear + 1) % array.length == front;
}
}
除此以外,还有如双端队列的数据结构。其实现可以分为很多种,可以拿链表实现,也可以拿数组实现,甚至栈实现都可以。
---------------------------------最后编辑于2023.5.3下午五点左右