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移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
![](https://img-blog.csdnimg.cn/img_convert/9ad5a73121d892c95be876bb885c76a4.jpeg)
总结
笔者之前工作是在金融公司可能并不是特别追求技术,而笔者又是喜欢追求技术的人,所以格格不入,只能把目标放在互联网大厂了。也希望大家都去敢于尝试和追逐自己的梦想!
BATJ大厂Android高频面试题
觉得有收获的记得点赞,关注+收藏哦!你们的点赞就是我的动力!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
并且会持续更新!**
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
![](https://img-blog.csdnimg.cn/img_convert/9ad5a73121d892c95be876bb885c76a4.jpeg)
总结
笔者之前工作是在金融公司可能并不是特别追求技术,而笔者又是喜欢追求技术的人,所以格格不入,只能把目标放在互联网大厂了。也希望大家都去敢于尝试和追逐自己的梦想!
BATJ大厂Android高频面试题
[外链图片转存中…(img-J97E331S-1711991789756)]
[外链图片转存中…(img-YFJ0cSBM-1711991789756)]
[外链图片转存中…(img-5Y86Yf6b-1711991789756)]
[外链图片转存中…(img-yznoCsBs-1711991789756)]
觉得有收获的记得点赞,关注+收藏哦!你们的点赞就是我的动力!