IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> java数据结构——栈和队列 -> 正文阅读

[数据结构与算法]java数据结构——栈和队列

目录

Stack:FILO

栈的应用场景

使用数组代码实现栈

?使用链表代码实现栈

Queue:FIFO

队列应用场景

?使用数组代码实现队列

使用链表代码实现队列


Stack:FILO

栈是一个操作受限的线性表,仅能在一端进行添加和删除数据,先进后出FILO

通过链表和数组实现

代码实现

栈的应用场景

  • 实际工作不常用,可能会存在于某些jdk或者第三方插件的源码中
  • 函数调用栈函数调用栈
  • 反序字符串
  • 浏览器的前进后退功能
  • 编译器利用栈实现表达式求值

  • 括号匹配问题

  • 利用栈实现 DFS: depth-first-search? 深度优先遍历

使用数组代码实现栈

import java.util.HashMap;

/**
 * 实现集合类
 * 模拟的数据结构是栈
 * 底层结构是数组
 */
public class MyArrayStack<T> {
    private final int MAX_CAPACITY = Integer.MAX_VALUE - 8;
    private final  int INIT_CAPACITY = 10;// 数组的默认容量

    private Object[] objs;// 这个集合类底层持有的数组
    private int size;// 这个集合类存储的元素数量

    public MyArrayStack(){
         objs = new Object[INIT_CAPACITY];
    }
    public MyArrayStack(int initCapacity){
        if (initCapacity < 1 || initCapacity > MAX_CAPACITY)throw new IllegalArgumentException("parame is Illegal");
        objs = new Object[initCapacity];
    }

    public boolean push(T value){
        // 在添加的时候, 要先判断底层数组是否满了
        if (size == objs.length){
            // 数组满了--> 扩容
            int newLen  = getLen();// 获取扩容的长度
            grow(newLen);// 根据要扩容的长度, 扩容这个数组
        }

        // 到这一步, 意味着, 数组一定有位置可供添加数据

        // 添加元素, 栈顶在size-1位置,   栈底在下标为0的位置
        objs[size] = value;
        size++;

        return true;
    }
    // 根据一个新长度扩容底层数组
    private void grow(int newLen) {
        Object[] newObjs = new Object[newLen];

        // 把旧数组的数据转移到新数组
        for (int i = 0; i < objs.length; i++) {
            newObjs[i] = objs[i];
        }

        objs = newObjs;
    }
    // 获取一个数组的新长度
    private int getLen() {
        // 旧数组长度
        int oldLen = objs.length;

        // 新长度扩为原来的二倍
        int newLen = oldLen * 2;

        if (newLen >= MAX_CAPACITY || newLen < 0){
            newLen = MAX_CAPACITY;
        }

        if (newLen == oldLen)throw new RuntimeException("stack can not add");

        return newLen;
    }

    // 栈的出栈方法
    public T pop(){
        if (isEmpty()) throw new RuntimeException("stack is empty");

        T value = (T)objs[size - 1];
        size--;

        return value;
    }

    // 栈的查看栈顶元素方法
    public  T peek(){
        if (isEmpty()) throw new RuntimeException("stack is empty");

        return  (T) objs[size - 1];
    }


    public boolean isEmpty(){
        return size == 0;
    }
    public int  size(){
        return size;
    }

}
public class Demo2 {
    public static void main(String[] args) {

        MyArrayStack<String> stack = new MyArrayStack<>(2);
        stack.push("zs");
        stack.push("ls");
        stack.push("wu");
        stack.push("zl");


        // zs  - ls  - wu   -zl
        // 栈底              栈顶
        // 0    1      2      3


        // zs  - ls  - wu   -zl
        // 栈底      栈顶
        // 0    1      2
        String pop = stack.pop();
        System.out.println(pop);

        System.out.println(stack);


        // zs  - ls  - wu   - aa
        // 栈底              栈顶
        // 0    1      2     3
        stack.push("aa");
        System.out.println(stack);

    }
}

?使用链表代码实现栈

/**
 * 实现集合类
 * 模拟的数据结构是栈
 * 底层结构是链表: 单链表
 */
