线性数据—栈、队列、链表

news2024/11/23 11:47:55

一、栈 Stack(存取O(1))

先进后出,进去123,出来321。
基于数组:最后一位为栈尾,用于取操作。
基于链表:第一位为栈尾,用于取操作。

1.1、数组栈 

/**
 * 基于数组实现的顺序栈; items[0]:表头/栈底;  items[size-1]:表尾/栈顶;
 */
public class MyArrayStack {
    // 存储元素的 数组
    private String items[];
    // 栈实际大小
    private int size =0;
    // 栈的容量
    private int capacity = 0;

    public MyArrayStack(int capacity) {
        this.size = 0;
        this.capacity = capacity;
        this.items = new String[capacity];
    }

    /**
     * 入栈
     */
    public boolean push(String item) {
        if(size >= capacity){
            throw new IndexOutOfBoundsException("MyArrayStack 栈的内存满了");
        }
        items[size] = item;
        size++;
        return true;
    }

    /**
     * 出栈
     */
    public String pop() {
        if(size<=0){
            throw new IndexOutOfBoundsException("MyArrayStack 栈的内存空了");
        }
        String item = items[size-1];
        items[size-1] = null;
        size--;
        return item;
    }
}

1.2、链表栈 

/**
 * 基于链表实现的链式栈  top: 表尾/栈顶;
 */
public class MyLinkedStack {

    // 表尾/栈顶;
    private Node top = null;

    /**
     * 入栈
     */
    public void push(String value) {
        Node node = new Node(value,null);
        if(top != null){
            node.nextNode = top;
        }
        top = node;
    }

    /**
     * 出栈
     */
    public String pop() {
        if(top==null){
            throw new IndexOutOfBoundsException("MyLinkedStack 栈的内存空了");
        }
        String retValue = top.getValue();
        top = top.nextNode;
        return retValue;
    }

    /**
     * 节点
     */
    private static class Node{
        // 存储数据
        private String value;
        // 下个节点
        private Node nextNode;
        public Node(String value, Node nextNode) {
            this.value = value;
            this.nextNode = nextNode;
        }
        public String getValue() {
            return value;
        }
    }
}

二、队列 Queue (存取O(1))

先进先出(FIFO)的有序列表 

2.1、数组单向队列 (存取O(1))

/**
 * 基于数组实现的顺序队列
 */
public class MyArrayQueue {

    private String [] items;

    // 容量
    private int capacity = 0;

    // 队头下标
    private int head = 0;

    // 队尾下标
    private int tail = 0;

    public MyArrayQueue(int capacity) {
        this.items = new String [capacity];
        this.capacity = capacity;
    }

    /**
     * 入队
     */
    public boolean enqueue(String item) {
        if(capacity == tail){
            throw new IndexOutOfBoundsException("MyArrayQueue 容量满了");
        }
        items[tail] = item;
        tail++;
        return true;
    }

    /**
     * 出队
     */
    public String dequeue() {
        if(head==tail){
            throw new IndexOutOfBoundsException("MyArrayQueue 容量空了");
        }
        String retValue = items[head];
        head++;
        return retValue;
    }
}

2.2、链表单向队列 

/**
 * 基于链表实现的链式队列
 */
public class MyLinkedListQueue {
    // 队头
    private Node head = null;
    // 队尾
    private Node tail = null;

    /**
     * 入队
     */
    public void enqueue(String value) {
        Node node = new Node(value,null);
        if(tail==null){
            head = node;
            tail = node;
        }else {
            tail.next=node;
            tail=node;
        }
    }

    /**
     * 出队
     */
    public String dequeue() {
        if(head==null){
            throw new IndexOutOfBoundsException("MyLinkedListQueue 队列空了");
        }
        String retValue = head.getValue();
        head = head.next;
        if (head == null) {
            tail = null;
        }
        return retValue;
    }

    private static class Node{
        private String value;
        private Node next;
        public Node(String value, Node next) {
            this.value = value;
            this.next = next;
        }
        public String getValue() {
            return value;
        }
    }
}

三、链表 LinkedList 

3.1、单向链表 

/**
 * 单向普通链表
 */
public class MyLinkedList {
    // 链表大小
    private int size;
    // 表头
    private Node head;

    /**
     * 插入
     */
    public void insert(int index, String value) {
        if(index<0){
            throw new IndexOutOfBoundsException("MyLinkedList 下标越界了");
        } else {
            if(head==null){
                head = new Node(value,null);
            }else {
                if(index>=size){
                    index = size-1;
                }
                Node prev = head;
                for(int i=0;i<index;i++){
                    prev = prev.next;
                }
                Node node = new Node(value,prev);
                prev.next =node;
            }
            size++;
        }
    }

