gpt4 book ai didi

java - 如何在java中使红黑树泛型

转载 作者:行者123 更新时间:2023-12-03 12:29:25 24 4
gpt4 key购买 nike

我正在研究红黑树并编写了完整的工作代码,如下所示。我浏览了泛型教程,了解到通过单个类声明,可以指定一组相关方法。如何将它应用到我的红黑树算法中?在泛型案例中会发生什么?如果可能的话,你能帮我解决这个问题吗?这是完整的代码:

import java.util.Scanner;

public class RedBlackTree {

private final int RED = 0;
private final int BLACK = 1;


private class Node {

int key = -1, color = BLACK;
Node left = nil, right = nil, parent = nil;

Node(int key) {
this.key = key;
}
}

private final Node nil = new Node(-1);
private Node root = nil;

public void printTree(Node node)
{
if (node == nil) {
return;
}
printTree(node.left);
System.out.print(((node.color==RED)?"Color: Red ":"Color: Black ")+"Key: "+node.key+" Parent: "+node.parent.key+"\n");
printTree(node.right);
}

private Node findNode(Node findNode, Node node)
{
if (root == nil) {
return null;
}

if (findNode.key < node.key) {
if (node.left != nil) {
return findNode(findNode, node.left);
}
} else if (findNode.key > node.key) {
if (node.right != nil) {
return findNode(findNode, node.right);
}
} else if (findNode.key == node.key) {
return node;
}
return null;
}

private void insert(Node node)
{
Node temp = root;
if (root == nil) {
root = node;
node.color = BLACK;
node.parent = nil;
} else {
node.color = RED;
while (true) {
if (node.key < temp.key) {
if (temp.left == nil) {
temp.left = node;
node.parent = temp;
break;
} else {
temp = temp.left;
}
} else if (node.key >= temp.key) {
if (temp.right == nil) {
temp.right = node;
node.parent = temp;
break;
} else {
temp = temp.right;
}
}
}
fixTree(node);
}
}

private void fixTree(Node node)
{
while (node.parent.color == RED) {
Node uncle = nil;
if (node.parent == node.parent.parent.left) {
uncle = node.parent.parent.right;

if (uncle != nil && uncle.color == RED) {
node.parent.color = BLACK;
uncle.color = BLACK;
node.parent.parent.color = RED;
node = node.parent.parent;
continue;
}
if (node == node.parent.right) {
//Double rotation needed
node = node.parent;
rotateLeft(node);
}
node.parent.color = BLACK;
node.parent.parent.color = RED;
//if the "else if" code hasn't executed, this
//is a case where we only need a single rotation
rotateRight(node.parent.parent);
} else {
uncle = node.parent.parent.left;
if (uncle != nil && uncle.color == RED) {
node.parent.color = BLACK;
uncle.color = BLACK;
node.parent.parent.color = RED;
node = node.parent.parent;
continue;
}
if (node == node.parent.left) {
//Double rotation needed
node = node.parent;
rotateRight(node);
}
node.parent.color = BLACK;
node.parent.parent.color = RED;

rotateLeft(node.parent.parent);
}
}
root.color = BLACK;
}

void rotateLeft(Node node)
{
if (node.parent != nil) {
if (node == node.parent.left) {
node.parent.left = node.right;
} else {
node.parent.right = node.right;
}
node.right.parent = node.parent;
node.parent = node.right;
if (node.right.left != nil) {
node.right.left.parent = node;
}
node.right = node.right.left;
node.parent.left = node;
} else {//Need to rotate root
Node right = root.right;
root.right = right.left;
right.left.parent = root;
root.parent = right;
right.left = root;
right.parent = nil;
root = right;
}
}

void rotateRight(Node node)
{
if (node.parent != nil) {
if (node == node.parent.left) {
node.parent.left = node.left;
} else {
node.parent.right = node.left;
}

node.left.parent = node.parent;
node.parent = node.left;
if (node.left.right != nil) {
node.left.right.parent = node;
}
node.left = node.left.right;
node.parent.right = node;
} else {//Need to rotate root
Node left = root.left;
root.left = root.left.right;
left.right.parent = root;
root.parent = left;
left.right = root;
left.parent = nil;
root = left;
}
}




void replace(Node target, Node with){
if(target.parent == nil){
root = with;
}else if(target == target.parent.left){
target.parent.left = with;
}else
target.parent.right = with;
with.parent = target.parent;
}

boolean delete(Node z){
if((z = findNode(z, root))==null)
return false;
Node x;
Node y = z;
int y_original_color = y.color;

if(z.left == nil){
x = z.right;
replace(z, z.right);
}else if(z.right == nil){
x = z.left;
replace(z, z.left);
}else{
y = treeMinimum(z.right);
y_original_color = y.color;
x = y.right;
if(y.parent == z)
x.parent = y;
else{
replace(y, y.right);
y.right = z.right;
y.right.parent = y;
}
replace(z, y);
y.left = z.left;
y.left.parent = y;
y.color = z.color;
}
if(y_original_color==BLACK)
fixDelColor(x);
return true;
}

void fixDelColor(Node x){
while(x!=root && x.color == BLACK){
if(x == x.parent.left){
Node w = x.parent.right;
if(w.color == RED){
w.color = BLACK;
x.parent.color = RED;
rotateLeft(x.parent);
w = x.parent.right;
}
if(w.left.color == BLACK && w.right.color == BLACK){
w.color = RED;
x = x.parent;
continue;
}
else if(w.right.color == BLACK){
w.left.color = BLACK;
w.color = RED;
rotateRight(w);
w = x.parent.right;
}
if(w.right.color == RED){
w.color = x.parent.color;
x.parent.color = BLACK;
w.right.color = BLACK;
rotateLeft(x.parent);
x = root;
}
}else{
Node w = x.parent.left;
if(w.color == RED){
w.color = BLACK;
x.parent.color = RED;
rotateRight(x.parent);
w = x.parent.left;
}
if(w.right.color == BLACK && w.left.color == BLACK){
w.color = RED;
x = x.parent;
continue;
}
else if(w.left.color == BLACK){
w.right.color = BLACK;
w.color = RED;
rotateLeft(w);
w = x.parent.left;
}
if(w.left.color == RED){
w.color = x.parent.color;
x.parent.color = BLACK;
w.left.color = BLACK;
rotateRight(x.parent);
x = root;
}
}
}
x.color = BLACK;
}

Node treeMinimum(Node subTreeRoot)
{
while(subTreeRoot.left!=nil){
subTreeRoot = subTreeRoot.left;
}
return subTreeRoot;
}

public void consoleUI() {
Scanner scan = new Scanner(System.in);
while (true) {
System.out.println("\n1. Insert () method\n"
+ "2. ToString() method\n"
+ "3. Contains() method\n"
+ "4. Delete() method\n"
+ "5. Exit \n");
int choice = scan.nextInt();

int item;
Node node;
switch (choice) {
case 1:
item = scan.nextInt();
while (item != 001) {
node = new Node(item);
insert(node);
item = scan.nextInt();
}
printTree(root);
break;

case 2:
printTree(root);
break;

case 3:
item = scan.nextInt();
while (item != 001) {
node = new Node(item);
System.out.println((findNode(node, root) != null) ? "found" : "not found");
item = scan.nextInt();
}
break;

case 4:
item = scan.nextInt();
while (item != 001) {
node = new Node(item);
System.out.print("\nDeleting item " + item);
if (delete(node)) {
System.out.print(": deleted!");
} else {
System.out.print(": entered item does not exist!");
}
item = scan.nextInt();
}
System.out.println();
printTree(root);
break;

case 5:
return;

}
}
}
public static void main(String[] args) {
RedBlackTree redblacktree = new RedBlackTree();
redblacktree.consoleUI();
}
}