public class MyLinkedStack<T> {

    private Node top;// 保存栈的栈顶
    private int size;// 这个栈中保存了多少个元素


    // 对于栈我们应该提供的三个方法:  入栈, 出栈, 查看栈顶元素
    //                              push    pop    peek

    /**
     * 给栈实现一个添加方法
     * @param value : 要添加的元素
     * @return : 添加是否成功
     */
    public boolean push(T value){
        top = new Node(value, top);
        size++;
        return true;
    }

    /**
     * 栈的删除操作
     * @return : 被删除的栈顶元素
     */
    public T pop(){
        // 判断链表为空
        if (isEmpty()) throw new RuntimeException("stack is empty");

        T value = top.value;// 保存原本栈顶值
        top = top.next; // 栈顶向栈底移动一个元素
        size--;

        return value;
    }

    /**
     * 栈的查看栈顶元素的方法
     * @return:  栈顶元素
     */
    public T peek(){
        // 判断链表为空
        if (isEmpty()) throw new RuntimeException("stack is empty");

        return top.value;
    }

    public  boolean isEmpty(){
        return size == 0;
    }
    public int size(){
        return size;
    }

    class Node{
        T value;
        Node next;
        public Node(T value, Node next) {
            this.value = value;
            this.next = next;
        }
    }
}
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Stack;

public class Demo {
    public static void main(String[] args) {

//        Stack<String> stack = new Stack<>();
//        stack.push("zs");
//        LinkedList<String> stack = new LinkedList<>();
//        stack.push("zs");


        MyLinkedStack<String> stack = new MyLinkedStack<>();
        stack.push("zs");
        stack.push("ls");
        stack.push("wu");
        stack.push("zl");

        // zs  ls  wu  zl
        // 栈底         栈顶

        String pop1 = stack.pop();
        String pop2 = stack.pop();

        System.out.println(pop1);
        System.out.println(pop2);

        System.out.println(stack.peek());




    }
}

Queue:FIFO

队列是一种操作受限的线性表,一端插入数据,另一端删除数据。可以通过链表和数组实现

队列应用场景

不常用,可能会存在于某些jdk或者第三方插件的源码中,并且用到的不是普通队列,一般在工程中用到的是阻塞队列

  • 利用队列实现 BFS:breadth first search 广度优先搜索/ 遍历

阻塞队列:队列满的时候,添加程序等待,队列空的时候,删除程序等待。常用于生产者-消费者模型,队列满时入队列就阻塞,队列空的时候,出队列就阻塞。

线程池:创建线程池,会指定一个阻塞队列来存储任务

面包——任务

消费者——线程

生产者——提交任务的程序

桌子——阻塞队列

缓存、利用队列实现BFS:breadth first search 广度优先搜索/遍历

分布式:服务分布在不同的地方,这些分布在不同位置的服务又可以相互关联通过某些途径。

?使用数组代码实现队列

public class MyArrayQueue<T> {

    private final  int MAX_CAPACITY = Integer.MAX_VALUE - 8;
    private final  int INIT_CAPACITY = 10;

    private Object[] arr;// 底层循环数组
    private int size;// 队列中存储了多少元素
    private int head;// 队头的下标
    private int end;// 队尾的下标

    public MyArrayQueue() {
       this.arr = new Object[INIT_CAPACITY];
    }
    public MyArrayQueue(int initCapacity) {
        if (initCapacity < 1 || initCapacity > MAX_CAPACITY)throw new IllegalArgumentException("initCapacity is Illegal");
        this.arr = new Object[initCapacity];
    }

    // offer  poll peek

