I am having trouble figuring out how to implement a binary search iterator.
My question is how do i implement an Iterator traversing "in order" while not using the collection classes?
Well the thing is that i have not a clue about how to add "parent" because i find the first 4 items in the iterator when going down but i dont seem to be able to go up since the "parent" either throws nullpointer or dont get the right items.
so how do i add "parent"?
void add(String string) {
if (string.compareTo(value) < 0) {
if(left.left == null){
left.parent = left;
}
if (left == null) {
size++;
left = new Node(string);
if...
thanks.
I suggest a three classes design:
BinarySearchTree: Public class, It represent a Binary search Tree. It contains the tree root as BinaryTreeNode.
BinaryTreeNode: Private nested class, It represent a Node, It has the key and the references: to children and to Its parent.
BinarySearchTreeIterator: Private nested class, It represent an iterator, It use a reference to a BinaryTreeNode to know the current element.
public class BinarySearchTree implements Iterable<String> {
private BinaryTreeNode root = null;
private int elements;
#Override
public Iterator<String> iterator() {
return new BinarySearchTreeIterator(root);
}
private static class BinarySearchTreeIterator implements Iterator<String> {
private BinaryTreeNode node;
public BinarySearchTreeIterator(BinaryTreeNode node) {
if (node != null) {
this.node = smallest(node);
} else {
this.node = node;
}
}
#Override
public boolean hasNext() {
return node != null;
}
private static BinaryTreeNode smallest(BinaryTreeNode n) {
if (n.left != null) {
return smallest(n.left);
} else {
return n;
}
}
#Override
public String next() {
String result = node.key;
if (node.right != null) {
node = smallest(node.right);
} else {
while (node.parent != null && node.parent.left != node) {
node = node.parent;
}
node = node.parent;
}
return result;
}
}
private static class BinaryTreeNode {
private String key;
private BinaryTreeNode parent;
private BinaryTreeNode left;
private BinaryTreeNode right;
public BinaryTreeNode(String key) {
this.key = key;
}
}
public boolean insert(String key) {
if (key == null) {
return false;
}
int lastElements = elements;
this.root = insert(key, root, null);
return lastElements < elements;
}
private BinaryTreeNode insert(String key, BinaryTreeNode node, BinaryTreeNode parent) {
BinaryTreeNode result = node;
if (node == null) {
result = new BinaryTreeNode(key);
result.parent = parent;
this.elements++;
} else {
int compare = key.compareTo(node.key);
if (compare < 0) {
result.left = insert(key, node.left, node);
} else if (compare > 0) {
result.right = insert(key, node.right, node);
}
}
return result;
}
public static void main(String[] args) {
BinarySearchTree tree = new BinarySearchTree();
String[] strings = {"l", "f", "t", "c", "g", "p", "u"};
for (String string : strings) {
System.out.println("insert: '" + string + "' " + tree.insert(string));
}
System.out.println("--");
for (String s : tree) {
System.out.println(s);
}
}
}
It prints:
insert: 'l' true
insert: 'f' true
insert: 't' true
insert: 'c' true
insert: 'g' true
insert: 'p' true
insert: 'u' true
--
c
f
g
l
p
t
u
Related
I have to implement an AVL Tree with some given interface functions. So far, everything seems to be fine, except when I call inside the main function "tree.search(3)" for example, it simply doesn't work and just returns one value or null. Does anyone have an idea why that is so?
AVLTree:
public class AVLTree implements SearchTree{
public class Node {
int key;
int height;
Node left;
Node right;
String string;
Node(int key, String _string) {
this.key = key;
this.string = _string;
}
}
public static void main(String[] args) {
AVLTree tree = new AVLTree();
tree.insert(5, "gambo");
tree.insert(9, "3");
tree.insert(3, "3");
System.out.println(tree.search(9));
}
private Node root;
public Node find(int key) {
Node current = root;
while (current != null) {
if (current.key == key) {
break;
}
current = current.key < key ? current.right : current.left;
}
return current;
}
// public void insert(int key) {
// root = insert(root, key);
// }
public void delete(int key) {
root = delete(root, key);
}
public Node getRoot() {
return root;
}
public int height() {
return root == null ? -1 : root.height;
}
private Node insert(Node node, int key, String string) {
if (node == null) {
System.out.println("yep new node");
return new Node(key, string);
} else if (node.key > key) {
node.left = insert(node.left, key, node.string);
} else if (node.key < key) {
node.right = insert(node.right, key, node.string);
} else {
throw new RuntimeException("duplicate Key!");
}
return rebalance(node);
}
private Node delete(Node node, int key) {
if (node == null) {
return node;
} else if (node.key > key) {
node.left = delete(node.left, key);
} else if (node.key < key) {
node.right = delete(node.right, key);
} else {
if (node.left == null || node.right == null) {
node = (node.left == null) ? node.right : node.left;
} else {
Node mostLeftChild = mostLeftChild(node.right);
node.key = mostLeftChild.key;
node.right = delete(node.right, node.key);
}
}
if (node != null) {
node = rebalance(node);
}
return node;
}
private Node mostLeftChild(Node node) {
Node current = node;
while (current.left != null) {
current = current.left;
}
return current;
}
private Node rebalance(Node z) {
updateHeight(z);
int balance = getBalance(z);
if (balance > 1) {
if (height(z.right.right) > height(z.right.left)) {
z = rotateLeft(z);
} else {
z.right = rotateRight(z.right);
z = rotateLeft(z);
}
} else if (balance < -1) {
if (height(z.left.left) > height(z.left.right)) {
z = rotateRight(z);
} else {
z.left = rotateLeft(z.left);
z = rotateRight(z);
}
}
return z;
}
private Node rotateRight(Node y) {
Node x = y.left;
Node z = x.right;
x.right = y;
y.left = z;
updateHeight(y);
updateHeight(x);
return x;
}
private Node rotateLeft(Node y) {
Node x = y.right;
Node z = x.left;
x.left = y;
y.right = z;
updateHeight(y);
updateHeight(x);
return x;
}
private void updateHeight(Node n) {
n.height = 1 + Math.max(height(n.left), height(n.right));
}
private int height(Node n) {
return n == null ? -1 : n.height;
}
public int getBalance(Node n) {
return (n == null) ? 0 : height(n.right) - height(n.left);
}
#Override
public void insert(int key, String string) {
root = insert(root, key, string);
}
#Override
public String search(int key) {
Node p = find(key);
return p.string.toString();
}
#Override
public long getCumulativeLengthOfSearchPaths() {
return 0;
}
}
Interface:
/**
* Organizes strings with keys in a search tree and collects some statistics
*/
public interface SearchTree {
/**
* Inserts a string with a given key into the tree. The position in the tree
* depends on the rank of the key with respect to all existing keys in the tree.
* Each key is to appear in the tree at most once. Hence, this method will not
* alter the tree if the key already exists in the tree.
*
* #param key the key of the string to be inserted
* #param string the string to be inserted
*/
public void insert(int key, String string);
/**
* Deletes a string with a given key from the tree.
*
* #param key the key of the string to be deleted
*/
public void delete(int key);
/**
* Searches for a string with a given key in the tree and returns the string if
* it exists.
*
* #param key the key of the string to be searched for
* #return the string to be searched for, null if the key does not exist in the
* tree
*/
public String search(int key);
public long getCumulativeLengthOfSearchPaths();
}
Was able to fix the issue. In case someone runs into the same problem:
I added node.string as the string value, but it needs to parameter as the argument:
node.left = insert(node.left, key, string);
I am having trouble removing a node from the user input and properly going to the last node, so it will be ready to add a new node after. I am refactoring this code to a larger implementation. However, I am unable to remove the node and go to the last node after. This is also using user input to find the proper node to remove. This is a generic linked list of a comparable type.
import java.util.Scanner;
import java.io.*;
class MyGenericList <T extends Comparable<T>>
{
private class Node<T>
{
T value;
Node<T> next;
}
private Node<T> first = null;
int count = 0;
public void add(T element)
{
Node<T> newnode = new Node<T>();
newnode.value = element;
newnode.next = null;
if (first == null)
{
first = newnode;
}
else
{
Node<T> lastnode = gotolastnode(first);
lastnode.next = newnode;
}
count++;
}
public void remove(T element)
{
Node<T> nn = new Node<T>();
Node<T> cur = first.next;
Node<T> prev = first;
nn.value = element;
boolean deleted = false;
while(cur != null && deleted == false)
{
if(cur.equals(element)) //data cannot be resolved or is not a field
{
prev.next = cur.next;
this.count--;
deleted = true;
}
}
prev = gotolastnode(prev);
prev.next = nn;
}
public T get(int pos)
{
Node<T> Nodeptr = first;
int hopcount=0;
while (hopcount < count && hopcount<pos)
{ if(Nodeptr != null)
{
Nodeptr = Nodeptr.next;
}
hopcount++;
}
return Nodeptr.value;
}
private Node<T> gotolastnode(Node<T> nodepointer)
{
if (nodepointer== null )
{
return nodepointer;
}
else
{
if (nodepointer.next == null)
return nodepointer;
else
return gotolastnode( nodepointer.next);
}
}
}
class Employee implements Comparable<Employee>
{
String name;
int age;
#Override
public int compareTo(Employee arg0)
{
// TODO Auto-generated method stub
return 0;
// implement compareto method here.
}
Employee( String nm, int a)
{
name =nm;
age = a;
}
}
class City implements Comparable<City>
{
String name;
int population;
City( String nm, int p)
{
name =nm;
population = p;
}
#Override
public int compareTo(City arg0) {
// TODO Auto-generated method stub
return 0;
// implement compareto method here.
}
}
public class GenericLinkedList
{
public static void main(String[] args) throws IOException
{
MyGenericList<Employee> ml = new MyGenericList<>();
ml.add(new Employee("john", 32));
ml.add(new Employee("susan", 23));
ml.add(new Employee("dale", 45));
ml.add(new Employee("eric", 23));
Employee e1 = ml.get(0);
System.out.println( "Name " + e1.name + " Age "+ e1.age );
ml.remove(new Employee("john", 32));
System.out.println( "Name " + e1.name + " Age "+ e1.age );
ml.add(new Employee("jerry", 35));
Employee e2 = ml.get(2);
System.out.println( "Name " + e2.name + " Age "+ e2.age );
}
}
The implementation of your remove method was faulty. Please see the fixed remove method below. Comments have been added in order to explain the changes.
The solution was tested via an online Java IDE and is verified to work properly.
public void remove(T element)
{
if(first == null) { // edge case - empty list
return;
}
else if(first.value.equals(element)) { // edge case - removing the first element
first = first.next;
this.count--;
return;
}
//Node<T> nn = new Node<T>(); // no need to create a new node, but rather remove an existing node.
Node<T> cur = first.next;
Node<T> prev = first;
//nn.value = element; //no need to create a new node and set its value attribute
boolean deleted = false;
while(cur != null && deleted == false)
{
if(cur.value.equals(element)) //data cannot be resolved or is not a field
{
prev.next = cur.next;
this.count--;
deleted = true;
}
else { // added missing advancement of the loop iterator - cur. prev must also be advanced
cur = cur.next;
prev = prev.next;
}
}
// This implementation adds the removed element to the end of the list, meaning
// it is not a remove method, but rather a move to the end implementation.
// In order to conform to what a remove method does, the last two code lines were commented out.
//prev = gotolastnode(prev);
//prev.next = nn;
}
You must also add an overridden implementation of equals in the Employee class (and other classes) which is used by your list:
class Employee implements Comparable<Employee>
{
String name;
int age;
#Override
public int compareTo(Employee arg0)
{
// sort first by name, then by age
if(name.equals(arg0.name)) {
return age - arg0.age;
}
return name.compareTo(arg0.name);
}
Employee( String nm, int a)
{
name =nm;
age = a;
}
#Override
public boolean equals(Object emp) {
boolean result = false;
if(emp != null && emp instanceof Employee) {
Employee e = (Employee)emp;
result = name.equals(e.name) && (age == e.age);
}
return result;
}
}
So i'm very much so stuck on my delete function. I keep getting about 20 errors throughout and several are different ones. When I delete the entire thing from my code though, it compiles, so I know it's only this that is missing and messing up my code, but I also really need it in my code of course! here's the delete function and I'll also list my node Class under it as well
public Node delete(Node t, int key){
if (t == null){
return t;
}
else if (key < t.getKey()){
t.getLeft() = delete(t.left, key);
}
else if(key > t.getKey()){
t.getRight() = delete(t.right, key);
}
else{
//Deleting a node with no subtrees
if (t.getLeft() == null && t.getRight() == null){
t = null;
t--;
}
//Node only has one subtree
else if(t.getLeft() != null && t.getRight() == null){
t = t.setLeft();
t--;
}
//Node only has one subtree again for opposite side
else if (t.getLeft() == null && t.getRight() != null){
t = t.setLeft();
t--;
}
//Finding minimum in the right side, and replace
else if (t.getLeft() != null && t.getRight() != null){
temp = t;
if (t.getRight().getRight() == null && t.getRight().getLeft() == null){
temp = successor(t.getLeft());
}
else{
temp = successor(t.getRight());
}
t.key = temp.key;
if (t.getRight().getRight() == null || t.getLeft().getLeft() == null){
t.setLeft() = delete(t.left, t.key);
}
else{
t.setRight() = delete(t.right, t.key);
}
}
}
}
public Node successor(Node t){
while (t.getLeft() != null){
t = t.left;
}
}
Here's my Node Class for reference to some of the functions like getLeft() and so on:
public class Node{
private Node next;
private String name;
private int ssn;
private int key;
private Node left;
private Node right;
public Node(String name, int ssn){
this.name = name;
this.ssn = ssn;
}
public Node getRight(){
return this.right;
}
public Node getLeft(){
return this.left;
}
public void setRight(Node p){
right = p;
}
public void setLeft(Node p){
left = p;
}
public void setNext(Node n){
this.next = n;
}
public int getSSN(){
return this.ssn;
}
public int getKey(){
return ssn%10000;
}
public String getName(){
return name;
}
public Node getNext(){
return this.next;
}
public void setSSN(int ssn){
this.ssn= ssn;
}
}
I'm trying to sort a linkedlist with generics but I'm having trouble with some casting issues. The code is throwing Bus can't be cast to Node. I know the problem is in the comparator (where I casted to Bus) but otherwise I don't know how could I call to the methods defined in Bus (irrelevant whether is Bus or another Object, just testing with a random one) . I've been researching the internet but couldn't find a solution. Here is the code:
/**
* Swaps the current node's element with the previous one
*/
public void swap(){
Object previous = getCurrent().getElement();
Object current = next().getElement();
getCurrent().setElement(previous);
previous().setElement(current);
}
public AbstractList<T> orderBy(Comparator<Node<T>> comparator){
setCurrent(getFirst());
Node<T> aux;
Node<T> current;
boolean check = true;
while (check){
check = false;
aux = getFirst();
current = getFirst().getNext();
while(hasNext()) {
if (comparator.compare(aux, current) > 0) {
check = true;
swap();
}
aux = current;
current = current.getNext();
}
}
return this;
}
The comparator:
import java.util.Comparator;
public class InternComparator implements Comparator<Node<Bus>>{
#Override
public int compare(Node<Bus> o1, Node<Bus> o2) {
return ((Bus)o1.getElement()).getIntern() - ((Bus)o2.getElement()).getIntern();
} //getIntern() returns an Integer
AbstractList (given by the professor):
import java.util.NoSuchElementException;
public class AbstractList<T> {
private Node<T> first;
private Node<T> current;
private Node<T> last;
private int size = 0;
public boolean hasNext(){
return current != last;
}
public boolean hasPrevious(){
return current != first;
}
public Node getCurrent(){
return current;
}
public void setCurrent(Node<T> current) {
this.current = current;
}
public int size(){
return size;
}
public boolean isEmpty(){
return first == last || first == null;
}
public void add(T t){
Node<T> a = new Node<T>(t);
if(first == null){
first = a;
}
if(last == null && first != null){
last = a;
last.setPrevious(first);
first.setNext(last);
}
Node<T> aux = last;
last.setNext(a);
last = a;
last.setPrevious(aux);
current = last;
size++;
}
public Node next(){
if(!hasNext()){
throw new RuntimeException("No elements available next.");
}
current = current.getNext();
return current;
}
public Node previous(){
if(!hasPrevious()){
throw new RuntimeException("No elements available previous.");
}
current = current.getPrevious();
return current;
}
public Node getFirst(){
return first;
}
public Node getLast(){
return last;
}
public void setFirst(Node<T> first){
this.first = first;
}
public void setLast(Node<T> last) {
this.last = last;
}
public void remove(T t){
current = first;
boolean removed = false;
while (hasNext()) {
if (current.getElement() == t || current.getElement().equals(t)) {
if(current != last && current != first) {
current.getNext().setPrevious(current.getPrevious());
current.getPrevious().setNext(current.getNext());
} else if(current == first){
current.getNext().setPrevious(null);
} else if(current == last){
current.getPrevious().setNext(null);
}
removed = true;
return;
}
current = next();
}
if(removed){
size--;
} else {
throw new NoSuchElementException("No such element on the list.");
}
}
public Node goTo(int pos){
if(pos > size){
throw new ArrayIndexOutOfBoundsException("Inexistent Position");
}
current = first;
for(int i = 0; i < pos; i++){
current = next();
}
return current;
}
public void insertAfter(T t){
Node<T> aux = new Node<>(t);
if(current != last) {
Node<T> next = current.getNext();
Node<T> previous = current;
current.getNext().setPrevious(aux);
current.setNext(aux);
aux.setNext(next);
aux.setPrevious(previous);
} else {
current.setNext(aux);
aux.setPrevious(current);
last = aux;
}
size++;
}
public void insertPrevious(T t){
Node<T> aux = new Node<>(t);
if(current != first) {
Node<T> previous = current.getPrevious();
Node<T> next = current;
current.getPrevious().setNext(aux);
current.setPrevious(aux);
aux.setNext(next);
aux.setPrevious(previous);
} else {
Node<T> aux1 = current;
current.setPrevious(aux);
first = aux;
first.setNext(aux1);
}
size++;
}
#Override
public String toString() {
String result = "";
current = first;
while(hasNext()) {
result += current.getElement() + "";
next();
}
return result;
}
}
class Node<T> {
private Object element;
private Node<T> prev;
private Node<T> next;
public Node(T element){
this.element = element;
}
public Node(T element, Node next){
this.element = element;
this.next = next;
}
public Node<T> getNext() {
return next;
}
public Node<T> getPrevious() {
return prev;
}
public Object getElement() {
return element;
}
public void setNext(Node<T> next) {
this.next = next;
}
public void setPrevious(Node<T> prev) {
this.prev = prev;
}
public void setElement(Object element) {
this.element = element;
}
}
Think again: your object is of type Node<Bus>; and you are wondering why the cast to Bus fails?
Or lets rephrase: do you assume that a Bus<People> represents a human being?
If you have a container, then you have to retrieve the contained value; and that can't be achieved by casting the container!
Or, to keep using strange pictures: you don't get an egg out of the box by declaring the box to be an egg. You open the box, and fetch the egg.
This question already exists:
Write an address book in java using a binary search tree [closed]
Closed 9 years ago.
Hello I am writing an AddressBook application in java and I have written the whole program. The only thing is that its not working as expected and there are no errors in the code so i am unable to troubleshoot it. Any help would be much appriciated.
EDIT: This is not a duplicate question as this includes all the methods. The other one didn't have the main method and is incomplete and as it was closed i was forced to ask a new question. Makes sense?
package com.addressbook;
public abstract class KeyedItem<KT extends Comparable<? super KT>> {
private KT searchKey;
public KeyedItem(KT key){
searchKey = key;
}
public KT getKey(){
return searchKey;
}
}
package com.addressbook;
public class People extends KeyedItem<String> {
private String address;
private String phone;
public People(String n, String a, String p){
super(n);
this.address = a;
this.phone = p;
}
public void setAddress(String a){
address = a;
}
public void setPhone(String p){
phone = p;
}
public String toString(){
return "Name:" + getKey() + "\nAddress:" + address + "\nPhone:" + phone;
}
public String getTheKey(){
return getKey();
}
}
package com.addressbook;
public class BinaryNode{
// Friendly data; accessible by other package routines
private People people; // The data in the node
private BinaryNode left; // Left child
private BinaryNode right; // Right child
// Constructors
public BinaryNode(People pe, BinaryNode l, BinaryNode r) {
people = pe;
left = l;
right = r;
}
public BinaryNode(People pe) {
people = pe;
left = right = null;
}
public void setData(People p){
people = p;
}
public String getSearch(){
return people.getTheKey();
}
public People getData(){
return people;
}
public BinaryNode getLeft(){
return left;
}
public BinaryNode getRight(){
return right;
}
}
package com.addressbook;
import com.addressbook.People;
import com.addressbook.BinaryNode;
public class AddressBook {
private BinaryNode root;
public AddressBook() {
super();
}
public AddressBook(People p) {
super();
root = new BinaryNode(p);
}
public void insert(People p){
insert(p, root);
}
public People get(String key) {
BinaryNode node = root;
while (node != null) {
if (key.compareTo(node.getSearch()) == 0) {
return node.getData();
}
if (key.compareTo(node.getSearch()) < 0) {
node = node.getLeft();
} else {
node = node.getRight();
}
}
return null;
}
protected BinaryNode insert(People p, BinaryNode node) {
if (node == null) {
return new BinaryNode(p);
}
if (p.getTheKey().compareTo(node.getSearch()) == 0) {
return new BinaryNode(p, node.getLeft(), node.getRight());
} else {
if (p.getTheKey().compareTo(node.getSearch()) < 0) { // add to left subtree
insert(p, node.getLeft());
} else { // add to right subtree
insert(p, node.getRight());
}
}
return node;
}
public void remove(String key) {
remove(key, root);
}
protected BinaryNode remove(String k, BinaryNode node) {
if (node == null) { // key not in tree
return null;
}
if (k.compareTo(node.getSearch()) == 0) { // remove this node
if (node.getLeft() == null) { // replace this node with right child
return node.getRight();
} else if (node.getRight() == null) { // replace with left child
return node.getLeft();
} else {
// replace the value in this node with the value in the
// rightmost node of the left subtree
node = getRightmost(node.getLeft());
// now remove the rightmost node in the left subtree,
// by calling "remove" recursively
remove(node.getSearch(), node.getLeft());
// return node; -- done below
}
} else { // remove from left or right subtree
if (k.compareTo(node.getSearch()) < 0) {
// remove from left subtree
remove(k, node.getLeft());
} else { // remove from right subtree
remove(k, node.getRight());
}
}
return node;
}
protected BinaryNode getRightmost(BinaryNode node) {
assert(node != null);
BinaryNode right = node.getRight();
if (right == null) {
return node;
} else {
return getRightmost(right);
}
}
protected String toString(BinaryNode node) {
if (node == null) {
return "";
}
return node.getData().toString() + "(" + toString(node.getLeft()) + ", " +
toString(node.getRight()) + ")";
}
public static void main(String[] arguments) {
AddressBook tree = new AddressBook();
People p1 = new People("person 1", "adresa 1", "404040404");
People p2 = new People("person 2", "adresa 2", "4040434345");
People p3 = new People("person 3", "adresa 3", "346363463");
People p4 = new People("person 4", "adresa 4", "435346346");
People p5 = new People("person 5", "adresa 5", "4363907402");
tree.insert(p1);
tree.insert(p2);
tree.insert(p3);
tree.insert(p4);
tree.insert(p5);
System.out.println(tree.get("person 1"));
}
}
On one hand:
public void insert(People p){
insert(p, root);
}
but that method begins with
protected BinaryNode insert(People p, BinaryNode node) {
if (node == null) {
return new BinaryNode(p);
}
which means, considering both pieces together, you always ignore the new root and hence your tree never fills. Try this instead:
public void insert(People p){
root = insert(p, root);
}
In the same manner you ignore the return value of insert inside insert too. You should handle them in a similar manner.