数据结构(四)——栈和队列(Stack and Queue)

1.栈

1.1概念

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈 顶,另一端称为栈底。

入栈:栈的插入操作被称作入栈,入栈数据在栈顶

出栈:栈的删除操作被称作出栈,出栈数据在栈顶。

生活实例:子弹上膛,单侧开的羽毛球桶

 1.2栈的使用

 方法测试:

public class demo {
    public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        //入栈测试
        stack.push(1);
        stack.push(2);
        stack.push(4);
        System.out.println(stack.size());//查看栈内元素个数
        System.out.println(stack.peek());//获取栈顶元素
        //出栈测试
        System.out.println("=================================");
        stack.pop();//4出栈
        System.out.println(stack.pop());//3出栈
        System.out.println(stack.size());//查看栈内元素个数
        System.out.println(stack.peek());//获取栈顶元素
        System.out.println("=================================");
        stack.pop();

        if (stack.isEmpty()) {
            System.out.println("栈空");
        }
        System.out.println(stack.size());//查看栈内元素个数

    }
}

测试结果:

 1.3栈的实现(硬代码实现)

package day_10_18_Stack;

import java.util.Arrays;

public class MyStack {
    //定义一个数组去存储数据
    private int[] elementData;
    private int size;
    //定义一下数组的默认大小
    private final int DEFAULT_CAPACITY = 3;

    //无参初始化
    public MyStack() {
        //创建一个大小为三的数组
        this.elementData = new int[DEFAULT_CAPACITY];
    }

    //含参初始化
    public MyStack(int capacity) {
        if (capacity < 0) {
            throw new RuntimeException("数组的大小不能小于0");
        } else if (capacity > 0) {
            this.elementData = new int[capacity];
        } else {
            this.elementData = new int[DEFAULT_CAPACITY];
        }
    }

    //入栈
    public void push(int data) {
        //先对数组进行扩容
        ensureCapcity();
        //将新的数据加入到栈顶
        elementData[size] = data;
        size++;

    }

    //出栈
    public int pop() {
        //获取栈顶
        int top = peek();
        size--;
        return top;
    }

    public int size() {
        return size;
    }


    //获取栈顶
    public int peek() {
        if (size == 0) {
            throw new RuntimeException("栈为空");
        }
        int top = elementData[size - 1];//获取栈顶
        return top;
    }

    //判断是否为空
    public boolean empty() {
        return size == 0;
    }


    //扩容
    public void ensureCapcity() {
        if (size == elementData.length) {
            this.elementData = Arrays.copyOf(elementData, elementData.length * 2);
        }
    }

}

测试代码:

package day_10_18_Stack;

public class demo2 {
    public static void main(String[] args) {
        MyStack stack=new MyStack();
        stack.push(1);
        stack.push(2);
        stack.push(4);
        System.out.println(stack.size());//查看栈内元素个数
        System.out.println(stack.peek());//获取栈顶元素
        //出栈测试
        System.out.println("=================================");
        stack.pop();//4出栈
        System.out.println(stack.pop());//3出栈
        System.out.println(stack.size());//查看栈内元素个数
        System.out.println(stack.peek());//获取栈顶元素
        System.out.println("=================================");
        stack.pop();
        System.out.println(stack.empty());
    }
}

测试结果:

 2.队列

2.1概念

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾(Tail/Rear) 出队列:进行删除操作的一端称为队头 (Head/Front)

2.2队列的使用

注意:Queue是个接口,在实例化时必须实例化LinkedList的对象,因为LinkedList实现了Queue接口。 

public class demo {
    public static void main(String[] args) {
        Queue<Integer> queue=new LinkedList<>();
        queue.offer(1);
        queue.offer(2);
        queue.offer(3);
        System.out.println(queue.size());
        System.out.println(queue.peek());
        queue.poll();
        queue.poll();
        queue.poll();
        if(queue.isEmpty()){
            System.out.println("队列为空");
        };
        System.out.println(queue.size());
    }
}

测试结果:

2.3队列的实现(硬代码实现)

public class MyQueue {
    //结构体定义
    private static class ListNode {
        int value;
        ListNode prev;
        ListNode next;

        //初始化
        public ListNode(int value) {
            this.value = value;
        }
    }

    //头节点和尾节点
    public ListNode head;
    public ListNode tail;
    public int size;

    //入队
    public void offer(int value) {
        ListNode node = new ListNode(value);
        if (head == null) {
            head = node;
            tail = node;
        } else {
            tail.next = node;
            node.prev = tail;
        }
        tail = node;
        size++;
    }

    //出队(从队头出队)
    public int poll() {
        if (isEmpty()) {
            throw new RuntimeException("队列为空,不能出队");
        }
        int value = head.value;//记录出队的元素值
        head = head.next;
        if (head == null) {
            tail = null;
        } else {
            head.prev.next = null;//处理出队的节点
            head.prev = null;
        }
        size--;
        return value;
    }

    //判断队列是否为空
    public boolean isEmpty() {
        return size == 0;
    }

    //查询队首的值
    public int peek() {
        if (isEmpty()) {
            throw new RuntimeException("队列为空");
        }
        return head.value;
    }

    //队列的大小
    public int size() {
        return size;
    }

    //输出队列
    public void display() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        //定义一个遍历节点
        ListNode current = head;
        while (current != null) {
            sb.append(current.value);
            if (current.next != null) {
                sb.append(",");
            }
            current = current.next;
        }
        sb.append("]");
        System.out.println(sb);
    }
}

测试:

public class demo1 {
    public static void main(String[] args) {
        MyQueue queue = new MyQueue();
        queue.offer(1);
        queue.offer(2);
        queue.offer(3);
        queue.display();
        System.out.println("队列大小是" + queue.size());
        System.out.println("队列的队头是" + queue.peek());

        queue.poll();
        queue.poll();
        System.out.println("出队两次");
        queue.display();
        queue.poll();
        System.out.println("出队一次");
        if (queue.isEmpty()) {
            System.out.println("队列为空");
        }
        ;
    }
}

测试结果:

2.4双端队列 (Deque)

双端队列(deque)是指允许两端都可以进行入队和出队操作的队列,deque 是 “double ended queue” 的简称。 那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。

Deque是一个接口,使用时必须创建LinkedList的对象。

猜你喜欢

转载自blog.csdn.net/m0_63975371/article/details/127439366