I have 1000 numbers and I make a binary tree and sort the tree. It prints 0 to 100 and the other 899 numbers are duplicates. How can I keep track of the frequency of each number. Like for example the number 28 appears 9 times. Keeping a count somehow. I've been working with one method but Idk if it's close or not. I'll post that method at the end.
public class bigTree {
int data;
int frequency;
bigTree Left, Right;
public bigTree makeTree(int x) {
bigTree p;
p = new bigTree();
p.data = x;
p.Left = null;
p.Right = null;
return p;
}
public void setLeft(bigTree t, int x) {
if (t.Left != null) {
// setLeft(t.Left, x);
System.out.println("Error");
}
else {
t.Left = makeTree(x);
}
}
public void setRight(bigTree t, int x) {
if (t.Right != null) {
//setRight(t.Right, x);
System.out.println("Error");
} else {
t.Right = makeTree(x);
}
}
public void insertLocation(bigTree tree, int v) {
// if (tree.data == v) {
//findDuplicate(v);
//}
if (v < tree.data) {
if (tree.Left != null){
insertLocation(tree.Left, v);
}
else {
setLeft(tree, v);
}
}
if (v > tree.data) {
if (tree.Right != null){
insertLocation(tree.Right, v);
} else {
setRight(tree, v);
}
}
}
public void sort(bigTree t) {
if (t.Left != null) {
sort(t.Left);
}
System.out.println(t.data + " freq = " + frequency);
if (t.Right != null) {
sort(t.Right);
}
}
public void dealArray( String[] x) {
int convert;
bigTree tree = makeTree(Integer.parseInt(x[0]));
for (int i = 1; i < x.length; i++){
//convert = Integer.parseInt(x[i]);
insertLocation(tree, Integer.parseInt(x[i]));
findDuplicate(Integer.parseInt(x[i]));
} sort(tree);
}
----A method that I thought could work but isnt----
public void findDuplicate(int number) {
bigTree tree, h, q;
tree = makeTree(number);
//while (//there are #'s in the list) { //1st while()
h = tree;
q = tree;
while (number != h.data && q != null) { //2nd while()
h = q;
if (number < h.data ) {
q = q.Left;
} else {
q = q.Right;
}
} //end of 2nd while()
if (number == h.data) {
//h.frequency++;
System.out.println("Duplcate: " + number + "freq = " + h.frequency++);
}
else {
if (number < h.data) {
setLeft(h,number);
}
else {
setRight(h, number);
}
}
//} // End of 1st while()
sort(h);
}
PrePost:
If you need to use the binary tree search, it appears that your code above is creating a new tree for each element that it is looking for. Instead you should have a single tree that you search, add / update for each element that you are looking for.
Previous Post:
Although #Woot4Moo's answer will work, there is the overhead of creating the count and incrementing. I would suggest using Guava's ListMultimap class to handle all this for you.
ListMultimap
ListMultimap<Integer, Integer> mymap;
for (Integer value : values){
mymap.put(value, value);
}
Map<Integer, List<Integer>> asmap = mymap.asMap();
for (Entry<Integer, List<Integer>> entry : asmap.entrySet()){
System.out.println(String.format("Value %d occurred %d times", entry.getKey(), entry.getValue().size());
}
So the first thing you need to do is select a data structure that can represent a value and the number of duplicates it has. The first thing that comes to mind is a Map
Map<Integer,Integer> // Keeps track of the integer that is the key and the count which is the value
So what needs to happen as you parse out your array (or whatever structure you are reading this values from) is do a check on the Map like so:
myMap.contains(integerToCheck);
if contains returns true you need to increment the value stored in myMap for that key. Else you need to insert a new key that uses integerToCheck and a new value of 1 .
Then to print those values you would do the following:
for(Map.Entry<Integer,Integer> entry: myMap.entrySet())
{
System.out.println(entry.getKey + " : " + entry.getValue());
}
I Think your heading in the right direction.
1) You need to sort your elements. There is a number of ways to do this.
enter link description here
2) You need to find the duplicate elements. This can be done by comparing ith element with i+1 element. You can store your answers in a Map.
Related
In advance, I apologize for my lack of experience, these are advanced concepts that are difficult to wrap my head around. From what I understand, linear probing is circular, it won't stop until it finds an empty cell.
However I am not sure how to implement it. Some example on how to would be greatly appreciated. Sorry again for the inexperience, I'm not some vetted programmer, I'm picking this up very slowly.
public boolean ContainsElement(V element)
{
for(int i = 0; i < capacity; i++)
{
if(table[i] != null)
{
LinkedList<Entry<K, V>> bucketMethod = table[i];
for(Entry<K, V> entry : bucketMethod)
{
if(entry.getElement().equals(element))
{
return true;
}
}
}
}
return false;
}
Here's a working hash table based on the pseudocode examples found in the Wikipedia article for open addressing.
I think the main differences between the Wikipedia example and mine are:
Treating the hashCode() a little bit due to the way Java does modulo (%) with negative numbers.
Implemented simple resizing logic.
Changed the logic in the remove method a little bit because Java doesn't have goto.
Otherwise, it's more or less just a direct translation.
package mcve;
import java.util.*;
import java.util.stream.*;
public class OAHashTable {
private Entry[] table = new Entry[16]; // Must be >= 4. See findSlot.
private int size = 0;
public int size() {
return size;
}
private int hash(Object key) {
int hashCode = Objects.hashCode(key)
& 0x7F_FF_FF_FF; // <- This is like abs, but it works
// for Integer.MIN_VALUE. We do this
// so that hash(key) % table.length
// is never negative.
return hashCode;
}
private int findSlot(Object key) {
int i = hash(key) % table.length;
// Search until we either find the key, or find an empty slot.
//
// Note: this becomes an infinite loop if the key is not already
// in the table AND every element in the array is occupied.
// With the resizing logic (below), this will only happen
// if the table is smaller than length=4.
while ((table[i] != null) && !Objects.equals(table[i].key, key)) {
i = (i + 1) % table.length;
}
return i;
}
public Object get(Object key) {
int i = findSlot(key);
if (table[i] != null) { // Key is in table.
return table[i].value;
} else { // Key is not in table
return null;
}
}
private boolean tableIsThreeQuartersFull() {
return ((double) size / (double) table.length) >= 0.75;
}
private void resizeTableToTwiceAsLarge() {
Entry[] old = table;
table = new Entry[2 * old.length];
size = 0;
for (Entry e : old) {
if (e != null) {
put(e.key, e.value);
}
}
}
public void put(Object key, Object value) {
int i = findSlot(key);
if (table[i] != null) { // We found our key.
table[i].value = value;
return;
}
if (tableIsThreeQuartersFull()) {
resizeTableToTwiceAsLarge();
i = findSlot(key);
}
table[i] = new Entry(key, value);
++size;
}
public void remove(Object key) {
int i = findSlot(key);
if (table[i] == null) {
return; // Key is not in the table.
}
int j = i;
table[i] = null;
--size;
while (true) {
j = (j + 1) % table.length;
if (table[j] == null) {
break;
}
int k = hash(table[j].key) % table.length;
// Determine if k lies cyclically in (i,j]
// | i.k.j |
// |....j i.k.| or |.k..j i...|
if ( (i<=j) ? ((i<k)&&(k<=j)) : ((i<k)||(k<=j)) ) {
continue;
}
table[i] = table[j];
i = j;
table[i] = null;
}
}
public Stream<Entry> entries() {
return Arrays.stream(table).filter(Objects::nonNull);
}
#Override
public String toString() {
return entries().map(e -> e.key + "=" + e.value)
.collect(Collectors.joining(", ", "{", "}"));
}
public static class Entry {
private Object key;
private Object value;
private Entry(Object key, Object value) {
this.key = key;
this.value = value;
}
public Object getKey() { return key; }
public Object getValue() { return value; }
}
public static void main(String[] args) {
OAHashTable t = new OAHashTable();
t.put("A", 1);
t.put("B", 2);
t.put("C", 3);
System.out.println("size = " + t.size());
System.out.println(t);
t.put("X", 4);
t.put("Y", 5);
t.put("Z", 6);
t.remove("C");
t.remove("B");
t.remove("A");
t.entries().map(e -> e.key)
.map(key -> key + ": " + t.get(key))
.forEach(System.out::println);
}
}
java.util.HashMap implementation of java.util.Map internally provides linear probing that is HashMap can resolve collisions in hash tables.
A similar question was asked here on SO: [BST with duplicates
User Sazzadur Rahaman posted the three scenarios for accomplishing BST with duplicates, but I need to know how to implement the third situation he mentioned which looks something like this:
Assume we are using the input: "RABSAB."
The tree with the counter variable in brackets would look like this:
R(1)
/ \
/ \
A(2) S(1)
\
\
B(2)
So basically, I want each element(node) to have a specific counter variable.
Is what I'm trying to do possible to implement in just my insert method? Or would I need some sort of other method in my BSTTree/Node class?
****EDIT** my BSTNode class, made changes from Compass's recommendations.
public class BSTNode {
String key;
BSTNode left, right;
int count=1;
public BSTNode(String key) {
this.key = key;
}
public void insert(String x) {
if (x.compareTo(this.key) > 0) {
if (right != null) {
right.insert(x);
} else {
right = new BSTNode(x);
}
} //Go right
else if (x.compareTo(this.key) < 0) {
if (left != null) {
left.insert(x);
} else {
left = new BSTNode(x);
}
} //Go left
else if (x.compareTo(this.key) == 0) {
count++;
} // It's a duplicate, update the count
}
}
EDIT, updated my output incrementing a counter like that doesn't seem to give the correct output, I'm inserting "RABSAB" and trying to count the number of duplicate nodes.
Inserting as follows:
String line = "R A B S A B";
String[] words = line.split(" ");
for (int i = 0; i < words.length; i++) {
t1 = t1.Insert(words[i], t1);
System.out.println(words[i] + " : " + t1.count);
}
I get the following output:
R : 1
A : 1
B : 1
S : 1
A : 1
B : 1
Thanks for your time everyone.
Inside your BSTNode class, outside of the Insert method, declare int counter = 1;
Then, within your else, you would do counter++;
So on creating a node, you'd have 1 of the element (since you created it, you know it exists).
As additional keys that match are found, you would increment the counter.
I do feel like there is an implementation issue with your Insert method (which should be lower-case insert to follow conventions). You're passing a Node t which I assume is the child of the Node. That should probably be declared as a field just like counter is.
Sample Pseudocoded Integer-based Node with Duplicates
public class Node() {
int value; //node's value
int counter = 1; //how many items of same type at node
Node leftChild = null;
Node rightChild = null;
public Node(int value) {
this.value = value;
}
public void insert(int newValue) {
if(newValue > value) {
if(rightChild != null)
rightChild.insert(newValue); //we tell the child to deal with it
else
rightChild = new Node(newValue); //we make it a child
}
else if(newValue < value) {
if(leftChild != null)
leftChild.insert(newValue);
else
leftChild = new Node(newValue);
}
else if(newValue == value) {
counter++; // we found a duplicate, increase count
}
}
}
This will work.
else {
t.count++;
}
return t;
I'm working on creating a program that will take an input text file and will print out the 10 most commonly used words and how many times they are used. However, it currently prints 10 random words, not ordered. Is there anything that I am missing?
public void insert(E word) {
if (word.equals("")) {
return;
}
//Adds 2 temporary nodes, and sets first to the first one if first is empty
Node temp = new Node(word);
Node temp2;
if (first == null) {
first = temp;
} else{
for (Node temp6 = first; temp6 != null; temp6 = temp6.next) {
if (temp6.key.equals(temp.key)) {
temp6.count++;
temp2 = temp6;
Node parent = first;
Node parent2 = first;
while (parent != null) {
if (parent.key.equals(word)) {
if (parent == first) {
first = first.next;
} else {
parent2.next = parent.next;
}
}
parent2 = parent;
parent = parent.next;
}
//replaces first with temp2 if temp2's count is higher than first's
if (temp2.count > first.count) {
Node temp3 = first;
first = temp2;
first.next = temp3;
}
//Adds 1 to the counter if the word is already in the linkedlist. Moves the node to the correct place and deletes the original node.
for (Node temp4 = first.next; temp4 != null; temp4 = temp4.next){
if(temp4.next.count < first.count){
Node temp5 = temp4.next;
temp4.next = temp2;
temp2.next = temp5;
break;
}
}
return;
}
}
current.next = temp;
}
current = temp;
}
The approach to your problem seems a bit overly complex at first glance. This may be because your Node class does something that requires a more complex approach. However, I would recommend using a Set. This way you can just create a POJO called Word that contains a String word, and Integer count. If you implement Comparable with this POJO then you can #Override compareTo(Word w) which you can then sort my count. Since a Set won't allow duplicates, you can then create a new Word for each word you read in, or simply increment the count of Word. Once you finish reading the entire file, you then just print out the first 10 objects in the list. Something to illustrate my point would be this example.
class Word implements Comparable<Word>{
String word;
Integer count;
Word(String w, Integer c) {
this.word = w;
this.count = c;
}
public String toString(){
return word + " appeared " + count + " times.";
}
#Override
public int compareTo(Word w) {
return this.count - w.count;
}
}
public class TestTreeMap {
public static void main(String[] args) {
//Add logic here for reading in from file and ...
}
}
Anyway, I hope this answer helps to point you in the right direction. As a side note, I tend to try and find the simplest solution, as the more clever we get the more unmaintainable our code becomes. Good luck!
Here is how we can do it using collection(s)
class WordCount {
public static void main (String[] are) {
//this should change. Used to keep it simple
String sentence = "Returns a key value mapping associated with the least key greater than or equal to the given key";
String[] array = sentence.split("\\s");
//to store the word and their count as we read them from the file
SortedMap<String, Integer> ht = new TreeMap<String, Integer>();
for (String s : array) {
if (ht.size() == 0) {
ht.put(s, 1);
} else {
if (ht.containsKey(s)) {
int count = (Integer) ht.get(s);
ht.put(s, count + 1);
} else {
ht.put(s, 1);
}
}
}
//impose reverse of the natural ordering on this map
SortedMap<Integer, String> ht1 = new TreeMap<Integer, String>(Collections.reverseOrder());
for (Map.Entry<String, Integer> entrySet : ht.entrySet()) {
//setting the values as key in this map
ht1.put(entrySet.getValue(), entrySet.getKey());
}
int firstTen = 0;
for (Map.Entry<Integer, String> entrySet : ht1.entrySet()) {
if (firstTen == 10)
break;
System.out.println("Word-" + entrySet.getValue() + " number of times-" + entrySet.getKey());
firstTen++;
}
}
}
there is one problem here...which is if there are two words with same frequency we see only one in the output.
So, I ended up modifying it again as below
class WordCount1 {
public static void main (String...arg) {
String sentence = "Returns a key value mapping mapping the mapping key the than or equal to the or key";
String[] array = sentence.split("\\s");
Map<String, Integer> hm = new HashMap<String, Integer>();
ValueComparator vc = new ValueComparator(hm);
SortedMap<String, Integer> ht = new TreeMap<String, Integer>(vc);
for (String s : array) {
if (hm.size() == 0) {
hm.put(s, 1);
} else {
if (hm.containsKey(s)) {
int count = (Integer) hm.get(s);
hm.put(s, count + 1);
} else {
hm.put(s, 1);
}
}
}
ht.putAll(hm);
int firstTen = 0;
for (Map.Entry<String, Integer> entrySet : ht.entrySet()) {
if (firstTen == 10)
break;
System.out.println("Word-" + entrySet.getKey() + " number of times-" + entrySet.getValue());
firstTen++;
}
}
and, the ValueComparator from here. Tweaked it a little and is as below
public class ValueComparator implements Comparator<String> {
Map<String, Integer> entry;
public ValueComparator(Map<String, Integer> entry) {
this.entry = entry;
}
public int compare(String a, String b) {
//return entry.get(a).compareTo(entry.get(b));
//return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));//from java source
return (entry.get(a) < entry.get(b) ? 1 : (entry.get(a) == entry.get(b) ? 1 : -1));
}
}
This program is case sensitive and in case you need case-insensitive behavior - just convert the strings to lowercase before putting into the Map.
Currently I have managed to get all 4 cases of rotation code right. My problem now is to get words that are in a range defined by the system. It is inclusive of start and exclusive of end stop words provided by the system.
The method I am using to get the total numbers of words is working correctly as I am using a nodeSize method whereby it is the addition of both left and right subtree and itself [left subtree+rightsubtree+1].The difference or number of words in a range is obtained as there are overlap points for both start and end stop words.
What I am using to update for all nodes sizes in an AVL tree is to implement nodeSize method in an inorder method. This works fine as i have checked earlier for small range details. The only issue now I encounter how to make it more time efficient when there are over 10,000 nodes in the tree and over 5000 queries for it.
public int nodeSize(BSTVertex T) {
if (T == null) {
return 0;
} else {
return nodeSize(T.left) + nodeSize(T.right) + 1;
}
}
public void insert(String v) {
root = insert(root, v);
}
protected BSTVertex insert(BSTVertex T, String v) {
if (T == null) {
return new BSTVertex(v);
}
if (T.key.compareTo(v) < 0) {
T.right = insert(T.right, v);
T.right.parent = T;
} else {// search to the left
T.left = insert(T.left, v);
T.left.parent = T;
}
T.totalNode = nodeSize(T);
int balance = nodeHeight(T.left) - nodeHeight(T.right);
if (balance == 2) {
int balance2 = nodeHeight(T.left.left) - nodeHeight(T.left.right);
if (balance2 == 1) {
T = rightRotation(T);
} else {//Left Right Case 2,-1
T.left = rotateLeft(T.left);
T = rightRotation(T);
}
}
if (balance == -2) {
int balance2 = nodeHeight(T.right.left) - nodeHeight(T.right.right);
if (balance2 == -1) {
T = rotateLeft(T); //single left for -1
} else {//Right left case, -2,1
T.right = rightRotation(T.right);
T = rotateLeft(T);
}
}
inorder(T);
return T;
}
I am having a few problems in my AVL tree implementation.. The code for all the rotations and the adding all seem to be correct and I dry-run the program to thoroughly check that it is running logically correct. I seem to be having a problem in my tree traversal (in-order) because it only outputs a few integers from the supposed 100. Also the search is always failing, regardless of what I enter. I cannot seem to grasp what is going on but I suspect that it has something to do with a few null pointers. Below is the code for the AVL tree, I am wondering if there's any incorrect code in the AddNode method or the rotation methods but they seem to be fine.. The classes are Node class, AVL class and AVL tree class which is the main class.
Node class
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 class
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;
}
}
Main Class
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();
}
}
The output for the traversal is just the following:
Traversal:
44
53
54
54
77
Suppose that there were 100 integers entered and among them were these. But the output for the traversal was only this.
Output for the search is like this:
Choice: 4
Please enter the integer to be searched: 44
Item found!
44
Choice: 4
Please enter the integer to be searched: 100
Search failed!
0
100 and 44 were both integers added to the tree, but 44 was found and 100 wasn't.. I don;t understand..
Anyone can guide me to a solution..?
Thanks in advance :)
Well, first the obvious thing... In your search method, you are abusing the root variable, which holds the root of your tree, setting it to new values as your search proceeds. So, after the first search, root points to the last node traversed in the search and no longer to the root node of the tree. All following searches are unlikely to find anything at all from that point on.
As your search is recursive, try passing on the node-to-be-searched-in as parameter:
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
}
}
(Edited to address the comments) You might have to expose this method like you do with your add/addNode method pair using a publicly available wrapper, and an internal implementation:
public int search(int key) {
return searchNode(root, key);
}
private int searchNode(Node node, int key) {
// Perform the recursive search, as above
}
There are other problems related to your add/addNode methods. Maybe I just overlooked it, but nowhere do you adjust the root node of your tree, if rotation would make it necessary. This, in effect, causes your tree to get out of balance, losing the AVL property over time.