上次对BinarySearchTree的总结不太常用,因为很多时候题目以及要求TreeNode的格式了,不能有parent节点,而且parent节点也会浪费一个空间,因而这里重新再写一遍更加标准的BST结构及其相应的操作。
class Node
{
//一个标准的Node
public int val;
public Node lnode;
public Node rnode;
public Node(int val)
{
this.val = val;
}
}
下面是BST类,分别有增加节点,查找节点,中序遍历所有节点,删除某个节点等方法
class BinarySearchTree
{
public Node rootNode;
//增加节点
public void AddNodeToTree(int val)
{
if(rootNode == null)
{
rootNode = new Node(val);
return;
}
Node current = rootNode;
while (true)
{
if (val < current.val)
{
if (current.lnode == null)
{
current.lnode = new Node(val);
break;
}
current = current.lnode;
}
else
{
if (current.rnode == null)
{
current.rnode = new Node(val);
break;
}
current = current.rnode;
}
}
}
//查找节点
public bool FindNode(Node node,int val)
{
if(node == null)
{
return false;
}
if(node.val == val)
{
return true;
}
if(node.val > val)
{
return FindNode(node.lnode, val);
}
else
{
return FindNode(node.rnode, val);
}
}
//中序输出所有节点
public void Inorder(Node theroot)
{
if (theroot != null)
{
Inorder(theroot.lnode);
WriteLine(theroot.val);
Inorder(theroot.rnode);
}
}
//删除某个节点
public bool DeleteNode(Node theRoot, int deleteVal)
{
//先找到该节点
if(rootNode == null)
{
return false;
}
Node current = theRoot;
Node parent = theRoot;
bool isLeftChild = false;
while(current.val != deleteVal)
{
parent = current;
if(current.val < deleteVal)
{
current = current.rnode;
isLeftChild = false;
}
else
{
current = current.lnode;
isLeftChild = true;
}
if (current == null)
{
return false;
}
}
//退出循环时,current就是待删除的节点,parent是待删节点的父节点
//下面分三种情况,进行分类处理
//待删除的是叶子节点
if(current.lnode == null && current.rnode == null)
{
if (isLeftChild) parent.lnode = null;
else
{
parent.rnode = null;
}
}
else if(current.lnode != null && current.rnode == null)
{
//左右左子树没有右子树
if (isLeftChild)
{
parent.lnode = parent.lnode.lnode;
}
else
{
parent.rnode = parent.rnode.lnode;
}
}
else if(current.lnode == null && current.rnode != null)
{
//只有右子树没有左子树
if (isLeftChild)
{
parent.lnode = parent.lnode.rnode;
}
else
{
parent.rnode = parent.rnode.rnode;
}
}
else
{
//待删除的节点左右子树都有
Node replace = current.rnode;
while(replace.lnode != null)
{
replace = replace.rnode.lnode;
}
DeleteNode(rootNode, replace.val);
current.val = replace.val;
}
return true;
}
}
注意在删除节点那里涉及树的重构因而分为三种不同的方法。注意在判断current==null的情况需要在current等于其左右节点之后判断。
需要多练习才能熟练操作。