    /**
     * 获取
     */
    public String get(int index){
        if(size<=0){
            throw new IllegalArgumentException("MyLinkedList 空链表");
        }
        if(index<0 || index>=size) {
            throw new IllegalArgumentException("MyLinkedList 下标越界了");
        }
        Node prev = head;
        for (int i=0;i<index;i++){
            prev = prev.next;
        }
        return prev.getValue();
    }

    private class Node{
        private String value;
        private Node next;
        public Node(String value, Node next) {
            this.value = value;
            this.next = next;
        }
        public String getValue() {
            return value;
        }
    }
}

3.2、双向链表 


public class MyDoubleLinkedList {
    // 链表大小
    private int size;
    // 表头
    private Node head;
    // 表尾
    private Node tail;

    /**
     * 插入
     */
    public void insert(int index,String data) {
        if(index < 0) {
            throw new IndexOutOfBoundsException("MyDoubleLinkedList  insert 下标越界");
        }
        Node node = new Node(data,null,null);
        if(index == 0) {
            head.next = node.next;
            head= node;
            return;
        }
        if(index >= size) {
            tail.prev = node.prev;
            tail= node;
            return;
        }
        Node cur = this.head;
        while(index != 0) {
            cur = cur.next;
            index--;
        }
        node.next = cur;
        cur.prev.next = node;
        node.prev = cur.prev;
        cur.prev = node;
    }

    public String get(int index){
        if(index<0||index>size){
            throw new IndexOutOfBoundsException("MyDoubleLinkedList get 下标越界了");
        }
        if(index<=(size/2)){
            Node cur = head;
            for(int i = 0;i<index-1;i++){
               cur = head.next;
            }
            return cur.getValue();
        }else {
            index = size-index;
            Node cur = tail;
            for (int i=size;i>index;i--){
                cur = cur.prev;
            }
            return cur.getValue();
        }
    }


    private class Node{
        public String value;
        public Node prev;
        public Node next;
        public Node(String value, Node prev, Node next) {
            this.value = value;
            this.prev = prev;
            this.next = next;
        }

        public String getValue() {
            return value;
        }
    }
}

3.3、跳表 

1.跳表由很多层结构组成,level是通过一定的概率随机产生的;
2.每一层都是一个有序的链表,默认是升序 ;
3.最底层(Level 1)的链表包含所有元素;
4.如果一个元素出现在Level i 的链表中,则它在Level i 之下的链表也都会出现;
5.每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素。


import java.util.Random;

public class SkipList {

    // 跳表中存储的是正整数,并且存储的数据是不重复的
    private static final int MAX_LEVEL = 16;
    // 结点的个数
    private int levelCount = 1;
    // 索引的层级数
    private final Node head = new Node();
    // 头结点
    private final Random random = new Random();

    // 查找操作
    public Node find(int value) {
        Node p = head;
        for (int i = levelCount - 1; i >= 0; --i) {
            while (p.next[i] != null && p.next[i].data < value) {
                p = p.next[i];
            }
        }
        if (p.next[0] != null && p.next[0].data == value) {
            return p.next[0];    // 找到,则返回原始链表中的结点
        } else {
            return null;
        }
    }

    // 插入操作
    public void insert(int value) {
        int level = randomLevel();
        Node newNode = new Node();
        newNode.data = value;
        newNode.maxLevel = level;   // 通过随机函数改变索引层的结点布置
        Node[] update = new Node[level];
        for (int i = 0; i < level; ++i) {
            update[i] = head;
        }
        Node p = head;
        for (int i = level - 1; i >= 0; --i) {
            while (p.next[i] != null && p.next[i].data < value) {
                p = p.next[i];
            }
            update[i] = p;
        }
        for (int i = 0; i < level; ++i) {
            newNode.next[i] = update[i].next[i];
            update[i].next[i] = newNode;
        }
        if (levelCount < level) {
            levelCount = level;
        }
    }

    // 删除操作
    public void delete(int value) {
        Node[] update = new Node[levelCount];
        Node p = head;
        for (int i = levelCount - 1; i >= 0; --i) {
            while (p.next[i] != null && p.next[i].data < value) {
                p = p.next[i];
            }
            update[i] = p;
        }
        if (p.next[0] != null && p.next[0].data == value) {
            for (int i = levelCount - 1; i >= 0; --i) {
                if (update[i].next[i] != null && update[i].next[i].data == value) {
                    update[i].next[i] = update[i].next[i].next[i];
                }
            }
        }
    }

