找个实习不容易,今天去面试,面试官先问了我JVM的很底层东西,因为看过深入了解JVM这本书答得很顺,结果面试官来劲了,先说 你给我写一个 平衡二叉查找树删除节点的代码,我故意念到 “平衡二叉查找树”,面试官见我认怂说那你写二叉查找吧,我只知道删除节点有三种情况,分为删除节点是否是叶子节点,有一个子节点,有两个子节点,但是当场手写代码还是没有写出来。回来在参考书的帮助下手写了一遍。哎,基础不行。
package graphic;
public class BinarySearchTree {
private TreeNode root = null;
/**
* 中序遍历
* @param root
*/
public void inOrder_tree_walk(){
inOrder(root);
}
private void inOrder(TreeNode root){
if(root==null){return;}
inOrder(root.left);
System.out.print(root+" ");
inOrder(root.right);
}
/**
* 返回指向key的节点指针
* @param root
* @param key
* @return
*/
public TreeNode treeSearch(int key){
if(root==null)return null;
TreeNode cur = root;
while(cur!=null && cur.value!=key){
if(cur.value >key){
cur = cur.left;
}else{
cur = cur.right;
}
}
return cur;
}
/**
* 返回包含最小key的节点指针
*/
public TreeNode treeMinimum(TreeNode root){
if(root==null)return null;
TreeNode cur = root;
while(cur.left!=null){
cur = cur.left;
}
return cur;
}
/**
* 返回包含最大key的节点指针
* @param root
* @return
*/
public TreeNode treeMaximum(TreeNode root){
if(root==null)return null;
TreeNode cur = root;
while(cur.right!=null){
cur = cur.right;
}
return cur;
}
/**
* 返回node 节点的后继节点
* @param root
* @param node
* @return
*/
public TreeNode treeSuccessor(TreeNode node){
//rigth branch is not null
if(node.right!=null)return treeMinimum(node.right);
//if the right branch is null
TreeNode cur = node.parent;
while(cur!=null && node == cur.right){
node = cur;
cur = cur.parent;
}
return cur;
}
/**
* 返回node 节点的前继节点
* @param root
* @param node
* @return
*/
public TreeNode treePredecessor(TreeNode node){
if(root.left!=null) return treeMaximum(root.left);
//the left branch is null
TreeNode cur = node.parent;
while(cur!=null && node==cur.left){
node = cur;
cur = cur.parent;
}
return cur;
}
/**
* 插入新节点
* @param root
* @param insert
*/
public void treeInsert(TreeNode insert){
if(root==null){
root = insert;
return ;
}
TreeNode cur = root;
TreeNode parent =null;
while(cur!=null){
parent = cur;
if(insert.value >=cur.value){cur = cur.right;}
else{cur = cur.left;}
}
if(insert.value >=parent.value){
parent.right = insert;
insert.parent = parent;
}else{parent.left = insert;insert.parent = parent;}
}
/**
* 删除目标节点
* @param root
* @param target
*/
public void delete(TreeNode target){
//find the node need to be deleted
TreeNode delNode;
//只有一个孩子或者是叶子节点
if(target.left==null || target.right==null){
delNode = target;
}else{
//如果有两个孩子就找到后继节点作为删除的节点
delNode = treeSuccessor(target);
}
//对于所有情况,要删除的节点最多只有一个孩子
//这个时候需要找到删除节点的孩子节点和父亲节点,并把父亲节点指向孩子节点,
//孩子节点的指针也指回新的父亲节点
TreeNode child;
if(delNode.left ==null){
child = delNode.right;
}else{child = delNode.left;}
TreeNode parent = delNode.parent;
if(parent.left == delNode){
parent.left = child;
}else{
parent.right = child;
}
if(child!=null){
child.parent = parent;
}
//delete the successor
if(delNode!=target){
target.value = delNode.value;
}
freeNode(delNode);
}
/**
* 删除包含key的第一个节点
* @param root
* @param key
*/
public void treeDelete(int key){
TreeNode searched = treeSearch(key);
delete(searched);
}
private void freeNode(TreeNode node){
node.parent =null;
node.left = null;
node.right = null;
}
private void addNode(TreeNode node){
treeInsert(node);
}
private class TreeNode{
TreeNode parent = null;
TreeNode left = null;
TreeNode right = null;
int value = 0;
@Override
public String toString() {
return value+"";
}
public TreeNode(int value) {
this.value = value;
}
}
public static void main(String[] args) {
BinarySearchTree tree = new BinarySearchTree();
TreeNode node = tree.new TreeNode(15);
tree.addNode(node);
node = tree.new TreeNode(6);
tree.addNode(node);
node = tree.new TreeNode(18);
tree.addNode(node);
node = tree.new TreeNode(3);
tree.addNode(node);
node = tree.new TreeNode(7);
tree.addNode(node);
node = tree.new TreeNode(17);
tree.addNode(node);
node = tree.new TreeNode(20);
tree.addNode(node);
node = tree.new TreeNode(2);
tree.addNode(node);
node = tree.new TreeNode(4);
tree.addNode(node);
node = tree.new TreeNode(13);
TreeNode node13= node;
tree.addNode(node);
node = tree.new TreeNode(9);
tree.addNode(node);
tree.inOrder_tree_walk();
System.out.println();
System.out.println(tree.treeSearch(15).parent);
System.out.println(tree.treeSuccessor(node13));
tree.treeDelete(6);
tree.inOrder_tree_walk();
}
}
相关推荐
本人手写的一款js树形控件,附带图片,代码简洁,注释齐全,可读性高,易于维护,方便移植,结构清晰,思路明了,界面美观,同时支持异步加载,对浏览器的兼容行强,你还可以根据自己的需要扩展功能,可大量应用于...
57.理论讲解:布隆过滤器.mp4 56.面试题:设计和实现一个LRU Cache缓存机制.mp4 55.理论讲解: LRU Cache.mp4 54.面试题:岛屿的个数&朋友圈(下).mp4 53....面试题:二叉树&二叉搜索树的最近公共祖先.mp4
前端面试题,小米、快手、百度手写代码实现,算法、函数实现、功能实现等以及常见面试手写代码实现
这是我面试了十三家所总结的手写代码题,希望能帮助您!
「2021」高频前端面试题汇总之手写代码篇.pdf
面试必备JS函数工具库手写.docx
二叉树源代码,纯手写好理解
面试嵌入式工程师常见的手写C语言函数,全部摘录与Rtthread内核源码进行少量修改
能在规定时间内写出功能健全、思路清晰、格式规整的代码,这是前端工程师的必备技能,所以面试时必考手写代码。本章将通过多个面试题,讲解前端常考的写代码问题,并总结出高质量代码的关键点。 ## 为何要考察 ...
MNIST手写字识别 ReLU激活函数 规则化 识别率最高可达到97.5
原生js结合jquery手写树形插件,详解编码思路,具体可使用示例,下载即可使用
自己手写代码实现卷积操作,展示不同卷积核的卷积效果。内附jupyter原文件
场论与复变函数_67_西电(梁昌洪)-手写课件,很有参考价值!希望对从事AI研发的同行有所帮助!!
关于Ajax的常见面试题 1,Ajax和javascript的区别? javascript是一种在浏览器端执行的脚本语言,Ajax是一种创建交互式网页应用的开发技术 ,它是利用了一系列相关的技术其中就包括javascript。 Javascript是由...
BP神经网络实现手写数字输入识别python 代码可以在下面链接中下载: https://gitee.com/cloud_maple/python_machine_learning.git 训练集和测试集都可以在下面链接中下载: 链接:...
支持动态生成树,区分叶子节点和根节点的点击方式,纯JS+JQ编写,代码易懂,支持修改。
JS Tree树形菜单,确实是够经典的WEB版树形菜单特效,带有节点连接线的树状折叠菜单,点击的时候会展开子菜单,适合用于WEB版的信息管理系统、CMS后台系统中,你喜欢的话,你可以用在任意你想要的地方。
面试的时候我们经常会问别人是理解什么是节流和防抖,严格的可能要求你写出节流和防抖函数,这里我们抛开loadsh工具库手写节流和防抖 1.节流函数throttle // 节流方案1,每delay的时间执行一次,通过开关控制 ...
本文提 出一 种基 于决策树算法的手写数字识别方法,该 方法通过提 取基 于密度的特征 ,通过训 练得到 一 个决策树分类模型 ,进而进行手写数字的识别。实验证明该方法能够快速有效的进行手写数字的识别。
Gbase 8s内置函数之字符串函数