Regarding finding the middle element of linked list - java

I am following the below approach to calculate the middle element from the linked list , but I want is there any built in method or any other approach which can also find the same easily , the approach that I am following is shown bellow..
import test.LinkedList.Node;
public class LinkedListTest {
public static void main(String args[]) {
//creating LinkedList with 5 elements including head
LinkedList linkedList = new LinkedList();
LinkedList.Node head = linkedList.head();
linkedList.add( new LinkedList.Node("1"));
linkedList.add( new LinkedList.Node("2"));
linkedList.add( new LinkedList.Node("3"));
linkedList.add( new LinkedList.Node("4"));
//finding middle element of LinkedList in single pass
LinkedList.Node current = head;
int length = 0;
LinkedList.Node middle = head;
while(current.next() != null){
length++;
if(length%2 ==0){
middle = middle.next();
}
current = current.next();
}
if(length%2 == 1){
middle = middle.next();
}
System.out.println("length of LinkedList: " + length);
System.out.println("middle element of LinkedList : " + middle);
}
}
class LinkedList{
private Node head;
private Node tail;
public LinkedList(){
this.head = new Node("head");
tail = head;
}
public Node head(){
return head;
}
public void add(Node node){
tail.next = node;
tail = node;
}
public static class Node{
private Node next;
private String data;
public Node(String data){
this.data = data;
}
public String data() {
return data;
}
public void setData(String data) {
this.data = data;
}
public Node next() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
public String toString(){
return this.data;
}
}
}
Output:-
length of LinkedList: 4
middle element of LinkedList : 2

The basic algorithm would be
Take two pointers
Make both pointing to first node
Increment first with two nodes and second with one, at a time.
Loop until the 1st loop reaches the end. At this point, the 2nd will be at the middle.
Example:-
while ( p2.next != null ) {
p2 = p2.next;
if (p2.next != null) {
p2 = p2.next;
p1 = p1.next;
}
}
It will definitely work in odd case, for even case you need to check one more condition if first point is allowed to move next but not next to next then both pointers will be at middle you need to decide which to take as middle.

I would recommend using the Java built in
LinkedList<Object e>
It gives you all the functionality you need like getting the length: list.size(), and the middle object:
list.get((list.size())/2);

Options:
Have a double linked-list and go from the back and front at the same time until you get to a common point.
Store the size of the list and simply stop when you've reached this half this size (similar to what the standard API's LinkedList does).
Other than that I don't think you can do better than your algorithm.

public Node getMiddleElement(Node head) {
Node slow_pointer=head;
Node fast_pointer=head;
while(fast_pointer.next!=null && fast_pointer.next.next!=null)
{
slow_pointer=slow_pointer.next;
fast_pointer=fast_pointer.next.next;
}
return slow_pointer;
}
Node mid_elem=PrintMiddleElement(head);
System.out.println(mid_elem.data);
I/P:5 10 15 25 35 25 40 O/P:25

Solution for this question:
Use two indexes, first and second, both initialized to 0
Increment first by 1 and second by 2 * first
Set value of first to middle
Loop will execute until value of second is less than list size
Here is code snippet for getting middle element of list or linked list:
private int getMiddle(LinkedList<String> list) {
int middle = 0;
int size = list.size();
for (int i = 0, j = 0; j < size; j = i * 2) {
middle = i++;
}
return middle;
}
LinkedList<String> list = new LinkedList<>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
list.add("6");
list.add("7");
int middle = getMiddle(list);
System.out.println(list.get(middle));

Related

how to print the last three nodes of a linked list?

