3
3
import java .util .Objects ;
4
4
5
5
/**
6
- * This class implements a Cursor Linked List.
7
- *
8
- * A CursorLinkedList is an array version of a Linked List. Essentially you have
9
- * an array of list nodes but instead of each node containing a pointer to the
10
- * next item in the linked list, each node element in the array contains the
11
- * index for the next node element.
6
+ * CursorLinkedList is an array-based implementation of a singly linked list.
7
+ * Each node in the array simulates a linked list node, storing an element and
8
+ * the index of the next node. This structure allows for efficient list operations
9
+ * without relying on traditional pointers.
12
10
*
11
+ * @param <T> the type of elements in this list
13
12
*/
14
13
public class CursorLinkedList <T > {
15
14
15
+ /**
16
+ * Node represents an individual element in the list, containing the element
17
+ * itself and a pointer (index) to the next node.
18
+ */
16
19
private static class Node <T > {
17
-
18
20
T element ;
19
21
int next ;
20
22
@@ -31,20 +33,26 @@ private static class Node<T> {
31
33
private static final int CURSOR_SPACE_SIZE = 100 ;
32
34
33
35
{
34
- // init at loading time
36
+ // Initialize cursor space array and free list pointers
35
37
cursorSpace = new Node [CURSOR_SPACE_SIZE ];
36
38
for (int i = 0 ; i < CURSOR_SPACE_SIZE ; i ++) {
37
39
cursorSpace [i ] = new Node <>(null , i + 1 );
38
40
}
39
41
cursorSpace [CURSOR_SPACE_SIZE - 1 ].next = 0 ;
40
42
}
41
43
44
+ /**
45
+ * Constructs an empty CursorLinkedList with the default capacity.
46
+ */
42
47
public CursorLinkedList () {
43
48
os = 0 ;
44
49
count = 0 ;
45
50
head = -1 ;
46
51
}
47
52
53
+ /**
54
+ * Prints all elements in the list in their current order.
55
+ */
48
56
public void printList () {
49
57
if (head != -1 ) {
50
58
int start = head ;
@@ -57,27 +65,36 @@ public void printList() {
57
65
}
58
66
59
67
/**
60
- * @return the logical index of the element within the list , not the actual
61
- * index of the [cursorSpace] array
68
+ * Finds the logical index of a specified element in the list.
69
+ *
70
+ * @param element the element to search for in the list
71
+ * @return the logical index of the element, or -1 if not found
72
+ * @throws NullPointerException if element is null
62
73
*/
63
74
public int indexOf (T element ) {
64
- Objects .requireNonNull (element );
65
- Node <T > iterator = cursorSpace [head ];
66
- for (int i = 0 ; i < count ; i ++) {
67
- if (iterator .element .equals (element )) {
68
- return i ;
75
+ if (element == null ) {
76
+ throw new NullPointerException ("Element cannot be null" );
77
+ }
78
+ try {
79
+ Objects .requireNonNull (element );
80
+ Node <T > iterator = cursorSpace [head ];
81
+ for (int i = 0 ; i < count ; i ++) {
82
+ if (iterator .element .equals (element )) {
83
+ return i ;
84
+ }
85
+ iterator = cursorSpace [iterator .next ];
69
86
}
70
- iterator = cursorSpace [iterator .next ];
87
+ } catch (Exception e ) {
88
+ return -1 ;
71
89
}
72
-
73
90
return -1 ;
74
91
}
75
92
76
93
/**
77
- * @param position , the logical index of the element , not the actual one
78
- * within the [cursorSpace] array . this method should be used to get the
79
- * index give by indexOf() method.
80
- * @return
94
+ * Retrieves an element at a specified logical index in the list.
95
+ *
96
+ * @param position the logical index of the element
97
+ * @return the element at the specified position, or null if index is out of bounds
81
98
*/
82
99
public T get (int position ) {
83
100
if (position >= 0 && position < count ) {
@@ -88,51 +105,76 @@ public T get(int position) {
88
105
if (counter == position ) {
89
106
return element ;
90
107
}
91
-
92
108
start = cursorSpace [start ].next ;
93
109
counter ++;
94
110
}
95
111
}
96
-
97
112
return null ;
98
113
}
99
114
115
+ /**
116
+ * Removes the element at a specified logical index from the list.
117
+ *
118
+ * @param index the logical index of the element to remove
119
+ */
100
120
public void removeByIndex (int index ) {
101
121
if (index >= 0 && index < count ) {
102
122
T element = get (index );
103
123
remove (element );
104
124
}
105
125
}
106
126
127
+ /**
128
+ * Removes a specified element from the list.
129
+ *
130
+ * @param element the element to be removed
131
+ * @throws NullPointerException if element is null
132
+ */
107
133
public void remove (T element ) {
108
134
Objects .requireNonNull (element );
109
-
110
- // case element is in the head
111
135
T tempElement = cursorSpace [head ].element ;
112
136
int tempNext = cursorSpace [head ].next ;
113
137
if (tempElement .equals (element )) {
114
138
free (head );
115
139
head = tempNext ;
116
- } else { // otherwise cases
140
+ } else {
117
141
int prevIndex = head ;
118
142
int currentIndex = cursorSpace [prevIndex ].next ;
119
-
120
143
while (currentIndex != -1 ) {
121
144
T currentElement = cursorSpace [currentIndex ].element ;
122
145
if (currentElement .equals (element )) {
123
146
cursorSpace [prevIndex ].next = cursorSpace [currentIndex ].next ;
124
147
free (currentIndex );
125
148
break ;
126
149
}
127
-
128
150
prevIndex = currentIndex ;
129
151
currentIndex = cursorSpace [prevIndex ].next ;
130
152
}
131
153
}
132
-
133
154
count --;
134
155
}
135
156
157
+ /**
158
+ * Allocates a new node index for storing an element.
159
+ *
160
+ * @return the index of the newly allocated node
161
+ * @throws OutOfMemoryError if no space is available in cursor space
162
+ */
163
+ private int alloc () {
164
+ int availableNodeIndex = cursorSpace [os ].next ;
165
+ if (availableNodeIndex == 0 ) {
166
+ throw new OutOfMemoryError ();
167
+ }
168
+ cursorSpace [os ].next = cursorSpace [availableNodeIndex ].next ;
169
+ cursorSpace [availableNodeIndex ].next = -1 ;
170
+ return availableNodeIndex ;
171
+ }
172
+
173
+ /**
174
+ * Releases a node back to the free list.
175
+ *
176
+ * @param index the index of the node to release
177
+ */
136
178
private void free (int index ) {
137
179
Node <T > osNode = cursorSpace [os ];
138
180
int osNext = osNode .next ;
@@ -141,44 +183,26 @@ private void free(int index) {
141
183
cursorSpace [index ].next = osNext ;
142
184
}
143
185
186
+ /**
187
+ * Appends an element to the end of the list.
188
+ *
189
+ * @param element the element to append
190
+ * @throws NullPointerException if element is null
191
+ */
144
192
public void append (T element ) {
145
193
Objects .requireNonNull (element );
146
194
int availableIndex = alloc ();
147
195
cursorSpace [availableIndex ].element = element ;
148
-
149
196
if (head == -1 ) {
150
197
head = availableIndex ;
198
+ } else {
199
+ int iterator = head ;
200
+ while (cursorSpace [iterator ].next != -1 ) {
201
+ iterator = cursorSpace [iterator ].next ;
202
+ }
203
+ cursorSpace [iterator ].next = availableIndex ;
151
204
}
152
-
153
- int iterator = head ;
154
- while (cursorSpace [iterator ].next != -1 ) {
155
- iterator = cursorSpace [iterator ].next ;
156
- }
157
-
158
- cursorSpace [iterator ].next = availableIndex ;
159
205
cursorSpace [availableIndex ].next = -1 ;
160
-
161
206
count ++;
162
207
}
163
-
164
- /**
165
- * @return the index of the next available node
166
- */
167
- private int alloc () {
168
- // 1- get the index at which the os is pointing
169
- int availableNodeIndex = cursorSpace [os ].next ;
170
-
171
- if (availableNodeIndex == 0 ) {
172
- throw new OutOfMemoryError ();
173
- }
174
-
175
- // 2- make the os point to the next of the @var{availableNodeIndex}
176
- cursorSpace [os ].next = cursorSpace [availableNodeIndex ].next ;
177
-
178
- // this to indicate an end of the list , helpful at testing since any err
179
- // would throw an outOfBoundException
180
- cursorSpace [availableNodeIndex ].next = -1 ;
181
-
182
- return availableNodeIndex ;
183
- }
184
208
}
0 commit comments