Elements are stored in contiguous memory (issue of allocation)
| Front of List | Middle of List | End of List | |
|---|---|---|---|
| get | O(1) | O(1) | O(1) |
| set | O(1) | O(1) | O(1) |
| insert | O(n) | O(n) | O(1) |
| remove | O(n) | O(n) | O(1) |
A linked list is a chain of nodes, where each node contains:
No need for contiguous memory allocation (nodes can be scattered anywhere in memory)
You have 10 minutes to complete the quiz.
Choose one option for each of the 4 questions.
To create a linked list:
NodeWrite a class in Java called Node that has two instance variables: data (any type), and a reference to another node.
Write the constructor method, and a set and get method for each instance variable.
public class Node<T> {
private T data;
private Node<T> next;
// constructor
public Node(T data) {
this.data = data;
next = null;
}
// setters
public void setNext(Node<T> next) {
this.next = next;
}
public void setData(T data) {
this.data = data;
}
// getters
public Node<T> getNext() {
return next;
}
public T getData() {
return data;
}
}LinkedList classLinkedList classA linked list has a head (reference to a Node)
LinkedList set up and constructorA toString() method to test our code
insert(Node) methodWrite a insert(Node)
toString() methodBefore we move on to other types of insert, lets create a toString() method to test our list insertion.
Write a toString() method that traverses the entire list
toString() solutionOur insert method has to traverse the entire list to insert a new node.
How can we improve on insertion time?
search() methodWrite a search() method that traverses the entire list trying to find a node that matches the argument value – if found, return the node, if not, return null
toString()search() solutionWhat we have implemented is an unsorted linked list – how many comparisons does it required to find a target element?
In the worst case, each node must be examined once, resulting in O(n) complexity – n is the number of elements in the list.
Removing a node takes a few more steps:
public Node<T> remove(T data) {
Node<T> currNode = head;
Node<T> previous = null;
while (currNode != null) {
if (currNode.getData().equals(data)) {
if (previous != null) {
previous.setNext(currNode.getNext());
} else {
head = head.getNext();
}
return currNode;
} else {
previous = currNode;
currNode = currNode.getNext();
}
}
return null;
}public Node<T> pop(int n) {
if (n >= 0 && n < length) {
Node<T> current = head;
Node<T> previous = null;
for (int i = 0; i < n; i++) {
previous = current;
current = current.getNext();
}
if (previous == null) return pop();
else previous.setNext(current.getNext());
length--;
return current;
}
return null;
}| Front of List | Middle of List | End of List | |
|---|---|---|---|
| get | O(1) | O(n) | O(1) |
| set | O(1) | O(n) | O(1) |
| insert | O(1) | O(n) | O(1) |
| remove | O(1) | O(n) | O(1) |
We just implemented a singly linked list
Doubly linked list:
Circular linked list:
Many linked list functions can be nicely implemented with recursion.
public Node<T> search(Node<T> node, T value) {
if (node == null) { // base case
return null;
}
if (node.getData().equals(value)) {
return node; // found node with matching value
}
// search next
return search(node.getNext(), value);
}
public Node<T> search(T value) {
// traverse all nodes, return the first
// node that data equals value argument
return search(head, value);
}Node.java
public class Node<T extends Comparable<T>> implements Comparable<Node<T>> {
private T data;
private Node<T> next;
public Node(T data) {
this.data = data;
next = null;
}
public T getData() {
return data;
}
public Node<T> getNext() {
return next;
}
public void setData(T data) {
this.data = data;
}
public void setNext(Node<T> next) {
this.next = next;
}
public int compareTo(Node<T> o) {
if (this == o) {
return 0;
}
if (o == null) {
return -1;
}
Node<T> aNode = (Node<T>) o;
return this.data.compareTo(aNode.getData());
}
}LinkedList.java
public class LinkedList<T extends Comparable<T>> {
public Node<T> head;
public Node<T> tail;
private int length;
public LinkedList(Node<T> node) {
head = node;
tail = node;
length++;
}
public void addNode(Node<T> node) {
tail.setNext(node);
tail = node;
length++;
}
public int length() {
return length;
}
public String toString() {
String message = "";
Node<T> current = head;
while (current != null) {
message += current.getData() + " ";
current = current.getNext();
}
return message;
}
public Node<T> search(T value) {
// traverse all nodes, return the first
// node that data equals value argument
Node<T> current = head;
while (current != null) {
if (current.getData().equals(value)) {
return current;
}
current = current.getNext();
}
// no node with value T, return null
return null;
}
public void remove(Node<T> node) {
// remove head?
if (head == node) {
head = head.getNext();
}
// remove matching object
Node<T> current = head;
Node<T> previous = null;
while (current != null) {
// check if objects are the same
if (current == node) {
previous.setNext(current.getNext());
length--;
}
previous = current;
current = current.getNext();
}
}
public void remove(T value) {
// remove first node with data equals value
// remove head?
if (head.getData().equals(value)) {
head = head.getNext();
}
// remove matching object
Node<T> current = head;
Node<T> previous = null;
while (current != null) {
// check if objects are the same
if (current.getData().equals(value)) {
previous.setNext(current.getNext());
length--;
}
previous = current;
current = current.getNext();
}
}
public void remove(int position) {
// remove node at Nth position
// remove first node with data equals value
// remove head?
if (position == 0) {
head = head.getNext();
}
// remove matching object
Node<T> current = head;
Node<T> previous = null;
int counter = 1;
while (current != null) {
// check if objects are the same
if (counter == position) {
previous.setNext(current.getNext());
length--;
}
previous = current;
current = current.getNext();
counter++;
}
}
public void sort() {
// lazy bubble sort
for (int i=0; i < length; i++) {
Node<T> current = head;
while (current != null) {
//System.out.println(current.getData() + " " + current.getNext().getData() + " " + current.compareTo(current.getNext()));
if (current.compareTo(current.getNext()) > 0) {
T temp = current.getData();
current.setData(current.getNext().getData());
current.getNext().setData(temp);
}
current = current.getNext();
}
}
}
}public class UseList {
public static void main(String[] args) {
Node<String> node = new Node<>("tomato");
LinkedList<String> list = new LinkedList<>(new Node<>("apple"));
list.addNode(new Node<>("kiwi"));
list.addNode(node);
list.addNode(new Node<>("banana"));
list.addNode(new Node<>("pineapple"));
System.out.println(list.length());
System.out.println(list);
System.out.println(list.search("pear"));
list.remove(node);
list.addNode(new Node<>("pear"));
list.addNode(new Node<>("orange"));
list.addNode(new Node<>("plum"));
list.addNode(new Node<>("tomato"));
list.addNode(new Node<>("lychee"));
System.out.println(list);
list.sort();
System.out.println(list);
}
}