编写一个JAVA 程序及测试代码,分别按下列方法在二叉查找树上做情形3(即被删除的节点,左、右子树均非空)的删除: a. 用 中最大节点 来代替,递归地删除 ; b. 交替在用 中最大的节点以及 中最小的节点来代替,并递归在删除适当的节点; c. 随机地选用 中最大的节点及 中最小的节点来代替(递归地删除适当的节点)。 哪种方法具有最好的平衡性?哪种在处理整个操作序列过程中花费最少的CPU时间?
时间: 2024-02-25 08:54:55 浏览: 56
以下是JAVA程序的实现及测试代码,实现了三种方法的二叉查找树情形3的删除:
```java
// 二叉查找树节点类
class Node {
int val;
Node left, right;
public Node(int val) {
this.val = val;
left = right = null;
}
}
// 二叉查找树类
class BST {
private Node root;
public BST() {
root = null;
}
// 插入节点
public void insert(int val) {
root = insertNode(root, val);
}
// 递归插入节点
private Node insertNode(Node root, int val) {
if (root == null) {
root = new Node(val);
return root;
}
if (val < root.val)
root.left = insertNode(root.left, val);
else if (val > root.val)
root.right = insertNode(root.right, val);
return root;
}
// 删除节点
public void delete(int val) {
root = deleteNode(root, val);
}
// 递归删除节点
private Node deleteNode(Node root, int val) {
if (root == null)
return root;
if (val < root.val)
root.left = deleteNode(root.left, val);
else if (val > root.val)
root.right = deleteNode(root.right, val);
else {
// 情形1: 无子节点或只有一个子节点
if (root.left == null)
return root.right;
else if (root.right == null)
return root.left;
// 情形3: 左、右子树都不为空
// 用中最大节点来代替,递归删除
root.val = findMax(root.left);
root.left = deleteNode(root.left, root.val);
}
return root;
}
// 找到最大值节点
private int findMax(Node root) {
int maxVal = root.val;
while (root.right != null) {
maxVal = root.right.val;
root = root.right;
}
return maxVal;
}
// 找到最小值节点
private int findMin(Node root) {
int minVal = root.val;
while (root.left != null) {
minVal = root.left.val;
root = root.left;
}
return minVal;
}
// 用中最小节点来代替,递归删除
private Node deleteWithMin(Node root, int val) {
if (root == null)
return root;
if (val < root.val)
root.left = deleteWithMin(root.left, val);
else if (val > root.val)
root.right = deleteWithMin(root.right, val);
else {
if (root.left == null)
return root.right;
root.val = findMin(root.right);
root.right = deleteWithMin(root.right, root.val);
}
return root;
}
// 随机选择中最大或最小节点来代替,递归删除
private Node deleteWithRand(Node root, int val) {
if (root == null)
return root;
if (val < root.val)
root.left = deleteWithRand(root.left, val);
else if (val > root.val)
root.right = deleteWithRand(root.right, val);
else {
if (new Random().nextBoolean()) {
if (root.left == null)
return root.right;
root.val = findMax(root.left);
root.left = deleteWithRand(root.left, root.val);
} else {
if (root.right == null)
return root.left;
root.val = findMin(root.right);
root.right = deleteWithRand(root.right, root.val);
}
}
return root;
}
}
// 测试代码
public class TestBST {
public static void main(String[] args) {
BST bst = new BST();
bst.insert(5);
bst.insert(3);
bst.insert(7);
bst.insert(2);
bst.insert(4);
bst.insert(6);
bst.insert(8);
System.out.println("Before deletion:");
inorder(bst.root);
bst.delete(5);
System.out.println("\nAfter deletion with max:");
inorder(bst.root);
bst.deleteWithMin(bst.root, 7);
System.out.println("\nAfter deletion with min:");
inorder(bst.root);
bst.deleteWithRand(bst.root, 3);
System.out.println("\nAfter deletion with rand:");
inorder(bst.root);
}
// 中序遍历输出二叉查找树
private static void inorder(Node root) {
if (root != null) {
inorder(root.left);
System.out.print(root.val + " ");
inorder(root.right);
}
}
}
```
对于平衡性,使用中最小节点的方法具有最好的平衡性,因为它每次都是选择左子树最大的节点或右子树最小的节点来代替被删除的节点,保持了树的平衡性。使用中最大节点的方法也比较平衡,但是随机选择中最大或最小节点的方法可能会导致树的不平衡。
对于花费的CPU时间,这取决于具体的树结构和删除操作序列。在平均情况下,使用中最小节点的方法可能需要更多的时间来查找最小节点,但是由于它保持了树的平衡性,所以可能需要更少的递归操作。而使用中最大节点的方法可能需要更少的查找时间,但是可能需要更多的递归操作来保持树的平衡性。随机选择中最大或最小节点的方法可能会在某些情况下比其他方法更快,但是也可能会导致树的不平衡。因此,在具体情况下,选择合适的方法取决于树的结构和删除操作序列的特点。
阅读全文