    public boolean offer(T value){
        if (size == arr.length){
            // 底层数组满了, 需要扩容
            int newLen = getLen();
            grow(newLen);
        }

        // 走到这, 意味着数组中有位置可以添加
        if (size == 0){
            // 原本数组没有存储元素
            arr[head] = value;
            end = head;
        }else {
            // 原本数组已经存储元素
            end = (end + 1) % arr.length;
            arr[end] = value;
        }

        size++;
        return true;
    }
    private void grow(int newLen) {
        Object[] newArr = new Object[newLen];

        // 把旧数组的数组转移到新数组
        for (int i = 0; i < arr.length; i++) {
            int index = (head + i) % arr.length;
            newArr[i] = arr[index];
        }

        // 重新定义指向
        arr = newArr;
        head = 0;
        end = size -1;
    }
    private int getLen() {
        // 旧数组长度
        int oldLen = arr.length;

        // 新长度扩为原来的二倍
        int newLen = oldLen * 2;

        if (newLen >= MAX_CAPACITY || newLen < 0){
            newLen = MAX_CAPACITY;
        }

        if (newLen == oldLen)throw new RuntimeException("stack can not add");

        return newLen;
    }

    public T poll(){
        if (isEmpty()) throw new  RuntimeException("queue is empty");

        T vlaue  = (T)arr[head];

        if (size == 1){// 原本队列中只剩一个元素
            head = 0;
            end = 0;
        }else {
            // 队列中有多个元素
            head = (head + 1) % arr.length;
        }
        size--;
        return vlaue;
    }


    public T peek() {
        if (isEmpty()) throw new RuntimeException("queue is empty");

        return (T)arr[head];
    }

        public boolean isEmpty(){
        return size == 0;
    }

}

public class Demo2 {
    public static void main(String[] args) {


        MyArrayQueue<String> queue = new MyArrayQueue<>(4);

        queue.offer("zs");
        queue.offer("ls");
        queue.offer("wu");
        queue.offer("zl");
        //  zs  ls  wu  zl
        //  0   1   2   3
        // head         end


        //  zs  ls  wu  zl
        //  0   1   2   3
        //     head     end
        String poll = queue.poll();


        //  aa  ls  wu  zl
        //  0   1   2   3
        // end head
        queue.offer("aa");


        //  ls  wu  zl  aa  bb
        //  0   1   2   3   4   5   6   7
        // head            end
        queue.offer("bb");



        System.out.println(queue);

    }
}

使用链表代码实现队列

/**
 * 实现一个集合类
 * 模拟的数据结构是队列
 * 底层结构是: 单链表
 */
public class MyLinkedQueue<T> {

    private Node head;// 队列的队头
    private Node end;// 队列的队尾
    private int size;// 队列存储了多少元素

    // 作为队列, 它应该存在哪些操作?
    // 入队列-> 添加    出队列 -> 删除     查看队头元素 --> 查找
    //  offer            poll                   peek

    public boolean offer(T value){

        if (isEmpty()){
            // 原队列为空, 这个新添加的元素, 既是队头又是队尾
            head = new Node(value, null );
            end = head;
            size++;
            return true;
        }else {
            // 原队列不空, 这个新添加的元素, 放在队尾
            Node newNode = new Node(value, null);
            end.next = newNode;
            end = newNode;
            size++;
            return true;
        }
    }

    public T poll(){
        if (isEmpty())throw new RuntimeException("queue is empty");

        // 链表不空
        T value = head.value;

        if (size == 1){
            // 队列中只剩一个元素
            head = null;
            end = null;
        }else {
            // 队列中多于一个元素
            head = head.next;
        }
        size--;
       return value;
    }

    public T peek() {
        if (isEmpty()) throw new RuntimeException("queue is empty");
        return head.value;
    }


    public boolean isEmpty(){
        return size == 0;
    }
    public int size(){
        return size;
    }

    class Node{
        T value;
        Node next;
        public Node(T value, Node next) {
            this.value = value;
            this.next = next;
        }
    }
}
import java.util.ArrayDeque;

public class Demo1 {
    public static void main(String[] args) {

//        ArrayDeque<String> queue = new ArrayDeque<>();
//        queue.offer("zs");
//        queue.poll();
//        queue.peek();

        MyLinkedQueue<String> queue = new MyLinkedQueue<>();

        queue.offer("zs");
        queue.offer("ls");
        queue.offer("wu");
        queue.offer("zl");

        //zs   -- ls   -- wu   -- zl
        //队头                     队尾

        String poll = queue.poll();
        System.out.println(queue.peek());

        System.out.println(queue);



    }
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-10 14:44:49  更:2021-07-10 14:45:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 17:40:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码