数据结构-自定义栈、队列、二分查找树、双向链表

/*** 底层是数组*/
public class MyStack {private long [] arr; // 底层是数组private int top = -1; // 核心【栈顶的索引(指针)】public MyStack() {super();arr = new long[10];}public MyStack(int capacity) {super();arr = new long[capacity]; // 自定义长度}/*** 压栈* @param value*/public void push(long value) {if(isFull())throw new IllegalArgumentException("Stack is full");arr[++top] = value;}/*** 弹栈【每次都是从栈顶取出元素】* @return*/public long pop() {if(isEmpty())  // 当栈空的时候,就不能弹栈了throw new IllegalArgumentException("Stack is empty");return arr[top--];}/*** 查看栈顶的元素* @return*/public long peek() {if(isEmpty())  // 当栈空的时候,就不能弹栈了throw new IllegalArgumentException("Stack is empty");return arr[top];}/*** 判断栈是否是空的* @return*/public boolean isEmpty() {return top == -1;}/*** 判断是否满栈了* @return*/public boolean isFull() {return top == arr.length-1;}
}

队列

/*** 自定义队列  FIFO : 先进先出  【底层是数组】*/
public class MyQueue {private long [] arr; // 底层是数组private int front = 0; // 队头索引private int rear = 0;  // 队尾索引private int elements = 0; // 队列中实际的元素个数public MyQueue() {super();arr = new long[10];}public MyQueue(int capacity) {super();arr = new long[capacity]; // 自定义长度}/*** 入队列【从队尾添加元素】* @param value*/public void enqueue(long value) {if(isFull())throw new QueueException("Queue is full");arr[rear++] = value;elements++;}/*** 出队列 【从队头取出元素】* @return*/public long dequeue() {if(isEmpty())throw new QueueException("Queue is empty");elements--;return arr[front++];}/*** 查看队头的元素* @return*/public long top() {if(isEmpty())throw new QueueException("Queue is empty");return arr[front];}/*** 判断队列是否是空的* @return*/public boolean isEmpty() {return elements == 0;}/*** 队列满了* @return*/public boolean isFull() {return elements == arr.length;}/*** 队列中的元素个数* @return*/public int size() {return elements;}
}

二分查找树

/*** 	二叉查找树【二叉搜索树】* 		1. 底层 Node* 		2. 树根root*/
public class BinarySearchTree {private Node root; // 树根public BinarySearchTree() {super();}/*** 	二叉树的添加【口诀 : 左小右大】* @param value* @return true 添加成功  false 添加失败了*/public boolean add(long value) {Node node = new Node(value); // 添加的新节点if(root == null) { // 空树root = node; // 把新添加的第一个元素作为树根return true;}Node parent = null; // 当前节点的父节点Node current = root; // 每次都要从树根去查询for(;;) {parent = current; // 确定当前节点的父节点if(value < current.data) { // 左小:值小的放节点的左边current = current.leftChild;if(current == null) {parent.leftChild = node;return true;}}else if(value > current.data) { // 右大:值大的放节点的右边current = current.rightChild;if(current == null) {parent.rightChild = node;return true;}}else { // 节点值相等了:去重return false; // TreeSet的去重原理【重复的节点不会添加】}}}/***      根据值来找二叉树中的节点(递归思想)*              时间复杂度O(log2n)  ~ O(n) , 近似于二分查找* @param value* @return*/public Long find(long value) {if(root == null)  // 空树return null;Node current = root; // 每次查询都要从树根开始while(value != current.data) { // 没要找到此节点时,则继续遍历左/右子节点来查找if(value < current.data) { // 左小current = current.leftChild;}else { // 右大current = current.rightChild;}if(current == null) { // 找到树的最后一个节点都还没有找到该数值的节点return null;}}return current.data;}/***      获取树根  * @return*/public Node getRoot() {return root;}/*** 	递归 : 从任意节点进行前序遍历【根左右】* @param localNode*/public void preOrder(Node localNode) {if(localNode != null) {//1. 前序遍历根节点System.out.println(localNode);//2. 前序遍历左子节点preOrder(localNode.leftChild);//3. 前序遍历右子节点preOrder(localNode.rightChild);}}/*** 	递归 : 从任意节点进行中序遍历 【左根右】* @param localNode*/public void inOrder(Node localNode) {if(localNode != null) {//1. 中序遍历左子节点inOrder(localNode.leftChild) ;//2. 中序遍历根节点System.out.println(localNode);//3. 中序遍历右子节点inOrder(localNode.rightChild) ;}}/*** 	递归 : 从任意节点进行后序遍历 【左右根】* @param localNode*/public void postOrder(Node localNode) {if(localNode != null) {//1. 后序遍历左子节点postOrder(localNode.leftChild); //2. 后序遍历右子节点postOrder(localNode.rightChild); //3. 后序遍历根节点System.out.println(localNode);}}/***	 树结构的底层节点类*/@SuppressWarnings("unused") class Node{private long data; // 数据域private Node leftChild; // 当前节点的左子节点private Node rightChild; // 当前节点的右子节点public Node(long data) {super();this.data = data;}public Node getLeftChild() {return leftChild;}public Node getRightChild() {return rightChild;}@Overridepublic String toString() {return String.valueOf(data);}}
}