My whole code to try to get the las three nodes of a linked list is:
Node class:
package com.company;
public class Node {
public int data;
public Node nextNode;
public Node(int data) {
this.data = data;
this.nextNode = null;
}
public int getData() {
return data;
}
}
Linked list class;
package com.company;
public class LinkedList {
public Node head;
public int size;
public LinkedList() {
this.head = null;
this.size = 0;
}
public void add(int data) {
Node node = new Node(data);
if (head == null) {
head = node;
} else {
Node currentNode = head;
while(currentNode.nextNode != null) {
currentNode = currentNode.nextNode;
}
currentNode.nextNode = node;
}
size++;
}
public void printData() {
Node currentNode = head;
while(currentNode != null) {
int data = currentNode.getData();
System.out.println(data);
currentNode = currentNode.nextNode;
}
}
public void printLastThree(){
Node currentNode = head;
int i = this.size - 3;
while(i <= this.size) {
int data = currentNode.getData();
System.out.println(data);
currentNode = currentNode.nextNode;
i++;
}
}
}
Main class:
package com.company;
public class Main {
public static void main(String[] args) {
LinkedList ll = new LinkedList();
ll.add(1);
ll.add(2);
ll.add(3);
ll.add(4);
ll.add(5);
ll.add(6);
ll.add(7);
ll.add(8);
ll.add(9);
ll.add(10);
ll.add(11);
ll.add(12);
ll.printData();
System.out.println();
ll.printLastThree();
}
}
As you can see, in the linked list class I try to print the last three nodes of the linked list with the printLastThree() method, but in console I just get:
1
2
3
4
And I would like to get:
10
11
12
Can you say me what I am doing wrong?
I try in printLastThree() method to get the total size of the linked list and substract 3 positions, and then get to the total size of the linked list, but that doesn't work.
Thanks.
Once can see from your code that currentNode starts as the head node, and its value gets printed in the first iteration of the loop. This is not what you want.
You'll first have to skip nodes, which do not get printed. You already calculated how many such nodes need to be skipped (this.size - 3), so you only need to add the loop to actually skip that many nodes:
public void printLastThree(){
Node currentNode = head;
// First SKIP nodes (not to be printed)
for (int i = size - 3; i > 0; i--) {
currentNode = currentNode.nextNode;
}
// ...and only then start printing
while (currentNode != null) {
int data = currentNode.getData();
System.out.println(data);
currentNode = currentNode.nextNode;
}
}
You can also do it with one loop, and make the printing conditional on the current index:
public void printLastThree(){
Node currentNode = head;
for (int i = 0; i < size; i++) {
if (i >= size - 3) { // Are we at the last three nodes?
int data = currentNode.getData();
System.out.println(data);
}
currentNode = currentNode.nextNode;
}
}
the bug is in printLastThree().
You need to move the currentNode from head to position: size-3; But don't print it just yet.
Then after that, move again from size-3 to size-1 and during this move, print it out.
try 2 while loops. Later you can also make it into 1 while loop from start to end with if condition whether to print or not.

Removing middle number of a queue

I need to create a method in which I remove the middle number of a Linked queue. [1,2,3,4,5] turns into [1,2,4,5] and if the queue is even-numbered you round down and remove from there. So [1,2,3,4] turns into [1,3,4].
I am unsure how to go by removing the middle number and then adding back in the other numbers I removed.
This is what I currently have.
...
public class LinkedQueue {
Node head;
Node front;
Node rear;
int count;
int elements;
public void enqueue(int numEnqueue) {
Node node = rear;
rear=new Node();
rear.numEnqueue=numEnqueue;
rear.next=null;
if (front==null)
front = rear;
else
node.next = rear;
count++;
elements=count;
}
//
public void dequeue() {
for(int i=0;i<6;i++) {
int numEnqueue = front.numEnqueue;
front = front.next;
count--;
System.out.print("\nDequeueing: "+numEnqueue);
}
}
public void show() {
Node node = front;
System.out.print("\n\nQueued linked elements: ");
while(node!=null) {
System.out.print(node.numEnqueue+" ");
node=node.next;
}
}
public void removeMiddle() {
int half = 0;
half=elements/2;
for (int i=0;i<half;i++) {
int numEnqueue = front.numEnqueue;
front = front.next;
}
}
}
...
Driver code
...
public class Driver {
public static void main(String[] args) {
LinkedQueue link=new LinkedQueue();
link.enqueue(1);
link.enqueue(7);
link.enqueue(3);
link.enqueue(4);
link.enqueue(9);
link.enqueue(2);
link.show();
link.dequeue();
link.enqueue(1);
link.enqueue(7);
link.enqueue(3);
link.enqueue(4);
link.enqueue(9);
link.enqueue(2);
link.removeMiddle();
link.show();
}
}
...
Node code
public class Node {
int numEnqueue;
Node next;
}
Since this is homework, I'll offer pseudo code/advice:
given a queue of length n, you need to remove element (n - 1) / 2 (int arithmetic truncates the fractional part of the division for you).
in a loop that iterates (n - 1) / 2 times, starting with the root node, advance to the next node each iteratation
remove the node the loop ends on
The actual solution is slightly more complicated than this, and you may find that it easier to remove the next node due to each node not having a reference to its predecessor. In which case, iterating to the root would count as one iteration of the loop.

