数组结构六:二分搜索树

if (e.compareTo(node.e) < 0)

node.left = add(node.left, e);

else if ((e.compareTo(node.e) > 0))

node.right = add(node.right, e);

return node;

}

/**

  • 向以node为根的二分搜索树中插入元素E,递归算法

  • 而对于递归算法来说,要看两部分:

  • 第一,递归终止的条件

  • 第二,递归组成的逻辑

*/

private void add1(Node node, E e) {

// 第一,递归终止的条件

// 但是如下代码过于臃肿

if (e.equals(node.e))

return;

else if (e.compareTo(node.e) < 0 && node.left == null) {

node.left = new Node(e);

size++;

return;

} else if (e.compareTo(node.e) > 0 && node.right == null) {

node.right = new Node(e);

size++;

return;

}

if (e.compareTo(node.e) < 0)

add(node.left, e);

else

add(node.right, e);

}

//看二分搜索树中是否包含元素e

public boolean contains(E e) {

return contains(root, e);

}

//看以node为根的二分搜索树中是否包含元素e,递归算法

private boolean contains(Node node, E e) {

if (node == null)

return false;

if (e.compareTo(node.e) == 0)

return true;

else if (e.compareTo(node.e) < 0)

return contains(node.left, e);

else // e.compareTo(node.e) > 0

return contains(node.right, e);

}

// 二分搜索树的前序遍历

public void preOrder() {

preOrder(root);

}

// 前序遍历以node为根的二分搜索树,递归算法

private void preOrder(Node node) {

if (node == null)

return;

System.out.println(node.e);

preOrder(node.left);

preOrder(node.right);

}

// 二分搜索树的非递归前序遍历

public void preOrderNR() {

Stack stack = new Stack<>();

stack.push(root);

while (!stack.isEmpty()) {

Node cur = stack.pop();

System.out.println(cur.e);

if (cur.right != null)

stack.push(cur.right);

if (cur.left != null)

stack.push(cur.left);

}

}

// 二分搜索树的中序遍历

public void inOrder() {

inOrder(root);

}

// 中序遍历以node为根的二分搜索树,递归算法

private void inOrder(Node node) {

if (node == null)

return;

inOrder(node.left);

System.out.println(node.e);

inOrder(node.right);

}

// 二分搜索树的后序遍历

public void postOrder() {

postOrder(root);

}

// 后序遍历以node为根的二分搜索树,递归算法

private void postOrder(Node node) {

if (node == null)

return;

postOrder(node.left);

postOrder(node.right);

System.out.println(node.e);

}

// 二分搜索树的层序遍历

public void levelOrder() {

Queue q = new LinkedList<>();

q.add(root);

while (!q.isEmpty()) {

Node cur = q.remove();

System.out.println(cur.e);

if (cur.left != null)

q.add(cur.left);

if (cur.right != null)

q.add(cur.right);

}

}

// 寻找二分搜索树的最小元素

public E minmum() {

if (size == 0)

throw new IllegalArgumentException(“BST is empty!”);

return minmum(root).e;

}

// 返回以node 为根的二分搜索树的最小值所在的点

private Node minmum(Node node) {

if (node.left == null)

return node;

return minmum(node.left);

}

// 寻找二分搜索树的最大元素

public E maximum() {

if (size == 0)

throw new IllegalArgumentException(“BST is empty!”);

return maximum(root).e;

}

// 返回以node 为根的二分搜索树的最大值所在的点

private Node maximum(Node node) {

if (node.right == null)

return node;

return minmum(node.right);

}

// 从二分搜索树中删除最小值所在节点,返回最小值

public E removeMin() {

E ret = minmum();

root = removeMin(root);

return ret;

}

// 删除掉以node为根的二分搜索树中的最小节点

// 返回删除节点后新的二分搜索树的根

private Node removeMin(Node node) {

if (node.left == null) {

Node rightNode = node.right;

node.right = null;

size–;

return rightNode;

}

node.left = removeMin(node.left);

return node;

}

// 从二分搜索树中删除最大值所在节点

public E removeMax() {

E ret = maximum();

root = removeMax(root);

return ret;

}

// 删除掉以node为根的二分搜索树中的最大节点

// 返回删除节点后新的二分搜索树的根

private Node removeMax(Node node) {

if (node.right == null) {

Node leftNode = node.left;

node.left = null;

size–;

return leftNode;

}

node.right = removeMax(node.right);

return node;

}

// 从二分搜索树中删除元素为e的节点

public void remove(E e) {

root = remove(root, e);

}

// 删除掉以node为根的二分搜索树中值为e的节点,递归算法

// 返回删除节点后新的二分搜索树的根

private Node remove(Node node, E e) {

if (node == null)

return null;

if (e.compareTo(node.e) < 0) {

node.left = remove(node.left, e);

return node;

} else if (e.compareTo(node.e) > 0) {

node.right = remove(node.right, e);

return node;

} else { // e == node.e 需要删除当前节点

// 待删除节点左子树为空的情况

if (node.left == null) {

Node rightNode = node.right;

node.right = null;

size–;

return rightNode;

}

// 待删除节点右子树为空的情况

if (node.right == null) {

Node leftNode = node.left;

node.left = null;

size–;

return leftNode;

}

// 待删除节点左右子树都不为空的情况

// 找到比待删除节点大的最小节点,即待删除节点右子树的最小节点

// 用这个节点顶替待删除节点的位置

Node successor = minmum(node.right);

successor.right = removeMin(node.right);

successor.left = node.left;

// 让node节点与二分搜索树脱离关系

node.left = node.right = null;

return successor;

}

}

@Override

public String toString() {

StringBuilder res = new StringBuilder();

generateBSTString(root, 0, res);

return res.toString();

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

总结

笔者之前工作是在金融公司可能并不是特别追求技术,而笔者又是喜欢追求技术的人,所以格格不入,只能把目标放在互联网大厂了。也希望大家都去敢于尝试和追逐自己的梦想!
BATJ大厂Android高频面试题

觉得有收获的记得点赞,关注+收藏哦!你们的点赞就是我的动力!

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

并且会持续更新!**

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

总结

笔者之前工作是在金融公司可能并不是特别追求技术,而笔者又是喜欢追求技术的人,所以格格不入,只能把目标放在互联网大厂了。也希望大家都去敢于尝试和追逐自己的梦想!
BATJ大厂Android高频面试题

[外链图片转存中…(img-J97E331S-1711991789756)]

[外链图片转存中…(img-YFJ0cSBM-1711991789756)]

[外链图片转存中…(img-5Y86Yf6b-1711991789756)]

[外链图片转存中…(img-yznoCsBs-1711991789756)]

觉得有收获的记得点赞,关注+收藏哦!你们的点赞就是我的动力!

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值