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

news/2024/10/22 17:20:11/
java">/*** 底层是数组*/
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;}
}

队列

java">/*** 自定义队列  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;}
}

二分查找树

java">/*** 	二叉查找树【二叉搜索树】* 		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);}}
}

双向链表

java">
/*** 	双向链表*     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.ppmy.cn/news/1459449.html

相关文章

鸿蒙内核源码分析(信号量篇) | 谁在负责解决任务的同步

基本概念 信号量&#xff08;Semaphore&#xff09; 是一种实现任务间通信的机制&#xff0c;可以实现任务间同步或共享资源的互斥访问。 一个信号量的数据结构中&#xff0c;通常有一个计数值&#xff0c;用于对有效资源数的计数&#xff0c;表示剩下的可被使用的共享资源数…

Spring如何控制Bean的加载顺序

前言 正常情况下&#xff0c;Spring 容器加载 Bean 的顺序是不确定的&#xff0c;那么我们如果需要按顺序加载 Bean 时应如何操作&#xff1f;本文将详细讲述我们如何才能控制 Bean 的加载顺序。 场景 我创建了 4 个 Class 文件&#xff0c;分别命名为 FirstInitialization Se…

如何使用dockerfile文件将项目打包成镜像

要根据Dockerfile文件来打包一个Docker镜像&#xff0c;你需要遵循以下步骤。这里假设你已经安装了Docker环境。 1. 准备Dockerfile 确保你的Dockerfile文件已经准备就绪&#xff0c;并且位于你希望构建上下文的目录中。Dockerfile是一个文本文件&#xff0c;包含了用户可以调…

美股订单类型有哪些

美股交易中&#xff0c;订单类型是投资者执行交易指令的重要工具。了解不同类型的订单&#xff0c;可以帮助投资者制定更有效的交易策略&#xff0c;并控制风险。 1. 市价单&#xff1a;快速成交&#xff0c;不惧踏空 市价单&#xff08;Market Order&#xff09;是一种以当时…

日常java选择题

目录 题目 题目 来自牛客网 1.下面代码输出结果是? int i 5; int j 10; System.out.println(i ~j); A.Compilation error because" ~" doesnt operate on integers B.-5 C.-6 D.15 解析&#xff1a;这段代码的目的是通过位运算符~来反转j的位&#xff0c;然…

探索Python循环:索引值的获取与应用

在Python编程中&#xff0c;我们经常需要在循环中使用索引值来访问列表、元组或其他序列类型的元素。本文将详细讲解如何在’for’循环中访问索引值&#xff0c;并提供示例代码及运行结果&#xff0c;帮助初学者更好地理解和应用这一概念。 基本原理 在Python中&#xff0c;f…

局域网手机端远程控制手机

局域网手机端远程控制手机 随着科技的进步和智能设备的普及&#xff0c;远程控制技术在日常生活与工作中的应用越来越广泛。其中&#xff0c;局域网内的手机端远程控制手机技术&#xff0c;因其便捷性和实用性&#xff0c;受到了众多用户的关注。本文将简要介绍该技术及其应用…

STM32_HAL_RTC_中断实现闹钟

1STM32设置 在STM32Cude中设置RTC//具体设置看先前发的文章 再打开闹钟中断&#xff08;如下图&#xff09; 2代码思路 2.1启动闹钟&#xff08;HAL_RTC_SetAlarm_IT(&hrtc,&sAlarm,FORMAT_BCD)&#xff09; 2.2设置回调函数&#xff08;void HAL_RTC_AlarmAEventC…