Link List : initializing the header - java

So I'm working on a problem to print the nth element from the last of the list.
I have the method and a procedure figured out. This procedure finds the element.
public Node nth_element(Node head, int n){
// head to point to the first element in the list
// n is the element to be returned from the tail of the list
---do the function here---
}
Now when I'm in the main class and calling the above method. My Linked List class where the above method is declared initializes the head to null in its constructor.
How do i initialize the head?
This is my main class:
public class Main
{
static void main()
{
List l = new List() //initialize the list
//then i add the elements into the list using insert()
//display()
//now
**Node mynode = l.nth_element(head, value);**
// how do i initialize this head
}

In your self-defined linked list class List, you need to put head as the class field as
public class List {
private Node head = null;
// all method for List....
}
Then when you implement nthElement method, you don't have to use head as your first argument since it's already a class member and you can use it directly in your class methods. But if you do need to, then you can create a public method in List class:
public Node getHead() {
return head;
}
Your nthElement method will look like
public Node nthElement(Node head, int n) {
//implementation ...
}
Then in the main method, you can call nthElement like
Node mynode = l.nthElement(l.getHead(), value);
But make sure that your list is not empty. Otherwise, head is null.

Adding to #tonga's answer.
Your class List constructor should be something like:
private Node head;
public List(Node head)
{
this.head = head;
}
and then create your list
List l = new List(new Node(1));

Related

Why to have a parent class for linked list

This is a general question, maybe about OOP concept. I am just starting with DS implementation in JAVA.
I am trying to implement Linked List and on all online rsources, I see a similar practice:
Make a node class.
Make a class Linked List that has a node object.
Similarly I saw for stack, queues and trees. My question is, if I implement LinkedList by only having one class that looks like below:
class LinkList {
int data;
LinkList next; }
I am still able to do all the operations. So the concept of having a second class that contains a root or a header is only for OOP purpose or something else?
I wrote the following code and it works all well without the need to have a header pointer. I use a references variable in all the methods and the main class's object still keeps the track of the head.
/* package codechef; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
class LinkList {
int data;
LinkList next;
LinkList(){
data = 0;
next = null;
}
LinkList(int data) {
this.data = data;
next = null;
}
LinkList insertAtBegin(int data){
LinkList newBegin = new LinkList(data);
newBegin.next = this;
return newBegin;
}
void insertAtPlace(int data, int insertData){
LinkList newNode = new LinkList(insertData);
LinkList iterator = this;
while(iterator!=null && iterator.data!=data){
iterator = iterator.next;
}
if(iterator.data == data)
{
newNode.next = iterator.next;
iterator.next = newNode;
}
}
void insertAtLast(int data) {
if(next == null){
next = new LinkList(data);
}
else{
next.insertAtLast(data);
}
}
}
/* Name of the class has to be "Main" only if the class is public. */
class Codechef
{
public static void main (String[] args) throws java.lang.Exception
{
// your code goes here
LinkList linkList = new LinkList(6);
linkList.insertAtLast(5);
linkList.insertAtLast(3);
linkList.insertAtLast(2);
linkList.insertAtLast(1);
linkList = linkList.insertAtBegin(10);
LinkList iterator = linkList;
while(iterator!=null){
System.out.print(iterator.data);
iterator = iterator.next;
}
System.out.print("\n");
linkList.insertAtPlace(5,-1);
iterator = linkList;
while(iterator!=null){
System.out.print(iterator.data);
iterator = iterator.next;
}
}
}
You must keep track of the head of the linked list somewhere. Otherwise, how would you iterate over the entire list, or search for an element in the list?
If your LinkList is essentially a node (with data and reference to the next node), you would have to implement all the linked list operations (add, delete, etc...) in some separate class that keeps track of the head node of the list.
This brings you back to a linked list class that uses a node class.
As for the code you added, LinkList insertAtBegin(int data) will only insert a node at the beginning of the list if you call it on the first node of the list. But there's nothing stopping you from calling it on any node of the list, in which case it will essentially return a new list that starts with the new elements and ends with a sub-list of the original list.
There are several reasons to have two classes:
to distinguish the notion of a list and that of a single node,
to avoid the awkward returning of the head node from each method,
to avoid letting the client of the class have the responsibility to keep track of the head node,
to hide the implementation details, so that the class could be more easily replaced with an equivalent one,
etc...
Your LinkList class would just be a node class in the first example, because it holds the data and the node that comes after it
The general purpose of having a LinkedList class is to have a "wrapper" for the list, it's just a class that holds the head of the list (which in the case of a linked list, is the list) and perhaps some functionalities such as a find function or anything else you'd need.
so in your case (2nd example) it is just a wrapper class that implements some extra functionalities (insertAtBegin(), insertAtPlace() and insertAtLast())

Pointers in LinkedList in Java

I am studying the linked lists,and I'm having a little problem understanding references and pointers in Java (and also have some questions for which I can't find answer on the internet.) Namely,I have a class LinkedList that uses class Node like this:
public class LinkedList {
public Node head;
public LinkedList(int data) {
head = new Node(data);
}
}
and this is my Node class:
public class Node {
public int data;
public Node next;
public Node(int data2) {
data = data2;
}
}
I also have method toStringLL() inside LinkedList which looks like:
public void toStringLL() {
LinkedList l=this;
while(l.head.next != null) {
System.out.print(l.head.data+"->");
l.head = l.head.next;
}
System.out.print(l.head.data);
System.out.println("");
}
I don't understand why this toStringLL() changes my head of linked list,when I am iterating through it with l.head=l.head.next? Shouldn't my head stay the same?I thought that when I write LinkedList l=this,I can freely iterate through l,without affecting this(or am I wrong?) Now when I use Node n=this.head instead of LinkedList l=this,it works,but I have difficulty figuring out why that works and the previous doesn't.. Can someone explain to me the difference between these two?
I don't understand why this toStringLL() changes my head of linked list,when I am iterating through it with l.head=l.head.next?Shouldn't my head stay the same?
When you make the assignment
LinkedList l = this;
you are not creating a new LinkedList object. You are just defining a references to the existing LinkedList object.
Therefore, l.head = l.head.next does exactly the same as this.head = this.head.next. Both change your original list.
On the other hand, when you write
Node n = this.head
you are not changing the head of your List. You are declaring a variable that initially refers to the head of your List, but when you change that variable to refer to other Nodes of your list, the head variable of your list (this.head) remains unchanged.
When you set
l.head=l.head.next;
you change your head.

