I made an SListClass which stands for sinle-linked list class and a node class SListNode. I'm having a problem with the removeLast method. When I print out the list of nodes, the first item is still there. I don't understand why
public class SListClass {
private SListNode head;
private double size;
SListClass(){
head = null;
size = 0;
}
SListClass(SListNode node){
head = node;
}
public void insertFront(int item){
head = new SListNode(item, head);
size++;
}
public void addLast(SListNode head, int value){
SListNode first = head;
while(first.next != null){
first = first.next;
}
first.next = new SListNode(value, null);
size++;
}
public void removeFirst(SListNode head){
head = head.next;
}
/*public String toString(){
return String.format(head + "");
}
*/
public String print(){
String result = head.item + " ";
if(head.next != null){
result += head.next.print();
}
return result;
}
public static void main(String[] args) {
SListNode list = new SListNode(21, new SListNode(5, new SListNode(19, null)));
SListClass x = new SListClass(list);
x.insertFront(33);
x.insertFront(100);
x.addLast(list, 123);
x.addLast(list, 9999);
x.removeFirst(list);
System.out.println(x.print());
}
}
output: 100 33 21 5 19 123 9999
The SListNode class:
public class SListNode {
protected int item;
protected SListNode next;
public SListNode(int item, SListNode next){
this.item = item;
this.next = next;
}
public SListNode(int item){
this(item, null);
}
public int getItem() {
return item;
}
public void setItem(int item) {
this.item = item;
}
public SListNode getNext() {
return next;
}
public void setNext(SListNode next) {
this.next = next;
}
}
Change the removeFirst to this.head = head.next. The head in the parameter list is hiding the class field head.
Also, consider this: in a removeFirst method, do you really want a head parameter, or should you use the head field instead since that is the real head for the linked list you are trying to update? If you don't want that parameter anymore, just delete the parameter from the method signature; then the field head is not hidden, so head = head.next does fine.
First of all, your naming is bad. Every class is a class, so ending the name of a class with Class is just noise. On the contrary S doesn't mean anything. If you must explain what SListClass stands for, then it means that the name is bad, and that you should choose another name, which doesn't need any explanation, like SinglyLinkedList.
The users of your class shouldn't care how the list retains the information. It should never have to pass a Node to any method. Only a value. So the following methods should be modified:
SListClass(SListNode node) --> SinglyLinkedList(int value)
void addLast(SListNode head, int value) --> void addLast(int value) : the list knows what the head node is. It makes no sense to pass it as argument.
void removeFirst(SListNode head) --> void removeFirst() : the list knows what the first node is. It makes no sense to pass it as argument
Once you get the API right, you'll see that everything will be much easier to figure out, because you won't confuse the actual head of the list with the unnecessary head passed as argument.
Related
I doesnt quite get why the part with the object names down there works? I invoke the method append(int number) with a parameter in my main method and create a List of Node Objects that store integer values this way. However, why wont the object names "temp" and "current" be replaced when a call append a second, a third.... time. They are always the same object names and one object name cant refer to multiple objects, I thought. When I call the method elementAt(), I get everytime the response I wanna have, but I dont know exactly why it did work.
Heres my Code for the Class MyList
public class MyList
{
Node head;
int count;
Node temp;
Node current;
public MyList(){
head= new Node(0);
count = 0;
}
public void append(int number){
temp = new Node(number);
current = head;
while(current.getNext() != null){
current = current.getNext();
}
current.setNext(temp);
count++;
}
public int elementAt(int number){
if(head != null){
current = head.getNext();
for(int i = 0; i < number ; i++){
if(current.getNext() == null){
return 0;
}
current = current.getNext();
}
return current.item;
}
return 0;
}
}
Heres the Code for the Class Node
public class Node {
public int item;
public Node next;
public Node(int item){
this.item = item;
}
public Node getNext(){
return next;
}
public void setNext(Node next){
this.next = next;
}
}
Heres the code for my the Main Class
public class MainList {
public static void main(String[] args) {
MyList list = new MyList();
list.append(10);
list.append(20);
list.append(30);
list.append(40);
list.append(50);
list.append(60);
list.append(40);
System.out.println(list.elementAt(0));
}
}
Having a lot of trouble trying to write a recursive method to add a new Node to the end of a LinkedList. I've been staring at this for a looooong time and still my terminal is printing blanks...if someone can help me out that would be greatly appreciated! Still trying to wrap my head around the concept of recursion. If I try to do the problem iteratively with a while loop, then I'm able to do it no problem but my assignment requires me to write it recursively. Thanks for the help :)
public class LinkedList
{
//
//Instance variable
//
private Node top;
//
//Instance and static methods below
//
//Accessor for the top Node
public Node getTop()
{
return top;
}
public void add(Object data) {
Node newNode = new Node(data,null);
addRec(top,newNode);
}
private Node addRec(Node start, Node newNode) {
if (start == null) {
start = newNode;
return start;
}
start.setLink(addRec(start.getLink(), newNode));
return start;
}
public String toString() {
String value = "";
Node current = top;
while (current != null) {
value += current.getData();
current = current.getLink();
}
return value;
}
Node class:
public class Node
{
//
//Instance variables
//
private Object data;
private Node link;
//
//Constructor
//
public Node (Object initData, Node initLink)
{
data = initData;
link = initLink;
}
//
//Accessors
//
public Object getData()
{
return data;
}
public Node getLink()
{
return link;
}
public void setData(Object data) {
this.data = data;
}
//
//Mutators
//
public void setLink(Node newLink)
{
link = newLink;
}
}
Recursively adding a node to the linked list is a fairly straightforward concept.
Lets look at the algorithm:
1] If the given node does not have a node after it (which we will call the next node), we add the current node.
2] Otherwise, we add the node to the next node. This would involve performing step 1 on the next node.
If you notice, Step 2 has a recursive call to step 1, as it is referencing the same node.
To implement this, first, we create a child class called Node, inside the LinkedList. This will require an int to store the data, and a Node that points to the next Node.
we create the method add() inside Node.
To implement step 1, we check if next is equal to null. If it is, we add the node as the next on on the linked list.
if(this.next== null)this.next= toAdd;
To implement step 2, we say otherwise, we call the method add on the next Node, and pass the value to add.
if(this.next== null)this.next= toAdd;
Now, we have to implement this in the class LinkedList.
We declare a root node, where the list starts.
Now, we declare a method that will do the following:
add a value to root.
That's it.
Recursion takes care of the rest.
Think about it, if root has a node after it, the data will be added to the next node, and so on.
Therefore, problem sorted, you have your list!
public class LinkedList
{
private Node root;
private class Node{
int data;
Node next;
public Node(int data){
this.data = data;
this.next = null;
}
public void add(Node toAdd){
if(this.next== null)this.next= toAdd;
else this.next.add(toAdd);
}
}
public LinkedList(int root){
this.root = new Node(root);
}
public void add(int toAdd){
this.root.add(new Node(toAdd));
}
}
I already wrote a small program of single linked list with add and traverse method in that. Now I want to convert it into a doubly linked list. I know all the concept of doubly linked list but I am facing little difficulty to implement it in my program.
public class SingleLinkList<T> {
private Node<T> head;
private Node<T> tail;
public void add(T element)
{
Node<T> nd = new Node<T>();
nd.setValue(element);
if (head==null)
{
head = nd;
tail = nd;
}
else
{
tail.setNextRef(nd);
tail = nd;
}
}
public void traverse(){
Node<T> tmp = head;
while(true){
if(tmp == null){
break;
}
System.out.println(tmp.getValue());
tmp = tmp.getNextRef();
}
}
public static void main (String args[])
{
SingleLinkList<Integer> s1 = new SingleLinkList<Integer>();
s1.add(2);
s1.add(3);
s1.add(3);
s1.traverse();
}
}
class Node<T> {
private T value;
private Node<T> nextRef;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
public Node<T> getNextRef() {
return nextRef;
}
public void setNextRef(Node<T> nextRef) {
this.nextRef = nextRef;
}
public int compareTo(T arg)
{
if (arg==this.value)
{
return 0;}
else
{return 1;}
}
}
Add a Node<T> prevRef field to your list class with appropriate getters and setters and then add this method:
public void linkReverse(Node<T> head) {
if (head == null) {
return;
}
head.setPrevRef(null);
if (head.getNextRef() == null) {
return;
}
Node<T> prev = head;
Node<T> curr = head.getNextRef();
while (curr != null) {
curr.setPrevRef(prev);
prev = curr;
curr = curr.getNextRef();
}
}
This method will walk down a currently singly linked list and will link each node in reverse, leaving the list doubly linked.
Of course, you would need to modify the other methods as well, but this is at least a good starting point.
just add private Node<T> prevRef; instance variable to Node class, and set it during add() method. I suggest that traverse() will receive a boolean (or even better, enum) direction argument
I'm implementing a singly linked list in Java. What I don't like about this code is that I need to check if (head.next == null) every time I add an element. But the condition is met only once, when adding the first element.
Is there a way to implement a singly linked non-circular list without such a condition?
package sample;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class SinglyLinkedList<T> implements Iterable<T> {
private Node<T> head = new Node<T>(null);
private Node<T> last = null;
public SinglyLinkedList(T... elements) {
addAll(elements);
}
public void add(T element) {
if (head.next == null) {
head.next = new Node<T>(element);
last = head.next;
} else {
Node<T> newNode = new Node<T>(element);
last.next = newNode;
last = last.next;
}
}
public void addAll(T... elements) {
for (T element : elements) {
add(element);
}
}
#Override
public String toString() {
Iterator<T> iterator = iterator();
if (!iterator.hasNext()) {
return "[]";
}
StringBuilder builder = new StringBuilder();
builder.append("[");
while (iterator.hasNext()) {
T element = iterator.next();
builder.append(element);
if (!iterator.hasNext()) {
return builder.append("]").toString();
}
builder.append(", ");
}
return builder.toString();
}
#Override
public Iterator<T> iterator() {
return new Iterator<T>() {
Node<T> current = head;
#Override
public boolean hasNext() {
return current.next != null;
}
#Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Node<T> temp = current;
current = current.next;
return temp.next.element;
}
};
}
private static class Node<T> {
private Node<T> next;
private T element;
Node(T element) {
this.element = element;
}
#Override
public String toString() {
return element.toString();
}
}
}
You could initialize last to be pointing to head and then your if is redundant:
private Node<T> head = new Node<T>(null);
private Node<T> last = head;
public void add(T element) {
Node<T> newNode = new Node<T>(element);
last.next = newNode;
last = last.next;
}
There are many cases where "good OO design" allows you to go without if/else checks; most often by using some form of polymorphism.
Meaning: instead of asking some object about some property, to then make a decision on that in your client code, you somehow make sure that your client code can simply call a method on some other object. And then, the "if" is "hidden" within the code that initially generated that "other object" and gave it to your client code. (you find some nice examples how that works in these videos).
But - I think this would be clear overkill in this case!
The point is: from a readability point of view, that one check really doesn't hurt (you could refactor things into more methods maybe). And performance ... doesn't matter either. If your code is called so often that it would matter, the JIT will kick in anyway, and probably create code that that takes the correct branch directly for most cases.
Thus: this is a nice implementation; and I think you shouldn't worry about this one if-check there!
I'm trying to create a method that will add a node to a linked list but so far have been unsuccessful. Here's my code with my member vars:
private Object data;
private int size = 0;
private Node head = null;
private Node tail = null;
public void add(Object item){
Node temp = head;
if (head != null) {
// THIS IS THE PROBLEM SITE
while(temp.getNext()!=null){
temp=temp.getNext();
}
//set next value equal to item
Node ab = (Node) item; // It says this is an invalid cast. How do I get around this??
ab.setNext(ab);
}
else{
head = new Node(item);
}
size++;
}
Also here's my Node class for reference:
public class Node {
// Member variables.
private Object data; // May be any type you'd like.
private Node next;
public Node(Object obj) {
this.data = obj; // Record my data!
this.next = null; // Set next neighbour to be null.
}
// Sets the next neighbouring node equal to nextNode
public void setNext(Node nextNode){
this.next=nextNode;
}
// Sets the item equal to the parameter specified.
public void setItem(Object newItem){
this.data = newItem;
}
// Returns a reference to the next node.
public Node getNext(){
return this.next;
}
// Returns this node ís item.
public Object getItem() {
return this.data;
}
Thanks for your time!
you don't want to cast your item as a node, you want to create a new node and set the data in it to be the item
replace this :
Node ab = (Node) item; // It says this is an invalid cast. How do I get around this??
ab.setNext(ab);
by something like this :
Node newNode = new Node();
newNode.setData(item);
temp.setNext(newNode);