I'm using a custom LinkedList class that goes like this:
public class LinkedList {
// Get and Set methods are NOT necessary!
private LinkedList next;
private final String word;
public LinkedList(String word, LinkedList next) {
this.word = word;
this.next = next;
}
Now my task is to write a method that takes an array of Strings, and coverts each string object into a LinkedList WITHOUT loops, so using recursion. How can this be done without loops? This is unimaginable to me. Where do I begin?
Edit: Let me clarify that the function I'm supposed to write only takes one argument, which is an array of Strings, and returns a LinkedList..
enter code here
public LinkedList arrayToLinkedList(String[] myArray)
{
String[] toConvert = myArray;
List<String> toConvertList = (List) Arrays.asList(toConvert);
LinkedList<String> convertedLinkedList = new LinkedList<String>(toConvertList);
return convertedLinkedList;
}
Probably just me, but I don't like any of the solutions provided.
/**
* Creates linked list from array input.
*
* #param input
* data array
* #return linked list with data
*/
public static LinkedList Of(String[] input) {
// Checks if array has elements.
if (input == null || input.length < 1)
return null;
// Starts creating the array using overload 2.
return LinkedList.Of(input, 0);
}
/**
* Creates linked list from array input (overload 2).
*
* #param input
* data array
* #param i
* counter to remember at what element is current
* #return linked list with data
*/
public static LinkedList Of(String[] input, int i) {
//Tests if counter is within array elements.
if (input.length - 1 > i)
// Returns new element with (current element data, reference
// to next element). Note that next element will be returned
// by this same method (this is why it is recursive).
return new LinkedList(input[i], LinkedList.Of(input, i + 1));
//Last element. From here backtracking will begin.
return new LinkedList(input[i], null);
}
Here is something else:
public String toString() {
StringBuilder sb = new StringBuilder(this.word);
LinkedList tmp = this;
while (tmp.next != null) {
sb.append(" > ");
tmp = tmp.next;
if (tmp.word != null)
sb.append(tmp.word);
}
return sb.toString();
}
And to test:
String str = "Neque porro quisquam est qui dolorem ipsum quia "
+ "dolor sit amet, consectetur, adipisci velit...";
LinkedList ll = LinkedList.Of(str.split("\\s+"));
System.out.println(ll);
I'm not sure what language you are using, but here's a general idea:
public LinkedList myfunction(String arr[]) {
if(arr.empty == true)
return void;
//return the array minus the first element
String shorterarray[] = substr(arr[],1);
//recursively create the next element
LinkedList myItem = new LinkedList(arr[0], myfunction(shorterarray[]));
}
You'll have to do the subtring and boundary checking in whatever language you are using.
How about:
public static void main(String[] args) {
String[] data = new String[] { "1", "2", "3" };
LinkedList head = build(data);
while (head != null) {
System.out.println(head.word);
head = head.next;
}
}
private static LinkedList build(String[] data) {
if (data == null || data.length == 0) {
return null;
}
LinkedList head = new LinkedList(data[0], null);
build(head, data, 1);
return head;
}
private static LinkedList build(LinkedList node, String[] data, int index) {
if (index == data.length) {
return node;
}
node.next = build(new LinkedList(data[index], null), data, ++index);
return node;
}
private static class LinkedList {
private final String word;
private LinkedList next;
public LinkedList(String word, LinkedList next) {
this.word = word;
this.next = next;
}
}
To add, it might also be worth while pointing out that creating collections with recursion is really bad in practice - it can easily blow out your stack size.
First, anything you can do with iteration (looping) you can do with recursion, and vice-versa (though without tail-call elimination, something Java doesn't have, recursion is often more expensive than iteration).
When trying to figure out how to solve a problem recursively you want to figure out how to break off one or more pieces of the problem that look like the same sort of problem but only smaller. With list problems that often means that when given an n element list you want to recursively handle n-1 elements. You also need to have a base case so the recursion will terminate. With lists the base case is usually a list of 0 elements.
An array is a lot like a list, but Java arrays don't have slicing (ie: you can't pass around just a piece of an array) so you'll want a helper method that knows which piece of the array we care about:
private static LinkedList fromArray(String[] a, int offset) {
Since your LinkedList class breaks down into a word and then the tail part of the list (pointed to by next) it makes sense for us to also deal with the tail part of the input array. The offset parameter lets us know how much of the tail part of the array we'll be looking at: it's the first index we care about.
The public method will just call the helper method giving it an offset of 0:
public static LinkedList fromArray(String[] a) {
return fromArray(a, 0);
}
An offset of 0 means we care about element 0 (the first element) and every element after it.
So now to write the "helper" method, which is where all of the real work is done.
First, get the base case out of the way. The base case is where the part of the array we're converting is empty. That would be the case if offset >= a.length. In that case we want to return an empty LinkedList, which is actually represented by null. So return null in that case.
Once the base case is taken care of, think about the recursive case. We have one or more elements in the part of the array we care about. Let's create a LinkedList to hold the first of those elements, a[offset]. (The first element we care about, that is. Recall that the helper only cares about the part of the array starting at offset up to the end.) The rest of the elements can be handled by calling ourselves passing in the same array, but incrementing offset by one, as we don't want the recursive call to handle the element we already handled.
Call a function that takes three arguments; a source array, a current position in the array, and a destination linked list.
Does that get your head going/can you figure it out from there?
Try this:
private LinkedList formlist(LinkedList list, String[] str, int length, int i) {
if(i==length)
return list;
return formlist(new LinkedList (str[i],list),str,length,i+1);
}
Ok, since there is the requirement for a single method with String[] args.
here is a java example. (based on a previous answer but converted to java)
private LinkedList build(String arr[]) {
if(arr.length == 0)
return null;
//return the array minus the first element
String shorterarray[] = Arrays.copyOfRange(arr, 1, arr.length);
//recursively create the next element
return new LinkedList(arr[0], build(shorterarray));
}
Related
I have two fields in my custom class List:
LinkedList<String> breadList;
Iterator<String> iterator.
And I've defined two methods:
showBreadList() - for displaying the contents of the list;
addInOrder() - for inserting a new element into the list (the list should be updated in such a way so that elements are maintained in sorted order).
My code:
public class List {
class LinkedListExample {
private LinkedList<String> breadList = new LinkedList<>(); // <-- Edit from the answer: public to private
Iterator<String> iterator;
public void showBreadList() {
iterator = breadList.iterator();
System.out.println("Values in breadList: ");
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
public void addInOrder(String bread) {
ListIterator<String> stringListIterator = breadList.listIterator();
while(stringListIterator.hasNext()) {
if(stringListIterator.next().compareTo(bread) == 0) {
} else if(stringListIterator.next().compareTo(bread) > 0) {
stringListIterator.previous();
stringListIterator.add(bread);
} else if(stringListIterator.next().compareTo(bread) < 0) {
}
}
stringListIterator.add(bread); // <-- Edit: added
}
}
public static void main(String[] args) {
List list = new List();
List.LinkedListExample lle = list.new LinkedListExample();
lle.addInOrder("Ciabatta");
lle.addInOrder("Wheat Bread");
lle.addInOrder("White Bread");
lle.addInOrder("Sourdough");
lle.addInOrder("Flatbread");
lle.showBreadList();
}
}
The list gets populated in the main() method via addInOrder().
Expected output:
Values in breadList:
Ciabatta
Flatbread
Sourdough
Wheat Bread
White Bread
Actual output:
Value in breadList:
I.e. I'm getting nothing. Can anybody give a hint on what I'm doing wrong?
Seems like the goal of your assignment is to learn how to deal with a ListIterator.
The core thing to understand about the Iterators that their cursor always occupies a position in between the elements of the list (and it might also be positioned before the first element and right after the last element). And that's the position where a new element gets inserted when you invoke ListIterator.add().
Here's a quote from the official tutorial Provided by Oracle:
Intuitively speaking, the cursor is always between two elements — the
one that would be returned by a call to previous and the one that
would be returned by a call to next. The n+1 valid index values
correspond to the n+1 gaps between elements, from the gap before the
first element to the gap after the last one. The following figure
shows the five possible cursor positions in a list containing four
elements.
In the method addInOrder() you've messed around with conditions. If fact, only one condition that would check if the next is lexicographically greater than the given string would be enough. If the next is greater we continue iteration, if not we need to move the iterator the previous position by calling previous() and then break from the loop.
Method add() will be invoked on the iterator after the loop, when iterator is the right position to insert a new element.
That's how you can fix your method:
public void addInOrder(String bread) {
ListIterator<String> iterator = breadList.listIterator();
while (iterator.hasNext()) {
String next = iterator.next();
if (next.compareTo(bread) > 0) { // if the next element is lexicographically greater than `bread`, `bread` has to be inserted before it
iterator.previous(); // moving to the position where the new `bread` should be inserted
break; // breaking out from the loop
}
}
iterator.add(bread); // inserting the new kind of bread
}
Example with the sample data from the question:
LinkedListExample lle = new LinkedListExample();
lle.addInOrder("Ciabatta");
lle.addInOrder("Wheat Bread");
lle.addInOrder("White Bread");
lle.addInOrder("Sourdough");
lle.addInOrder("Flatbread");
lle.showBreadList();
Output:
Ciabatta
Flatbread
Sourdough
Wheat Bread
White Bread
just to start off, this is homework and thank you for your assistance ahead of time. I keep getting stuck on little problems so I am hoping you guys can help me with one. What I am trying to do is create a linked list that has multiples functions. The one I am having trouble with is sorting(I can do the other ones). Each node holds a string, an integer and a double. I need to be able to sort by each of these and by the order it was inputted, on the user's request. ***It is also important to mention that the variables in my object are private and my object is called list1. Basically, I have to make one linked list for the chronological order and one for each other order.
My plan is to insert the nodes in their correct order as the user inputs them. So as the user inputs a node, that node needs to go in the correct place in the chronological list and in the other lists. So, I need to copy the node to do this. However, I cannot simply just say
icopy(copy for integer) = newNode(node the user just inputted)
That only changes the address. When I went to my instructor he told me that I should say:
icopy.data = newNode.data;
("data" being the shortcut way of mentioning that I need to get the individual data types within the node.) So I wrote:
icopy.GetI() = newNode.GetI();
When I do this I encounter this error: unexpected type required:variable, found:value. I am not sure what to do. Any assistance would be appreciated and I would be happy to clarify anything.
*GetI: method in my object that gives access to the integer value in each node.
*p: pointer for the Chronological
*pi: pointer for the integer.
*fi: front of the integer linked list
public static void main(String args[])
{
String repeat = "y";
boolean inserted = false;
list1 fChr = null;
list1 p = fChr;
list1 icopy = null;
list1 scopy = null;
list1 dcopy = null;
list1 fd = fChr;//front of the double list
list1 fi = null;//front of the integer list
list1 fStr = fChr;//front of the string list~
while(repeat.equals("y"))//while the user agrees to adding a new node
{
if(fChr == null)// if the front is empty
{
fChr = new list1();//create a new node by calling object and sets it as the front
}
else
{
p = fChr;
while(p.next != null)//finds the end of the Linked list
{
p = p.next;//moves the pointer p down the list
}
list1 newNode = new list1();
icopy.GetI() = newNode.GetI();// make a copy of newNode
p.next = nexNode;//put in chronological order
while(p != null)
{
if(fi == null)
{
fi = n;
}
else if(n.GetI() < fi.GetI)//check at beginning
{
//put at beginning
}
else if(icopy.GetI() < p.next.GetI())//check in between nodes
{
//put in between
}
//does it go at the end
}
}
repeat = JOptionPane.showInputDialog("Would you like to add a node [y/n]");
}
PrintMenu(fChr, fi, fd, fStr);// sends the user to the menu screen
}
There are a few things here that you are not understanding. Firstly, in Java iCopy.getI() = ... makes no sense. When a method returns a value it needs to be assigned to a variable if you wish to change it. If you want to change the instance variable you need a separate method called something like iCopy.setI().
It sounds as though you're not asking for help with the sorting so I'll restrict my answer to creating copies of the list.
What your professor is getting at is that the easiest way to ensure the data is consistent in your several linked lists is to separate the class storing the data from the nodes of the list. So I would expect your class structure to end up looking something like:
class Data {
private final int intValue;
private final String strValue;
private final double doubleValue;
}
class Node {
private final Data data;
private Node next;
public Node(Data data) {
this.data = data;
this.next = null;
}
}
Now if you want to create a new linked list with the same data as the old one then you can add a constructor to Node that creates a reference to the original data:
class Node {
public Node copy() {
Node copy = new Node(data);
if (next != null)
copy.next = next.copy();
return copy;
}
}
Hopefully you can see what that does: it creates a new node referencing the same data as this one and then uses recursion to copy the rest of the list.
Now creating each of the sort orders could look like:
Node listByInt = list.copy();
/* code to sort listByInt according to data.intValue */
Add a comment if you want some hints on sorting as well but I suggest you get your code to the point of having equal copies of lists before attempting that.
As a final note, you don't necessarily need to have separate linked lists to solve this problem. An alternative would be to store the original insertion order in the node. You could then sort by any order (including original insertion order) before printing the list. Personally I'd prefer that as a solution unless there are performance issues (e.g. you need to use each sorted list many times).
I have this code below where I am inserting a new integer into a sorted LinkedList of ints but I do not think it is the "correct" way of doing things as I know there are singly linkedlist with pointer to the next value and doubly linkedlist with pointers to the next and previous value. I tried to use Nodes to implement the below case but Java is importing this import org.w3c.dom.Node (document object model) so got stuck.
Insertion Cases
Insert into Empty Array
If value to be inserted less than everything, insert in the beginning.
If value to be inserted greater than everything, insert in the last.
Could be in between if value less than/greater than certain values in LL.
import java.util.*;
public class MainLinkedList {
public static void main(String[] args) {
LinkedList<Integer> llist = new LinkedList<Integer>();
llist.add(10);
llist.add(30);
llist.add(50);
llist.add(60);
llist.add(90);
llist.add(1000);
System.out.println("Old LinkedList " + llist);
//WHat if you want to insert 70 in a sorted LinkedList
LinkedList<Integer> newllist = insertSortedLL(llist, 70);
System.out.println("New LinkedList " + newllist);
}
public static LinkedList<Integer> insertSortedLL(LinkedList<Integer> llist, int value){
llist.add(value);
Collections.sort(llist);
return llist;
}
}
If we use listIterator the complexity for doing get will be O(1).
public class OrderedList<T extends Comparable<T>> extends LinkedList<T> {
private static final long serialVersionUID = 1L;
public boolean orderedAdd(T element) {
ListIterator<T> itr = listIterator();
while(true) {
if (itr.hasNext() == false) {
itr.add(element);
return(true);
}
T elementInList = itr.next();
if (elementInList.compareTo(element) > 0) {
itr.previous();
itr.add(element);
System.out.println("Adding");
return(true);
}
}
}
}
This might serve your purpose perfectly:
Use this code:
import java.util.*;
public class MainLinkedList {
private static LinkedList<Integer> llist;
public static void main(String[] args) {
llist = new LinkedList<Integer>();
addValue(60);
addValue(30);
addValue(10);
addValue(-5);
addValue(1000);
addValue(50);
addValue(60);
addValue(90);
addValue(1000);
addValue(0);
addValue(100);
addValue(-1000);
System.out.println("Linked List is: " + llist);
}
private static void addValue(int val) {
if (llist.size() == 0) {
llist.add(val);
} else if (llist.get(0) > val) {
llist.add(0, val);
} else if (llist.get(llist.size() - 1) < val) {
llist.add(llist.size(), val);
} else {
int i = 0;
while (llist.get(i) < val) {
i++;
}
llist.add(i, val);
}
}
}
This one method will manage insertion in the List in sorted manner without using Collections.sort(list)
You can do it in log (N) time Complexity simply. No need to iterate through all the values. you can use binary search to add value to sorted linked list.just add the value at the position of upper bound of that function.
Check code... you may understand better.
public static int ubound(LinkedList<Integer> ln, int x) {
int l = 0;
int h = ln.size();
while (l < h) {
int mid = (l + h) / 2;
if (ln.get(mid) <= x) l = mid + 1;
else h = mid;
}
return l;
}
public void solve()
{
LinkedList<Integer> ln = new LinkedList<>();
ln.add(4);
ln.add(6);
ln.add(ubound(ln, 5), 5);
out.println(ln);
}
Output : [4, 5, 6]
you can learn about binary search more at : https://www.topcoder.com/community/data-science/data-science-tutorials/binary-search/
#Atrakeur
"sorting all the list each time you add a new element isn't efficient"
That's true, but if you need the list to always be in a sorted state, it is really the only option.
"The best way is to insert the element directly where it has to be (at his correct position). For this, you can loop all the positions to find where this number belong to"
This is exactly what the example code does.
"or use Collections.binarySearch to let this highly optimised search algorithm do this job for you"
Binary search is efficient, but only for random-access lists. So you could use an array list instead of a linked list, but then you have to deal with memory copies as the list grows. You're also going to consume more memory than you need if the capacity of the list is higher than the actual number of elements (which is pretty common).
So which data structure/approach to take is going to depend a lot on your storage and access requirements.
[edit]
Actually, there is one problem with the sample code: it results in multiple scans of the list when looping.
int i = 0;
while (llist.get(i) < val) {
i++;
}
llist.add(i, val);
The call to get(i) is going to traverse the list once to get to the ith position. Then the call to add(i, val) traverses it again. So this will be very slow.
A better approach would be to use a ListIterator to traverse the list and perform insertion. This interface defines an add() method that can be used to insert the element at the current position.
Have a look at com.google.common.collect.TreeMultiset.
This is effectively a sorted set that allows multiple instances of the same value.
It is a nice compromise for what you are trying to do. Insertion is cheaper than ArrayList, but you still get search benefits of binary/tree searches.
Linked list isn't the better implementation for a SortedList
Also, sorting all the list each time you add a new element isn't efficient.
The best way is to insert the element directly where it has to be (at his correct position).
For this, you can loop all the positions to find where this number belong to, then insert it, or use Collections.binarySearch to let this highly optimised search algorithm do this job for you.
BinarySearch return the index of the object if the object is found in the list (you can check for duplicates here if needed) or (-(insertion point) - 1) if the object isn't allready in the list (and insertion point is the index where the object need to be placed to maintains order)
You have to find where to insert the data by knowing the order criteria.
The simple method is to brute force search the insert position (go through the list, binary search...).
Another method, if you know the nature of your data, is to estimate an insertion position to cut down the number of checks. For example if you insert 'Zorro' and the list is alphabetically ordered you should start from the back of the list... or estimate where your letter may be (probably towards the end).
This can also work for numbers if you know where they come from and how they are distributed.
This is called interpolation search: http://en.wikipedia.org/wiki/Interpolation_search
Also think about batch insert:
If you insert a lot of data quickly you may consider doing many insertions in one go and only sort once afterwards.
Solution of Amruth, simplified:
public class OrderedList<T extends Comparable<T>> extends LinkedList<T> {
private static final long serialVersionUID = 1L;
public boolean orderedAdd(T element) {
ListIterator<T> itr = listIterator();
while(itr.hasNext()) {
if (itr.next().compareTo(element) > 0) {
itr.previous();
break;
}
}
itr.add(element);
}
}
Obviously it's O(n)
I need to implement a Linked List of integers from zero (not using existing LinkedList class).
This is the code:
A single Link class
public class Link {
public int data;
public Link nextLink;
public Link(int d1) {
data = d1;
}
public void printListElements(){
System.out.println(data);
}
}
and the LinkedList class
public class LinkedList {
private Link first;
public LinkedList(){
first = null;
}
public void add(int data1){
Link linklist = new Link(data1);
linklist.nextLink = first;
first = linklist;
}
public void printList(){
Link current=first;
System.out.println("List Elements are ");
while(current!=null){
current.printListElements();
current=current.nextLink;
}
}
}
As you see it has already add and printList method. But how do i make a get() method, which returns a value of a specific index.
This is what i mean:
public static void main(String args[]){
LinkedList MyList = new LinkedList();
MyList.add(1);
MyList.add(2);
MyList.add(3);
MyList.add(4);
System.out.println("MyList.get(0)"); // should get 1
System.out.println("MyList.get(1)"); // should get 2 etc
}
Thank You in advance.
Well, since it's a linked list, you don't have any way to directly access any element except the first one, right? So the only way to do it is to start there and step through (by successively following the links to the next element) until you reach the element specified by the index, and then return that. The easiest way to do that is with a loop.
You can't do that with your current implementation. Because you are adding every new node as the head node.
If you change your add() so that every new node is added as the last node then you can do that using your index value passed to get() as the loop counter.
In LinkedList you have your elements reverted.
public int get(int i) {
int n = indexOf(first); // count-1 actually
Link current = first;
while (n > i) {
--n;
current = current.nextLink;
}
return current.data;
}
private int indexOf(Link link) {
if (link == null) {
return -1;
}
return 1 + indexOf(link.nextLink);
}
I would recommend using a dual linked list:
class Node<T> {
Node<T> next;
Node<T> prev;
T data;
}
class LinkedList<T> {
Node<T> head;
Node<T> tail;
int count;
}
Your add method would actual just create a new node, and attach it to the "next" pointer of the tail, reassign the tail, and increment the count. (yes you could do this with a single linked list as well as long as you have a tail pointer)
Which this approach, add is a constant time operation and preserves insertion order (unlike the single linked list approach you were taking, where insertion order is not preserved).
Also, you could optimize the "get" to see if the requested index is closer to the head or tail, and traverse from the appropriate end to get the node you want.
I assume this is homework, so i don't want to give the entire code away.
I am creating a partially ordered set as an abstract data type in java, and I have to make an iterator version of the set of numbers, and an iterator for the relations. Now for the elements, I've used HashSet of integer, and for the relations, I've used an ArrayList of pairs (pairs is a class I created that takes 2 ints as parameter which basically is like (x, y)). I need to make 2 iterators, one for s and one for r, but they have to follow a certain ordering,
1. if (x, y) belong to R, then the iterator of s should return x before it returns y
2. if (x, y) and (y, z) belong to R, then iterator of r should return (x, y) before it returns (y, z)
I made a helper method that check first for to check if the element n in the set is the first element in a pair then it returns it, but I cant seem to check if it is second element, how can I check for the first element if it is returned or not?
Here is my code:
private class IntGenerator implements Iterator {
private Iterator<Integer> i;
public IntGenerator () {
i = S.iterator();
}
public boolean hasNext() {
return i.hasNext();
}
public Object next() {
int n = i.next();
for (Pair p : R) {
if (isInFirstElmPair(p, n)) return n;
else (isInSecondElmPair(p, n)) {
// should check for the first element
// if it was returned or not
}
}
}
public void remove() { throw new UnsupportedOperationException(); }
}
I would really appreciate any kind of help, or hint in this code.
Thanks
EDIT:
Okay, I've wrote the code to it after adding a new set which will hold the returned elements, and this is what I wrote:
Set<Integer> returnedNumbers = new HashSet<Integer> ();
public Object next() {
int n = i.next();
for (Pair p : R) {
if (isInSecondElmPair(p, n)) {
if (returnedNumbers.contains(p.getFirstElm())) {
returnedNumbers.add(n);
return n;
}else{
returnedNumbers.add(p.getFirstElm());
return p.getFirstElm();
}
}else{
returnedNumbers.add(n);
return n;
}
}
}
Is this code correct? Also, eclipse seems to give me an error telling me I need to return a value outside the loop, but I already returned inside for every case why does it need more?
Appreciate the help
Well, to check if a value was previously returned, you of course need to keep track of all values that were returned previously.
So in your iterator, you could define
Set<Integer> previouslyReturned = new HashSet<Integer>();
and then, before returning it in your for loop, add it there:
if (isInFirstElmPair(p, n)) {
previouslyReturned.add(n);
return n;
}
else (isInSecondElmPair(p, n)) {
if (previouslyReturned.contains(n) {
// do one thing
} else {
// do another thing
}
}
This way, however, you are constructing a set of s in the order in which it shall be returned inside the iterator. It would make sense to create this once (consider a LinkedHashSet), keep it somewhere else and iterate over it.
Generally I am not sure that this approach will lead to what you want. Do you know anything about theorder of elements in S and R? If the iteration order is arbitrary (i.e. because relations were added in unpredictable order) then the iterator will first return the first half of the first relation pair, even if that element is in the second half of another pair. Do you have to use an element HashSet and a relation List?