- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在我的 AVL 树实现中遇到了一些问题。所有旋转和添加的代码似乎都是正确的,我空运行程序以彻底检查它是否在逻辑上正确运行。我的树遍历(按顺序)似乎有问题,因为它只输出假定的 100 中的几个整数。此外,无论我输入什么,搜索总是失败。我似乎无法理解发生了什么,但我怀疑它与一些空指针有关。下面是 AVL 树的代码,我想知道 AddNode 方法或旋转方法中是否有任何不正确的代码,但它们似乎没问题。这些类是节点类、AVL 类和主类 AVL 树类.
节点类
private int data;
private Node left;
private Node right;
private int height;
public Node(int m) {
data = m;
left = null;
right = null;
height = 0;
}
public void setToleft(Node newleft) {
left = newleft;
}
public Node getleftNode() {
return left;
}
public void setToright(Node newright) {
right = newright;
}
public Node getrightNode() {
return right;
}
public int getData() {
return data;
}
public int getHeight(){
return height;
}
public void setHeight(int height){
this.height = height;
}
AVL类
public Node root;
public AVL(int root) {
this.root = new Node(root); // since root presently has no left or right children, height is currently 0
}
public int Height(Node n) {
if (n == null) { //basis step
return -1;
} else { //add one for every path
if (n.getleftNode() == null && n.getrightNode() == null) {
return 0;
}
return 1 + Math.max(Height(n.getleftNode()), Height(n.getrightNode()));
}
}
public void add(int data) {
addNode(data, root);
root.setHeight(Math.max(Height(root.getleftNode()), Height(root.getrightNode())) + 1);
}
public void addNode(int data, Node n) {
if (data < n.getData()) {
if (n.getleftNode() == null) {
n.setToleft(new Node(data));
} else {
addNode(data, n.getleftNode());
}
n.setHeight(Math.max(Height(n.getleftNode()), Height(n.getrightNode())) + 1);
if ((Height(n.getleftNode()) + 1) - (Height(n.getrightNode()) + 1) == Math.abs(2)) {
if (data < n.getleftNode().getData()) {
n = LLRotation(n);
} else {
n = LRRotation(n);
}
}
} else if (data >= n.getData()) { //>= also caters for duplicates and inserts them infront of same value
if (n.getrightNode() == null) {
n.setToright(new Node(data));
} else {
addNode(data, n.getrightNode());
}
n.setHeight(Math.max(Height(n.getleftNode()), Height(n.getrightNode())) + 1);
if ((Height(n.getrightNode()) + 1) - (Height(n.getleftNode()) + 1) == Math.abs(2)) {
if (data >= n.getrightNode().getData()) {
n = RRRotation(n);
} else {
n = RLRotation(n);
}
}
}
}
public Node LLRotation(Node n) { //single
Node n1 = n.getleftNode();
n.setToleft(n1.getrightNode());
n1.setToright(n);
n.setHeight(Math.max(Height(n.getleftNode()), Height(n.getrightNode())) + 1);
n1.setHeight(Math.max(Height(n1.getleftNode()), Height(n)) + 1);
//compares heights of left and right subtrees and gets max
//the above source code is of course vital since the node height must be resetted after rotations
//adding 1 at the end of the last two code lines is important since
//initially the height is only calculated from subtrees onwards
//same for single right rotation below
return n1;
}
public Node RRRotation(Node n) { //single
Node n1 = n.getrightNode();
n.setToright(n1.getleftNode());
n1.setToleft(n);
n.setHeight(Math.max(Height(n.getleftNode()), Height(n.getrightNode())) + 1);
n1.setHeight(Math.max(Height(n1.getrightNode()), Height(n)) + 1);
return n1;
}
public Node LRRotation(Node n) { //double
n.setToleft(RRRotation(n.getleftNode()));
return LLRotation(n);
}
public Node RLRotation(Node n) { //double
n.setToright(LLRotation(n.getrightNode()));
return RRRotation(n);
}
public void inOrderTraversal(Node n) {
if (n != null) {
inOrderTraversal(n.getleftNode()); //recursive call to the left subtree
System.out.println(n.getData()); //line which makes the actual node to display its data
inOrderTraversal(n.getrightNode()); //recursive call to the right subtree
}
}
public void traverse() {
inOrderTraversal(root); // can be called in main class to automatically traverse tree from its root
}
public int search(int x) {
try {
if (x == root.getData()) { //basis step
System.out.println("Item found!");
return x;
}
if (x < root.getData()) {
root = root.getleftNode();
return search(x);//recursive call
} else {
root = root.getrightNode();
return search(x);//recursive call
}
} catch (NullPointerException e) {
System.out.println ("Search failed!");
return 0;
}
}
主类
public static void main(String[] args) throws IOException {
Scanner s = new Scanner(System.in);
AVL tree = null;
int choice = 0;
System.out.println("AVL TREE");
System.out.println("\n Choose an option from the menu: ");
System.out.println("\n\t 1.) Create file of 100 integers");
System.out.println("\n\t 2.) Create the tree");
System.out.println("\n\t 3.) In-Order traverse and show tree");
System.out.println("\n\t 4.) Search for integer");
System.out.println("\n\t 5.) Quit");
while (choice != 5) {
System.out.print("\nChoice: ");
choice = s.nextInt();
switch (choice) {
case 1:
createFile();
break;
case 2:
try {
FileReader readto = new FileReader("Integers.txt");
BufferedReader br = new BufferedReader(readto);
String line = br.readLine(); //reads text at start of file
line = br.readLine(); // skipping empty lines
line = br.readLine();
line = br.readLine();
int root = Integer.parseInt(line); //extracts first integer from the line
System.out.println("Root: " + root);
tree = new AVL(root);
int x = 0;
while (x != 99) {
try {
line = br.readLine();
int next = Integer.parseInt(line);
tree.add(next);
System.out.println(next);
x++;
} catch (NumberFormatException e) {
};
}
System.out.println("Tree successfully populated!");
} catch (FileNotFoundException e) {
System.out.println("ERROR: File not found!");
}
break;
case 3:
System.out.println("In-Order traversel executed. The now balanced tree shall now be printed in");
System.out.println("ascending order and also the left and right children of each node shall be printed.\n");
System.out.println("Traversal: ");
tree.traverse();
break;
case 4:
System.out.print("Please enter the integer to be searched: ");
int x = s.nextInt();
System.out.println(tree.search(x));
break;
case 5:
System.exit(0);
break;
default:
System.out.println("ERROR: Choice out of bounds!");
}
}
}
static void createFile() throws IOException {
Random r = new Random();
File intfile = new File("Integers.txt");
FileWriter writeto = new FileWriter("Integers.txt");
BufferedWriter bw = new BufferedWriter(writeto);
if (!(intfile.exists())) {
System.out.println("ERROR: File not found!");
} else {
bw.write("The following integers are randomly generated");
bw.newLine();
bw.write("and will be used to construct the AVL tree:");
bw.newLine();
bw.newLine();
int x;
System.out.println("The following random numbers shall be used to build the AVL tree: \n");
for (int i = 0; i < 100; i++) {
x = r.nextInt(100) + 1;
bw.write(String.valueOf(x));
bw.newLine();
System.out.println(x);
}
bw.close();
}
}
遍历的输出如下:
遍历:4453545477
假设输入了 100 个整数,其中有这些。但是遍历的输出只是这样。
搜索的输出是这样的:选择:4请输入要查找的整数:44找到元素!44
选择:4请输入要查找的整数:100搜索失败!0
100 和 44 都是添加到树中的整数,但是找到了 44 而没有找到 100..我不明白..
任何人都可以指导我找到解决方案......?
提前致谢:)
最佳答案
嗯,首先是显而易见的事情......在你的 search
方法中,你滥用了 root
变量,它保存着你的树的根,将它设置为新的值作为您的搜索 yield 。因此,在第一次搜索之后,root
指向搜索中遍历的最后一个节点,不再指向树的根节点。从那时起,所有后续搜索都不太可能找到任何东西。
由于您的搜索是递归的,请尝试将要搜索的节点作为参数传递:
int search(Node node, int key) {
if (node == null) {
return 0; // missing from tree
} else if (key < node.getData()) {
return search(node.getLeft(), key);
} else if (key > node.getData()) {
return search(node.getRight(), key);
} else {
return node.getData(); // found it
}
}
(已编辑 以解决评论)您可能必须像使用 add
/addNode
方法对一样公开此方法,使用公开可用的包装器和内部实现:
public int search(int key) {
return searchNode(root, key);
}
private int searchNode(Node node, int key) {
// Perform the recursive search, as above
}
还有其他与您的add
/addNode
方法相关的问题。也许我只是忽略了它,但是如果需要旋转的话,你不会在任何地方调整树的根节点。这实际上会导致您的树失去平衡,随着时间的推移失去 AVL 属性。
关于java - AVL树遍历,搜索问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8552891/
关于 B 树与 B+ 树,网上有一个比较经典的问题:为什么 MongoDb 使用 B 树,而 MySQL 索引使用 B+ 树? 但实际上 MongoDb 真的用的是 B 树吗?
如何将 R* Tree 实现为持久(基于磁盘)树?保存 R* 树索引或保存叶值的文件的体系结构是什么? 注意:此外,如何在这种持久性 R* 树中执行插入、更新和删除操作? 注意事项二:我已经实现了一个
目前,我正在努力用 Java 表示我用 SML 编写的 AST 树,这样我就可以随时用 Java 遍历它。 我想知道是否应该在 Java 中创建一个 Node 类,其中包含我想要表示的数据,以及一个数
我之前用过这个库http://www.cs.umd.edu/~mount/ANN/ .但是,它们不提供范围查询实现。我猜是否有一个 C++ 范围查询实现(圆形或矩形),用于查询二维数据。 谢谢。 最佳
在进一步分析为什么MySQL数据库索引选择使用B+树之前,我相信很多小伙伴对数据结构中的树还是有些许模糊的,因此我们由浅入深一步步探讨树的演进过程,在一步步引出B树以及为什么MySQL数据库索引选择
操作系统的那棵“树” 今天从一颗 开始,我们看看如何从小树苗长成一颗苍天大树。 运转CPU CPU运转起来很简单,就是不断的从内存取值执行。 CPU没有好好运转 IO是个耗费时间的活,如果CPU在取值
我想为海洋生物学类(class)制作一个简单的系统发育树作为教育示例。我有一个具有分类等级的物种列表: Group <- c("Benthos","Benthos","Benthos","Be
我从这段代码中删除节点时遇到问题,如果我插入数字 12 并尝试删除它,它不会删除它,我尝试调试,似乎当它尝试删除时,它出错了树的。但是,如果我尝试删除它已经插入主节点的节点,它将删除它,或者我插入数字
B+ 树的叶节点链接在一起。将 B+ 树的指针结构视为有向图,它不是循环的。但是忽略指针的方向并将其视为链接在一起的无向叶节点会在图中创建循环。 在 Haskell 中,如何将叶子构造为父内部节点的子
我在 GWT 中使用树控件。我有一个自定义小部件,我将其添加为 TreeItem: Tree testTree = new Tree(); testTree.addItem(myWidget); 我想
它有点像混合树/链表结构。这是我定义结构的方式 struct node { nodeP sibling; nodeP child; nodeP parent; char
我编写了使用队列遍历树的代码,但是下面的出队函数生成错误,head = p->next 是否有问题?我不明白为什么这部分是错误的。 void Levelorder(void) { node *tmp,
例如,我想解析以下数组: var array1 = ["a.b.c.d", "a.e.f.g", "a.h", "a.i.j", "a.b.k"] 进入: var json1 = { "nod
问题 -> 给定一棵二叉树和一个和,确定该树是否具有从根到叶的路径,使得沿路径的所有值相加等于给定的和。 我的解决方案 -> public class Solution { public bo
我有一个创建 java 树的任务,它包含三列:运动名称、运动类别中的运动计数和上次更新。类似的东西显示在下面的图像上: 如您所见,有 4 种运动:水上运动、球类运动、跳伞运动和舞蹈运动。当我展开 sk
我想在 H2 数据库中实现 B+ Tree,但我想知道,B+ Tree 功能在 H2 数据库中可用吗? 最佳答案 H2 已经使用了 B+ 树(PageBtree 类)。 关于mysql - H2数据库
假设我们有 5 个字符串数组: String[] array1 = {"hello", "i", "cat"}; String[] array2 = {"hello", "i", "am"}; Str
我正在处理树。每个节点都有带有 Tree * 值的对象。我读取的数据如下所示: 1 2 2 ... 这意味着,将 1 作为 0 的子节点,将 2 作为 1 的子节点,将 3 作为 o 2 的子节点。在
我正在寻找一个好的 JavaScript 树/树网格包。现在——在你回答之前: 它需要能够在大量节点上正常运行。可能有 1,000 个兄弟节点。它需要能够在 2 或 3 秒内绘制到 1,000 个节点
下面的代码块究竟是如何工作的?更具体地说,程序如何知道返回哪个选项? return ancestor (node1->left(), node2) || ancestor
我是一名优秀的程序员,十分优秀!