Java中二叉树节点删除的问题
我想尝试并实现我自己的BST作为练习,但我在节点移除方面遇到了困难。我不明白为什么它在某些情况下不起作用。我从一本书中得到了这个算法,但当我用随机元素测试它时,有些情况下它不会删除元素,甚至会打乱它们的顺序,因此它们不再被排序。我做错了什么?有什么更好的方法来实现这一点 注意:方法中的所有println()语句仅用于调试目的Java中二叉树节点删除的问题,java,data-structures,binary-search-tree,Java,Data Structures,Binary Search Tree,我想尝试并实现我自己的BST作为练习,但我在节点移除方面遇到了困难。我不明白为什么它在某些情况下不起作用。我从一本书中得到了这个算法,但当我用随机元素测试它时,有些情况下它不会删除元素,甚至会打乱它们的顺序,因此它们不再被排序。我做错了什么?有什么更好的方法来实现这一点 注意:方法中的所有println()语句仅用于调试目的 class TreeNode<T extends Comparable<T>> { T data; TreeNode<T>
class TreeNode<T extends Comparable<T>> {
T data;
TreeNode<T> left;
TreeNode<T> right;
TreeNode<T> parent;
TreeNode(T data) {
this.data = data;
}
boolean hasBothChildren() {
return hasLeftChild() && hasRightChild();
}
boolean hasChildren() {
return hasLeftChild() || hasRightChild();
}
boolean hasLeftChild() {
return left != null;
}
boolean hasRightChild() {
return right != null;
}
boolean isLeftChild() {
return this.parent.left == this;
}
boolean isRightChild() {
return this.parent.right == this;
}
}
public class BinaryTreeSet<T extends Comparable<T>> {
private TreeNode<T> root;
private void makeRoot(T element) {
TreeNode<T> node = new TreeNode<T>(element);
root = node;
}
private TreeNode<T> find(T element) {
TreeNode<T> marker = root;
TreeNode<T> found = null;
while (found == null && marker != null) {
int comparator = (marker.data.compareTo(element));
if (comparator > 0)
marker = marker.left;
else if (comparator < 0)
marker = marker.right;
else
found = marker;
}
return found;
}
private TreeNode<T> max(TreeNode<T> root) {
TreeNode<T> currentMax = root;
while (currentMax.hasRightChild()) {
currentMax = currentMax.right;
}
return currentMax;
}
// returns the inorder predecessor of node
private TreeNode<T> predecessor(TreeNode<T> node) {
return max(node.left);
}
// removes a given node with 0 or 1 children
private void removeNode(TreeNode<T> node) {
if (!node.hasChildren()) {
System.out.println("node with no children");
if (node.isLeftChild())
node.parent.left = null;
else
node.parent.right = null;
}
else {
System.out.println("node with 1 child");
if (node.isRightChild()) {
if (node.hasLeftChild())
node.parent.right = node.left;
else if (node.hasRightChild())
node.parent.right = node.right;
}
else if (node.isLeftChild()) {
if (node.hasLeftChild())
node.parent.left = node.left;
else if (node.hasRightChild())
node.parent.left = node.right;
}
}
node = null;
}
public BinaryTreeSet() {
root = null;
}
public void addElement(T element) {
if (root == null)
makeRoot(element);
else {
TreeNode<T> marker = root;
TreeNode<T> node = new TreeNode<T>(element);
boolean done = false;
while(!done) {
int comparator = marker.data.compareTo(element);
if (comparator > 0) {
if (marker.hasLeftChild())
marker = marker.left;
else {
marker.left = node;
done = true;
}
}
else if (comparator < 0) {
if (marker.hasRightChild())
marker = marker.right;
else {
marker.right = node;
done = true;
}
}
else
return;
node.parent = marker;
}
}
}
public boolean contains(T element) {
boolean found = (find(element) == null)? false : true;
return found;
}
public boolean removeElement(T element) {
TreeNode<T> node = find(element);
if (node == null)
return false;
// removal of a node with no children
if (!node.hasChildren()) {
if (node.isLeftChild()) {
node.parent.left = null;
}
else if (node.isRightChild()) {
node.parent.right = null;
}
}
// removal of a node with both children
else if (node.hasBothChildren()) {
TreeNode<T> pred = predecessor(node);
T temp = pred.data;
pred.data = node.data;
node.data = temp;
removeNode(pred);
}
// removal of a node with only 1 child
else {
if (node.isRightChild()) {
if (node.hasLeftChild())
node.parent.right = node.left;
else if (node.hasRightChild())
node.parent.right = node.right;
}
else if (node.isLeftChild()) {
if (node.hasLeftChild())
node.parent.left = node.left;
else if (node.hasRightChild())
node.parent.left = node.right;
}
}
node = null;
System.out.println("item removed: " + !contains(element));
return true;
}
}
类树节点{
T数据;
左树突;
特雷诺德右翼;
树状体亲本;
树节点(T数据){
这个数据=数据;
}
布尔hasBothChildren(){
返回hasLeftChild()&&hasRightChild();
}
布尔hasChildren(){
返回hasLeftChild()| | hasRightChild();
}
布尔hasleeftchild(){
返回左!=null;
}
布尔hasRightChild(){
返回右侧!=null;
}
布尔值isLeftChild(){
返回this.parent.left==this;
}
布尔isRightChild(){
返回this.parent.right==this;
}
}
公共类二进制树集{
独活根;
私有void makeRoot(T元素){
TreeNode=新的TreeNode(元素);
根=节点;
}
私有树节点查找(T元素){
TreeNode标记=根;
TreeNode found=null;
while(found==null&&marker!=null){
int comparator=(marker.data.compareTo(element));
如果(比较器>0)
marker=marker.left;
否则如果(比较器<0)
marker=marker.right;
其他的
发现=标记;
}
发现退货;
}
私有树节点最大值(树节点根){
TreeNode currentMax=根;
while(currentMax.hasRightChild()){
currentMax=currentMax.right;
}
返回电流最大值;
}
//返回节点的顺序前置项
专用TreeNode前置节点(TreeNode节点){
返回最大值(节点左侧);
}
//删除具有0或1个子节点的给定节点
私有void removeNode(TreeNode节点){
如果(!node.hasChildren()){
System.out.println(“没有子节点的节点”);
if(node.isLeftChild())
node.parent.left=null;
其他的
node.parent.right=null;
}
否则{
System.out.println(“具有1个子节点的节点”);
if(node.isRightChild()){
if(node.hasleeftchild())
node.parent.right=node.left;
else if(node.hasRightChild())
node.parent.right=node.right;
}
else if(node.isLeftChild()){
if(node.hasleeftchild())
node.parent.left=node.left;
else if(node.hasRightChild())
node.parent.left=node.right;
}
}
node=null;
}
公共二进制树集(){
root=null;
}
公共无效附加元素(T元素){
if(root==null)
makeRoot(元素);
否则{
TreeNode标记=根;
TreeNode=新的TreeNode(元素);
布尔完成=假;
而(!完成){
int comparator=marker.data.compareTo(元素);
如果(比较器>0){
if(marker.hasleeftchild())
marker=marker.left;
否则{
marker.left=节点;
完成=正确;
}
}
否则如果(比较器<0){
if(marker.hasRightChild())
marker=marker.right;
否则{
marker.right=节点;
完成=正确;
}
}
其他的
返回;
node.parent=标记;
}
}
}
公共布尔包含(T元素){
布尔值find=(find(element)==null)?false:true;
发现退货;
}
公共布尔removeElement(T元素){
树节点=查找(元素);
if(node==null)
返回false;
//删除没有子节点的节点
如果(!node.hasChildren()){
if(node.isLeftChild()){
node.parent.left=null;
}
else if(node.isRightChild()){
node.parent.right=null;
}
}
//删除包含两个子节点的节点
else if(node.hasBothChildren()){
TreeNode pred=前置节点(node);
温度=预测数据;
pred.data=node.data;
node.data=temp;
removeNode(pred);
}
//删除只有一个子节点的节点
否则{
if(node.isRightChild()){
if(node.hasleeftchild())
node.parent.right=node.left;
else if(node.hasRightChild())
node.parent.right=node.right;
}
else if(node.isLeftChild()){
if(node.hasleeftchild())
node.parent.left=node.left;
else if(node.hasRightChild())
node.parent.left=node.right;
}
}
node=null;
System.out.println(“删除项:+!包含(元素));
返回true;
}
}
找到了让我头疼的bug。问题出现在我删除具有0或1个子节点的节点的情况下。我没有更新它们的父节点,所以这会把代码搞乱。所以,而不是比如说,
if (node.hasLeftChild())
node.parent.right = node.left;
我应该写信的
if (node.hasLeftChild()) {
node.parent.left = node.left;
node.left.parent = node.parent;
}
在任何情况下,我都会和一个独生子女打交道。另外,我忘记了更新根,因为根是
boolean rootOncePrint = true;
public void printAllTree(TreeNode<T> startNode){
if(startNode == null) return;
//System.out.println(startNode.data);
if(rootOncePrint){
System.out.println("Root : " + startNode.data);
rootOncePrint = false;
}
if(startNode.hasChildren()){
if(startNode.hasLeftChild()){
printAllTree(startNode.left);
}
if(startNode.hasRightChild()){
printAllTree(startNode.right);
}
}
if(startNode != root){
T parentValue = startNode.parent.data;
T dataValue = startNode.data;
System.out.println(startNode.data + ((parentValue.compareTo(dataValue) > 0)?"L":"R"));
}
}