package com.sinjinsong.datastructure.tree;
import java.util.*;
/**
* Java实现二叉查找树 使用递归的操作一般设置两个方法,一个方法是public的(用于调用的),一个方法是private(实际递归的)
*
* @author New Song
*/
public class BinarySearchTree<E extends Comparable<E>> implements Cloneable {
private TreeNode<E> root;
// 用于使用先序遍历字符串建树
// 用于输出从根节点到各个叶子结点的所有路径
private static int index = -1;
public BinarySearchTree() {
}
public BinarySearchTree(TreeNode<E> root) {
this.root = root;
}
// 在node结点下创建子树,node初始值为root,在查找过程中变为root的子节点
// 如果root为空,那么root的值为data
// 否则就向下查找,直至找到合适的位置,创建新结点,赋值为data
// 不存在node的值等于data的情况,如果相等就没有插入的必要了
public void createCharBiTree(TreeNode<E> node, E data) {
if (root == null) {
root = new TreeNode<E>(data);
} else {
if (data.compareTo(node.val) < 0) {
if (node.left == null) {
node.left = new TreeNode<E>(data);
} else {
createCharBiTree(node.left, data);
}
} else {
if (node.right == null) {
node.right = new TreeNode<E>(data);
} else {
createCharBiTree(node.right, data);
}
}
}
}
// 插入一个结点
public void insert(E data) {
root = insert(root, data);
// 注意结果要赋值,否则在调完第二个insert方法后node就回收了,没有把结果赋给root
// 调用的时候将一个null赋给了node,即使node后来不为null了也没法把引用重新赋给root
}
// 也是需要递归进行查找的,递归地找到合适位置后插入,不允许有重复元素
private TreeNode<E> insert(TreeNode<E> node, E data) {
if (node == null) {
node = new TreeNode<>(data);
} else {
if (data.compareTo(node.val) < 0) {
node.left = insert(node.left, data);
} else if (data.compareTo(node.val) > 0) {
node.right = insert(node.right, data);
}
}
return node;
}
public TreeNode<E> search(E data) {
return search(root, data);
}
// 查找一个结点,使用递归
// 如果data即为当前结点的值,则返回当前结点
// 如果data小于当前结点,那么递归查找当前结点的左子树
// 否则,递归查找当前结点的右子树
private TreeNode<E> search(TreeNode<E> node, E data) {
if (node == null) {
return null;
}
int res = data.compareTo(node.val);
if (res > 0) {
return search(node.right, data);
} else if (res < 0) {
return search(node.left, data);
} else {
return node;
}
}
// 删除一个结点
public void delete(E data) {
root = delete(root, data);
}
private TreeNode<E> delete(TreeNode<E> node, E data) {
if (node == null) {
return null;
}
int res = data.compareTo(node.val);
if (res > 0) {
node.right = delete(node.right, data);
} else if (res < 0) {
node.left = delete(node.left, data);
// 删除一个结点不仅包括将自己赋为null,而且其父节点也要将其左子树/右子树赋为null
// 以下为找到的情况
// 如果找到的结点既没有左子树又没有右子树,那么直接设为null
// 如果只有左子树或只有右子树,那么将当前结点赋值为不为空的那一个子树
// 如果都有,那么找到当前结点的右子树中值最小的那个结点,删除它(因为它一定没有左子树,所以采用第二种删除策略即可)
// 然后将当前结点赋值为最小值
} else if (node.left != null && node.right != null) {
// 进行一次删除,删除的是以node的右子树为根节点,值为min的这个结点
// 包含了结点只有左子树或右子树或都没有的情况
node.val = findMin(node.right).val;
node.right = delete(node.right, node.val);
} else {
node = node.left == null ? node.right : node.left;
}
return node;
}
// 返回当前子树中的值最小的那个结点
private TreeNode<E> findMin(TreeNode<E> node) {
if (node == null) {
return null;
}
while (node.left != null) {
node = node.left;
}
return node;
}
private TreeNode<E> findMax(TreeNode<E> node) {
if (node == null) {
return null;
}
while (node.right != null) {
node = node.right;
}
return node;
}
public boolean isEmpty() {
return root == null;
}
// 后序遍历二叉树的深度
public int depth() {
return depth(root);
}
private int depth(TreeNode<E> curr) {
if (curr == null) {
return 0;
// 空树深度为0,递归结束,开始返回
} else {
// 这种情况实际上包含了两种情况:一种是叶子结点,此时返回的是1;另一种是非叶子结点,返回的是较深子树的深度+1
// 综合起来就是每遇到叶子结点,深度就加1,得到子树的深度,最后加上根节点的深度1
int leftDepth = depth(curr.left);
int rightDepth = depth(curr.right);
return leftDepth > rightDepth ? (leftDepth + 1) : (rightDepth + 1);
}
}
/**
* 非递归求深度,采用层序遍历的方式
*
* @return
*/
public int depthNoRec() {
TreeNode<E> curr;
Deque<TreeNode<E>> queue = new ArrayDeque<>();
queue.add(root);
int depth = 0;
while (!queue.isEmpty()) {
int levelSize = queue.size();
// 一层进行遍历,queue的长度即为该层节点个数
for (int i = 0; i < levelSize; i++) {
curr = queue.poll();
if (curr.left != null) {
queue.add(curr.left);
}
if (curr.right != null) {
queue.add(curr.right);
}
}
depth++;
}
return depth;
}
// 二叉树的结点个数
public int size() {
return size(root);
}
private int size(TreeNode<E> subTree) {
if (subTree == null) {
return 0;
} else {
int leftSubTreeSize = size(subTree.left);
int rightSubTreeSize = size(subTree.right);
return leftSubTreeSize + rightSubTreeSize + 1;
}
}
public int sizeOfLevel(int k) {
return sizeOfLevel(root, k);
}
/**
* 第k层节点个数就是第k-1层的孩子数
* k==0时,返回1
*
* @param curr
* @param k
* @return
*/
private int sizeOfLevel(TreeNode<E> curr, int k) {
if (curr == null) {
throw new NullPointerException();
}
if (k < 0) {
throw new IllegalArgumentException();
}
if (k == 0) {
return 1;
} else {
return sizeOfLevel(curr.left, k - 1) + sizeOfLevel(curr.right, k - 1);
}
}
public TreeNode<E> parent(TreeNode<E> curr) {
if (curr == null) {
return null;
}
return parent(root, curr);
}
/**
* 先序遍历
*
* @param root
* @param curr
* @r
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
算法与数据结构涵盖了以下主要内容: 数据结构(Data Structures): 逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法: 算法设计:研究如何将解决问题的步骤形式化为一系列指令,使得计算机可以执行以求解问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法与数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。
资源推荐
资源详情
资源评论
收起资源包目录
常见的数据结构与算法,Java语言实现.zip (258个子文件)
.gitignore 260B
BinarySearchTree.java 48KB
MatrixGraph.java 39KB
MyString.java 15KB
AVLTree.java 13KB
Sort.java 11KB
Main.java 9KB
MyLinkedList.java 9KB
Test.java 9KB
LeetCode146.java 9KB
LRUCache.java 9KB
MyDoubleLinkedList.java 8KB
MaxSubSum.java 6KB
Tree.java 5KB
MyHashMap.java 5KB
MaxPriorityQueue.java 5KB
Test.java 5KB
BiThreadTree.java 5KB
LinkedListClone.java 5KB
LinkedListIntersect.java 4KB
MyArrayList.java 4KB
TrieTree.java 4KB
ArrayToMaxTree.java 4KB
PalindromeOfLinkedList.java 4KB
StringMatcher.java 3KB
Polynomial.java 3KB
REMatch.java 3KB
LeetCode52.java 3KB
LeetCode79.java 3KB
L1OPL2.java 3KB
LeetCode139.java 3KB
LeetCode13.java 3KB
LeetCode151.java 3KB
OrderedCircularLinkedListInsertion.java 3KB
LeetCode138.java 3KB
ExpressionTree.java 3KB
LeetCode236.java 3KB
LeetCode38.java 3KB
Offer32.java 3KB
LinkedListLoopStart.java 3KB
LeetCode8.java 3KB
LeetCode1846.java 3KB
LeetCode4.java 3KB
LinkedListKInverse.java 3KB
LeetCode17.java 3KB
LinkedListPartition.java 3KB
MoveOddToFront.java 3KB
TopK.java 3KB
LeetCode394.java 3KB
LeetCode297.java 3KB
RobotMove.java 3KB
LeetCode402.java 2KB
LeetCode527.java 2KB
MyStack.java 2KB
Exchange.java 2KB
MatrixPath.java 2KB
LeetCode148.java 2KB
LeetCode1283.java 2KB
FindMostOccurNumber.java 2KB
Permutation.java 2KB
BinarySearch.java 2KB
LeetCode15.java 2KB
Offer07.java 2KB
BinarySearch.java 2KB
HuffmanTree.java 2KB
LeetCode23.java 2KB
LeetCode1143.java 2KB
MaxGapBetweenAdjacentElement.java 2KB
SuccessorNodeOfBinaryTree.java 2KB
LeetCode2.java 2KB
TwoStackSort.java 2KB
LeetCode122.java 2KB
LinkedListMergeSort.java 2KB
LeetCode22.java 2KB
LeetCode98.java 2KB
LeetCode82.java 2KB
LeetCode141.java 2KB
MatrixPrintClockWise.java 2KB
MyQueue.java 2KB
FindLastK.java 2KB
HeapSort.java 2KB
LeetCode33.java 2KB
LeetCode253.java 2KB
MaxOfSlidingWindow.java 2KB
LeetCode191.java 2KB
FindMinOfCircularOrderedArray.java 2KB
UnOrderedLinkedListRemoveDuplicateNodes.java 2KB
LeetCode5.java 2KB
LeetCode347.java 2KB
LeetCode190.java 2KB
LeetCode125.java 2KB
QuickSort.java 2KB
LeetCode155.java 2KB
LeetCode54.java 2KB
Offer31.java 2KB
LeetCode56.java 2KB
LeetCode21.java 2KB
LeetCode350.java 2KB
LeetCode268.java 2KB
LinkedQueue.java 2KB
共 258 条
- 1
- 2
- 3
资源评论
极致人生-010
- 粉丝: 2912
- 资源: 2826
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 信呼OA系统2.1.7版源码
- 3122080306 邹子轩 实验报告二.docx
- 基于STM32 NUCLEO板设计彩色LED照明灯(纯cubeMX开发)(大赛作品,文档完整,可直接运行)
- 发那科工业机器人保养大全
- Sphere.h
- REMD固有时间尺度分解信号分量可视化(Matlab完整源码和数据)
- 嵌入式系统双单片机STC89C52+STC15W104多功能学习板电路图可扩展 适用于单片机初学者和教学
- 基于STM32蓝牙控制小车系统设计(硬件+源代码+论文)大赛作品
- XILINXFPGA源码基于Spartan3火龙刀系列FPGA开发板VGA测试例程
- Java聊天室的设计与实现【尚学堂·百战程序员】
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功