I have to count nodes in Circular Doubly Linked List in interval [-100;100]. I know how to do that when i'm implementing a node. Here's code :
public void insert(int val){
....
if((val >= -100) && (val <= 100)){
number++;
}
.....
But when i'm deleting a node at given position (pos), i have no idea how to check the value of that node, so i don't know if "number" stays the same or it decreases.
Here is code of deleting node:
public void deleteAtPos(int pos){
if (pos == 1){
if(size == 1){
start = null;
end = null;
size = 0;
number = 0;
return;
}
start = start.getLinkNext();
start.setLinkPrev(end);
end.setLinkNext(start);
size--;
return;
}
if (pos == size){
end = end.getLinkPrev();
end.setLinkNext(start);
start.setLinkPrev(end);
size--;
}
}
Node ptr = start.getLinkNext();
for (int i = 2; i <= size; i++){
if (i == pos){
Node p = ptr.getLinkPrev();
Node n = ptr.getLinkNext();
p.setLinkNext(n);
n.setLinkPrev(p);
size--;
return;
}
ptr = ptr.getLinkNext();
}
}
From what i understand , you can simply check the value of the node by adding
ptr.getval() or start.getval() //depending on the value of pos(aasuming getval is your function to retrieve node data)
Related
i am a cse student who takes data structures course. Trying to implement binary search algorithm to my SinglyLinkedList class, somehow i've failed. Could you check it what's wrong please ?
The related method;
I've debugged and it just enters the loops this side: else if(temp.getElement() > target)
public int binarySearchLinkedList(SinglyLinkedList<E> list, E target) {
int left = 0;
int right = list.getSize();
while (left <= right) {
int mid = (left + right) / 2;
Node<E> temp = head;
for (int i = 0; i < mid - 1; i++) {
temp = temp.next;
}
if (temp.getElement() instanceof Number && target instanceof Number) {
if (Integer.parseInt(temp.getElement().toString()) == Integer.parseInt(target.toString())) {
return mid;
} else if (Integer.parseInt(temp.getElement().toString()) > Integer.parseInt(target.toString())) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
All class for better understanding;
public class SinglyLinkedList<E> {
private static class Node<E> {
private E element;
private Node<E> next;
public Node(E e, Node<E> n) {
element = e;
next = n;
}
private E getElement() {
return element;
}
private Node<E> getNext() {
return next;
}
private void setNext(Node<E> n) {
next = n;
}
}
private Node<E> head;
private Node<E> tail;
private int size;
public SinglyLinkedList() {
};
public int getSize() {
return size;
}
public void append(E e) {
if (head == null) {
head = new Node<E>(e, null);
tail = head;
size++;
return;
}
Node<E> temp = head;
while (temp != tail) {
temp = temp.next;
}
temp.setNext(tail = new Node<E>(e, null));
size++;
return;
}
public int binarySearchLinkedList(SinglyLinkedList<E> list, E target) {
int left = 0;
int right = list.getSize();
while (left <= right) {
int mid = (left + right) / 2;
Node<E> temp = head;
for (int i = 0; i < mid - 1; i++) {
temp = temp.next;
}
if (temp.getElement() instanceof Number && target instanceof Number) {
if (Integer.parseInt(temp.getElement().toString()) == Integer.parseInt(target.toString())) {
return mid;
} else if (Integer.parseInt(temp.getElement().toString()) > Integer.parseInt(target.toString())) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return -1;
}
public String toString() {
StringBuilder sb = new StringBuilder();
Node<E> temp = head;
while (temp != tail) {
sb.append(temp.getElement()).append(", ");
temp = temp.next;
if (temp == tail) {
sb.append(temp.getElement());
}
}
return sb.toString();
}
}
And the main method;
public static void main(String[] args) {
SinglyLinkedList<Integer> list = new SinglyLinkedList<>();
list.append(10);
list.append(20);
list.append(30);
list.append(40);
list.append(50);
list.append(60);
list.append(70);
list.append(80);
list.append(90);
list.append(100);
System.out.println(list);
System.out.println(list.binarySearchLinkedList(list, 30));
}
It returns;
10, 20, 30, 40, 50, 60, 70, 80, 90, 100
-1
I'm guessing this line is the biggest issue:
for (int i = 0; i < mid - 1; i++) {
Consider what happens if mid is 1. The loop won't execute, because it is not the case that 0 < 1-1. So the inspected node won't be the one you think it is. The actual node at index mid will never be inspected. So the outer loop will eventually exit, never having found the target. Presumably your method ends with return -1;.
Other issues include:
You're initializing right to an exclusive value, but treat it as inclusive elsewhere. Consider using int right = list.getSize() - 1;
You've declared a generic method, but implemented it only for Integer. One way around this would be to limit the generic type to one that supports Comparable - e.g., E extends Comparable<E>.
You're implementing a binary search in a linked list. In a linked list, linear search would be simpler and no less efficient. Or you could use a data structure that supports constant-time access by index, such as an array or ArrayList.
I have created a doubly-linked list that I fill with nodes in Java. I am trying to make a method that adds a node at a certain index. The problem is that I get NullPointerException if I try to add a node and there are no other nodes. So I would write list.add(0, 0); for example and I would get NullPointerException (the first number is index and second is value). However, if I first use my method that just puts in a node and then tries list.add(0, 0); or list.add(1, 0); it works. I believe the problem lies in how to iterate through the nodes. The code currently looks like this:
void add(int index, T t)
{
ListNode<T> node = header;
ListNode<T> newNode = new ListNode<T>(t);
if(index < 0 || index > size)
{
throw new IndexOutOfBoundsException("Index not allowed");
}
int counter = 0;
while(node.next != null && counter < index)
{
node = node.next;
counter++;
}
if(counter == 0)
{
header = newNode;
newNode.next = node;
}
else
{
node = node.previous;
ListNode<T> temp = node.next;
node.next = newNode;
newNode.next = temp;
}
newNode.previous = node;
newNode.next.previous = newNode;
size++;
}
And I believe that this is where the problem is:
while(node.next != null && counter < index)
Do you have an idea on how to do it instead? I can't think of another way.
I have been trying to come up with an algorithm to swap 2 nodes (not necesarily right next to each other) in a singly linked list for 2 days but for some reason I cannot do it.
Here is what I have, I am really new to coding and have been really stressed:
I have managed to place a temp node in but can't actually swap the nodes.
public void swap(int i, int j) {
current = head;
current2 = head;
sllNode temp = new sllNode(" ");
sllNode temp2 = new sllNode(" ");
for(int z = 0; i>z; z++)
current=current.next;
for(int q = 0; j>q; q++)
current2 = current2.next;
temp.next = current2.next.next;
current.next = temp;
current.next = current2.next.next;
current2.next = current;
Why exchange nodes, when you can exchange the data?
public void swap(int i, int j) {
sllNode ithNode = head;
for (int z = 0; z < i; z++) {
ithNode = ithNode.next;
}
sllNode jthNode = head;
for (int q = 0; q < j; q++) {
jthNode = jthNode.next;
}
// Swap the data
String data = ithNode.data;
ithNode.data = jthNode.data;
jthNode.data = data;
}
It would make sense to use a method:
public sllNode get(int i) {
sllNode current = head;
while (i > 0) {
current = current.next;
}
return current;
}
By the way:
The convention for class names is a beginning capital: SllNode.
Do not use fields for things like current and current2 where they can be local variables.
Exchanging nodes, the hard way
Here one has to think, so it is best to deal with special cases first, and then only treat i < j.
public void swap(int i, int j) {
if (i >= size() || j >= size()) {
throw new IndexOutOfBoundsException();
}
if (i == j) {
return;
}
if (j < i) {
swap(j, i);
return;
}
// i < j
sllNode ithPredecessor = null;
sllNode ithNode = head;
for (int z = 0; z < i; z++) {
ithPredecessor = ithNode;
ithNode = ithNode.next;
}
sllNode jthPredecessor = ithNode;
sllNode jthNode = ithNode.next;
for (int q = i + 1; q < j; q++) {
jthPredecessor = jthNode;
jthNode = jthNode.next;
}
// Relink both nodes in the list:
// - The jthNode:
if (ithPredecessor == null) {
head = jthNode;
} else {
ithPredecessor.next = jthNode;
}
sllNode jNext = jthNode.next;
//if (ithNode.next == jthNode) {
if (jthPredecessor == ithNode) {
jthNode.next = ithNode;
} else {
jthNode.next = ithNode.next;
}
// - The ithNode:
if (jthPredecessor == ithNode) {
} else {
jthPredecessor.next = ithNode;
}
ithNode.next = jNext;
}
No guarantee that the logic is okay. There are tricks:
//if (ithNode.next == jthNode) {
if (jthPredecessor == ithNode) {
Both conditions test whether i + 1 == j, but testing on a .next and then assigning makes the condition a momentary state. As you see it would have been easier to have one single if (i + 1 == j) { ... } else { ... } and handle both the ithNode and jthNode.
To do this, you need to swap 2 things: the node as next from the previous node, and the next node.
Once you found current and current2 which are the previous nodes of the nodes you want to swap, do this:
Swap the nodes:
sllNode tmp = current.next;
current.next = current2.next;
current2.next = tmp;
Then swap the next:
tmp = current.next.next;
current.next.next = current2.next.next;
current2.next.next = tmp;
// Swapping two elements in a Linked List using Java
import java.util.*;
class SwappingTwoElements {
public static void main(String[] args)
{
LinkedList<Integer> ll = new LinkedList<>();
// Adding elements to Linked List
ll.add(10);
ll.add(11);
ll.add(12);
ll.add(13);
ll.add(14);
ll.add(15);
// Elements to swap
int element1 = 11;
int element2 = 14;
System.out.println("Linked List Before Swapping :-");
for (int i : ll) {
System.out.print(i + " ");
}
// Swapping the elements
swap(ll, element1, element2);
System.out.println();
System.out.println();
System.out.println("Linked List After Swapping :-");
for (int i : ll) {
System.out.print(i + " ");
}
}
// Swap Function
public static void swap(LinkedList<Integer> list,
int ele1, int ele2)
{
// Getting the positions of the elements
int index1 = list.indexOf(ele1);
int index2 = list.indexOf(ele2);
// Returning if the element is not present in the
// LinkedList
if (index1 == -1 || index2 == -1) {
return;
}
// Swapping the elements
list.set(index1, ele2);
list.set(index2, ele1);
}
}
Output
Before Swapping Linked List :-
10 11 12 13 14 15
After Swapping Linked List :-
10 14 12 13 11 15
Time Complexity: O(N), where N is the Linked List length
I am working on an assignment where I have to sort an array and store the indices in a doubly linked list ADT that I have built.
Example:
{"A","B","C","A"} -> {0,3,1,2}
My current approach is to bring the indices into my ADT and then sort the ADT as I sort the array. As far as I can tell, I am doing the exact same operation on both the array and the doubly linked list every time either loop executes, but my output does not match up.
public static void main(String[] args ) {
List A = new List();
String[] inputArray = {"A","C","B","A"};
int i,j;
String key;
//load indices into doubly-linked list
for (int x = 0; x < inputArray.length; x++ ) {
A.append(x);
}
//begin insertion sort
for (j = 1; j < inputArray.length; j++) {
System.out.println(A);
System.out.println(Arrays.toString(inputArray));
key = inputArray[j];
i = j - 1;
while (i >= 0) {
if (key.compareTo(inputArray[i]) > 0) {
break;
}
inputArray[i+1] = inputArray[i];
//moveTo moves the cursor to <int>
A.moveTo(i);
//make sure we aren't trying to insert before first node
if (i > 0) { A.insertBefore(i+1); }
else { A.prepend(i+1); }
//remove node at cursor
A.delete();
i--;
}
inputArray[i+1] = key;
A.moveTo(i+1);
if (i > 0) { A.insertBefore(i+1); }
else { A.prepend(i+1); }
A.delete();
}
System.out.println(A);
System.out.println(Arrays.toString(inputArray));
}
The above code gives the following output:
run:
0 1 2 3
[A, C, B, A]
1 0 2 3
[A, C, B, A]
1 1 2 3
[A, B, C, A]
0 2 3 3
[A, A, B, C]
BUILD SUCCESSFUL (total time: 0 seconds)
EDIT: List.java
public class List {
private class Node{
//Fields
int data;
Node next, previous;
//Constructor
Node(int data) {
this.data = data;
next = null;
previous = null;
}
public String toString() { return String.valueOf(data); }
}
//Fields
private Node frontNode, backNode, cursorNode;
private int totalSize, cursorPosition;
//Constructor
List() {
frontNode = backNode = cursorNode = null;
totalSize = 0;
cursorPosition = -1;
}
//moveTo(int i): If 0<=i<=length()-1, moves the cursor to the element
// at index i, otherwise the cursor becomes undefined.
void moveTo(int i) {
if (i == 0) {
cursorPosition = i;
cursorNode = frontNode;
}
else if (i == length() - 1) {
cursorPosition = i;
cursorNode = backNode;
}
else if (i > 0 && i < length() - 1 ) {
cursorNode = frontNode;
cursorPosition = i;
for (int x=0; x < i; x++) {
cursorNode = cursorNode.next;
}
}
else {
cursorPosition = -1;
}
}
//prepend(int data): Inserts new element before front element in this List.
void prepend(int data) {
Node node = new Node(data);
if ( this.length() == 0 ) {
frontNode = backNode = node;
}
else {
frontNode.previous = node;
node.next = frontNode;
frontNode = node;
}
totalSize++;
//cursorPosition might change?
}
//insertBefore(int data): Inserts new element before cursor element in this
// List. Pre: length()>0, getIndex()>=0
void insertBefore(int data) {
Node node = new Node(data);
if ( this.length() > 0 && this.getIndex() >= 0 ) {
node.previous = cursorNode.previous;
node.next = cursorNode;
cursorNode.previous.next = node;
cursorNode.previous = node;
totalSize++;
}
else if ( this.length() <= 0 )
{
throw new RuntimeException
("Error: insertBefore called on empty list");
}
else {
throw new RuntimeException
("Error: insertBefore called without cursor set");
}
}
OK, thanks. I didn't know exactly what insertBefore() and prepend() were intended to do (I could have guessed, but programming should not be about guessing what methods are supposed to do; seeing the documentation is much better).
Since this is an assignment, I'm not going to give you the answer. But the clue is this: After the first pass through the loop, the dump of A gives you the same indices you started with, but rearranged. I think that's the way it's supposed to be after every loop iteration. But that's not true after the second pass through the loop (1 shows up twice, and 0 is gone). Think about it. When you called A.insertBefore() to rearrange the elements of A, what data should you have told insertBefore() to insert, and what did you actually insert?
Finding the width of binary tree.
In my code for each leave i create a entry in a hash map and keep updating it when i found a node at leave i.Finally i will iterate the hashmap to find max width.But how can i do it without using any classleel/global varaiables?
Map<Integer,Integer> mp = new HashMap<Integer,Integer>();
void width(Node node,int level){
if(node==null)
return;
if(mp.containsKey(level)){
int count = mp.get(level);
mp.put(level, count+1);
}else{
mp.put(level, 1);
}
width(node.left, level+1);
width(node.right, level+1);
}
Just create the HashMap inside the method, then move all the work into an auxillary method, like this:
void width(Node node,int level){
Map<Integer,Integer> mp = new HashMap<Integer,Integer>();
widthImpl(mp, node, level);
// find maximum
}
private void widthImpl(Map<Integer,Integer> mp, Node node, int level) {
if(node==null)
return;
if(mp.containsKey(level)){
int count = mp.get(level);
mp.put(level, count+1);
}else{
mp.put(level, 1);
}
widthImpl(mp, node.left, level+1);
widthImpl(mp, node.right, level+1);
}
You don't need to keep track of the number of nodes per level.
Define the horizontal position of each node as the number of right children minus the number of left children that were traversed from the root to the node. The width will then be the maximum horizontal position minus the minimum horizontal position. The min/max positions could be passed around a recursive traversal in an array of two components.
Here's a code example of what I mean:
int getWidth(Node node) {
// current[0] is the number of left children traversed of the current path
// current[1] is the number of right children traversed of the current path
int[] current = { 0, 0 };
// extremes[0] is the minimum horizontal position
// extremes[1] is the maximum horizontal position
int[] extremes = { 0, 0 };
computeExtremes(node, current, extremes);
return (extremes[1] - extremes[0]);
}
void computeExtremes(Node node, int[] current, int[] extremes) {
if (node == null) { return; }
int position = current[1] - current[0];
if (extremes[0] > position) {
extremes[0] = position;
}
if (extremes[1] < position) {
extremes[1] = position;
}
current[0]++;
computeExtremes(node.left, current, extremes);
current[0]--;
current[1]++;
computeExtremes(node.right, current, extremes);
current[1]--;
}
If I understand it correctly you want to do something like this?
public Map<Integer,Integer> width( Node node ) {
Map<Integer,Integer> mp = new HashMap<Integer,Integer>();
width( node, 1, mp );
return mp;
}
private void width( Node node, int level, Map<Integer,Integer> mp ) {
if(node==null)
return;
if(mp.containsKey(level)){
int count = mp.get(level);
mp.put(level, count+1);
}else{
mp.put(level, 1);
}
width(node.left, level+1);
width(node.right, level+1);
}
This uses #nathan's algo, but passes by value.
Pair<int, int> extremes(Node node, int x, int y) {
if (node == null) return makePair(x,y);
Pair p1 = extremes(node.left, x-1, y);
Pair p2 = extremes(node.right, x, y+1);
return makePair(min(p1.x, p2.x), max(p1.y, p2.y))
}
See https://www.geeksforgeeks.org/maximum-width-of-a-binary-tree/
Use recursive with hash table
int getWidth(struct node* root, int level)
{
if(root == NULL)
return 0;
if(level == 1)
return 1;
else if (level > 1)
return getWidth(root->left, level-1) +
getWidth(root->right, level-1);
}
Use queue to dequeue parent and replace with children nodes
static int maxwidth(node root)
{
// Base case
if (root == null)
return 0;
// Initialize result
int maxwidth = 0;
// Do Level order traversal keeping
// track of number of nodes at every level
Queue<node> q = new LinkedList<>();
q.add(root);
while (!q.isEmpty())
{
// Get the size of queue when the level order
// traversal for one level finishes
int count = q.size();
// Update the maximum node count value
maxwidth = Math.max(maxwidth, count);
// Iterate for all the nodes in
// the queue currently
while (count-- > 0)
{
// Dequeue an node from queue
node temp = q.remove();
// Enqueue left and right children
// of dequeued node
if (temp.left != null)
{
q.add(temp.left);
}
if (temp.right != null)
{
q.add(temp.right);
}
}
}
return maxwidth;
}
Something a little different:
int[] width(Node node){
if(node==null) {
return new int[]{};
}
int[] la = width(node.left);
int[] ra = width(node.right);
return merge(1, la, ra);
}
private int[] merge(int n0, int[] la, int[] ra) {
int maxLen = Math.max(la.length, ra.length);
int[] result = new int[maxLen+1];
result[0] = n0;
for (int i = 0; i < maxLen; ++i) {
result[i+1] = i >= la.length
? ra[i] : i >= ra.length
? la[i] : la[i] + ra[i];
}
return result;
}