双向链表


/*** 	双向链表*     1. 底层是Node(data, next ,previous)*     2. first头节点  last尾结点*/
public class DoubleLinkedList {private Node first; // 头节点private Node last; // 尾节点private int elements; // 链表中真实的节点个数public DoubleLinkedList() {super();}/*** 判断是否是空链表* * @return*/public boolean isEmpty() {return first == null;}/*** 从链表头部添加元素* @param value*/public void addFirst(Object value) {Node node = new Node(value);if (first == null) { // 空链表last = node; // 指定尾节点}else { // 不是空链表时first.previous = node;}node.next = first;first = node;elements++;}/*** 从链表尾部添加节点* * @param value*/public void addLast(Object value) {Node node = new Node(value);if (first == null) { // 空链表first = node; // 指定尾节点} else {last.next = node; // 图步骤1:  向链表尾部追加节点node.previous = last; // 图步骤2 :把曾经的last变为倒数第二个节点}last = node; // 图步骤3 : 新添加的节点就是尾部节点elements++;}/***    从链表尾部添加节点* @param value*/public void add(Object value) {addLast(value);}/*** 	删除链表的头节点* @return*/public Object removeFirst() {if(first == null) // 空链表不用删除return null;Node removeNode = first; // 临时保存被删除的头节点if(removeNode.next == null) { // 删除到链表只剩余最后一个节点时last = null;}else {removeNode.next.previous = null; // 头节点是不会存在previous的}first= first.next;elements--;return removeNode.data;}/*** 	删除链表的尾节点* @return*/public Object removeLast() {if(first == null) // 空链表不用删除return null;Node removeNode = last; // 临时保存被删除的头节点if(removeNode.next == null) { // 链表只剩余最后一个元素了first = null;}else { // 链表中还有节点removeNode.previous.next = null; // 尾节点时没有下一个节点的}last = last.previous;elements--;return removeNode.data;}@Overridepublic String toString() {Node current = first; // 双向链表从头节点开始一个个遍历元素StringBuilder builder = new StringBuilder();builder.append("[");while (current != null) {builder.append(current);current = current.next;if (current != null) {builder.append(", ");}}builder.append("]");return builder.toString();}/*** 从链表尾部向前遍历(倒序)* @return*/public String reverse() {Node current = last; // 双向链表从尾节点开始一个个遍历元素StringBuilder builder = new StringBuilder();builder.append("[");while (current != null) {builder.append(current);current = current.previous;if (current != null) {builder.append(", ");}}builder.append("]");return builder.toString();}/*** 	查找节点 (双向链表可以从头节点也可以从尾节点查找)   1~1000* @param value* @return*/public Object find(Object value) {// 双端链表要从头节点first开始查找元素Node current = first;while (current != null) {if (current.data == value) {return current.data;}current = current.next; // 遍历}return null;}/*** 	根据数据值来删除对应的链表节点* @param obj* @return*/public Object remove(Object value) {if(first == null) // 空链表不能删除节点return null;//1.遍历查找需要删除的节点	Node current = first; // 当前遍历的节点while(current.data !=  value) { // 判断节点的值是否是要删除的值if(current.next == null) // 已经找到链表的最后一个节点了return null;current = current.next; // 遍历思想}//2.删除查找到的节点if(current == first) { // 删除的就是头节点元素     if(current.next == null)// 处理 : 链表中就一个元素,且删除的就是这个元素时last = null;first = current.next;}else { // 删除的中间节点或尾结点current.previous.next = current.next; // current给删除了(current就成为垃圾,GC)}elements--;return current.data;}/*** 	链表中真实的节点个数* @return*/public int size() {return elements;}private class Node { // 底层Node节点类private Object data; // 数据域private Node next; // 指针域(保存的是下一个节点的引用)private Node previous; // 指针域(保存的是上一个节点的引用)public Node(Object data) {super();this.data = data;}@Overridepublic String toString() {return String.valueOf(data);}}
}

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

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