    // 随机函数
    private int randomLevel() {
        int level = 1;
        for (int i = 1; i < MAX_LEVEL; ++i) {
            if (random.nextInt() % 2 == 1) {
                level++;
            }
        }
        return level;
    }

    // Node内部类
    public static class Node {
        private int data = -1;
        private final Node[] next = new Node[MAX_LEVEL];
        private int maxLevel = 0;
        // 重写toString方法
        @Override
        public String toString() {
            return "{data:" +
                    data +
                    "; levels: " +
                    maxLevel +
                    " }";
        }
    }

    // 显示跳表中的结点
    public void display() {
        Node p = head;
        while (p.next[0] != null) {
            System.out.println(p.next[0] + " ");
            p = p.next[0];
        }
        System.out.println();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1069502.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记录:Unity脚本的编写2.0

目录 前言控制方法键盘控制鼠标控制虚拟控制器控制 平移和旋转 前言 前面记录了一些简单的unity脚本用来控制unity中对象模型的移动&#xff08;或者不能叫控制&#xff0c;毕竟它是开启之后自己在跑的&#xff09;&#xff0c;那么让模型可以根据用户的操作来进行变化的方法自…

SQL监控工具

什么是 SQL 监控 SQL 监视是跟踪和分析整个 MSSQL 生态系统的过程&#xff0c;以识别性能问题并防止依赖数据库的应用程序变慢和/或遇到中断&#xff0c;它有助于获取有关 SQL 服务器的数据库会话、查询、作业、CPU 和内存资源、群集、配置和可用性组的信息。 为什么 MSSQL 监…

JavaScript 笔记: 函数

1 函数声明 2 函数表达式 2.1 函数表达式作为property的value 3 箭头函数 4 构造函数创建函数&#xff08;不推荐&#xff09; 5 function 与object 5.1 typeof 5.2 object的操作也适用于function 5.3 区别于⼀般object的⼀个核⼼特征 6 回调函数 callback 7 利用function的pr…

TensorFlow入门(十、共享变量)

使用tf.Variable方法创建变量 使用tf.Variable方法创建变量时有两点需要注意: ①一般情况下,使用tf.Variable方法创建的变量都有作用域,也可叫做变量的可用性范围,即在变量所属的模型内,变量的名字是有效可用的。 ②使用tf.Variable方法创建变量时,会生成一个新的变量。如果在一…

激活函数与loss的梯度

激活函数&#xff1a; 最开始由生物学家对青蛙的神经元机制进行研究发现&#xff0c;青蛙的神经元有多个输入x0、x1、x2&#xff0c;响应值是他们加权后的结果&#xff0c;但响应值如果小于阈值&#xff0c;则不会响应&#xff0c;而只有大于阈值时&#xff0c;才会有固定的响应…

LeetCode 1277. 统计全为 1 的正方形子矩阵【动态规划】1613

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

紫光 DDR3 IP核调试

1. IP核简介 直接编写DDR2/DDR3的逻辑工作量不太大&#xff0c;但是涉及到双边延、高速率的读取&#xff0c;时序很复杂。因此一般抖采用IP核实现。紫光的SDRAM IP核为HMIC_H IP。 HMIC_H IP 包括了 DDR Controller、DDR PHY 和 PLL&#xff0c;用户通过 AXI4 接口实现数据的读…

十三、MySQL 主从复制

一、MySQL 主从复制 1. 主从复制原理 主库 有一个 工作线程 I/O dump thread&#xff08;转储线程&#xff09;。从库 有两个工作线程 I/O thread 和 SQL thread。主库 通过 I/O dump thread 给 从库 I/O thread 传送 binlog 日志。 主从同步过程中&#xff1a; 主库 把接收的…

大厂笔试真题【栈】美团2023春招-火车迷【欧弟算法】全网最全大厂秋招题解

文章目录 题目描述与示例题目描述输入描述输出描述示例一输入输出 示例二输入输出 解题思路代码pythonJavaC时空复杂度 华为OD算法/大厂面试高频题算法练习冲刺训练 题目描述与示例 题目描述 小美是一个火车迷。最近她在观察家附近火车站的火车驶入和驶出情况&#xff0c;发现…

C/C++学习 -- Base64算法

Base64算法概述 Base64是一种用于将二进制数据表示为ASCII字符集中的可打印字符的编码方法。它由64个不同的字符组成&#xff0c;通常包括26个大写字母、26个小写字母、10个数字以及两个特殊字符&#xff08;通常是""和"/"&#xff09;。Base64编码的目的…

【Vue基础-数字大屏】地图标记涟漪效果设置

一、需求说明 将地图中北京市、陕西市、南宁市分别以实心圆、涟漪圆、涟漪圆标记出来 二、代码实践 涉及三个文件 1、App.vue: <template><Screen1/> </template> <script> import Screen1 from "./components/Screen1.vue"; export def…

如何应对数据安全四大挑战?亚马逊云科技打出“组合拳”

数字经济时代&#xff0c;数据被公认为继土地、劳动力、资本、 技术之后的又一重要生产要素。对于企业而言&#xff0c;数据则是一切创新与关键决策的根源。 然而&#xff0c;企业在发挥数据资产的商业价值方面&#xff0c;却面临诸多挑战&#xff0c;比如敏感数据识别、跨组织…

【高阶数据结构】图详解第一篇:图的基本概念及其存储结构(邻接矩阵和邻接表)

文章目录 1. 图的基本概念1.1 什么是图1.2 有向图和无向图1.3 完全图1.4 邻接顶点1.5 顶点的度1.6 路径1.7 路径长度1.8 简单路径与回路1.9 子图1.10 连通图1.11 强连通图1.12 生成树 2. 图的存储结构2.1 邻接矩阵2.2 邻接矩阵代码实现结构定义构造函数添加边打印图测试 2.3 邻…

leetCode 718.最长重复子数组 动态规划 + 优化(滚动数组)

718. 最长重复子数组 - 力扣&#xff08;LeetCode&#xff09; 给两个整数数组 nums1 和 nums2 &#xff0c;返回 两个数组中 公共的 、长度最长的子数组的长度 。 示例 1&#xff1a; 输入&#xff1a;nums1 [1,2,3,2,1], nums2 [3,2,1,4,7] 输出&#xff1a;3 解释&…

2023年台州市第三届网络安全技能大赛(MISC)这是神马

这是神马 考点&#xff1a;冰蝎流量特征数据包&#xff0c;需要解密 emoj解密 冰蝎之前做过 特征就是先base64编码在AES编码 我们在数据包里面找到了密钥&#xff1a;144a6b2296333602 这里我们知道了密钥我们就去解密 先筛选HTTP协议 导出HTTP数据流可以看到传了shell.php 随…

美容美甲小程序商城的作用是什么

美容院往往有很高需求&#xff0c;女性悦己经济崛起&#xff0c;加之爱美化程度提升&#xff0c;无论线下环境还是线上互联网信息冲击&#xff0c;美容服务、化妆产品等市场规格一直稳增不减。 通过【雨科】平台制作美容美甲商城&#xff0c;售卖相关服务/产品&#xff0c;模块…

记两次内网入侵溯源

1.1、入侵告警 1、某天深夜主机防护突然爆出CS木马后门&#xff0c;这攻击队不讲武德呀&#xff0c;还好没睡着2、赶紧叫醒旁边看流量设备的哥们儿&#xff0c;尝试Shiro 反序列漏洞攻击成功3、测试目标网站存在shiro反序列化漏洞1.2、上机排查 1、上机将CS木马下载下来&…

Vue3 reactive和ref详解

reactive Vue3.0中的reactive reactive 是 Vue3 中提供的实现响应式数据的方法。在 Vue2 中响应式数据是通过 defineProperty 来实现的&#xff0c;在 Vue3 中响应式数据是通过 ES6 的 Proxy来实现的。reactive 参数必须是对象 (json / arr)如果给 reactive 传递了其它对象 默…

基于JavaWeb的家用电器信息管理系统

本系统采用基于JAVA语言实现、架构模式选择B/S架构&#xff0c;Tomcat7.0及以上作为运行服务器支持&#xff0c;基于JAVA等主要技术和框架设计&#xff0c;idea作为开发环境&#xff0c;数据库采用MYSQL5.7以上。 开发环境&#xff1a; JDK版本&#xff1a;JDK1.8 服务器&…

intel深度相机 D455及D4系列入门教程(逐行代码讲解)

1.介绍 Intel RealSense D435、D455等D4系列&#xff1a; Intel D4系列深度相机是由英特尔&#xff08;Intel&#xff09;公司推出的一款深度感知摄像头&#xff0c;专为实现计算机视觉和深度学习应用而设计。这款相机使用了英特尔的深度感知技术&#xff0c;结合了摄像头和红…