Add linkedlist to linkedlist, JAVA - java

I want to design a linkedlist to another linkedlist, so far I have this method in MyLinkedList class:
public void addList(int index, E e){
if(index == 0){
addFirst(e);
} else if (index >= size){
addLast(e);
}
else{
Node<E> current = head;
for(int i = 1; i < index; i++){
current = current.next;
}
Node<E> temp = current.next;
current.next = new Node<E>(e);
(current.next).next = temp;
size++;
}
}
I'm stuck on the method itself, my main program has two LinkedLists that looks like this:
MyLinkedList<String> strings1 = new MyLinkedList<String>();
strings1.add("java");
strings1.add("language");
strings1.add("cooler");
strings1.add("noob");
System.out.println(list1);
MyLinkedList<String> strings2 = new MyLinkedList<String>();
strings2.add("artistic");
strings2.add("cereal");
strings2.add("bowl");
System.out.println(list2);
Then I wanna add the linkedlist of string2 into linkedlist of string1. How would I do that?
I have thought of using
strings1.addList(2, strings2);
but it didn't work, it won't let me add strings2 to strings1
I'm thinking the output would look like this if I have it done:
java, language, artistic, cereal, bowl, cooler, noob
or something similar, please help!

You have a method in your class which accepts a single node, simply call this as many times as you need for the second list:
e.g.
void addAll(int index, MyList<> second_list)
{
for(Object o : second_list)
{
addList(index, o);
++index;
}
}
The above range based for loop may not work unless your class has implemented the proper interfaces, I'm being lazy - use the normal iteration that your class supports...

Easiest possible way....
public void insertList(int index, List<String> list) {
Collections.reverse(list);
for (String str : list) {
add(index, str);
}
}

Use the method addAll(int index, Collection c) to add the two lists together.
strings1.addAll(startIndex, strings2);
You also have to implement the List interface to your class MyLinkedList..
It also isn't really clear what your MyLinkedList class looks like?

Related

To merge two sorted linked lists. Is there a better way to create new Linked list heads in java?

