I tried to implement a linked list in java using the code below:
class Linkedlist<T>{
private node head, tail;
public Linkedlist(){
head = new node(null);
tail = head;
}
public boolean insert(T value){
if(head.getValue() == null){
this.head.setValue(value);
head.setNext(null);
return true;
}
node insertNode = new node(value);
tail.setNext(insertNode);
tail = insertNode;
return true;
}
public boolean insert(T value, int index) {
if ( sizeOfList() == index + 1 ) return false;
node temp = this.head.getNext();
node prvtmp = this.head;
for (int i = 0; i <= index; i++) {
temp = temp.getNext();
prvtmp = temp;
System.out.println("for loop");
}
node insertNode = new node(value);
System.out.println("node created");
prvtmp.setNext(insertNode);
insertNode.setNext(temp);
System.out.println("temps");
return true;
}
public int sizeOfList(){
int size = 0;
node temp = this.head;
while(temp.getNext() != null){
temp = temp.getNext();
size++;
}
return size;
}
public String[] rtrnList(){
node temp = this.head;
int listSize = sizeOfList();
String[] resualt = new String[listSize + 1];
for (int i = 0;i <= listSize;i++){
resualt[i] = String.valueOf(temp.getValue());
temp = temp.getNext();
}
return resualt;
}
}
Class node:
public class node<T> {
private T value;
private node next;
public node(T value){
this.value = value;
this.next = null;
}
public void setValue(T value) {
this.value = value;
}
public void setNext(node next) {
this.next = next;
}
public T getValue() {
return value;
}
public node getNext() {
return next;
}
}
When I try to run the insert method with one argument it works fine, but when I run it with two arguments:
import java.util.Arrays;
public class main {
public static void main(String[] args){
Linkedlist list = new Linkedlist();
list.insert(2);
list.insert(2);
list.insert(2);
list.insert(2);
list.insert(2);
list.insert(2);
list.insert(11, 3);
System.out.println(Arrays.toString(list.rtrnList()));
System.out.println("finished");
}
}
The program doesn't reach the line that prints finished, but if we delete the line: list.insert(11, 3);
Then the program works just fine.
output:
for loop
for loop
for loop
for loop
node created
finish insert
The problems is inside the for loop of your insert(T value, int index) method when you are updating the value of prvtm and temp. In your code you are first setting the value of temp to temp.getnext() and as the temp is already changed setting prvtmp to temp creating a loop which is why when you are trying to print the list it's getting into an infinite loop while calculating the size of the list.
Just put the prvtmp = temp line before temp = temp.getNext() like following code snippet. This will solve the problem.
public boolean insert(T value, int index) { // 2 2 2 2 2 2
if ( sizeOfList() == index + 1 ) return false;
node temp = this.head.getNext();
node prvtmp = this.head;
for (int i = 0; i <= index; i++) {
prvtmp = temp;
temp = temp.getNext();
System.out.println("for loop");
}
node insertNode = new node(value);
System.out.println("node created");
prvtmp.setNext(insertNode);
insertNode.setNext(temp);
System.out.println("temps");
return true;
}
Also if you are trying to insert in the given index update the condition of the for loop from:
i <= index to i < index - 1
Happy coding!
while inserting there is a cyclic refrence made , you can use this code for above purpose
public boolean insert(T value, int index) {
if(index > sizeOfList())
{
return false;
}
else if(index == sizeOfList())
{
if(insert(value))
return true;
else
return false;
}
else
{
node previous = this.head;
for (int i = 1; i <= index; i++) {
if(i==index-1)
{
node newnode = new node(value);
newnode.setNext(previous.getNext());
previous.setNext(newnode);
break;
}
previous = previous.getNext();
}
}
return true;
}
Output
[2, 2, 11, 2, 2, 2, 2]
Related
I would like to write a method public void reverseFrom(int index) which reverses a list from the given index.
I would like to only use the LinkedList class below.
public class LinkedList {
public Node head = null;
public class Node {
public int value;
public Node next;
Node(int value, Node next) {
this.value = value
this.next = next;
}
}
}
I have a method to reverse a LinkedList:
public void reverse() {
Node tmp = head;
Node prev = null;
Node nextNode = null;
while(tmp != null) {
nextNode = tmp.next;
tmp.next = prev;
prev = tmp;
tmp = nextNode;
}
head = prev;
}
So far, for the reverseFrom method, I have:
public void reverseFrom(int index) {
if(index == 0) {
reverse();
} else if (index == 1) {
return;
} else {
Node tmp = head;
for(int i = 0; i < index; i++) {
tmp = tmp.next;
}
Node newHead = tmp;
/*** Node prev = null;
Node nextNode = null;
while(newHead != null) {
nextNode = newHead.next;
newHead.next = prev;
prev = newHead;
newHead = nextNode;
}
newHead = prev; ***/
}
}
I have tried using the code from reverse() but it does not work (that which is commented out).
How can I then reverse the list from newHead?
You could base the logic on the reverse method, but use an extra reference to the node that is at index - 1. During the loop decrement index. As long as it is positive, don't change the next reference of the current node. When it hits zero, take note of where we start the reversal, and as the current node will become the very last one, set its next reference to null. When index is negative, perform the usual reversal logic.
After the loop, check whether we need to change the head or whether we need to attach the reversed part to the node at index-1:
public void reverseFrom(int index) {
Node tmp = head;
Node prev = null;
Node nextNode = null;
Node tail = null; // node at index - 1
while (tmp != null) {
nextNode = tmp.next;
if (index == 0) {
// We arrived at the part that needs reversal
tmp.next = null;
tail = prev;
} else if (index < 0) {
// Perform normal reversal logic
tmp.next = prev;
}
index--;
prev = tmp;
tmp = nextNode;
}
if (tail == null) {
head = prev;
} else {
tail.next = prev;
}
}
public class ReverseList<T> extends LinkedList<T>{
public void reverseFrom(int idx) {
if (idx < 0 || idx > size()) {
return;
}
Stack<T> stack = new Stack<T>();
while (idx < size()) {
stack.push(remove(idx));
}
while (!stack.isEmpty()) {
add(stack.pop());
}
}
/******* Alternative slution ***************/
public void reverseFrom(int idx) {
if (idx < 0 || idx > size()) {
return;
}
reverseFromInternal(idx, size()-1);
}
private void reverseFromInternal(int a, int b) {
if (a >= b) {
return;
}
T far = remove(b);
T near = remove(a);
add(a, far);
add(b, near);
reverseFromInternal(a + 1, b - 1);
}
/****************************************/
public static void main(String [] args) {
ReverseList<String> list = new ReverseList<>();
for (int i = 0; i < 10; i++) {
list.add(Integer.toString(i));
}
list.reverseFrom(5);
System.out.println(list);
}
}
public void reverseFrom(int index) {
if (index == 0) {
reverse();
return;
}
Node tmp = head;
Node previous = null;
for (int i = 0; i < index; i++) {
previous = tmp;
tmp = tmp.next;
}
Node newHead = tmp;
LinkedList subLinkedList = new LinkedList();
subLinkedList.head = newHead;
subLinkedList.reverse();
previous.next = subLinkedList.head;
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
First of all pardon me if the way I'm asking is wrong, I'm new at programming and still need a lot of learning, here is my code
This is my Node class
public class Node
{
int value;
Node link;
void setValue(int a){
value = a;
}
int getValue(){
return value;
}
void setNode(Node i){
link = i;
}
Node getNode(){
return link;
}
}
And this one my NodeContainer class
public class NodeContainer
{
Node tail;
Node head;
void setHead(int i){
Node a = new Node();
a.setValue(i);
head = a;
tail = head;
}
Node getHead(){
return head;
}
void addNode(int i){
Node a = new Node();
a.setValue(i);
tail.setNode(a);
tail = a;
}
void addNode(int i,int index){
Node a = new Node();
a.setValue(i);
int c = 1;
Node temp = head;
Node first = head;
while(head!=null){
head = head.getNode();
if(c==index-1){
a.setNode(head.getNode());
temp = head;
temp.setNode(a);
}
c++;
}
head = first;
head.setNode(temp);
}
int count(){
int c = 1;
boolean have = true;
if(head!=null){
while(head.getNode()!=null){
c++;
head = head.getNode();
}
return c;
}
else{
have = false;
return 0;}
}
}
i just cant think a way to insert a node in spesific index, i tried it on addNode method have tried so many ways i can think of but it cant work, thanks in advance
Comments:
You do not need to keep track of the tail (necessarily) I see you are new to linked lists, so perhaps try to master the basics before adding extra features.
Also, try adding some white space in your code, it makes it easier to read.
I heavily commented the section that covers inserting at a specified index. put all these files in the same folder, the compile it. You should get the output that follows:
Output:
0 1 2 3 4 5 6 7 8 9
inserting -1 at position 5
0 1 2 3 4 -1 5 6 7 8 9
Main class:
class test {
public static void main(String[] args) {
NodeContainer linkedList = new NodeContainer();
for (int i = 0; i < 10; i++) {
linkedList.addNode(i);
}
display(linkedList.head);
// NOTE - indexes start at 0, not 1
System.out.println("inserting -1 at position 5");
linkedList.addNode(-1, 5);
display(linkedList.head);
}
public static void display(Node node) {
while (node != null) {
System.out.print(node.value + " ");
node = node.link;
}
System.out.println();
}
}
Node Container class:
public class NodeContainer {
public Node head;
public int size;
public NodeContainer() {
size = 0;
head = null;
}
public void addNode(int i) {
Node node = new Node(i);
if (head == null) {
head = node;
} else {
Node temp;
temp = head;
while (temp.link != null) {
temp = temp.link;
}
temp.link = node;
}
size++;
}
public void addNode(int i, int index) {
Node node;
Node temp;
int count;
// If we want to insert
// into the front of the list
if (index == 0) {
// User a constructor instead of
// making a new node every time,
// then typing set value
node = new Node(i);
node.link = head;
head = node;
// If the index is within the linkedlist
} else if (index > 0 && index < size) {
count = 0;
temp = head;
// Keep looking until the index prior to
// the one we want to insert at
while(temp.link != null && count < size) {
// Once we find it, break out the loop
if (count == index-1) {
break;
}
// Keep traversing the list
temp = temp.link;
// increment counter
count++;
}
// Instantiate the node
node = new Node(i);
// Point this node's link to
// the n-1th node's link
node.link = temp.link;
// Set n-1th node's next to this
// node (effectively putting it
// in position n)
temp.link = node;
// Otherwise don't do anything
} else {
;
}
}
}
Node class:
public class Node {
public int value;
public Node link;
// User a constructor
public Node(int i) {
value = i;
link = null;
}
public void setValue(int a) {
value = a;
}
public int getValue() {
return value;
}
public void setNode(Node i) {
link = i;
}
public Node getNode() {
return link;
}
}
I have updated your original code snippet to be like this :
public class Node
{
int value;
Node next;
void setValue(int value){
this.value = value;
}
int getValue(){
return this.value;
}
void setNext(Node next){
this.next = next;
}
Node getNext(){
return this.next;
}
}
public class NodeContainer {
Node tail;
Node head;
void setHead(int i) {
Node a = newNode(i);
head = a;
tail = a;
}
private Node newNode(int value) {
Node node = new Node();
node.setValue(i);
return node;
}
void addNode(int i) {
Node a = newNode(i);
Node tmp = this.head;
while(tmp.getNext() != null){
tmp = tmp.getNext();
}
tmp.setNext(a);
tail = a;
}
void addNode(int value, int index) {
//TODO : add check on head
Node a = newNode(value);
Node tmp = this.head;
int i = 0;
while(tmp.getNext()!=null && i < index) {
tmp = tmp.getNext();
i++;
}
//TODO : add check on tmp
Node next = tmp.getNext();
tmp.setNext(a);
a.setNext(next);
}
int count() {
//...
}
}
So my problem is that I wanna delete a node based on a value inputted by the user, in my program I can already, add, search, and delete the node in the last position, but so far I haven't been able to delete a specific value inputted by the user, if for example I have 1,2,3,4 elements in my list I wanna be able to point at, say 2, and delete it. here are my functions, the last one is the uncompleted one:
//searches node
public void searchNode(int input){
Node temp = first;
boolean found = false;
if(!isEmpty()){
for(int i = 0 ; i<size ; i ++){
if(temp.value == input){
System.out.println(input + " found in the position: " + (i+1));
found = true;
break;
}
temp = temp.rightNode;
}
if(!found)
System.out.println("value not found.");
}
}
//deletes last node
public void deleteLastNode(){
if(isEmpty()){
System.out.println("There are no nodes to delete.");
}
if(last == first){
first = null;
last = null;
} else {
Node current = first;
while(current.rightNode != last){
current = current.rightNode;
}
current.rightNode = null;
last = current;
}
size --;
}
//delete element, input by user.
public void deleteInputByUser(int input) {
Node temp = first;
boolean found = false;
if(isEmpty()){
System.out.println("There are no nodes to delete.");
} else {
}
size--;
}
//Node class
public class Node{
int value;
Node rigthNode;
public Node(int value){
this.value = value;
}
}
Deletion of a node in a Linked List by value is not so bad. This pseudocode should help you get started:
deleteNodeByValue(int val) {
if (head.val = val) {
head = head.next
return
}
current = head
while (current.next != null) {
if (current.next.val = val) {
current.next = current.next.next
return
}
current = current.next
}
}
Find the nodeToDelete and his previousNode, then
previousNode.rightNode = nodeToDelete.rightNode;
you can do it this way. The following code will remove the element once the index is given.
public boolean deleteAt(int index){
Node current=first;
if(index==0){
first=current.rightNode;
return true;
}
currentIndex=0;
previousNode=first;
current=first.rightNode;
while(current!=null){
if(currentIndex==index){
previousNode.rightNode=current.rightNode;
return true;
}
currentIndex++;
previousNode=current;
current=current.rightNode;
}
return false;
}
You could try something like that.
public void deleteNodeByValue(int input) {
Node currNode = first;
boolean found = false;
Node prevNode = first;
if (!isEmpty()) {
for (int i = 0; i < size; i++) {
if (currNode.value == input) {
///////DELETE START
if (currNode == first) {
first = currNode.rightNode;
} else {
prevNode.rightNode = currNode.rightNode;
if (currNode == last)
last = prevNode;
}
////DELETE END
found = true;
size--;
break;
}
prevNode = currNode;
currNode = currNode.rightNode;
}
if (!found)
System.out.println("value not found.");
}
}
I implemented doubly linked lists using nodes in Java. My code for the Node and linked list classes are below. Any suggestions for improving the design and/or running times of the operations?
public class Node implements Comparable<Node>{
Node next;
Node previous;
Object element;
int index;
public Node(Object element){
this.element = element;
this.next = null;
this.previous = null;
}
public Node(Object element, Node next, Node previous){
this.element = element;
this.next = next;
this.previous = previous;
}
public Node(Object element, Node next, Node previous, int index){
this.element = element;
this.next = next;
this.previous = previous;
this.index = index;
}
//Getter Method
public Node get_next(){
return this.next;
}
//For comparable class
public int compareTo(Node x){
if (this.element.equals(x.element)){
return 0;
}
else
return 1;
}
public boolean compare_index(int index){
if (this.index == index){
return true;
}
else
return false;
}
}
public class Mylinkedlists{
Node first_node;
Node last_node;
int size = 0;
//Constructors
public Mylinkedlists(Object element){
Node temp = new Node(element, last_node,first_node,0);
first_node = new Node (null,temp,null);
last_node = new Node(null,null,temp);
size+=1;
}
public Mylinkedlists(){
first_node = new Node (null,last_node,null);
last_node = new Node(null,null,first_node);
}
//Returns size of Node
public int size(){
return size;
}
//Adds element to end of linked list
public void add(Object element){
Node to_add = new Node(element);
Node temp = last_node.previous;
size+=1;
//Pointer changes
last_node.previous.next = to_add;
last_node.previous = to_add;
to_add.previous = temp;
to_add.next = last_node;
to_add.index = size-1;
}
//Inserts Element after node
public void insert(Object add_after, Object element_to_add) throws NotFoundException{
Node current = first_node.next;
Node insert_after = new Node(add_after);
Node to_add = new Node(element_to_add);
//find the node
while (current.compareTo(insert_after) != 0){
current = current.next;
}
//Inserts element after node
if (current.compareTo(insert_after) == 0){
Node temp = current.next;
current.next.previous = to_add;
to_add.next = temp;
current.next = to_add;
to_add.previous = current;
size+=1;
}
else
throw new NotFoundException("Element not in list");
}
//Removes element from linked list
public void remove(Object element) throws NotFoundException{
boolean stop = false;
Node search_for = new Node(element);
Node current = first_node.next;
for (int i = 0; i < size && !stop; i ++){
//Compares nodes
if (current.compareTo(search_for) == 1){
current.next.previous = current.previous;
current.previous.next = current.next;
current.next = null;
current.previous = null;
size-=1;
stop = true;
}
else
current = current.next;
}
//If element not in list
if (stop == false && current.next == null)
throw new NotFoundException("Element not in list");
}
//Removes element from end of linked list
public void remove_From_End(){
last_node.previous.next = null;
Node temp = last_node.previous.previous;
last_node.previous.previous = null;
last_node.previous = temp;
last_node.previous.next = last_node;
size -= 1;
}
//Returns true if list contains element, else false
public boolean contains(Object element){
boolean contains = false;
Node current = first_node.next;
Node with_element = new Node(element);
while (current.next != null){
if (current.compareTo(with_element) == 0)
return true;
else
current = current.next;
}
return contains;
}
public Object get(int index) throws NotFoundException{
if (index < 0 || index > (size-1))
throw new NotFoundException("Index out of range");
Node current = first_node;
for (int i = 0; i <= index; i++){
current = current.next;
}
return current.element;
}
public String toString(){
String temp = "";
Node temp2 = first_node;
for (int i = 0 ; i < size; i++){
temp2 = temp2.next;
temp += String.valueOf(temp2.element) + " ";
}
return temp;
}
}
For example, I access the elements of the Node class directly using dot(.) notation. Are getter and setter methods the only alternative? Moreover, is there any other implementation of the get method that would take less than O(n) time?
It is impossible for access to a linked list to take less than O(n). You will need to traverse through the array to access indivividual elements. There are faster ways to access individual elements, but that would require changing your data structure. The easiest data structure that I can think of would be an array. But then your insert and remove would be O(n).
So, in choosing your data structure, the question becomes what will you be doing more of insert and remove, or get?
I am doing some exercises on practice-it website. And there is a problem that I don't understand why I didn't pass
Write a method deleteBack that deletes the last value (the value at the back of the list) and returns the deleted value. If the list is empty, your method should throw a NoSuchElementException.
Assume that you are adding this method to the LinkedIntList class as defined below:
// A LinkedIntList object can be used to store a list of integers.
public class LinkedIntList {
private ListNode front; // node holding first value in list (null if empty)
private String name = "front"; // string to print for front of list
// Constructs an empty list.
public LinkedIntList() {
front = null;
}
// Constructs a list containing the given elements.
// For quick initialization via Practice-It test cases.
public LinkedIntList(int... elements) {
this("front", elements);
}
public LinkedIntList(String name, int... elements) {
this.name = name;
if (elements.length > 0) {
front = new ListNode(elements[0]);
ListNode current = front;
for (int i = 1; i < elements.length; i++) {
current.next = new ListNode(elements[i]);
current = current.next;
}
}
}
// Constructs a list containing the given front node.
// For quick initialization via Practice-It ListNode test cases.
private LinkedIntList(String name, ListNode front) {
this.name = name;
this.front = front;
}
// Appends the given value to the end of the list.
public void add(int value) {
if (front == null) {
front = new ListNode(value, front);
} else {
ListNode current = front;
while (current.next != null) {
current = current.next;
}
current.next = new ListNode(value);
}
}
// Inserts the given value at the given index in the list.
// Precondition: 0 <= index <= size
public void add(int index, int value) {
if (index == 0) {
front = new ListNode(value, front);
} else {
ListNode current = front;
for (int i = 0; i < index - 1; i++) {
current = current.next;
}
current.next = new ListNode(value, current.next);
}
}
public boolean equals(Object o) {
if (o instanceof LinkedIntList) {
LinkedIntList other = (LinkedIntList) o;
return toString().equals(other.toString()); // hackish
} else {
return false;
}
}
// Returns the integer at the given index in the list.
// Precondition: 0 <= index < size
public int get(int index) {
ListNode current = front;
for (int i = 0; i < index; i++) {
current = current.next;
}
return current.data;
}
// Removes the value at the given index from the list.
// Precondition: 0 <= index < size
public void remove(int index) {
if (index == 0) {
front = front.next;
} else {
ListNode current = front;
for (int i = 0; i < index - 1; i++) {
current = current.next;
}
current.next = current.next.next;
}
}
// Returns the number of elements in the list.
public int size() {
int count = 0;
ListNode current = front;
while (current != null) {
count++;
current = current.next;
}
return count;
}
// Returns a text representation of the list, giving
// indications as to the nodes and link structure of the list.
// Detects student bugs where the student has inserted a cycle
// into the list.
public String toFormattedString() {
ListNode.clearCycleData();
String result = this.name;
ListNode current = front;
boolean cycle = false;
while (current != null) {
result += " -> [" + current.data + "]";
if (current.cycle) {
result += " (cycle!)";
cycle = true;
break;
}
current = current.__gotoNext();
}
if (!cycle) {
result += " /";
}
return result;
}
// Returns a text representation of the list.
public String toString() {
return toFormattedString();
}
// ListNode is a class for storing a single node of a linked list. This
// node class is for a list of integer values.
// Most of the icky code is related to the task of figuring out
// if the student has accidentally created a cycle by pointing a later part of the list back to an earlier part.
public static class ListNode {
private static final List<ListNode> ALL_NODES = new ArrayList<ListNode>();
public static void clearCycleData() {
for (ListNode node : ALL_NODES) {
node.visited = false;
node.cycle = false;
}
}
public int data; // data stored in this node
public ListNode next; // link to next node in the list
public boolean visited; // has this node been seen yet?
public boolean cycle; // is there a cycle at this node?
// post: constructs a node with data 0 and null link
public ListNode() {
this(0, null);
}
// post: constructs a node with given data and null link
public ListNode(int data) {
this(data, null);
}
// post: constructs a node with given data and given link
public ListNode(int data, ListNode next) {
ALL_NODES.add(this);
this.data = data;
this.next = next;
this.visited = false;
this.cycle = false;
}
public ListNode __gotoNext() {
return __gotoNext(true);
}
public ListNode __gotoNext(boolean checkForCycle) {
if (checkForCycle) {
visited = true;
if (next != null) {
if (next.visited) {
// throw new IllegalStateException("cycle detected in list");
next.cycle = true;
}
next.visited = true;
}
}
return next;
}
}
// YOUR CODE GOES HERE
}
My work so far is this:
public int deleteBack(){
if(front==null){
throw new NoSuchElementException();
}else{
ListNode current = front;
while(current!=null){
current = current.next;
}
int i = current.data;
current = null;
return i;
}
}
Don't you want to iterate until the current.next is != null?
What you have now passes the entire list, and your last statements do nothing, since current is null already.
Think about the logic you have here
while(current!=null){
current = current.next;
}
When that loop exits, current == null, and then you try to access current's data. Does this point you in the right direction?
// This is the quick and dirty
//By Shewan
public int deleteBack(){
if(size()== 0){ throw new NoSuchElementException(); }
if(front==null){ throw new NoSuchElementException();
}else{
if(front.next == null){
int i = front.data;
front = null;
return i;
}
ListNode current = front.next;
ListNode prev= front;
while(current.next!=null){
prev = current;
current = current.next;
}
int i = current.data;
prev.next = null;
return i;
}
}