Skip to content

Commit 7f9f169

Browse files
committed
Add DoublyLinkedList as a doubly linked list
1 parent c740825 commit 7f9f169

File tree

5 files changed

+369
-0
lines changed

5 files changed

+369
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
package br.com.zevolution.datastructure.doublylinkedlist;
2+
3+
import java.util.NoSuchElementException;
4+
5+
public class DoublyLinkedList {
6+
7+
private Node first = null;
8+
private Node last = null;
9+
private int totalElements = 0;
10+
11+
public void addFirst(Object element) {
12+
if (this.totalElements == 0) {
13+
Node node = new Node(element);
14+
this.first = node;
15+
this.last = node;
16+
} else {
17+
Node node = new Node(element, this.first);
18+
this.first.setPrevious(node);
19+
this.first = node;
20+
}
21+
22+
this.totalElements++;
23+
}
24+
25+
public void add(Object element) {
26+
if (this.totalElements == 0) {
27+
this.addFirst(element);
28+
} else {
29+
Node node = new Node(element);
30+
this.last.setNext(node);
31+
node.setPrevious(this.last);
32+
this.last = node;
33+
34+
this.totalElements++;
35+
}
36+
}
37+
38+
public void add(int position, Object element) {
39+
if (!this.isValidContentPosition(position))
40+
throw new UnoccupiedPosition();
41+
42+
if (position == 0) {
43+
this.addFirst(element);
44+
} else if (position == this.totalElements) {
45+
this.add(element);
46+
} else {
47+
Node previousNode = this.getNode(position -1 );
48+
Node nextNode = previousNode.getNext();
49+
50+
Node node = new Node(element, previousNode.getNext());
51+
node.setPrevious(previousNode);
52+
53+
previousNode.setNext(node);
54+
nextNode.setPrevious(node);
55+
56+
this.totalElements++;
57+
}
58+
}
59+
60+
public void removeFirst() {
61+
if (this.totalElements == 0)
62+
throw new NoSuchElementException();
63+
64+
this.first = this.first.getNext();
65+
this.totalElements--;
66+
67+
if (this.totalElements == 0) {
68+
this.last = null;
69+
}
70+
}
71+
72+
public void removeLast() {
73+
if (this.totalElements == 1) {
74+
this.removeFirst();
75+
} else {
76+
Node lastButOne = this.last.getPrevious();
77+
lastButOne.setNext(null);
78+
this.last = lastButOne;
79+
this.totalElements--;
80+
}
81+
}
82+
83+
public void remove(Object element) {
84+
Node node = this.hasNode(element);
85+
if (node == null) return;
86+
87+
if (node.getPrevious() == null) {
88+
this.removeFirst();
89+
} else if (node.getNext() == null) {
90+
this.removeLast();
91+
} else {
92+
this.removeNode(node);
93+
}
94+
}
95+
96+
public void remove(int position) {
97+
if (position == 0) {
98+
this.removeFirst();
99+
} else if (position == this.totalElements -1) {
100+
this.removeLast();
101+
} else {
102+
Node node = this.getNode(position);
103+
this.removeNode(node);
104+
}
105+
}
106+
107+
public Object get(int position) {
108+
return this.getNode(position).getElement();
109+
}
110+
111+
public int size() {
112+
return this.totalElements;
113+
}
114+
115+
public boolean has(Object element) {
116+
return this.hasNode(element) != null;
117+
}
118+
119+
private Node hasNode(Object element) {
120+
Node node = this.first;
121+
122+
while (node != null) {
123+
if (node.getElement().equals(element)) {
124+
return node;
125+
}
126+
127+
node = node.getNext();
128+
}
129+
130+
return null;
131+
}
132+
133+
@Override
134+
public String toString() {
135+
if (this.totalElements == 0) return "[]";
136+
137+
Node node = this.first;
138+
139+
StringBuilder builder = new StringBuilder("[");
140+
141+
for (int i = 0; i < this.totalElements -1; i++) {
142+
builder.append(node.getElement()).append(", ");
143+
node = node.getNext();
144+
}
145+
146+
builder.append(node.getElement()).append("]");
147+
148+
return builder.toString();
149+
}
150+
151+
private boolean isValidContentPosition(int position) {
152+
return position >= 0 && position < this.totalElements;
153+
}
154+
155+
private Node getNode(int position) {
156+
if (!this.isValidContentPosition(position))
157+
throw new UnoccupiedPosition();
158+
159+
Node node = this.first;
160+
for (int i = 0; i < position; i++) {
161+
node = node.getNext();
162+
}
163+
return node;
164+
}
165+
166+
private void removeNode(Node node) {
167+
Node previousNode = node.getPrevious();
168+
Node nextNode = node.getNext();
169+
170+
previousNode.setNext(nextNode);
171+
nextNode.setPrevious(previousNode);
172+
173+
node = null;
174+
175+
this.totalElements--;
176+
}
177+
178+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package br.com.zevolution.datastructure.doublylinkedlist;
2+
3+
public class InvalidPosition extends RuntimeException {
4+
5+
private static final long serialVersionUID = -3536404610449816152L;
6+
7+
public InvalidPosition() {
8+
super("Invalid position");
9+
}
10+
11+
public InvalidPosition(String message) {
12+
super(message);
13+
}
14+
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package br.com.zevolution.datastructure.doublylinkedlist;
2+
3+
public class Node {
4+
5+
private Node previous;
6+
private Node next;
7+
private Object element;
8+
9+
public Node(Object element) {
10+
this(element, null);
11+
}
12+
13+
public Node(Object element, Node next) {
14+
this.element = element;
15+
this.next = next;
16+
}
17+
18+
public Node getPrevious() {
19+
return previous;
20+
}
21+
22+
public void setPrevious(Node previous) {
23+
this.previous = previous;
24+
}
25+
26+
public Node getNext() {
27+
return next;
28+
}
29+
30+
public void setNext(Node next) {
31+
this.next = next;
32+
}
33+
34+
public Object getElement() {
35+
return element;
36+
}
37+
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package br.com.zevolution.datastructure.doublylinkedlist;
2+
3+
public class UnoccupiedPosition extends InvalidPosition {
4+
5+
private static final long serialVersionUID = -2300538444121627252L;
6+
7+
public UnoccupiedPosition() {
8+
super("There is no value in this position");
9+
}
10+
11+
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package br.com.zevolution.datastructure.doublylinkedlist;
2+
3+
import static org.junit.Assert.*;
4+
5+
import java.util.NoSuchElementException;
6+
7+
import org.junit.Test;
8+
9+
public class DoublyLinkedListTest {
10+
11+
@Test
12+
public void should_Contain_OneRecordInDoublyLinkedList() {
13+
DoublyLinkedList doublyLinkedList = new DoublyLinkedList();
14+
doublyLinkedList.add("José Lucas");
15+
16+
assertEquals(1, doublyLinkedList.size());
17+
}
18+
19+
@Test
20+
public void should_Contain_TwoRecordsInDoublyLinkedList() {
21+
DoublyLinkedList doublyLinkedList = new DoublyLinkedList();
22+
doublyLinkedList.add("Beatriz");
23+
doublyLinkedList.add("José Lucas");
24+
25+
assertEquals(2, doublyLinkedList.size());
26+
}
27+
28+
@Test
29+
public void should_MakeSure_ObjectPosition() {
30+
DoublyLinkedList doublyLinkedList = new DoublyLinkedList();
31+
doublyLinkedList.add("Beatriz");
32+
doublyLinkedList.add("José Lucas");
33+
doublyLinkedList.add(0, "Laura");
34+
35+
assertEquals("Laura", doublyLinkedList.get(0));
36+
assertEquals("Beatriz", doublyLinkedList.get(1));
37+
assertEquals("José Lucas", doublyLinkedList.get(2));
38+
}
39+
40+
@Test
41+
public void should_MakeSure_AddFirst_ObjectPosition() {
42+
DoublyLinkedList doublyLinkedList = new DoublyLinkedList();
43+
doublyLinkedList.add("Beatriz");
44+
doublyLinkedList.add("José Lucas");
45+
doublyLinkedList.addFirst("Laura");
46+
47+
assertEquals("Laura", doublyLinkedList.get(0));
48+
assertEquals("Beatriz", doublyLinkedList.get(1));
49+
assertEquals("José Lucas", doublyLinkedList.get(2));
50+
}
51+
52+
@Test
53+
public void should_MakeSure_RemoveFirst_ObjectPosition() {
54+
DoublyLinkedList doublyLinkedList = new DoublyLinkedList();
55+
doublyLinkedList.add("José Lucas");
56+
doublyLinkedList.add("Beatriz");
57+
doublyLinkedList.add("Laura");
58+
59+
doublyLinkedList.removeFirst();
60+
61+
assertNotEquals("José Lucas", doublyLinkedList.get(0));
62+
assertEquals("Beatriz", doublyLinkedList.get(0));
63+
assertEquals(2, doublyLinkedList.size());
64+
}
65+
66+
@Test
67+
public void should_MakeSure_RemoveLast_ObjectPosition() {
68+
DoublyLinkedList doublyLinkedList = new DoublyLinkedList();
69+
doublyLinkedList.add("Beatriz");
70+
doublyLinkedList.add("Laura");
71+
doublyLinkedList.add("José Lucas");
72+
73+
doublyLinkedList.removeLast();
74+
75+
int lastPosition = doublyLinkedList.size() - 1;
76+
assertNotEquals("José Lucas", doublyLinkedList.get(lastPosition));
77+
assertEquals("Laura", doublyLinkedList.get(lastPosition));
78+
assertEquals(2, doublyLinkedList.size());
79+
}
80+
81+
@Test
82+
public void should_MakeSure_RemovePosition_ObjectPosition() {
83+
DoublyLinkedList doublyLinkedList = new DoublyLinkedList();
84+
doublyLinkedList.add("Beatriz");
85+
doublyLinkedList.add("José Lucas");
86+
doublyLinkedList.add("Laura");
87+
88+
doublyLinkedList.remove(1);
89+
90+
assertNotEquals("José Lucas", doublyLinkedList.get(1));
91+
assertEquals("Beatriz", doublyLinkedList.get(0));
92+
assertEquals("Laura", doublyLinkedList.get(1));
93+
assertEquals(2, doublyLinkedList.size());
94+
}
95+
96+
@Test
97+
public void should_Be_Empty() {
98+
DoublyLinkedList doublyLinkedList = new DoublyLinkedList();
99+
doublyLinkedList.add("Beatriz");
100+
doublyLinkedList.add("José Lucas");
101+
doublyLinkedList.add("Laura");
102+
103+
for (int i = doublyLinkedList.size(); i > 0; i--) {
104+
doublyLinkedList.removeFirst();
105+
}
106+
107+
assertEquals(0, doublyLinkedList.size());
108+
}
109+
110+
111+
@Test(expected = UnoccupiedPosition.class)
112+
public void should_ThrowException_When_UnoccupiedPosition() {
113+
DoublyLinkedList doublyLinkedList = new DoublyLinkedList();
114+
doublyLinkedList.add("zevolution");
115+
116+
doublyLinkedList.add(1, "noitulovez");
117+
}
118+
119+
@Test(expected = NoSuchElementException.class)
120+
public void should_ThrowException_When_NoSuchElement() {
121+
DoublyLinkedList doublyLinkedList = new DoublyLinkedList();
122+
123+
doublyLinkedList.removeFirst();
124+
}
125+
126+
}

0 commit comments

Comments
 (0)