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
Related
I am trying to swap elements but the cycle is infinite.
The problem is in method change() or find().
I am just learning JAVA, so its hard to me to understand where is the mistake.
import java.util.*;
public class CustomLinkedList {
class Node{
int element;
Node next;
Node(int element){
this.element = element;
}
}
private Node first;
private Node last;
private int size;
private Node temp;
public void add(int element) {
Node newNode = new Node(element);
if(first == null) {
first = last = newNode;
} else {
last.next = newNode;
last = newNode;
}
size++;
}
public void output() {
Node current = first;
if(current == null) {
System.out.println("YOUR LIST IS EMPTY!!! ADD SOME ELEMENTS!!!");
}
else {
while(current != null) {
System.out.print("["+current.element+ "]" + " ");
current = current.next;
}
System.out.println();
}
}
public Node find(int index) {
Node current = first;
for(int i = 0; i < index; i++) {
current = current.next;
}
return current;
}
public void change(int index, int k) {
int count = 0;
while(count < k) {
Objects.checkIndex(index, size);
Node our = find(index);
temp = our.next;
our.next = our;
our = temp;
our = null;
count++;
index++;
}
}
}
Maybee, someone know how to do this.
When you swap two elements in a linked list, you actually need to modify up to three elements. For example, look at the following sub-list:
... -> a -> b -> c -> d -> ...
If you swap c and b, you get:
... -> a -> c -> b -> d -> ...
Now, the following has changed:
The next of a is now c (it was b).
The next of b is now d (it was c).
The next of c is now b (it was d).
Three nodes changed. Your code in the change() method only modifies two nodes, it forgets about node a.
Update
Possible implementation of a swap method:
/**
* Swaps the elements at the i-th and the (i-1)-th indices.
*/
public void swap(int index) {
Objects.checkIndex(index, size - 1);
if (index == 0) {
// Before swap: first -> x -> y
Node oldFirst = first;
Node x = first.next;
Node y = x.next;
// After swap: x -> first -> y
x.next = first;
first.next = y;
first = x;
// Update `last` if last two elements swapped
if (size == 2) {
last = oldFirst;
}
} else {
// Before swap: a -> b -> c -> d
Node a = find(index - 1);
Node b = a.next;
Node c = b.next;
Node d = c.next;
// After swap: a -> c -> b -> d
a.next = c;
b.next = d;
c.next = b;
// Update `last` if last two elements swapped
if (index == size - 2) {
last = b;
}
}
}
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 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)
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?
Similar to this: Is there any way to do n-level nested loops in Java?
I want to create a recursive function, which generates N nested loops, where the indicies depend on the depth of the loop. So basically, I want to do this recursively:
// N = 3, so we want three nested loops
for(int i1 = 0; i1 < max; i1++){
for(int i2 = i1+1; i2 < max; i2++){
for(int i3 = i2+1; i3 < max; i3++){
int value1 = getValue(i1);
int value2 = getValue(i2);
int value3 = getValue(i3);
doSomethingWithTheValues( ... );
}
}
}
I've looked at the answers in the other question, and tried to modify the answer (by oel.neely), but without luck. My guess is that it only needs a small modification, but right now, I'm just confusing myself!
Its C#, but should be easily convertable to Java:
class ImmutableStack<T>
{
public readonly T Head;
public readonly ImmutableStack<T> Tail;
public ImmutableStack(T head, ImmutableStack<T> tail)
{
this.Head = head;
this.Tail = tail;
}
public static ImmutableStack<T> Cons(T head, ImmutableStack<T> tail)
{
return new ImmutableStack<T>(head, tail);
}
public static ImmutableStack<T> Reverse(ImmutableStack<T> s)
{
ImmutableStack<T> res = null;
while (s != null)
{
res = Cons(s.Head, res);
s = s.Tail;
}
return res;
}
}
class Program
{
static void AwesomeRecursion(int toDepth, int start, int max, ImmutableStack<int> indices)
{
if (toDepth < 0)
{
throw new ArgumentException("toDepth should be >= 0");
}
else if (toDepth == 0)
{
Console.Write("indices: ");
indices = ImmutableStack<int>.Reverse(indices);
while (indices != null)
{
Console.Write("{0}, ", indices.Head);
indices = indices.Tail;
}
Console.WriteLine();
}
else
{
for (int i = start; i < max; i++)
{
AwesomeRecursion(toDepth - 1, i + 1, max, ImmutableStack<int>.Cons(i, indices));
}
}
}
static void Main(string[] args)
{
AwesomeRecursion(4, 1, 10, null);
Console.WriteLine("Done");
Console.ReadKey(true);
}
}
We keep the indices on an immutable stack since it makes backtracking so much easier than mutable stacks or queues.