public class Node<T> {
Node next;
T data;
Node(T data, Node next) {
this.data = data;
this.next = next;
}
public String toString() {
return data.toString() + ", next: " + (next != null ? next.data.toString() : "null");
}
}
class SinglyLinkedList<T> {
Node<T> head;
SinglyLinkedList(Node<T> head) {
this.head = head;
}
public int size() {
Node<T> node = head;
int size = 1;
while (node.next != null) {
node = node.next;
size++;
}
return size;
}
public int search(T data) {
Node<T> node = head;
int index = 0;
while (node != null) {
if (node.data.equals(data)) {
return index;
}
node = node.next;
index++;
}
return -1;
}
public String toString() {
Node<T> node = head;
StringBuilder strb = new StringBuilder(node.data.toString());
int i = 0;
while (node.next != null && i++ < 99) {
node = node.next;
strb.append(',').append(node.data.toString());
}
return strb.toString();
}
public void reverse() {
// TODO: consider what happens when there is only one node
Node<T> previous = null;
Node<T> current = head;
Node<T> tmp;
while (current != null) {
tmp = current.next;
current.next = previous;
previous = current;
current = tmp;
}
head = previous;
}
public T get(int n) {
return getNode(n).data;
}
private Node<T> getNode(int n) {
// TODO: handle out of range
Node<T> node = head;
for (int i = 1; i < n + 1; i++) {
node = node.next;
}
return node;
}
public void insert(int index, T data) {
Node<T> node = head;
// TODO: hondle out of range
for (int i = 1; i < index; i++) {
node = node.next;
}
Node<T> newNode = new Node<>(data, node.next);
node.next = newNode;
}
public void delete(int index) {
// TODO: handle out of range and attempt to delete(0) when there is only one node
Node<T> node = head;
Node<T> previous = null;
for (int i = 1; i < index + 1; i++) {
previous = node;
node = node.next;
}
if (previous != null) {
previous.next = node.next;
} else {
head = node.next;
}
}
public void swap(int first, int second) {
Node<T> a = getNode(first);
Node<T> b = getNode(second);
Node<T> beforeA = null;
if (first > 0) {
beforeA = getNode(first - 1);
}
Node<T> beforeB = null;
if (second > 0) {
beforeB = getNode(second - 1);
}
if (beforeA != null) {
beforeA.next = b;
}
if (beforeB != null) {
beforeB.next = a;
}
Node<T> tmp = a.next;
a.next = b.next;
b.next = tmp;
if (head == a) {
head = b;
} else if (head == b) {
head = a;
}
}
/*
* A lot easier to swap data than nodes, but may be heavier
*/
public void swapData(int first, int second) {
Node<T> firstNode = getNode(first);
Node<T> secondNode = getNode(second);
T tmp = firstNode.data;
firstNode.data = secondNode.data;
secondNode.data = tmp;
}
}
class Main {
public static void main(String[] args) {
SinglyLinkedList<String> sll = new SinglyLinkedList<>(new Node<>("foo", null));
sll.insert(1, "bar");
sll.insert(1, "brabra");
System.out.println(sll.size());
System.out.println(sll.search("bar"));
System.out.println(sll.toString());
for (int i = 0; i < sll.size(); i++) {
System.out.println(sll.get(i).toString());
}
sll.reverse();
System.out.println("after reverse: " + sll.toString());
sll.swap(1, 2);
System.out.println("after swap: " + sll.toString());
sll.swap(0, 1);
System.out.println("after swap: " + sll.toString());
sll.delete(1);
System.out.println("after delete(1): " + sll.toString());
sll.delete(0);
System.out.println("after delete(0): " + sll.toString());
}
}