I'm trying to write a method that will take in two Queues (pre-sorted Linked Lists) and return the merged, in ascending order, resulting Queue object. I pasted the Queue class, the merge method starts 1/2 way down.
I'm having trouble calling merge, this is how I am trying to call it from my main method, can anyone help with this call with new1 and new2. Thanks so much Everyone!
Please let me know if anyone notices anything else out of place. Thanks!
///////////////// //Testing with a call of merge method & 2 Queues///////////////////
public class test {
public static void main (String args[]){
Queue new1 = new Queue();
new1.enqueu(1);
new1.enqueu(3);
new1.enqueu(5);
Queue new2 = new Queue();
new1.enqueu(2);
new1.enqueu(4);
new1.enqueu(6);
merge(new1, new2);
//How to call merge? Queue.merge(new1, new2)???
/////////////////Queue/Merge method below////////////////////////
public class Queue {
private Node first, last;
public Queue(){
first = null;
last = null;
}
public void enqueu(int n){
Node newNode = new Node(n);
if (first == null)
{
first = newNode;
last = newNode;
}
else
{
last.setNext(newNode);
last = newNode;
}
}
public int dequeue(){
int num = first.getNum();
first = first.getNext();
if(first == null)
last = null;
return num;
}
public Boolean isEmpty() { return first == null; }
////////////////////////Begin Queue merge/////////////////////////////////
Queue merge(Queue q1, Queue q2) {
Queue result = new Queue();
boolean q1empty = q1.isEmpty();
boolean q2empty = q2.isEmpty();
while (!(q1empty || q2empty)) {
if (q1.first.getNum() < q2.first.getNum()) {
result.enqueu(q1.dequeue());
q1empty = q1.isEmpty();
} else {
result.enqueu(q2.dequeue());
q2empty = q2.isEmpty();
}
}
if (!q1empty) {
do {
result.enqueu(q1.dequeue());
} while (!q1.isEmpty());
} else if (!q2empty) {
do {
result.enqueu(q2.dequeue());
} while (!q2.isEmpty());
}
return result;
}}
You have what appears to be a bug here:
Queue new1 = new Queue();
new1.enqueu(1);
new1.enqueu(3);
new1.enqueu(5);
Queue new2 = new Queue();
new1.enqueu(2);
new1.enqueu(4);
new1.enqueu(6);
You've added six elements to new1 and zero to new2.
Since your merge method is an instance method of the Queue class, you need to call it on an instance of Queue, such as
Queue q = new Queue();
Queue merged = q.merge(new1, new2);
However since merge appears to have no side-effects and does not alter any state of the Queue instance, you probably want to just make this method static so that it belongs to the Queue class and not an instance of Queue. For example:
static Queue merge(Queue q1, Queue q2) {
...
}
//in main()...
Queue merged = Queue.merge(new1, new2);
A simple approach to merging two sorted Iterators into another Iterator:
public static Iterator<Object> merge(final Iterator<Object> it1,
final Iterator<Object> it2, final Comparator<Object> comp) {
return new Iterator<Object>() {
private Object o1 = it1.hasNext() ? it1.next() : null, o2 = it2
.hasNext() ? it2.next() : null;
#Override
public boolean hasNext() {
return o1 != null || o2 != null;
}
#Override
public Object next() {
if (o1 == null && o2 == null)
throw new NoSuchElementException();
Object ret;
if (o1 == null) {
ret = o2;
o2 = it2.hasNext() ? it2.next() : null;
} else if (o2 == null) {
ret = o1;
o1 = it1.hasNext() ? it1.next() : null;
} else {
if (comp.compare(o1, o2) <= 0) {
ret = o1;
o1 = it1.hasNext() ? it1.next() : null;
} else {
ret = o2;
o2 = it2.hasNext() ? it2.next() : null;
}
}
return ret;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Not implemented");
}
};
}
Related
So, I am trying to write two overloaded remove methods for LinkedList class, where one takes an index of an element that needs to be removed and another one that takes Object that needs to be removed. But when I try to make a LinkedList of integer and call the latter method, method that takes in index is called instead. Is there any way around this??
(PS. I know you can just change the name of the method, but I am given an interface file that requires me to write overloaded methods)
public E remove(int index) {
for (int i = 0; i < index;i++) {
curNode = curNode.next();
}
if (curNode == head && curNode == tail) {
head = null;
tail = null;
}
else {
URNode sucNode = curNode.next();
URNode prevNode = curNode.prev();
if (sucNode != null)
sucNode.setPrev(prevNode);
else {
prevNode.setNext(null);
tail = prevNode;
}
if (prevNode != null)
prevNode.setNext(sucNode);
else {
sucNode.setPrev(null);
head = sucNode;
}
}
numElements--;
return null;
}
public boolean remove(Object o) {
URNode curNode = head;
for (int i = 0; i < numElements;i++) {
if (curNode.element() == o) {
remove(i);
return true;
}
curNode = curNode.next();
}
return false;
}
public static void main(String args[]){
LinkedList intList = new LinkedList();
intList.add(1);
intList.add(2);
intList.add(3);
intList.remove(1); //I want this to remove node with element 1, instead of node with index of 1
//[2][3] should be returned, not [1][3]
}
intList.remove(Integer.valueOf(1)); // just make it Integer but not int
It works fine and gives me the correct output until it enters the last object to add to nonEmptyList in the sample() method. I have managed to find out where it is looping, which is in the while loop in the add(item) method. I can't change the methods or returns, so if anyone could suggest a way I could prevent this infinite loop, that would be appreciated.
public class SampleableListImpl implements SampleableList {
public int size;
public Object firstLink = null; //Made a link class to manage each object, this class is the linkedlist (manager) of the object private
public ReturnObjectImpl ro;
int count;
SampleableListImpl emptyList;
SampleableListImpl nonEmptyList;
public ReturnObject add(Object item) {
if (firstLink == null){
firstLink = item;
size++;
firstLink.setIndex(0);
System.out.println("Added linkedlink at 0");
} else if (firstLink != null){
Object current = firstLink;
while (current.getNextNode() != null){ //LOOPS HERE AFTER sample() sends the last object to be added to nonEmptyList
current = current.getNextNode();
}
current.setNextNode(item);
size++;
current.getNextNode().setIndex(size - 1);
System.out.println("Added a new link to the existing linkedlist at " + current.getNextNode().getIndex());
}
return null;
}
public SampleableList sample() {
if (firstLink == null){
System.out.println("List is empty, so returning an empty sampableList");
return emptyList = new SampleableListImpl();
}
Object current = firstLink;
if (firstLink.getNextNode().getNextNode() != null){
nonEmptyList = new SampleableListImpl();
System.out.println("Adding to firstNode in nonEmptyList");
nonEmptyList.add(firstLink);
while (current.getNextNode().getNextNode() != null){
current = current.getNextNode().getNextNode();
System.out.println("Adding " + current.getIndex() + " to nonEmptyList");
nonEmptyList.add(current);
}
} else {
nonEmptyList.firstLink = current;
System.out.println("There is only a head - no other objects to sample");
}
System.out.println("returning nonEmptyList");
return nonEmptyList;
}
}
And I am running this
SampleableListImpl sampList = new SampleableListImpl();
Object ob = new Object();
Object ob1 = new Object();
Object ob2 = new Object();
Object ob3 = new Object();
Object ob4 = new Object();
sampList.add(ob);
sampList.add(ob1);
sampList.add(ob2);
sampList.add(ob3);
sampList.add(ob4);
sampList.sample();
When all 5 objects are added just before call sample():
ob.getNextNode() will return ob1.
ob1.getNextNode() will return ob2.
ob2.getNextNode() will return ob3.
ob3.getNextNode() will return ob4.
ob4.getNextNode() will return null.
sample() will in the first loop add ob again:
ob.getNextNode() will return ob1.
ob1.getNextNode() will return ob2.
ob2.getNextNode() will return ob3.
ob3.getNextNode() will return ob4.
ob4.getNextNode() will return ob.
In the second loop within sample() it will try to add ob2, but it can no longer reach the end of your list.
What you could do to get around this, is create a copy of each object you want to add from sample() (and set their next node to null before adding).
I am having a problem with Iterators. I am writing a custom linked list as using an iterator to be able to traverse the list.
The iterator looks like this:
public class NodeIterator implements Iterator<Node> {
private Node current = head;
private Node lastReturned = head;
public boolean hasNext() {
return lastReturned.getLink() != null;
}
public Node next() {
lastReturned = current;
current = current.getLink();
return lastReturned;
}
public void remove() {
removeNode(lastReturned);
lastReturned = null;
}
}
I'm still in the early stages so I'm testing the data structures from the console by populating the nodes with this method.
private static void MethodToPopulateNodes() {
MyObject o = new MyObject();
String[] responses = new String[prompts.length];
scanner = new Scanner(System.in);
boolean done = false;
String s = null;
while (!done) {
int i = 0;
for (String prompt : prompts) {
System.out.println(prompt);
s = scanner.nextLine();
if (s.equalsIgnoreCase("stop")) {
done = true;
break;
} else {
responses[i] = s;
}
i++;
}
if (done) {
break;
}
o = new MyObject(responses);
myNode.add(c);
}
}
When I try to use the iterator when there is only one Node, it doesn't do anything. No errors or anything. However, if I have multiple nodes, this foreach works flawlessly.
public static void main(String[] args) {
myNode = new Node();
methodToPopulateLinkedList();
for (Node node : myNode) {
//toString is overridden for my object
System.out.println(node.getData().toString());
}
}
UPDATE: I edited the iterator to return hasNext() == true on the first iteration:
public class NodeIterator implements Iterator<Node> {
private boolean done = false;
private Node current = head;
private Node lastReturned = head;
public boolean hasNext() {
if (head == tail && head != null && !done) {
done = true;
return true;
}
return lastReturned.getLink() != null;
}
public Node next() {
lastReturned = current;
current = current.getLink();
return lastReturned;
}
public void remove() {
removeNode(lastReturned);
lastReturned = null;
}
}
I feel like that is super janky but it works. It seems like Java calls hasNext() first before calling next so I have to treat the special case differently.
|123
hasNext() == true
next() == 1
1|23
hasNext() == true
next() == 2
12|3
Where | equals the cursor. Is that accurate? Is there a better way to solve this?
If there's just one Node, it would have the special case of its ->next being null. Before the loop, try printing out the first node, I think your loop might be looking one ahead.
I need to merge two lists of strings in java and I'm not too sure on the best way to do it. I have to use iterators and the compareTo() method. For example...
Example: L1: A,B,C,D L2: B,D,F,G result: A,B,B,C,D,D,F,G
I can assume the input lists are already sorted and i cant use the contains() method. I have some initial checks but the while loop is what im stuck on.
public static ListADT<String> merge(ListADT<String> L1,ListADT<String> L2) throws BadListException {
ListADT<String> L3 = new ArrayList<String>;
if(L1 == null || L2 == null) {
throw new BadListException();
}
Iterator<String> itr1 = new L1.iterator();
Iterator<String> itr2 = new L2.iterator();
if(L1.size() == 0 && L2.size() == 0) {
return L3;
}
if(L1.size() == 0 && L2.size() != 0) {
for(int i = 0; i < L2.size(); i++) {
return L3.add(L2.get(i));
}
}
if(L2.size() == 0 && L1.size() != 0) {
for(int i = 0; i < L1.size(); i++) {
return L3.add(L1.get(i));
}
}
while(itr1.hasNext() || irt2.hasNext()) {
//merge the lists here?
}
}
Any help would be appreciated.
It's fairly straightforward if you just use variables to hold the current value from each iterator. This solution assumes your lists do not contain null, but it would not be difficult to add null-handling since the lists are sorted.
package com.example;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class IteratorMerge {
/**
* #param args
*/
public static void main(String[] args) {
List<String> list1 = Arrays.asList(new String[]{"A", "B", "C", "D"});
List<String> list2 = Arrays.asList(new String[]{"B", "D", "F", "G"});
System.out.println(merge(list1, list2));
}
public static List<String> merge(List<String> L1,List<String> L2) {
List<String> L3 = new ArrayList<String>();
Iterator<String> it1 = L1.iterator();
Iterator<String> it2 = L2.iterator();
String s1 = it1.hasNext() ? it1.next() : null;
String s2 = it2.hasNext() ? it2.next() : null;
while (s1 != null && s2 != null) {
if (s1.compareTo(s2) < 0) { // s1 comes before s2
L3.add(s1);
s1 = it1.hasNext() ? it1.next() : null;
}
else { // s1 and s2 are equal, or s2 comes before s1
L3.add(s2);
s2 = it2.hasNext() ? it2.next() : null;
}
}
// There is still at least one element from one of the lists which has not been added
if (s1 != null) {
L3.add(s1);
while (it1.hasNext()) {
L3.add(it1.next());
}
}
else if (s2 != null) {
L3.add(s2);
while (it2.hasNext()) {
L3.add(it2.next());
}
}
return L3;
}
}
Here's some pseudocode for the basic algorithm:
while(itr1 && itr2)
{
if(itr1 value < it2 value)
add itr1 to list
increment itr1
else
add itr2 to list
increment itr2
}
check if itr1 or itr2 still have more elements
while itr1 or itr2 has more elements, add those elements to the list
We know that the lists are sorted, so at each stage, we simply grab the smallest element from each list and add it to the merged list. If, at the end, one of the iterators is exhausted and the other is not, then we can simply iterate through the one which still has elements, appending each element in turn to the merged list.
As you've seen, doing this with Iterators in Java is a bit of a pain as next() removes the element. One way of getting around this is to utilize two Queues, one for each Iterator, that store the values from the call to next(). You then need to compare the head of each queue, adding the minimum to the merged list and then removing it from its respective Queue.
As you've found, it is sort of a pain to merge using iterators. Let's explicitly state why:
For each step of the merge, you want to inspect the first element of both sequences, but you only want to advance through one.
Iterator#next() bundles these inspect and advance operations into one operation, so it is impossible to inspect the head of both sequences without also advancing through both.
What you need is a way to peek at the first element in an Iterator without advancing it. If you had this ability, then the merge would look something like:
public <T extends Comparable<T>> List<T> merge(Iterator<T> it1, Iterator<T> it2) {
PeekableIterator<T> seq1 = new PeekableIterator<T>(it1);
PeekableIterator<T> seq2 = new PeekableIterator<T>(it2);
List<T> merged = new ArrayList<T>();
while (seq1.hasNext() && seq2.hasNext()) {
if (seq1.peekNext().compareTo(seq2.peekNext()) < 0) {
merged.add(seq1.next());
} else {
merged.add(seq2.next());
}
}
while (seq1.hasNext()) {
merged.add(seq1.next());
}
while (seq2.hasNext()) {
merged.add(seq2.next());
}
return merged;
}
And it turns out that it is not too difficult to create this PeekableIterator! You just need to keep track of whether or not you currently have a peeked element, and what that element is.
public class PeekableIterator<T> implements Iterator<T> {
private final Iterator<T> backing;
private boolean havePeek = false;
private T peek;
public PeekableIterator(Iterator<T> backing) {
this.backing = backing;
}
#Override
public boolean hasNext() {
return havePeek || backing.hasNext();
}
#Override
public T next() {
if (havePeek) {
havePeek = false;
return peek;
} else {
return backing.next();
}
}
public T peekNext() {
if (!havePeek) {
peek = backing.next();
havePeek = true;
}
return peek;
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
}
EDIT
I didn't notice the comment above referring to the PeekingIterator in Google's Guava library, which is more or less the same as the PeekableIterator here. If you have access to third party libraries, this would certainly be preferable to rolling your own.
Don't try to manage merging of an empty list with a non empty one as a special case, just loop until at least one of the iterators is valid and do your work directly there:
public static ListADT<String> merge(ListADT<String> L1,ListADT<String> L2) throws BadListException {
ListADT<String> L3 = new ArrayList<String>;
Iterator<String> itr1 = new L1.iterator(), itr2 = new L2.iterator();
while (itr1.hasNext() || itr2.hasNext()) {
if (!itr1.hasNext())
L3.add(itr2.next());
else if (!itr2.hasNext())
L3.add(itr1.next());
else {
String s1 = peek from itr1
String s2 = peek from itr2;
if (s1.compareTo(s2) < 0) {
L3.add(itr1.next());
L3.add(itr2.next());
}
else {
L3.add(itr2.next());
L3.add(itr1.next())
}
}
}
}
public class MergeIterator {
public static void main(String[] args) {
List<String> s1 = new ArrayList<String>();
s1.add("a");
s1.add("z");
s1.add("b");
s1.add("k");
s1.add("c");
Collections.sort(s1);
List<String> s2 = new ArrayList<String>();
s2.add("p");
s2.add("a");
s2.add("d");
s2.add("n");
s2.add("m");
Collections.sort(s2);
Iterator<String> it1 = s1.iterator();
// sortIterator(it1);
Iterator<String> it2 = s2.iterator();
System.out.println();
combine(it1, it2);
}
private static Iterator<String> combine(Iterator<String> it1,
Iterator<String> it2) {
Iterator<String> it3 = null;
List<String> l1 = new ArrayList<>();
String s1 = null, s2 = null;
while (it1.hasNext() || it2.hasNext()) { //line 1
s1 = (s1 == null ? (it1.hasNext() ? it1.next() : null) : s1); //line 2
s2 = (s2 == null ? (it2.hasNext() ? it2.next() : null) : s2); // line 3
if (s1 != null && s1.compareTo(s2) < 0) { // line 4
l1.add(s1);
s1 = null;
} else {
l1.add(s2);
s2 = null;
}
}
it3 = l1.iterator();
return it3;
}
}
I would like to use a linked list in order to perform extractions and insertions of elements, trying out all combinations for a heuristic. Linked lists are more efficient for this type of operations.
Since I would want to try all possible pairs of extractions/inserts, I used two different iterators over the list. This raises a "ConcurrentModificationException". How could I perform this operation efficiently, without re-traversing the list every time, as this would defeat the whole purpose of using a list in the first place?
Here is the relevant part of the code:
ListIterator<Integer> it1 = data.listIterator();
ListIterator<Integer> it2;
while(it1.hasNext()) {
int i = it1.next();
it2 = data.listIterator();
while(it2.hasNext()) {
if (i == it2.next()) continue; // continue right away when the indexes are equal
it1.remove();
it2.add(i);
if (length() < best)
return true;
}
// when the swap is not better/consistent
it2.remove();
it1.add(i);
}
return false;
Thanks
You can't use multiple iterators simultaneously on a LinkedList, however you can with a CopyOnWriteArrayList
Try this:
List<Integer> safeData = new CopyOnWriteArrayList(date);
// your code, but working with safeData rather than data
If I get you right, you look for a data structure that offers several iterators for manipulating the list. This is technically difficult for the original java.util.LinkedList because it does housekeeping for the current index and this is only possible in an efficient way if there are no parallel changes at unknown positions in the list by other iterators. But, you can easily implement a simple LinkedList that does not do this housekeeping and supports adding/removing through several iterators. Then, an iterator does not know its position in the list, but I bet you do not care. Just use something like this:
public class MyList<T> {
private MyNode<T> first = null, last = null;
public MyNode<T> getFirst() {
return first;
}
public MyNode<T> getLast() {
return last;
}
public boolean contains(MyNode<T> n) {
return n.list == this;
}
/**
* If beforeMe is null, toInsert is inserted at the end of the list.
* #return inserted node
*/
public void insertBefore(MyNode<T> beforeMe, MyNode<T> newNode) {
if (newNode == null) {
throw new IllegalArgumentException("toInsert must not be null!");
}
if (newNode.list != null) {
throw new IllegalArgumentException("This node is already in the list " + newNode.list);
}
if (beforeMe == null) {
if (last == null) {
newNode.prev = newNode.next = null;
first = last = newNode;
} else {
last.next = newNode;
newNode.prev = last;
newNode.next = null;
last = newNode;
}
} else {
newNode.prev = beforeMe.prev;
newNode.next = beforeMe;
if (beforeMe.prev != null) {
beforeMe.prev.next = newNode;
} else {
first = newNode;
}
beforeMe.prev = newNode;
}
newNode.list = this;
}
/**
* If beforeMe is null, t is inserted at the end of the list.
* #return inserted node
*/
public MyNode<T> insertBefore(MyNode<T> beforeMe, T t) {
MyNode<T> newNode = new MyNode<T>(t);
insertBefore(beforeMe, newNode);
return newNode;
}
public void remove(MyNode<T> n) {
if (n == null || n.list != this) {
throw new IllegalArgumentException("Node is not in the list!");
}
if (n.prev != null) {
n.prev.next = n.next;
} else {
first = n.next;
}
if (n.next != null) {
n.next.prev = n.prev;
} else {
last = n.prev;
}
n.prev = n.next = null;
n.list = null;
}}
public class MyNode<T> {
private T t;
/**
* written only by MyList
*/
MyNode<T> prev = null;
/**
* written only by MyList
*/
MyNode<T> next = null;
/**
* written only by MyList
*/
MyList<T> list = null;
public T get() {
return t;
}
public void set(T t) {
this.t = t;
}
public MyNode<T> previous() {
return prev;
}
public MyNode<T> next() {
return next;
}
public MyList<T> list() {
return list;
}
/**
* called only by MyList.
* #param t
*/
MyNode(T t) {
this.t = t;
}}
You can use ANY number of iterators on a LIST when you are doing only a read operation. Since you are doing a remove / add here, you can't use the same list with two different iterators as it will cause the ConcurrentModificationException as you are experiencing now.
What you like to achieve? May be, people can help you with different options.