I'm trying to write my own CustomLinkedList<E> to rapidly pass labs where I need to implement stacks and queues. I can pass the labs without this class (since I don't need to implement iterable at all), but I would like to grasp the concept since I'm learning java anyway.
I've got most of things running and tested now, but I couldn't make iterator to work properly yet.
The first approach was "post-increment", e.g.:
E result = current.getValue();
current = current.getNext();
return result;
which I found to be broken, because then when I reach the end of the list, I won't be able to get back. My hasNext() just checks if the current is null, thus the ability to go back is lost.
The second approach was to add dummy Node on creation, to model the beginning. It had an issue of determining if I'm at the beginning of the list, since with this approach I don't know where is the beginning until its too late.
Iterator(Node root)
{
current = new Node(null, null, root);
}
public E next()
{
//checks and stuff
current = current.getNext();
return current.getValue();
}
So, question is: is it possible to implement ListIterator<> only knowing the current element? If yes, some code scratches would be great.
EDIT:
Node:
private class Node
{
private Node prev;
private T value;
private Node next;
Node(Node prev, T value, Node next) {
this.setPrev(prev);
this.setValue(value);
this.setNext(next);
}
//getters and setters
}
CustomLinkedList<E>:
public class CustomLinkedList<T> implements Iterable<T>{
private class Node {/**/}
private class Iterator implements java.util.ListIterator<T> {
Node current;
public Iterator(Node root) //from the first approach
{
current = root;
}
//other methods
}
Node root;
int size;
//Object methods, and some basic Collection methods
}
I would do something like this:
public class CustomLinkedList<T> implements Iterable<T>{
private class Node {/**/}
private class Iterator implements ListIterator<T> {
Node next, previous;
Iterator() {
next = root;
previous = null;
}
public boolean hasNext() {
return next != null;
}
public T next() {
if ( ! hasNext()){
throw new NoSuchElementException();
}
previous = next;
next = next.getNext();
return previous;
}
public boolean hasPrevious() {
return previous != null;
}
public T previous() {
if ( ! hasPrevious() ){
throw new NoSuchElementException();
}
next = next.getPrevious();
previous = next.getPrevious();
return next;
}
}
Node root;
int size;
//Object methods, and some basic Collection methods
}
This doesn't implement the other methods of the ListIterator interface, but you get the idea. You need to think of your iterator's cursor as being in-between the previous and the next element, not on one of them. For a proper implementation, see Jorn Vernee's link.
Related
I have the class:
public class Node
{
private String id;
private List<Node> children;
}
I need to create a deep copy of a List of it List, but given that there might circular references I was trying implementing the Cloneable interface and overriding the clone method but I keep getting Stackoverflow exception, so I wonder if there is a way to deep copy it that's fast and removes the circular dependencies in the process?
Class using cloneable, when I try to clone and it has circular references I get the error mention about
public class Node implements Cloneable
{
private String id;
private List<Node> children;
#Override
public Object clone() throws CloneNotSupportedException {
Node clone = (Node) super.clone();
if (children != null) {
List<Node> cloneChildren = new ArrayList<>(children.size());
for (Node child : children) {
cloneChildren.add((Node) child.clone());
}
clone.setChildren(cloneChildren);
}
return clone;
}
public List<Node> getChildren() {
return children;
}
public void setChildren(List<Node> children) {
this.children = children;
}
}
The easiest approach is to use an IdentityHashMap<Node,Node> to keep track of previously seen Nodes, mapping Nodes to be copied with Nodes copied thus far.
public Node copy() {
Map<Node,Node> copied = new IdentityHashMap<>();
return copy(copied, this);
}
private static Node copy(Map<Node,Node> copied, Node orig) {
Node existing = copied.get(orig);
if (existing != null) {
return existing;
}
Node copy = new Node();
copy.id = orig.id;
copy.children = new ArrayList<>();
copied.put(orig, copy);
for (Node child : orig.children) {
copy.children.add(copy(copied, child));
}
return copy;
}
(As usual, code compiled but not tested.)
I was thinking there is a 'clever' approach using Floyd's Tortoise and Hare Algorithm, but this is complicated by it not being a singly-linked list.
Working on an assignment. Taking classes online and I've emailed my prof with the same question but I'm hoping to get a quicker response from you wonderful people here (as I only have 2 hours per day that I can work on school and Ive hit a roadblock).
Assignment is to finish the code for a binary search tree and blah blah implement some stuff.
I'm hung up on one chunk of code that I just cant understand.
This is a code snippet from the LinkedBinaryTree class that was provided.
LinkedBinaryTree relies on a BinaryTreeNode class for the nodes.
public class LinkedBinaryTree<T> implements BinaryTreeADT<T>, Iterable<T>
{
protected BinaryTreeNode<T> root;
protected int modCount;
}
//Constructors
public LinkedBinaryTree()
{
root = null;
}
public LinkedBinaryTree(T element)
{
root = new BinaryTreeNode<T>(element);
}
public LinkedBinaryTree(T element, LinkedBinaryTree<T> left,
LinkedBinaryTree<T> right)
{
root = new BinaryTreeNode<T>(element);
root.setLeft(left.root);
root.setRight(right.root);
}
This is primarily what I fail to grasp.
root.setLeft(left.root);
root.setRight(right.root);
What is .root and how does that work.
The variable is being used in two places? is this some kind of recursion/magic that I just haven't encountered yet? (And currently fail to understand) If so, I will get reading let me know and point me in the right direction.
I will post the code for the BinaryTreeNode methods below. I don't understand these parameters that are being passed.
root is a variable of the type BinaryTreeNode but in its use it is passing a LinkedBinaryTree either left or right as the parameters for a method that requires a variable of type BinaryTreeNode
public class BinaryTreeNode<T>{
protected T element;
protected BinaryTreeNode<T> left, right;
//Constructors
public BinaryTreeNode(T obj)
{
element = obj;
left = null;
right = null;
}
public BinaryTreeNode(T obj, LinkedBinaryTree<T> left, LinkedBinaryTree<T> right)
{
element = obj;
if (left == null)
this.left = null;
else
this.left = left.getRootNode();
if (right == null)
this.right = null;
else
this.right = right.getRootNode();
}
And the methods in question
public void setLeft(BinaryTreeNode<T> node)
{
left = node;
}
public void setRight(BinaryTreeNode<T> node)
{
right = node;
}
This is a binary tree, as mentioned.
Every not-null node has a node to the left and right. Sometimes the value of nodes are null.
As explained in the comments of the question, you are calling the root variable from the type BinaryTreeNode. It would only make sense because the code was written.
I realize that there are a few good threads already existing which discuss how to implement a linked list in Java, however I can't seem to find one which does not use a constructor like this,
public LinkList() {
Link = null;
}
or something along these lines. However, I have not done this in my code, and therefore I am having trouble with writing a few of the methods.
I have a class called Link which contains the following code, note without any constructor like the one displayed above:
public class Link {
private Link next = null;
private String value = null;
public Link getNext(){
return next;
}
public void setNext(Link nextLink){
next = nextLink;
}
public String getValue(){
return value;
}
public void setValue(String aValue){
value = aValue;
}
}
and then I have my LinkedList class, which contains the following code:
public class LinkedList {
private Link head = null;
private Link tail = null;
public Link getHead(){
return head;
}
public void setHead(Link aLink){
head = aLink;
}
public Link getTail(){
return tail;
}
public void setTail(Link aLink){
tail = aLink;
}
public boolean isEmpty(){
return(head == null && tail == null);
}
public void addLast(String aString){
Link link = new Link();
link.setValue(aString);
//tail.setNext(link);
if(isEmpty()){
head = link;
}else{
tail.setNext(link);
}
tail = link;
}
public void addFirst(String aString) {
Link link = new Link();
link.setValue(aString);
if(isEmpty()){
tail = link;
}else{
head.setNext(link);
}
head = link;
}
public Link removeFirst(){
Link temp = head;
head = temp.getNext();
temp.setNext(null);
return temp;
}
}
My addFirst Method, and my isEmpty Method both seem to be working but my addLast and removeFirst Methods are not. I have drawn pictures, looked at pseudo code, and searched around the internet, but I just cannot seem to figure this out.
I need to know how to get my addLast and removeFirst methods working without having to add in the constructor at the beginning like all the rest of the example code I keep seeing.
Here are the Tests they need to pass:
#Test
public void testRemoveFirst(){
list.addFirst("three");
list.addFirst("two");
list.addFirst("one");
assertTrue("one".equals(list.removeFirst()));
assertTrue("two".equals(list.removeFirst()));
assertTrue("three".equals(list.removeFirst()));
}
#Test
public void testAddLast(){
list.addFirst("three");
list.addFirst("two");
list.addFirst("one");
assertTrue( "three".equals(list.removeLast()));
assertTrue( "two".equals(list.removeLast()));
assertTrue( "one".equals(list.removeLast()));
assertNull(list.removeLast());
}
One change in your code is needed: you want the new link to point to your old head as "next" (not the other way round) because you want to insert it at the beginning.
public void addFirst(String aString) {
Link link = new Link();
link.setValue(aString);
if (isEmpty()) {
tail = link;
} else {
link.setNext(head);
}
head = link;
}
Also, you need to change your tests as now you compare String to Link instances instead of String to String
assertTrue("one".equals(list.removeFirst().getValue()));
assertTrue("two".equals(list.removeFirst().getValue()));
assertTrue("three".equals(list.removeFirst().getValue()));
After those changes the test passes for me (the first one, you didn't implement removeLast method for the second one).
You do not need a constructor to assign null, 0 and false to object fields. Fields get these values automatically. Simply remove the constructor that only does such assignments and it will be no any difference in execution.
You can also assign other default values like int a = 17 directly in declaration, and you can also include expressions like int b = a + 1 assuming that the field a has been declared before. But you cannot pass parameters that must have different values for different instances. This is what the constructor is for.
You may still have other bugs remaining but it will be no constructor to blame.
Most often developers simply use the ready solution, LinkedList.
My assignment deals with Huffman encoding and I am using a priority queue of trees to create it. I am trying to implement comparable for my Tree class and then have a compare To method so that the Trees can be sorted in the priority queue by frequency. I am getting some error messages when trying to do this and I am not sure why.
n00832607.java:249: error: Tree is not abstract and does not override abstract method
compareTo(Object) in Comparable
class Tree implements Comparable
^
n00832607.java:423: error: method does not override or implement a method from a supertype
#Override
^
Here is the code that is giving me trouble.
//Begin tree class
class Tree implements Comparable
{
private Node root; // first node of tree
// -------------------------------------------------------------
public Tree(char data, int frequency) // constructor
{
root = new Node();
root.iData = frequency;
root.dData = data;
}
public Tree(Tree leftChild, Tree rightChild)
{
root = new Node();
root.leftChild = leftChild.root;
root.rightChild = rightChild.root;
root.iData = leftChild.root.iData + rightChild.root.iData;
}
protected Tree(Node root)
{
this.root = root;
}
//end constructors
//Misc tree methods inbetween the constructors and compareTo, I can post them if that would help
#Override
public int compareTo(Tree arg0)
{
Integer freq1 = new Integer(this.root.iData);
Integer freq2 = new Integer(arg0.root.iData);
return freq1.compareTo(freq2);
}
} // end class Tree
////////////////////////////////////////////////////////////////
Also here is my Node class if that is of any help
//Begin node class
////////////////////////////////////////////////////////////////
class Node
{
public int iData; // data item (frequency/key)
public char dData; // data item (character)
public Node leftChild; // this node's left child
public Node rightChild; // this node's right child
public void displayNode() // display ourself
{
System.out.print('{');
System.out.print(iData);
System.out.print(", ");
System.out.print(dData);
System.out.print("} ");
}
} // end class Node
////////////////////////////////////////////////////////////////
You're using the raw Comparable type, instead of using the generic Comparable<Tree> type. To compile, as is, your compareTo() method should thus take an Object as argument, and not a Tree. But of course, the correct way to fix it is to make your class implement Comparable<Tree>.
Also, note that instead of creating two new Integer instances at each comparison, you could simply use (since Java 7):
return Integer.compare(this.root.iData, arg0.root.iData);
In Lucene, I am using the TaxonomyReader to read an index of a taxonomy stored in my disk. For a given category, I need to find all categories that are its children. However, in the Lucene's API I could find a method to retrieve the parent but not with the children. There is a method called getChildrenArrays() that returns a ChildrenArrays object. As you can see, this class only has two methods:
getYoungestChildArray
getOlderSiblingArray
I want to implement Enumerator using these two methods. Does someone know how to do it?
I got the following:
private class EnumChildren implements Enumeration<Integer> {
int category, current;
int[] next, first;
public EnumChildren(int category) {
ChildrenArrays childrenArrays = tr.getChildrenArrays();
first = childrenArrays.getYoungestChildArray();
next = childrenArrays.getOlderSiblingArray();
current = first[category];
}
public boolean hasChildren() {
return (current != TaxonomyReader.INVALID_ORDINAL);
}
#Override
public boolean hasMoreElements() {
current = next[current];
return (current != TaxonomyReader.INVALID_ORDINAL);
}
#Override
public Integer nextElement() {
return current;
}
}
Ans is used as:
ordinal = tr.getOrdinal(new CategoryPath(nodeCategory.getPath(), '/'));
EnumChildren childrenEnumeration = new EnumChildren(ordinal);
if (childrenEnumeration.hasChildren()) {
do {
int current = childrenEnumeration.nextElement();
Category child = new Category(tr.getPath(current).toString());
addChildren(child);
nodeCategory.children.add(child);
} while (childrenEnumeration.hasMoreElements());
}