ArrayStoreException when attempting to store an array of linked list

I'm attempting to create an array of linked list which will deal with hash value collisions. I have an array of an objects which I have tried to store the linkedList but it doesn't seem to work. Is there something I'm doing wrong, or is there a more efficient route I should take.
This is the error I get when running my code.
Exception in thread "main" java.lang.ArrayStoreException: linkedList
at p7b.Insert(p7b.java:57)
at p7b.main(p7b.java:31)
Here is my method
public static void Insert(int hashVal, String key,int[] arrayNums, Object[] arrayString){
Node newNode = new Node(key,null);
linkedList list = new linkedList();
if (arrayString[hashVal] == null){
arrayString[hashVal] = list;
}
Here is the linkedList code:
public class linkedList{
private Node head;
private int size;
public linkedList(){
size = 0;
head = null;
}//end default constructor
public boolean isEmpty(){
return size == 0;
}//end isEmpty
public int size(){
return size;
}//end size
protected Node find(int index){
Node curr = head;
for(int skip = 0; skip < index; skip++){
curr = curr.getNext();
}//end for
return curr;
}//end find
public Object get(int index){
if (index >=0 && index < size) {
// get reference to node, then data in node
Node curr = find(index);
Object dataItem = curr.item();
System.out.println(dataItem);
return dataItem;
}
else
return "error";
}//end get
public void add(int index, String item){
if(index>= 0 && index < size+1){
if(index == 0) {
//insert the new node containing item at
//beginning of list
Node newNode = new Node(item,head);
head = newNode;
head.setNext(head);//--------------------
}
else {
Node prev = find(index-1);
//insert the new node containing item after
//the node that prev references
Node newNode = new Node(item,head.getNext()); //changed prev to head
head.setNext(newNode); //prev.next = newNode --//changed prev to ead
head = newNode;
}//end if
}
sizeplus();
/*if(index == 16){//fffff
for(int i = 0; i < 50; i++){
System.out.println(head.item());-------------EXR
head = head.getNext();
System.out.println("----------");
}//ifffffff
}
*/
}//end add
public int sizeplus(){
size+=1;
return size;
}
public void remove(int index){
int num = index;
while(size>0){
//System.out.println("strt");
if(index>= 0 /*&& index < size*/){
if(index == 0) {
//delete the first node from the list
System.out.println("REMOVED :"+head.item());//----------------EXR
head = head.getNext();
}
else {
Node prev = find(index-1);
// delete the node after the node that prev
//references, save regerence to node
Node curr = prev.getNext();
System.out.println(curr.item());
if(size > 1){
}
else{
System.out.print("is the last one left");
}
prev.setNext(curr.getNext());
curr = prev.getNext();
index+=num-1;
}//end if
size--;
//System.out.println(size+" <-size || index-> " +index);
}//end if
}
}//end remove
public Node getH(){
return head;
}
}//end class
ALSO: how would i change from linked list to the next
here is what i tried.
linkedList list = new linkedList();
list = arrayString[i];
p7b.java:44: error: incompatible types
list = arrayString[i];
^
required: linkedList
found: Object
1 error
From your main method :
Object[] arrayString = new String[40];
...
Insert(hashVal,key,arrayNums,arrayString);
You are passing a String array to your method.
Therefore you can't put linkedList instances in this array.
If you want this array to contain linkedList instances, change the code to :
Object[] arrayString = new linkedList[40];
...
Insert(hashVal,key,arrayNums,arrayString);
or even better :
linkedList[] arrayString = new linkedList[40];
...
Insert(hashVal,key,arrayNums,arrayString);
and change the signature of Insert to accept a linkedList[] instead of Object[].
Here's the culprit:
Object[] arrayString = new String[40];
You're claiming that it's an Object[], but it's actually backed by a String[] instead. Java can't make the determination at compile time that you're not going to be able to store any old Object into that array, so it blows up at run time.
What you should do is type the array correctly - if it's going to hold linkedList entities, it should be linkedList entities.
linkedList[] linkedLists = new linkedList[40];
More specifically, you are using the array in a lot of different places. Be consistent with its usage.
Having a few thoughts about your code: it's not...correct. You're creating a linked list, right? There's no reason to use arrays unless the list itself is backed by them.
I can't vouch for the correctness of your linkedList.add method right now, but you don't want to use arrays for this at all. Create a single instance of a linked list outside of that method and store all of the data you care about in it.
public static void insert(String key, int index, linkedList list) {
list.add(index, key);
}
(As a general thought, linked lists don't have index positions that you simply insert into, so the index portion is completely superfluous.)

Order a linked list alphabetically by name

I am having an issue organizing a linked list alphabetically. I am reading the names in from a text file and storing them into a linked list. The problem I am having is how to sort them alphabetically. If anybody could point me in the right direction that would be amazing. The idea is to get the value of the first 3 letters in each name and compare them to the first 3 in the next name. But where would I compare the letters together?
Here is the LinkedListNode class:
public class LinkedListNode
{
private String data;
private LinkedListNode next;
public LinkedListNode(String data)
{
this.data = data;
this.next = null;
}
public String getData()
{
return data;
}
public LinkedListNode getNext()
{
return next;
}
public void setNext(LinkedListNode n)
{
next = n;
}
}
Here is the LinkedList file with the main method:
import java.io.*;
import java.util.Scanner;
public class LinkedList {
public LinkedListNode head;
String fname;
public static void main(String[] args) throws FileNotFoundException{
Scanner scan = new Scanner(new File("Names.txt"));
LinkedList l = new LinkedList();
int i = 1;
while(scan.hasNext()) {
String s = scan.nextLine();
l.insertBack(s);
i++;
}
System.out.print(l.showList());
}
public LinkedList() {
this.head = null;
}
public void insertBack(String data){
if(head == null){
head = new LinkedListNode(data);
}else{
LinkedListNode newNode = new LinkedListNode(data);
LinkedListNode current = head;
while(current.getNext() != null){
current = current.getNext();
}
current.setNext(newNode);
}
}
public String showList(){
int i = 0, j;
String retStr = "List nodes:\n";
LinkedListNode current = head;
while(current != null){
i++;
retStr += "Node " + i + ": " + current.getData() + "\n";
current = current.getNext();
}
return retStr;
}
}
Some pseudo code for you:
OUTER:
for word in file
node = head
while node.next
if word > node.word
node.next
else
Node temp = new Node(word)
temp.next = word.next
node.next = temp
continue OUTER
node.next = new Node(word)
This is an as-you-go insertion sort. After every insert the file will be sorted. Or you could use other sorting algorithms after you read all of the data
if it's if word > node.word this part you're having trouble with, the String#compareTo method will be useful
Try using Collections.sort(list)
Also, for comparing, you can use compareTo function under Comparable Interface
To do easy comparisons, your nodes should implement Comparable. The base Java libraries tend to rely upon this for easy sorting.
The Comaprable interface will require you to implement compareTo (see below).
public int <LinkedListNode> compareTo(LinkedListNode n){
//Case insensitively compare the first 3 characters of the two nodes
String myHead = data.substring(0,3).toLowerCase();
String comparableHead = n.data.substring(0,3).toLowerCase();
return (myHead.compareTo(comparableHead));
}
If you use a standard List structure like, ArrayList, the Collections.sort(list) will be able to use this method to order your list.
And here's an insertion sort based "insert" function for your runTime, using this comparable.
public void insert(String data){
LinkedListNode newNode = new LinkedListNode(data);
if(head == null){
head = newNode;
}else{
LinkedListNode current = head;
LinkedListNode prev;
//This is missing some key edge cases, but it inserts properly in the general case. You'll have to add to it to handle things like running off the list, or this needing to be inserted before the head.
while(current.getNext() != null){
if(current.compareTo(newNode)<0){
newNode.setNext(current);
prev.setNext(newNode);
break;
}
prev = current;
current = current.getNext();
}
}
}

How to add a display method to a Java Linked List implementation that displays only the first and the last 10 items on the list?

UPDATE: Thanks to all who answered I did what I was assigned to do. This is really a great forum and I was surprised to find so many helpful and friendly-minded people here :)
What I did was to modify the print method in the following way:
public static void print(ListNode start){
System.out.println("Printing the first 10 elements on the list:");
System.out.print("{");
ListNode previous = start;
ListNode current = start;
for (int i = 0; i<10; i++){
current=current.next;
}
for(ListNode node = start; node != current; node = node.next){
System.out.print(node);
}
System.out.println("}");
System.out.println("Printing the last 10 elements on the list:");
System.out.print("{");
while(current != null){
previous = previous.next;
current = current.next;
}
for(ListNode node = previous; node != current; node = node.next){
System.out.print(node);
}
System.out.println("}");
System.out.println("End of list");
}
END OF UPDATE
I'm learning Algorithms and Data structures in Java and I need to add a specific display method to an existing exercise Linked List implementation but I don't know how to do it.
So there is a linked list that contains many items (say thousands) and I need a display method that shows only the first and the last 10 items on the list.
Can you suggest to me a way to do it?
The Linked list implementation that I need to work on is the following:
import java.util.*;
public class Main {
public static class ListNode {
//A linked list node. The data field is represented by the field int data
//The next item is referenced by the reverence value next
int data;
ListNode next;
public ListNode(){
this.data = 0; this.next = null;
}
public ListNode(int data){
this();this.data = data;
}
public ListNode(int data, ListNode next){
this.data = data;this.next = next;
}
public String toString() {
return "[" + this.data + "]";
}
//The linked list is referenced by the first node.
//An empty list is referenced by a null reference.
//That's why all methods for the list are public static -
//(null doesn't have methods)
//Returns the beginning of a list with length "length"and
//elements with random values
public static ListNode generate(int length) {
ListNode start = null;
Random rn = new Random();
for(int i = 0; i < length; i++){
start = new ListNode(rn.nextInt(10000), start);
}
return start;
}
//Displays the list to the console from the specified starting point
public static void print(ListNode start){
System.out.print("{");
for(ListNode node = start; node != null; node = node.next){
System.out.print(node);
}
System.out.println("}");
}
//Counts how many elements there are in the list
public static int length(ListNode L){
int k=0;
for(;L!=null;k++,L=L.next);
return k;
}
//Returns a node with key searchd if found in the list
public static ListNode search(ListNode start, int searchd){
for(ListNode node = start; node != null; node = node.next){
if(node.data == searchd){ return node; }
}
return null;
}
//If a node with the specified key is found in the list L
//a new node with the value keyAfter is inserted after it.
public static void insertAfter(ListNode L, int key, int keyAfter){
while(L!=null && L.data!=key)L=L.next;
if(L!=null){
L.next= new ListNode(keyAfter,L.next);
}
}
//Inserts a node with key "keyBefore" before the node
//with the specified key
public static ListNode insertBefore(ListNode L, int key, int keyBefore){
ListNode p = null, r=L;
while(L!=null && L.data!=key){
p=L;L=L.next;
}
if(p!=null){
p.next= new ListNode(keyBefore,p.next);return r;
}
else{
p=new ListNode(keyBefore,L);return p;
}
}
//Inserts a new element with the specified key in a sorted list
//with ascending values so that the list remains sorted
public static ListNode insertOrd(ListNode L, int key){
ListNode p = null, r=L;
while(L!=null && L.data<key){
p=L;L=L.next;
}
if(p!=null){
p.next= new ListNode(key,p.next);return r;
}
else{
p=new ListNode(key,L);return p;
}
}
//Generates a sorted list with a specified lenght
public static ListNode generateOrd(int length) {
ListNode start = null;
Random rn = new Random();
for(int i = 0; i < length; i++){
start = insertOrd(start,rn.nextInt(10000));
}
return start;
}
//Takes two ordered lists and returns a merged and sorted list
//that combines the elements in the original lists
public static ListNode merge(ListNode a, ListNode b){
if(a==null)return b;
if(b==null)return a;
ListNode r = null;
if(a.data<=b.data){
r=a;a=a.next;
}else{
r=b;b=b.next;
}
ListNode last=r;
while(a!=null && b!=null){
if(a.data<=b.data){
last.next=a;a=a.next;
}else{
last.next=b;b=b.next;
}
last=last.next;
}
if(a!=null)last.next=a;else last.next=b;
return r;
}
//Splits a list evenly and returns the beginning of the 2-nd part
public static ListNode split(ListNode L){
int n=length(L)/2;
ListNode t=L;
for(int i=0;i<n-1;i++,t=t.next);
ListNode secPart = t.next;
t.next=null;
return secPart;
}
//Sorts a list in an ascending order
public static ListNode mrgSort(ListNode L){
if(L==null || L.next==null)return L;
ListNode b = split(L);
L=mrgSort(L); b= mrgSort(b);
return merge(L,b);
}
};//End of class ListNode
public static void main(String[] args){
ListNode a = ListNode.generateOrd(10);
ListNode.print(a);
ListNode b = ListNode.generateOrd(10);
ListNode.print(b);
a=ListNode.merge(a,b);
ListNode.print(a);
b=ListNode.split(a);
ListNode.print(a);
ListNode.print(b);
ListNode c = ListNode.generate(20);
ListNode.print(c);
c = ListNode.mrgSort(c);
ListNode.print(c);
}
}
Alright, I am not going to write the code for you but ill tell you how to go about doing it.
Initially say you have two pointers (head1 and head2) which point to the first node of the list. Move head2 ten steps forward keeping head1 at the same place.
Now, after ten steps you have head1 at 0 and head2 at 9th position. Now move both together till head2 hits NULL. Once head2 hits NULL, start moving head1 alone and print each node till head1 reaches head2.
Hope this helps
This is a fairly odd implementation of a Linked list.
What sticks out is
The amount of static members
No class representing the actual list.
The static members in node should be placed in a LinkedList class. Check out the members of the JavaAPIs LinkedList class.
The other members are similar to what is found in the Collections class.
As it stands the easiest solution is as peraueb suggests in the comments follow the print method; i.e. Do as print does, and store the link to the 10:th to last node. noMAD's idea will work fine there.
The usual way to do it would be to have a LinkedList class handle references / links to the first and the last Node. The Node itself should contain links/references to the previous as well as the next node. This is the suggestion of Nactives answer. Now you are manually dealing with those in main(...).
For that you need a reference to your first and your last item.
Best way is also to make it a duuble linked list: http://en.wikipedia.org/wiki/Doubly_linked_list
Basicly, at the front of your list it is still the same.
But now you can also access your list at the end and move to the beginning of your list.

Categories