相关文章

leetcode刷题:884、977

884.比较含退格的字符串 给定 s 和 t 两个字符串&#xff0c;当它们分别被输入到空白的文本编辑器后&#xff0c;如果两者相等&#xff0c;返回 true 。# 代表退格字符。 注意&#xff1a;如果对空文本输入退格字符&#xff0c;文本继续为空。 方法一、用栈 #include <i…

8.MyBatis 操作数据库(进阶)

文章目录 1.动态SQL插入1.1使用注解方式插入数据1.2使用xml方式插入数据1.3何时用注解何时用xml&#xff1f;1.4使用SQL查询中有多个and时&#xff0c;如何自动去除多余and1.4.1方法一&#xff1a;删除and之后的代码如图所示&#xff0c;再次运行1.4.2方法二&#xff1a;加上tr…

Linux服务器上网络端口测试

在使用telnet 111.22.345.66 80在Linux主机上尝试连接目标IP地址111.22.345.66的80端口时&#xff0c;会看到以下四行返回信息的含义解释&#xff1a; Trying 111.22.345.66...&#xff1a; 这一行指示telnet正在尝试与IP地址为111.22.345.66的主机建立连接。这表明telnet正尝…

elasticsearch安装配置注意事项

安装Elasticsearch时&#xff0c;需要注意以下几个重要事项&#xff1a; 1、版本选择&#xff1a;选择与你系统和其他组件&#xff08;如Logstash、Kibana&#xff09;兼容的Elasticsearch版本。 2、Java环境&#xff1a;Elasticsearch是基于Java构建的&#xff0c;因此确保已…

书生·浦语大模型实战营之 OpenCompass大模型评测

书生浦语大模型实战营之 OpenCompass &#xff1a;是骡子是马&#xff0c;拉出来溜溜 为什么要研究大模型的评测&#xff1f; 百家争鸣&#xff0c;百花齐放。 首先&#xff0c;研究评测对于我们全面了解大型语言模型的优势和限制至关重要。尽管许多研究表明大型语言模型在多…

Linux cmake 初窥【2】

1.开发背景 基于上一篇的基础上&#xff0c;再次升级 2.开发需求 基于 cmake 指定源文件目录可以是多个文件夹&#xff0c;多层目录 3.开发环境 ubuntu 20.04 cmake-3.23.1 4.实现步骤 4.1 准备源码文件 工程目录如下 顶层脚本 compile.sh 负责执行 cmake 操作&#xff0…

FSC森林认证是什么?

FSC森林认证&#xff0c;又称木材认证&#xff0c;是一种运用市场机制来促进森林可持续经营&#xff0c;实现生态、社会和经济目标的工具。FSC森林认证包括森林经营认证&#xff08;Forest Management, FM&#xff09;和产销监管链认证&#xff08;Chain of Custody, COC&#…

微搭低代码入门06分页查询

目录 1 创建自定义代码2 编写分页代码3 创建页面4 创建变量5 配置数据列表总结 我们在数据模型章节介绍了微搭后端服务编写的三种方式&#xff0c;包括Http请求、自定义代码、云函数。本篇我们详细讲解一下利用自定义代码开发分页查询的功能。 1 创建自定义代码 打开控制台&am…

Qt——入门基础