最佳答案

通用化的基本步骤:

  1. 类声明:

    class RedBlackTree<KeyType extends Comparable<KeyType>, ValueType>

    假设每个节点存储两个值 - 一个键,它确定在有序树中的位置,一个可为空的值,它不能。 ValueType是可选的,但它确实以树的形式提供了一个高效的 map 实现。(根据 4caSTLe 的评论:将 Comparable<KeyType> 替换为 Comparable<? super KeyType> 没有意义,因为不可能将非 KeyType 插入树中)

  2. 类实现(Node类):替换int key的两种情况与 KeyType key ;添加实例变量 ValueType val (选修的)。如果添加了 ValueType,Node 构造函数将变为:

    Node(KeyValue key, KeyValue val) {
    this.key = key;
    this.val = val;
    }
  3. 类用法(方法 consoleUI ),类型实例化 KeyTypeValueTypeNode期间声明,例如:

    Node<Integer, String> node;
    ...
    node = new Node(item, val);

    Node<Integer, Void> node;
    ...
    node = new Node(item, null);

* 结果 *

import java.util.Scanner;

public class RedBlackTree<KeyType extends Comparable<KeyType>, ValueType> {

private static final int RED = 0;
private static final int BLACK = 1;
private static final Node nil = new Node(-1); ******
private Node root = nil;

private class Node {
KeyType key;
ValueType val;
color = BLACK;
Node left = nil, right = nil, parent = nil;

Node(int key) {
this.key = key;
this.val = val;
}
}

// believe remaining code is unchanged (except for adding val param)
// ...
// ...

public void consoleUI() {
Scanner scan = new Scanner(System.in);
while (true) {
System.out.println("\n1. Insert () method\n"
+ "2. ToString() method\n"
+ "3. Contains() method\n"
+ "4. Delete() method\n"
+ "5. Exit \n");
int choice = scan.nextInt();

int item;
Node<Integer, Void> node;
switch (choice) {
case 1:
item = scan.nextInt();
while (item != 001) {
node = new Node(item, null);

etc

一般建议:将您的类分成 2 个。将树的用法隐藏在树类本身中是没有意义的。创建类调用 RedBlackTreeTest并移动consoleUImain进入其中。

关于java - 如何在java中使红黑树泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40603255/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com