Head node of Linked List

So I was wondering how I could create a new empty linked list, using my class definition of List and node, with a first head node pointing to null without having to hold any integer value. The thing is I'm not allowed to change the given methods or add any to the definition, so whenever I create a list, in the constructor I'm not sure how I'm supposed to asign head to null. Here's part of the codes:
public class Node {
private Node next;
private int key;
Node(Node nxt, int keyValue) {
key = keyValue;
next = nxt;
}
Node getNext() {
return next;
}
int getKey() {
return key;
}
void putNext(Node nxt) {
next = nxt;
}
}
Class List
public class List {
private Node head;
List() {
head = new Node(null, -1); // arbitary value for head
head.putNext(null);
}
This is what I came up with. I just assign a random value to variable key in head node. But if I do this, it will kinda mess up with my later methods that used recursive like deletion or finding sum or find max, min, etc
Is there any other way around I can do to deal with this issue?
In an Empty Linked List Head is Just a pointer which points to Nothing. You dont need to worry about creating an object to which current head points. Just create a head pointer and assign it to NULL. When you are actually adding a Node assign the address of first node to Head. Thats it...
public class List {
private Node *head;
List() {
head = NULL;
}
}

regarding this keyword (java)

I have a question regarding the output of the following program. The output is null. This is what I thought as well. Im thinking its because the methods called before display simply modify a copy of head and not head itself. Im assuming that I could get around this using a this.head= something right?
Heres the code:
public class List {
private Node head;
public List (){
int max=3;
int i;
head=null;
Node aNode=new Node(0);
for (i=0; i<max; i++) {
aNode.setNum(i);
add (aNode);
aNode.setNext(null);
}
}
public void add(Node aNode) {
Node temp;
if(head==null)
head=aNode;
else {
temp=head;
while(temp.getNext()!=null)
temp=temp.getNext();
temp.setNext(aNode);
}
}
public void display() {
Node temp=head;
while(temp!=null) {
System.out.println(temp.getNext());
temp=temp.getNext();
}
}
}
public class Node {
private int num;
private Node next;
public Node (int n) {num=n; next=null;}
public int getNum() {return num;}
public void setNum(int n) {num=n;}
public void setNext(Node n) {next=n;}
public Node getNext() {return next;}
}
public class Driver {
public static void main(String args[]) {
List aList=new List();
aList.display();
}
}
The add relies on receiving a new Node with next being null. So move Node aNode = new Node(); inside the for-loop.
Some sanitary remarks.
(Unimportant) Use current instead of temp, or anything else.
Fields in classes are by default null/0/0.0/false.
Before I answer your question, here is a side note...
Im thinking its because the methods called before display simply modify a copy of head and not head itself.
This is NOT correct.
Here is why...
public void display() {
// Basically, this says, make temp a REFERENCE of head...NOT A COPY!!!!
Node temp=head;
while(temp!=null) {
System.out.println(temp.getNext());
temp=temp.getNext();
}
}
Now, to answer your question, the reason temp is null is because head is null. And the reason head is null is because you never initialize it.
From you constructor...
public List (){
int max=3;
int i;
// Here you're saying "set head to null".
// So when you call display, head is NULL. You MUST initialize this.
head=null;
Node aNode=new Node(0);
for (i=0; i<max; i++) {
aNode.setNum(i);
add (aNode);
aNode.setNext(null);
}
}
Look at this code from the constructor:
Node aNode=new Node(0);
for (i=0; i<max; i++) {
aNode.setNum(i);
add (aNode);
aNode.setNext(null);
}
You create one new node, and then keep trying to add that node to the list. You need the first line to be inside the for loop, so you create lots of nodes. After the constructor completes, your list only contains one node, with the value 3. Then later, in display():
System.out.println(temp.getNext());
You start by calling getNext() on the first node. Since there's only one node, getNext() returns null, which is what you print out. You should replace this line with
System.out.println(temp);
The error is nothing to do with the this keyword at all. You only need this.foo (when foo is some data member of your class) to disambiguate when you have a both a member and a local variable or parameter with the same name.

Sorted linked list implementation

i am a novice programmer, to be specific, i am learning java programming and i am supposed to implement sortedLinkedList class that extends LinkedList class from the java library. The list has to store persons in ascending order of their surnames. I have already written my Person class that implements Comparable interface. my problem is, I have been struggling implementing this sortedLinkedClass but to no avail. My code runs without any compiling or run time error but the program does not print anything. Another thing as you can see , I am testing it with Integers instead of Persons and it throws NullPointerException when trying to add a number that is already in the list. My code is as it is below.
import java.util.*;
public class SortedLinkedList< E> extends LinkedList<E>
{
private Link<E> first;
private Link<E> last;
/**
* Constructor for objects of class SortedLinkedList
*/
public SortedLinkedList()
{
//super();
first = null;
last = null;
}
/*
* Link class for creating Link nodes in the SortedLinkedList objects
*/
private class Link<E>
{
public Comparable<E> data;
public Link next;
}
/*
* Overiding add method from LinkedList class
*/
public boolean add(E obj)
{
Link newLink = new Link();
newLink.data = (Comparable<E>)obj;
// When the list is initially empty
if (first == null)
{
first = newLink;
last = newLink;
return true;
}
// When the element to be added is less than the first element in the list
if (newLink.data.compareTo(first.data) < 0)
{
//newLink.data = obj;
newLink.next = first;
first = newLink;
return true;
}
// When the element to be added is greater than every element in in list
// and has to be added at end of the list
if (newLink.data.compareTo(last.data) > 0)
{
//newLink.data = obj;
last.next = newLink;
last = newLink;
return true;
}
//When the element to be added lies between other elements in the list
if (newLink.data.compareTo(first.data) >= 0 && newLink.data.compareTo(last.data) <= 0)
{
//newLink.data = obj;
Link current = first.next;
Link previous = first;
while (newLink.data.compareTo(current.data) <= 0)
{
previous = current;
current = current.next;
}
previous.next = newLink;
newLink.next = current;
}
return true;
}
public static void main (String[] args)
{
LinkedList<Integer> list = new SortedLinkedList<Integer>();
list.add(4);
list.add(5);
list.add(10);
list.add(9);
//list.add(5);
ListIterator<Integer> iterator = list.listIterator();
while (iterator.hasNext())
{
System.out.println(iterator.next());
}
}
}
If you must use a LinkedList, all you really have to do is override the "add" method so that it inserts your element in the correct position. You can do that by invoking the add(integer,Object) method which inserts your element in a specific position.
Here's a quick and dirty (and non-generic :P) implementation of what I'm talking about.
public class PersonLinkedList extends LinkedList<Person> {
public boolean add(Person personToAdd) {
int index = 0;
for( ; index<size() ; index++){
Person personAlreadyInList = get(index);
if(personToAdd.compareTo(personAlreadyInList) < 0){
break;
}
}
add(index, personToAdd);
return true;
};
public static void main(String[] args) {
Person amy = new Person("Amy");
Person bob = new Person("Bob");
Person claire = new Person("Claire");
PersonLinkedList list = new PersonLinkedList();
list.add(bob);
list.add(claire);
list.add(claire);
list.add(amy);
list.add(bob);
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Person person = (Person) iterator.next();
System.out.println(person);
}
}
}
class Person implements Comparable<Person>{
private String name;
public Person(String name) { this.name = name; }
public String getName() { return name; }
#Override
public String toString() { return getName();}
#Override
public int compareTo(Person p) {
return name.compareTo(p.name);
}
}
The reason nothing gets printed is because you store the data in your own linked list data tree and not the LinkedList's data tree. You don't override the iterator method, so the iterator will loop through LinkedList's data which is empty. This is also a problem with all the other methods in LinkedList.
Are you sure you need to inherit from the LinkedList class or are you suppose to make your own class.
If you are supposed to inherit from LinkedList get rid of you node and use LinkedList for storing the data. Your add method would then use a ListIterator to find the correct spot for adding and use the add method of ListIterator.
If you don't inherit from LinkedList then extend AbstractSequentialList.
Note:
Both of these options should not be used in real code. Adding automatic sorting breaks the List interface.
The whole problem is a perfect example of "prefer composition over inheritance".
If this is homework do it as instructed, otherwise I'd recommend changing the exercise to implement a SortedCollection backed by a LinkedList. Then implement Collection and use a List as a member variable.
You could use a SortedSet if you don't need to support elements with the same sort key.
Also, the reason your code doesn't print anything is because you override adding items to the list, but not iterating (the iterator() or listIterator() methods.) Extending LinkedList doesn't automagically make your data structure iterable unless you modify its contents using the base class add(), remove(), and other methods.
besides iterator, add/remove override, I think your algorithm to sort is not correct. And that leads to the nullpointer exception when you add existing elements into your "sortedLinkedList".
while (newLink.data.compareTo(current.data) <= 0)
{
previous = current;
current = current.next;
}
I think what you wanted is while (newLink.data.compareTo(current.data) >0) . not <=0. here is the mistake.
since "=0" is in while condition, it will go through the whole list, till the last element, then execute:
(current is the last now)
previous = current;
current = current.next; (now, current is Null, since last.next is Null)
finally, current is Null, then comes again, current = current.next; Bang! Nullpointer.
so I guess the Nullpointer was thrown at this line.

Categories