In this program, I have created the head node inside the class LinkedList.
public class LinkedList {
public class Node {
public int data;
public Node next;
}
Node Head=null
void IntersectionOfTwoSortedLists(Node ListA, Node ListB){
while (ListA!=null && ListB!=null) {
if (ListA.data == ListB.data){
System.out.println(ListA.data);
InsertAtEnd(ListA.data);
}
if(ListA.data<ListB.data)
ListA=ListA.next;
else
ListB=ListB.next;
}
}
and the main function in a different class looks like this.
public static void main(String[] args) {
LinkedList list = new LinkedList();
LinkedList list2= new LinkedList();
for(int i=0;i<n;i++){
list.InsertAtEnd(sc.nextInt());
}
System.out.println("Enter the list 2 elements");
for(int i=0;i<n;i++){
list2.InsertAtEnd(sc.nextInt());
}
LinkedList intersect= new LinkedList();
intersect.IntersectionOfTwoSortedLists(list.Head,list2.Head);
creating a new object of the linked list class every time a good practice or is there a better way to do this? Thanks in advance!
If you perform operations over two different lists in such case you have to create two different objects. you can use copy but here in your case, it will not work because if you do so then update in one list will affect others too.

how to set next of last element of linked list to first element in LinkedList data structure?

I am trying to use java.util.LinkedList to get a linked list and change it somehow to a circular linked list.
Like is it possible to set next of the last element to first (as it can be done in a self-made linked list)?
If not then please suggest me another way to accomplish my goal.
No, you can't generate a circular LinkedList. A circular LinkedList would not be able to implement its own API. How would LinkedList.add work, for example, if the list had no end?
You identified the solution: implement your own linked list.
You can't use LinkedList, but you can implement your own solution.
For example you can just create class containing list and declare you own API for use it. E.g.
public static class CircularList<T> implements Iterable<T> {
private LinkedList<T> list = new LinkedList<>();
public void add(T num) {
list.add(num);
}
#Override
public Iterator<T> iterator() {
return new Iterator<T>() {
int idx = 0;
#Override
public boolean hasNext() {
return true;
}
#Override
public T next() {
if (list.isEmpty()) {
throw new RuntimeException();
}
if (idx + 1 < list.size()) {
return list.get(++idx);
}
idx = 0;
return list.get(0);
}
};
}
}
This is a simple implementation of a circular list.

Linked List Constructor with initial value

I'm working on a Linked List project, and i'm having a great trouble with the constructor.
i already implemented the default constructor (creates empty list. AKA data = null, size = 0) but the other constructor is really confusing me !!!!
i want to implement a constructor that creates a linked list with valueS/elementS in it (String[]). My first thought was "Piece of cake, all i have to do is :
Use the default constructor to create an empty linked list
Use a for-each loop within a for loop.
The for-each loop is to iterate the string array and add them to my empty linked list.
The for loop is needed to keep a track of the index."
Here is my Code:
public LinkedList(String[] data)
{
LinkedList l = new LinkedList();
for (int i = 0; i <= data.length; i++)
{
for (String d : data)
{
l.add(d, i);
i++;
}
}
}
i tested my code by using this constructor but it does not work.
i know there is a silly mistake somewhere but my logic/mind is blind to see it.
Well you're not really referring to "this" anymore in the constructor you've written. You create a linked list l and modify that one, but you never actually work on "this". Also I agree with the others, the second for loop is unnecessary.
This also lets you use this(), which is a cool functionality to get to know. Helps you keep your code DRY and bug free.
public LinkedList(String[] data){
this(); //Call the default constructor to set up default properties
for (String d : data){
add(d); //Call on this
}
}
You need to change the arguments to the add method, it expects the index to be the first argument. See http://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html#add(int,%20E).
for (String d : data)
{
l.add(i, d);
i++;
}
Another way of doing this would be to just add l.add(d) in the loop. With this new elements are guaranteed to be inserted at the end of the list.
I would use l.add(i, d) when I want to insert specifically at a given location.
Does your class extend LinkedList? If so, here is what I would do:
public class MyLinkedList extends LinkedList<String> {
...
public MyLinkedList(String... array) {
super();
if (array != null && array.length > 0) {
for (String s : array) {
add(s);
}
}
}
...
}
It isn't a great idea to extend LinkedList. If you want an easy way to create a new LinkedList with elements use the following method:
public static <E> LinkedList<E> newLinkedList(
#SuppressWarnings("unchecked") final E... elements) {
final LinkedList<E> list = new LinkedList<E>();
Collections.addAll(list, elements);
return list;
}
....
LinkedList<String> yourList = newLinkedList("foo", "bar", "baz");

Remove List<String> duplicates using equals

I'm fairly new to Java and I've been trying to solve the following problem unsuccessfully.
Write a Java method that will remove duplicates from a given list.
Assuming:
Method accepts type List
Return type is void
Duplicates are determined using equals()
Main:
Creates an instant of List and loads it with duplicate String values
Invoke removeDuplicates(), pass in this list
Outputs modified list to the console.
I can solve the problem by passing in my list to a new HashSet and copy it back.
But the problem is:
Question is asking me to solve it using equals()...
If the return type is void, how can i output it in the main ?
import java.util.*;
public class Question1 {
public static void main(String[] args) {
String[] words = {"good","better", "best", "best", "first" , "last", "last", "last", "good"};
List<String> list = new ArrayList<String>();
for (String s : words) {
list.add(s);
}
removeDuplicates(list);
}
static void removeDuplicates(List<String> array){
HashSet<String> hs = new HashSet<>();
hs.addAll(array);
array.clear();
array.addAll(hs);
for (String x : array){
System.out.println(x);
}
}
}
EDIT: well, this one works, but as you can see i'm not using equals() and i'm printing out from my static method, not from main.
Also, is there any way I can populate the List faster than using String[] ?
java.util.HashSet uses Object.equals(Object) in its implementation of Set.add(Object) to determine that the element being inserted is unique (as defined by not being equal to another element). HashSet also has the advantage of allowing you to do the de-duping process in O(n) time vs a more naive approach of comparing every element to every other element in O(n^2) time.
The code in main will see the modified list, because the List object is mutable. When a method changes the state of a passed in argument the calling code will see those changes.
removeDuplicates creates a set, then iterates over the input list. If it encounters an element in the input list, that is also in the set, removeDuplicates removes the element from the input list, otherwise it adds the element to the set.
Java is a call-by-reference language (sort of). This means, the method removeDuplicates can modify the List<String> array that it receives and the caller will see that modified list after the call to removeDuplicates returned.
Here's how you would do the same thing without using a Set and just using equals() (also to somewhat answer your "EDIT" question about initializing a List) :
public static void main(String[] args) {
List<String> list = new ArrayList<String>(Arrays.asList(new String[] {
"good", "better", "best", "best", "first", "last", "last", "last",
"good"}));
removeDuplicates(list);
for (String x : list) {
System.out.println(x);
}
}
static void removeDuplicates(List<String> array) {
for (int i = 0; i < array.size(); i++) {
String next = array.get(i);
// check if this has already appeared before
for (int j = 0; j < i; j++) {
// if it has, stop the search and remove it
if (next.equals(array.get(j))) {
array.remove(i);
// decrement i since we just removed the i'th element
i--;
// stop the search
break;
}
}
}
}
That said, using HashSet is a better idea since as has already been pointed out it is more efficient.
If you want the efficiency of HashSet but still preserve the order of the List you could do something like this :
static void removeDuplicates(List<String> array) {
Set<String> set = new HashSet<String>();
for (int i = 0; i < array.size(); i++) {
String next = array.get(i);
// check if this has already appeared before
if (!set.add(next)) {
// if it has then remove it
array.remove(i);
// decrement i since we just removed the i'th element
i--;
}
}
}
The probably easiest way would be to use a Set in the first place, which by definition does not allow duplicates.
For your actual problem, you can do several approaches:
The easy but slow approach: compare each element A with each other element N in the list. If A.equals(N) remove N. Hint: you only need to compare A to each further element, as you have already checked each element before A.
The faster approach: sort the list using the natural comperator. Now you no longer need to compare each element A vs N, but only A vs the next few elements. To be exact: until you find the first element that is not equal to A. In this case you can assume that there is no further duplicate of A (thanks to the sorting) and continue with this next element as A.
The Map approach (fast but takes more memory): for each element put into the list, put the same element into a Map with any Object as value. Now you can just look-up whether or not that element is already in the map, and if it is, it is a duplicate.
The best way would be the 2nd approach as the sorting is very fast, you only need to get each element once, and there is no 2nd list necessary.
Edit: The 2nd approach in code:
static void removeDuplicates(List<String> array) {
if (array.size() <= 1) {
return;
}
Collections.sort(array);
final Iterator<String> it = array.iterator();
String a = it.next(), n;
while (it.hasNext()) {
n = it.next();
if (((a == null) && (n != null))
|| ((a != null) && (a.equals(n) == false))) {
a = n;
} else {
it.remove();
}
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("good");
list.add("better");
list.add("best");
list.add("best");
list.add("first");
list.add("last");
list.add("last");
list.add("last");
list.add("good");
removeDuplicates(list);
System.out.println(list.toString());
}
public static void removeDuplicates(List<String> list) {
if (list != null) {
for (int i = 0; i < list.size(); i++) {
ListIterator<String> listIterator = list.listIterator();
while (listIterator.hasNext()) {
int nextIndex = listIterator.nextIndex();
String nextElement = listIterator.next();
if (list.get(i).equals(nextElement) && i != nextIndex)
listIterator.remove();
}
}
}
}
}

Get method in a implemented Linked List, Java

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.

Categories

Resources