Confused about choosing a loop to iterate a linked list - java

My problem is in the add method. I think I know what I want it to do but I can't figure out what type of loop I should use to look through the list. As you can see I started to make a if else loop but I couldn't figure out what I should use as the counter. I'm pretty sure I have the right logic in dealing with the add but I feel like I'm not quite there yet. I was thinking of using compareTo in some fashion.
import java.util.*;
public class OrderedLinkedList<E extends Comparable<E>>
{
private Node topNode;
private class Node
{
private E data;
private Node nextNode;
public Node(E data)
{
this.data = data;
nextNode = null;
}
}
public OrderedLinkedList()
{
topNode = null;
}
public boolean empty()
{
if(topNode == null)
return true;
return false;
}
public String toString()
{
String myString = "";
Node nextNode = topNode;
while(nextNode != null)
{
myString = topNode + " -> " + nextNode;
nextNode = topNode.nextNode;
}
return myString;
}
public void add(E data)
{
Node myNode = new Node(data);
Node priorNode = topNode;
Node currentNode = topNode;
if(___)
{
priorNode = currentNode;
currentNode = currentNode.nextNode;
}
else
{
priorNode.nextNode = myNode;
myNode.nextNode = currentNode;
}
}
}

Since you don't typically know the length of a linked list until you've walked down it, the usual thing would be to use a while loop (as you've done in your toString() method)

Perhaps using a doubly linked list would be more beneficial. Consider the following alterations to your class:
import java.util.*;
public class OrderedLinkedList<E extends Comparable<E>>
{
private Node head;
private Node tail;
private class Node
{
private E data;
private Node nextNode;
private Node prevNode;
public Node(E data)
{
this.data = data;
nextNode = null;
prevNode = null;
}
public void setNext(Node node)
{
this.nextNode = node;
}
public Node getNext()
{
return this.nextNode;
}
public void setPrev(Node node)
{
this.prevNode = node;
}
public Node getPrev()
{
return this.prevNode;
}
public E getData()
{
return this.data;
}
public int compareTo(Node that) {
if(this.getData() < that.getData())
{
return -1;
}
else if(this.getData() == that.getData()
{
return 0;
}
else
{
return 1;
}
}
}
public OrderedLinkedList()
{
head = new Node(null);
tail = new Node(null);
head.setNext(tail);
tail.setPrev(head);
}
public boolean empty()
{
if(head.getNext() == tail)
{
return true;
}
return false;
}
public void add(E data) {
Node tmp = new Node(data);
if(this.empty()) {
this.addNodeAfterNode(tmp, head);
} else {
Node that = head.getNext();
// this while loop iterates over the list until finding the correct
// spot to add the new node. The correct spot is considered to be
// when tmp's data is >= that's data, or the next node after 'that'
// is tail. In which case the node is added to the end of the list
while((tmp.compareTo(that) == -1) && (that.getNext() != tail)) {
that = that.getNext();
}
this.addNodeAfterNode(tmp, that);
}
}
private void addNodeAfterNode(Node addNode, Node afterNode)
{
addNode.setNext(afterNode.getNext());
afterNode.getNext().setPrev(addNode);
afterNode.setNext(addNode);
addNode.setPrev(afterNode);
}
}

Related

how do I call the previous Node of an unknow object?

I am using custom made data structure and, in this project, I am using a doubly LinkedList to implement a blockchain.
so I have made a Main class and a Block class and of course the LinkedList class, the LinkedList class was made to accept data of the type Block so when I try to add elements to my list i pass on a new block with the information the problem is after the first element I don't know how to call the hash value of the previous block.
basically in every block class there should be a hash and the hash of the previous block in block one there is no prev hash so its 0 but the second block and onwards is where I am lost.
this is my block class
import java.util.Date;
public class Block {
public String hash;
public String previousHash;
private String data;
private long timeStamp;
public Block(String data, String previousHash) {
this.data = data;
this.previousHash = previousHash;
this.timeStamp = new Date().getTime();
this.hash = calculateHash();
}
public String calculateHash() {
String calculatehash = StringUtil.applySha256(
previousHash + Long.toString(timeStamp) + data);
return calculatehash;
}
}
this is my doubly LinkedList file
class Node {
private Block data; // node storing int data
private Node nextNode; // the next pointer node, the arrow in drawing
private Node prevNode;
// don't forget the class constructor
public Node(Block data2) {
this.data = data2;
}
// since we made variable private
// to access them we need setters and getters
public Block getData() {
return this.data;
}
public Node getNextNode() {
return this.nextNode;
}
public Node getPrevNode() {
return this.prevNode;
}
public Block setData(Block data) {
return this.data = data;
}
public Node setNextNode(Node nextNode) {
return this.nextNode = nextNode;
}
public Node setpervNode(Node prevNode) {
return this.prevNode = prevNode;
}
#Override
public String toString() {
return "Data: " + this.data;
}
}
public class DoublyLinkedlist {
private Node head;
private Node tail;
private int size = 0;
public DoublyLinkedlist() {
}
public int getSize() {
return this.size;
}
public void addFirst(Block data) {
Node node = new Node(data);
if (this.tail == null && this.head == null) {
this.tail = node;
this.head = node;
} else if (this.head == null) {
this.head = node;
} else {
Node old = this.head;
node.setNextNode(old);
this.head = node;
old.setpervNode(this.head);
}
this.size++;
}
public void addLast(Block data) {
Node node = new Node(data);
if (this.tail == null && this.head == null) {
this.tail = node;
this.head = node;
} else if (this.tail == null) {
this.tail = node;
} else {
Node old = this.tail;
this.tail.setNextNode(node);
this.tail = node;
this.tail.setpervNode(old);
}
this.size++;
}
public Node removeFirst() {
Node removed = this.head;
this.head = this.head.getNextNode();
this.size--;
return removed;
}
#Override
public String toString() {
String output = "[size=" + this.size + "] >> ";
Node fromHead = this.head;
while (fromHead != null) {
output = output + fromHead.getData();
if (fromHead != this.tail)
output = output + " >> ";
fromHead = fromHead.getNextNode();
}
output += "\n";
Node fromTail = this.tail;
while (fromTail != null) {
output = output + fromTail.getData();
if (fromTail != this.head)
output = output + " << ";
fromTail = fromTail.getPrevNode();
}
return output;
}
public boolean contains(Block data) {
Node current = this.head;
while (current != null) {
if (current.getData() == data) {
return true;
}
current = current.getNextNode();
}
return false;
}
public void clear() {
while (this.head != null) {
this.removeFirst();
}
System.out.println("List Is Cleared!");
}
}
and this is my Main class
public class Main {
public static DoublyLinkedlist blockchain = new DoublyLinkedlist();
public static void main(String[] args) {
blockchain.addFirst(new Block("hi i am the first block", "0"));
blockchain.addLast(new Block("yo i am the second block", blockchain.get(blockchain.getSize()-1.hash)));
}
}
i tried using the get method based on a tutorial that was implementing using an arraylist but obviously it's a wrong syntax.
The main program should not have to deal with retrieving hashes, not even with creating blocks. Instead aim for your main code to look like this:
public class Main {
public static DoublyLinkedlist blockchain = new DoublyLinkedlist();
public static void main(String[] args) {
blockchain.addLast("Hi, I am the first block");
blockchain.addLast("Yo, I am the second block");
}
}
Then your other classes would also need some adaptations. In Node I would add a constructor that can take a second argument, so it can establish the link with a previous node:
public Node(Block data, Node prevNode) { // Additional constructor
this.data = data;
this.prevNode = prevNode;
if (prevNode != null) {
prevNode.setNextNode(this);
}
}
In the DoublyLinkedList class, remove the addFirst method: you don't want to add blocks before any existing blocks, as that would invalidate the hashes of the blocks that are already in the list. Blocks should only be added at the end.
The addLast method should take a string instead of a Block instance, and this method can also be used for adding the very first block.
public void addLast(String data) {
tail = new Node(new Block(data, tail != null ? tail.getData().hash : "0"), tail);
if (head == null) head = tail;
size++;
}

Finding and Deleting a Node from this linked list in java

I have to write a program that implements a linked list of Students, in this case Student is a separate class that will be called. My linked List is supposed to be able to find a Student using the Name of that student and this is the area where my program fails it doesn't seem to find that Node for that Student, hence it also wont delete. I am writing this for a class and the professor does not allow the use of the built in Linked List class.
This is My Code
public class StudentList {
StudentNode head;
public StudentList() {
shead = null;
}
public void setShead(StudentNode data) {
shead = data;
}
public StudentNode getShead() {
return shead;
}
public void insert(StudentNode data) {
StudentNode iterator = head;
if (iterator == null) {
head = data;
} else {
while (iterator.getnext() != null) {
iterator = iterator.getnext();
}
iterator.setnext(data);
}
}
public void delete(StudentNode data) {
StudentNode iterator = head;
StudentNode current;
if (iterator == data) {
head = iterator.getnext();
} else {
while (iterator.getnext() != null) {
if (iterator.getnext().equals(data)) {
// current
iterator.setnext(iterator.getnext().getnext());
// current.setSptr(iterator.getnext());
break;
} else {
iterator = iterator.getSptr();
}
}
}
}
public StudentNode find(String n) {
StudentNode iterator = head;
StudentNode result = null;
while (iterator.getnext() != null) {
if (iterator.getStudent().getName().equals(n)) {
result = iterator;
System.out.println("" + iterator.getStudent().getName());
} else {
result = null;
}
iterator = iterator.getnext();
}
return result;
}
public void print(){
StudentNode iterator = head;
while(iterator != null){
JOptionPane.showMessageDialog(null,""+ iterator.getStudent().getName());
iterator = iterator.getnext();
}
}
}
This is the Node
public class StudentNode{
private Student data;
private StudentNode next;
public StudentNode(){
data = null;
next = null;
}
public StudentNode(Student data){
this.data = data;
next = null;
}
public Student getStudent(){
return data;
}
public void setStudent(Student data){
this.data = data;
}
public StudentNode getnext(){
return next;
}
public void setnext(StudentNode next){
this.next = next;
}
}
`if(iterator == data){` // <-- It just checks for same reference
head = iterator.getnext();
}
if(iterator.getnext().equals(data)){ // <-- Here also, since you havent overridden equals method.. references will be comparaed
Also, I dont see you calling find method
You should override equals method in StudentNode, where you can compare Student object and check whether these are equal or not.

Iterator for a linkedlist

My project should implement two classes. A basic linked list and a sorted linked list. Everything seems to be working fine except for some reason I can't iterate through the sorted linked list. The class structure is as follows:
public class BasicLinkedList<T> implements Iterable<T> {
public int size;
private class Node {
private T data;
private Node next;
private Node(T data) {
this.data = data;
next = null;
}
}
private Node head;
private Node tail;
public BasicLinkedList() {
head = tail = null;
}
//Add, remove method
public Iterator<T> iterator() {
return new Iterator<T>() {
Node current = head;
#Override
public boolean hasNext() {
return current != null;
}
#Override
public T next() {
if(hasNext()){
T data = current.data;
current = current.next;
return data;
}
return null;
}
#Override
public void remove(){
throw new UnsupportedOperationException("Remove not implemented.");
}
};
Now when I test this class it works just fine. The iterator works and I can test it all. The problem is in the sorted linked list class which extends this one. Here's its implementation and a comparator class that I'm using in the constructor:
public class SortedLinkedList<T> extends BasicLinkedList<T>{
private class Node{
private T data;
private Node next;
private Node(T data){
this.data = data;
next = null;
}
}
private Node head;
private Node tail;
private Comparator<T> comp;
public SortedLinkedList(Comparator<T> comparator){
super();
this.comp = comparator;
}
Here's the comparator class and the test I ran in a separate class:
public class intComparator implements Comparator<Integer>{
#Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
}
public static void main(String[] args) {
System.out.println("---------------SortedLinkedList--------------");
SortedLinkedList<Integer> sortedList = new SortedLinkedList<Integer>(new intComparator());
sortedList.add(3);
sortedList.add(5);
sortedList.add(2);
for(int i: sortedList){
System.out.println(i);
}
}
Nothing prints out. I assumed the iterator that was inherited would help me traverse this no problem and clearly its legal because the for-each loop compiles. It's just that nothing gets printed out. I debugged it and all the adding, removing stuff works as expected. It's just that the iterator isn't doing what it's supposed to. Should I create a separate new iterator for this class? But wouldn't that be redundant code since I already inherit it? Help appreciated!
EDIT: Here's the add method for the sorted list
public SortedLinkedList<T> add(T element){
Node n = new Node(element);
Node prev = null, curr = head;
if(head == null){
head = n;
tail = n;
}
//See if the element goes at the very front
else if(comp.compare(n.data, curr.data) <= 0){
n.next = head;
head = n;
}
//See if the element is to be inserted at the very end
else if(comp.compare(n.data, tail.data)>=0){
tail.next = n;
tail = n;
}
//If element is to be inserted in the middle
else{
while(comp.compare(n.data, curr.data) > 0){
prev = curr;
curr = curr.next;
}
prev.next = n;
n.next = curr;
}
size++;
return this;
}
1) SortedLinkedList extends BasicLinkedList but both have
private Node head;
private Node tail
this is wrong. If you want to inherit those field in the sub class, you should mark the variables as protected in the super class and remove them from the subclass.
2) Same goes for private class Node. You are declaring the Node class in both the SortedLinkedList and BasicLinkedList. What you should do is declare it once, (maybe in the super class?) and use the same class in both places. If you do this, the constructor, and the fields should be accessible to both classes. So you will have to change the access modifier (private is what you have now).
I will post below code that works, but I haven't spent any time on the design. Just posting it to demonstrate how you could change the code to make it work. You will have to decide which access modifiers to use and where to put the classes.
import java.util.Comparator;
import java.util.Iterator;
public class Test {
public static void main(String[] args) {
System.out.println("---------------SortedLinkedList--------------");
SortedLinkedList<Integer> sortedList = new SortedLinkedList<Integer>(new intComparator());
sortedList.add(3);
sortedList.add(5);
sortedList.add(2);
for (int i : sortedList) {
System.out.println(i);
}
}
}
class BasicLinkedList<T> implements Iterable<T> {
public int size;
class Node {
T data;
Node next;
Node(T data) {
this.data = data;
next = null;
}
}
protected Node head;
protected Node tail;
public BasicLinkedList() {
head = tail = null;
}
// Add, remove method
public Iterator<T> iterator() {
return new Iterator<T>() {
Node current = head;
#Override
public boolean hasNext() {
return current != null;
}
#Override
public T next() {
if (hasNext()) {
T data = current.data;
current = current.next;
return data;
}
return null;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Remove not implemented.");
}
};
}
}
class SortedLinkedList<T> extends BasicLinkedList<T> {
private Comparator<T> comp;
public SortedLinkedList(Comparator<T> comparator) {
super();
this.comp = comparator;
}
public SortedLinkedList<T> add(T element) {
Node n = new Node(element);
Node prev = null, curr = head;
if (head == null) {
head = n;
tail = n;
}
// See if the element goes at the very front
else if (comp.compare(n.data, curr.data) <= 0) {
n.next = head;
head = n;
}
// See if the element is to be inserted at the very end
else if (comp.compare(n.data, tail.data) >= 0) {
tail.next = n;
tail = n;
}
// If element is to be inserted in the middle
else {
while (comp.compare(n.data, curr.data) > 0) {
prev = curr;
curr = curr.next;
}
prev.next = n;
n.next = curr;
}
size++;
return this;
}
}
class intComparator implements Comparator<Integer> {
#Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
}

return a linked list of first n elements

Ok guys I need to write a method; MyLinkedList getFirst(int n) – Returns a linked list of the first n elements. If the list is empty or n > size return null.
and I'm lost, I've done the mothods add, remove, add to middle, print a string of elements, and so on but this one has me stuck..
all I have so far is:
public MyLinkedList<E> getFirst(int n) {
if(n > size ) {
return null;
}
Node<E> current = head;
for (int i = 0; i == n; i++) {
current.next = new Node<E>(e);
}
}
I know this code is pretty wrong but its all I can think of been working on this assignment for a while and I'm just running out of steam I guess lol
Thanks for any and all help.
Create an empty list
Add the head to the list
Continuing adding the next node to the list until you have the first n nodes.
public MyLinkedList getFirstN(int n) {
MyLinkedList firstNList=new MyLinkedList();//create an empty list
if(n>size)
firstNList= null;
else {
Node tmp=head; //initialise tmp Node to the head(beginning) of list
for(int i=0;i<n;i++) {
firstNList.add(tmp);//add current node to the end of list
tmp=tmp.getNext();
}
}
return firstNList;
}
Implement the add(Node node) method to append a Node to the end of list.
You can use this as prototype and proceed with any operation
public class Node {
private int data;
private Node next;
public Node(int data) {
this.data = data;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
public Node(int data, Node next) {
this.data = data;
this.next = next;
}
}
public class LinkedList {
private Node start;
public LinkedList() {
start = null;
}
public void insert(int x) {
if(start == null) {
start = new Node(x, start);
} else {
Node temp = start;
while(temp.getNext() != null) {
temp = temp.getNext();
}
Node newNode = new Node(x,null);
temp.setNext(newNode);
}
}
public void getFirst() {
if(start == null) {
System.out.println("\n List is empty !!");
}
else {
Node temp = start;
System.out.println("\n First Element is --->" + temp.getData());
}
}
}
public class MainClass {
public static void main(String[] args) {
LinkedList ll = new LinkedList();
System.out.println("\n--- Inserting 100 ---\n");
ll.insert(100);
ll.insert(101);
ll.insert(102);
ll.insert(103);
System.out.println("\n--- First Element ---\n");
ll.getFirst();
}
}

Delete first node in a LinkedListNode

I thought I had this program working but unfortunately I've overlooked something. How do you delete the first Node and convert the second node into the front of the Linked List. I've tries a multitude of approaches but end up with the same result.(LinkedList remaining unchanged) Any guidance would be much appreciated.
Node Class
public class Node {
private String data;
private Node next;
Node(String data, Node next)
{
this.data = data;
this.next = next;
}
public void setData(String d)
{
data = d;
}
public void setNext(Node n)
{
next = n;
}
public String getData()
{
return data;
}
public Node getNext()
{
return next;
}
Main
public static void main(String[] args) {
Node list = new Node("NODE 1",new Node("NODE 2",new Node("NODE 3", null)));
list = insertSecond(list,"New Node");
list = addLast(list,"LAST NODE");
printList(list);
System.out.println();
deleteNode(list, "NODE 1");
printList(list);
}
public static Node deleteNode(Node list,String str)
{
Node temp = list;
Node prev = list;
while(temp != null)
{
if(temp.getData().equals(str))
{
if(temp.getData().equals(list.getData()))
{
list = list.getNext();
return deleteNode(list,str);
}
else
{
prev.setNext(prev.getNext().getNext());
}
}
prev = temp;
temp = temp.getNext();
}
return list;
Your deleteNode function should return the head of new list. This is required only in one edge case which you described - deleting head of that list.
list = deleteNode(list, str);
Also you don't need to recursively execute deleteNode method, iteration over node elements should be enough:
public static Node deleteNode(Node list, String str) {
// I'm assuming that you are deleting the first inscance of the string
Node temp = list;
Node prev = list;
while(temp != null) {
if(temp.getData().equals(str)) {
if(temp.getData().equals(list.getData())) {
return list.getNext();
}
else {
prev.setNext(temp.getNext());
return list;
}
}
prev = temp;
temp = temp.getNext();
}
return list;
}

Categories