目录 Qt入门第一个应用程序 main.cpp widget.h widget.cpp widget.ui .pro Hello World程序 对象树 编辑框 按钮 Qt 窗口坐标系 Qt入门第一个应用程序 main.cpp 这就像一开始学语言时都会打印一个“Hello World”一样&#xff0c;我们先来看看创建好一个项目后&…

LeetCode 难题解析 —— 正则表达式匹配 (动态规划)

10. 正则表达式匹配 思路解析 这道题虽然看起来不难理解&#xff0c;但却存在多种可能&#xff0c;当然这种可能的数量是有限的&#xff0c;且其规律对于每一次判别都使用&#xff0c;所以自然而然就想到用 动态规划 的方法啦 接下来逐步分析可能的情况&#xff1a; &#x…

栈(使用顺序表构建)

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 目录 1、栈的概念2、栈的数组构建方法2.1 前言2.2 正文2.2.1 栈的初始化2.2.2 栈的销毁2.2.3 压…

Jupyter notebook和 Jupyter lab内核死亡问题的原因和解决方案

写在前面&#xff1a;之前也遇到过几次内核死亡的问题&#xff0c;也一直没有想解决办法。这里总结一下并提出几个解决办法。 首先明确一下jupyter出现内核死亡的原因&#xff1a;jupyter lab 或者 jupyter notebook 本身是一个web服务&#xff0c; 无法支持高并发和频繁的计算…

栈与队列(包括例题一道)

栈 栈的概念 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。 进行数据插入和删除操作的一端 称为栈顶&#xff0c;另一端称为栈底。 栈中的数据元素遵守后进先出 LIFO &#xff08; Last In First Out &#xff09;的原则。 压栈&…

libevent 梳理

C10K 背景 C10K问题&#xff1a;如何在一台物理机上同时服务 10000 个用户&#xff1f;这里 C 表示并发&#xff0c;10K 等于 10000&#xff1f; C10K 问题本质上是一个操作系统问题&#xff0c;需要考虑&#xff1a; 1.文件句柄数&#xff1a;每个客户连接都代表一个文件描述…

AI去衣技术在动画制作中的应用

随着科技的发展&#xff0c;人工智能&#xff08;AI&#xff09;已经在各个领域中发挥了重要作用&#xff0c;其中包括动画制作。在动画制作中&#xff0c;AI去衣技术是一个重要的工具&#xff0c;它可以帮助动画师们更加高效地完成工作。 AI去衣技术是一种基于人工智能的图像…

人际关系之【镜子、点到为止、脸色和蔼、懂自爱、弹性、试探】

人跟人是镜子 别人看到你的表情&#xff0c;当作一面镜子 儒家&#xff1a;先检查自己&#xff0c;容易进步 礼尚往来&#xff1a;一切往好处想&#xff0c;就会有好的结果 关于借钱&#xff1a; 没问题&#xff0c;我随时&#xff08;合适&#xff09;要用 个人和团体合在…

神经网络怎么把隐含层变量融合到损失函数中?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

【工具分享】Amnesia2勒索病毒解密工具

前言 Amnesia 勒索软件于 2017 年 4 月 26 日开始出现。Amnesia 主要通过 RDP&#xff08;远程桌面服务&#xff09;暴力攻击进行传播&#xff0c;允许恶意软件作者登录受害者的服务器并执行勒索行为。 特征 Amnesia 是一种用 Delphi 编程语言编写的勒索软件&#xff0c;它使…

Git撤回指定commit不保留更改

要撤销指定的commit但不保留这个commit中的更改&#xff0c;可以使用以下命令&#xff1a; git revert <commit_hash> --no-commit这里的<commit_hash>是你想要撤销的commit的哈希值。如果你想要在一个commit上使用这个命令&#xff0c;你可以用它的哈希值或者用H…

程序员的实用神器:助力软件开发的利器 ️

程序员的实用神器&#xff1a;助力软件开发的利器 &#x1f6e0;️ 程序员的实用神器&#xff1a;助力软件开发的利器 &#x1f6e0;️引言摘要自动化测试工具&#xff1a;保障代码质量的利剑 &#x1f5e1;️编写高效测试用例 持续集成/持续部署工具&#xff1a;加速交付的利器…