currently, I am working on implementing an AddAtIndex method and for the most part it seems to be working fine. However, my method is not passing my JUnit test and I can't seem to understand why. Thus, I have chosen to show the code I have done thus far:
**
* Add an element to the list at the specified index
* #param The index where the element should be added
* #param element The element to add
*/
public void add(int index, E element ) //Method should be O(1) time.
{
// TODO: Implement this method
if (index < 0) {
System.out.println("Can't add an element at a negative index.");
}
int i = 0;
LLNode<E> currentNode = head.next;
while ( i < size ) {
if ( i == index ) {
LLNode<E> newNode = new LLNode<E>(element);
LLNode<E> tempNode = new LLNode<E>(currentNode.data);
currentNode.next = tempNode;
currentNode.data = newNode.data;
newNode.prev = currentNode.prev;
newNode.next = tempNode;
tempNode.prev = newNode;
size++;
}
currentNode = currentNode.next;
i++;
}
}
My thought process behind the code is that the method creates a new Node, then it replaces the data at the specified index of the linked list. However, the data at the node it is replacing is stored in a temporary node which is incremented in position to the next node after the new node. I am about 80% confident in my implementation though the code looks a bit sloppy. I have created a driver to demonstrate the implementation. The drivers code is as follows:
public class LinkedListDriver {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyLinkedList<String> nameList = new MyLinkedList<String>();
nameList.add("Hamadi");
nameList.add("Ballo");
nameList.add(1, "Salisu");
nameList.add(2, "Galo");
System.out.println(nameList.toString());
System.out.println(nameList.size());
nameList.set(2, "Abdullahi");
System.out.println(nameList.toString());
nameList.remove(1);
System.out.println(nameList.toString());
MyLinkedList<Integer> list1 = new MyLinkedList<Integer>();
list1.add(65);
list1.add(21);
list1.add(42);
System.out.println(list1.toString());
list1.remove(0);
System.out.println(list1.toString());
}
}
The Output from the driver is as follows:
List: Hamadi, Salisu, Galo, Ballo,
4
Replacing Galo with Abdullahi
List: Hamadi, Salisu, Abdullahi, Ballo,
Removing Salisu from the list
List: Hamadi, Abdullahi, Ballo,
List: 65, 21, 42,
Removing 65 from the list
List: 21, 42,
The unit test fails however with the following error:
It fails at the AssertEquals method:
shortList.add(2, "E");
shortList.add(3, "F");
**assertEquals("AddAtIndex: at position 2 ", "E", shortList.get(2)); //fails here**
assertEquals("AddAtIndex: at position 3 ", "F", shortList.get(3));
assertEquals("AddAtIndex: List size is ", 6, shortList.size());
I would like to know what I'm doing wrong. I have this literally completely figured out, though I know that there is something a bit off about my AddAtindex method. Thanks!
You don't need that tempNode. Just create the newNode and insert it properly between currentNode and its previous node.
You should also consider the possibility of adding an element at the beginning (no previous) or end (no next) of the list.
I used head and tail as sentinel nodes. Created a new node to be added in the list.
public boolean add(E element) {
// create new element
LLNode<E> variable = new LLNode(element);
variable.next = null;
variable.prev = null;
// if element is null, throw exception
if (element == null) {
// return false;
throw new NullPointerException("Element is null");
} else {
// get the value stored in tail.prev in variable temp.
variable.prev = tail.prev;
variable.next = tail;
// now modify the tail node prev and new node next
tail.prev = variable;
// get prev node next link changed
variable.prev.next = variable;
// update size
if (head.next.next != tail) {
size++;
}
return true;
}
}
Related
I have these folowing methods and I want to implement this in a class called LinkedBag
void replace(T oldEntry, T newEntry){}
boolean isDuplicated(T anEntry){}
void doubleBag(){}
void replace(T oldEntry,T newEntry) replaces any entry that is equal to oldEntry with the new entry newEntry. For example,suppose that replace(A,D) is called on this bag {A,B,C,A}. The resulting bag should be {D,B,C,D}
the boolean returns true if the entry anEntry appears more than
one time in the bag and false otherwise. For example, calling isDuplicated(B) on the resulting
bag in part 1 should return false, but isDuplicated(D) should return true.
void doubleBag()adds to the bag a copy of each entry that appears in the bag. For example,
calling doubleBag() on the resulting bag in part 1 should change the bag contents to {4’D, 2’B, 2’C}.
Now so far I though of getting the frequency of a node and checking if the node is duplicated like:
public boolean isDuplicated(T anEntry){
Node currentNode =firstNode;
int counter=0;
while ((counter <numberOfEntries)&&(currentNode!=null))
if(anEntry.equals(currentNode)){
return true;
}
return false;
}
and for the replace method I tried assigning values to another variables then removing them and then reassigning them again but I don't think it's right
T entry=null;
T entry1 = null;
oldEntry=entry;
newEntry=entry1;
remove(oldEntry);
entry=newEntry;
entry1=oldEntry;
add(oldEntry);
add(newEntry);
System.out.println( oldEntry+" , "+newEntry );
}
as for the double bag I still don't know how to do it.
Excuse me for my bad programming I am learning java new, and still learning the basics.
Let's just briefly look at your replace method:
T entry = null;
T entry1 = null;
// entry and entry1 are both null
oldEntry = entry;
newEntry = entry1;
// entry, entry1, oldEntry and newEntry are all null.
remove(oldEntry); // remove null
entry = newEntry; // overwriting null with null
entry1 = oldEntry; // same as previous statement
add(oldEntry); // add null
add(newEntry); // add null again
// print "null , null"
System.out.println(oldEntry + " , " + newEntry);
It's not clear what you're trying to do, but at least what's here is just a bunch of nothing. What you probably want is a little more like this:
// assuming oldEntry and newEntry are set somewhere and are correct,
// and that remove and add work as expected:
remove(oldEntry);
add(newEntry);
// And you'll want to repeat this for as many duplicates as there are of oldEntry.
As for the doubleBag method, you'll want some way to walk over entries, and then duplicate them:
Node currentNode = head;
Node newHead = null;
Node newTail = null;
while (currentNode != null) {
Node first = new Node(currentNode.data);
Node second = new Node(currentNode.data);
first.next = second;
if (newHead != null) {
newTail.next = first;
newTail = second;
} else {
newHead = first;
newTail = second;
}
currentNode = currentNode.next;
}
return newHead;
This code traverses the input list starting at head, creates two copies of the node (named first and second), links them together and appends them to a new list, which it returns at the end.
That should get you started. Also, notice how the traversal works, and see how it differs from your isDuplicated implementation (which currently has an infinite loop). I'll leave it to you to fix your implementation.
I have a method that finds a node in a linked list with a certain id and adds items to the arraylist of that node.
ArrayList <String> elems;
public Place addElemToLst(String id, String elem) {
// if no nodes create new node
if (head == null) {
Node node = new Node(id);
node.elems.add(item);
head = unit;
} else if (head != null) {
Node curr = head;
while (curr.next != null && !curr.next.id.equals(id)) {
curr = curr.next;
}
// if there is a id match
if (curr.id.equals(id)) {
curr.elems.add(item);
}
// add new Node
else { // the error is in this section
Node node = new Node(id);
node.elems.add(elem);
curr.next = node;
}
}
return this;
}
The problem is when I call addElemToLst() on an id of lets say "item1" multiple times and keep adding elements to the arraylist, the arraylist will only keep the last item entered into the arraylist. Essential, the arraylist is always a size of 1 because previous entries keep getting replaced. Why is this and what is the error? I have isolated the error to the comment in the code.
Thanks
You are not checking the first element/head for the correct ID
while (curr.next != null && !curr.next.id.equals(id))
You can try something like this for the second half:
else {
Node curr = head;
Node prev = null;
while(curr != null){
if(curr.id == id){
curr.elems.add(elem);
return this;
}
prev = curr;
curr = curr.next;
}
Node node = new Node(id);
node.elems.add(elem);
prev.next = node;
}
}
Your approach to finding a node with a matching ID will return a few different false negatives, which will in turn cause existing nodes to be overwritten. The issue is that you're using a sliding window to inspect nodes and determine a match, but your criteria for sliding doesn't line up with your criteria for determining whether to append to an existing node or create a new node.
Here are a few examples to illustrate:
_ = null
x = node
o = node with matching ID
[ ] = sliding window (left side is `curr`, right side is `curr.next`)
x -> o -> _
[ ]
Since the matching node is at the end of the list, you should append
`elem` to it. However, your code checks `curr.id` (instead of `curr.next.id`),
incorrectly concludes that no matching node is found, and overwrites `curr.next`.
o -> x -> _
[ ]
[ ]
Here, the matching node is at the head of the list, but your code
skips it and incorrectly creates a new node at the end of the list.
o -> x -> x -> _
[ ]
[ ]
[ ]
Same as above, a new node is incorrectly inserted at the end of
the list since you skipped the matching node at the head of the list.
x -> o -> x -> _
[ ]
Since you're checking `curr.id` (instead of `curr.next.id`), your code
incorrectly concludes that a new node needs to be created, overwriting
the existing (matching) node and truncating the tail of the list.
Linked lists are tough to reason about, and combining while conditions makes it even more difficult to grok. Here is a fixed implementation that (IMO) is easier to reason about:
public Place addElemToLst(String id, String elem) {
// if the list is empty, create a new node
if (head == null) {
Node node = new Node(id);
node.elems.add(elem);
head = node;
return this;
}
Node curr = head;
while (curr.next != null) {
// if the matching node appears inside the list,
// append the element and return
if (curr.id.equals(id)) {
curr.elems.add(elem);
return this;
}
curr = curr.next;
}
// if the last node in the list is a match, use it
if (curr.id.equals(id)) {
curr.elems.add(elem);
// now that you've exhausted all nodes, create a new one
} else {
Node node = new Node(id);
node.elems.add(elem);
curr.next = node;
}
return this;
}
I have my code as following:
Node current=head;
if(current==null)//check
else{
while(current.getNext()!=null)
current=current.getNext(); //loop through to find the last node in the list
}
//if I find it then connect it with my newNode(add)
Node add=new Node("A");
current.setLink(add);
add.setLink(null);
But it does not work, I drawn a diagram but still have no idea what`s wrong with it.
the line
if(current==null) //why do you check if you don't have any statements afterwards?
this solution is for singly linked list:
public static Node addLast(Node head, Object x) {
// save the reference to the header so we can return it.
Node ret = head;
// check base case, head is null.
if (header == null) {
return new Node(x, null);
}
// loop until we find the end of the list
while ((head.next != null)) {
head = head.next;
}
// set the new node to the Object x, next will be null.
head.next = new Node(x, null);
return ret;
}
I'm working on a link list and not currently able to remove a speficic node by a key value. I ask a helper at my school and he is not sure why it isn't working.(There is also a lot of try-catches for another issue I apologize for how gross it looks)
Here is my remove method:
public void remove(int key) throws Exception {
Node tmp = first;
Node pred = first;
while (tmp != null) {
if (tmp.keyValue == key) {
pred = tmp;
tmp = tmp.next;
} else {
tmp = tmp.next;
}
}
Here is my main method creaing the list and trying to remove it and print it:
OrderedLinkedList oLL3 = new OrderedLinkedList();
try {
oLL3.insert("Should be removed", 5);
oLL3.insert("Shouldn't be removed 2nd", 15);
oLL3.insert("Shouldn't be removed", 10);
} catch (Exception e) {
System.out.println("Error: Two nodes with the same key value and the newest one won't be stored.");
}
try {
oLL3.remove(5);
} catch (Exception r) {
System.out.println("Error:No nod with the key value to be removed");
}
System.out.print("toString test removing node: \n" + oLL3.toString());
System.out.println("Number of nodes in the List:" + oLL3.listCount());
}
In this code shown you are deleting the first node of the linked list, and to delete the first node you need to point the "head" (or whatever the name of your head node is) to the second node, i.e.
head = head.next;
Your remove method is only assigning to local variables. That is not going to affect the state in your linked list. Assuming that the head of your list is the node held by the field first, you need to assign to either first or to the .next field in another node.
To remove the first node, you can do:
first = first.next;
To remove the node after node prev, you can do:
prev.next = prev.next.next;
(null-checking where appropriate)
I am trying to write a function addFirst() that takes an item and inserts it at the front of a doubly linked list. The doubly linked list has two dummy nodes, one on each end. The addFirst() method that I wrote so far only returns to two dummy nodes when I iterate through the list and print it. I cannot figure out what is wrong with my code.
public void addFirst(E item) {
if (item.equals(null)) { throw new NullPointerException(); }
Node node = new Node(item, null);
Node ptr = first;
ptr.next.prev = node;
node.prev = ptr;
node.next = ptr.next;
}
public static void main(String[] args) {
Deque<Integer> lst = new Deque<Integer>(); // empty list
lst.addFirst(1);
lst.addFirst(2);
lst.addFirst(3);
Iterator<Integer> it = lst.iterator(); // tests iterator method
while (it.hasNext()) {
Integer val = it.next();
System.out.println(val);
}
}
When I run main, all I get is:
null null
However, I expect:
null 3 2 1 null
Can anybody show me how I can fix my code so that I can add an item at the start of my doubly linked list in between the two dummy first and last nodes?
I found what I did wrong. I just needed to complete the chain by adding the line
ptr.next = node;
So my full code for this method looked like this:
public void addFirst(E item) {
if (item.equals(null)) { throw new NullPointerException(); }
Node node = new Node(item, null);
Node ptr = first;
ptr.next.prev = node;
node.prev = ptr;
node.next = ptr.next;
ptr.next = node;
}