Skip to content

Commit 32ee566

Browse files
authored
Merge pull request #8 from ascii-dev/implement_singly_linked_lists_with_partial_tests
implement singly linked lists with partial tests
2 parents 4aaac51 + 88dbee4 commit 32ee566

7 files changed

Lines changed: 458 additions & 1 deletion

File tree

.bazelrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ run --action_env=HOME
77

88
# --- Output Formatting ---
99
# Make the output look nicer (optional but recommended)
10-
test --test_output=errors
10+
test --test_output=errors --test_verbose_timeout_warnings

c/includes/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
exports_files(["greet.h"])
22
exports_files(["vector.h"])
3+
exports_files(["slinkedlist.h"])

c/includes/slinkedlist.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#ifndef C_SLINKEDLIST_H
2+
#define C_SLINKEDLIST_H
3+
#include <stddef.h>
4+
5+
typedef struct SLinkedList SLinkedList;
6+
7+
SLinkedList* slinkedlist_new();
8+
size_t slinkedlist_size(SLinkedList* list);
9+
short slinkedlist_empty(SLinkedList* list);
10+
void* slinkedlist_at(SLinkedList* list, int index);
11+
void slinkedlist_push_front(SLinkedList* list, const void* item);
12+
void* slinkedlist_pop_front(SLinkedList* list);
13+
void slinkedlist_push_back(SLinkedList* list, const void* item);
14+
void* slinkedlist_pop_back(SLinkedList* list);
15+
void* slinkedlist_front(SLinkedList* list);
16+
void* slinkedlist_back(SLinkedList* list);
17+
void slinkedlist_insert(SLinkedList* list, int index, const void* item);
18+
void slinkedlist_erase(SLinkedList* list, int index);
19+
void* slinkedlist_value_n_from_end(SLinkedList* list, int n);
20+
void slinkedlist_reverse(SLinkedList* list);
21+
void slinkedlist_remove_value(SLinkedList* list, const void* value);
22+
void slinkedlist_free(SLinkedList* list);
23+
24+
#endif // C_SLINKEDLIST_H

c/src/linkedlist/BUILD.bazel

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
load("@rules_cc//cc:defs.bzl", "cc_library")
2+
3+
cc_library(
4+
name = "slinkedlist",
5+
srcs = ["slinkedlist.c"],
6+
hdrs = ["//c/includes:slinkedlist.h"],
7+
strip_include_prefix = "//c",
8+
visibility = ["//visibility:public"],
9+
)

c/src/linkedlist/slinkedlist.c

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
#include "includes/slinkedlist.h"
2+
3+
#include <stddef.h>
4+
#include <stdlib.h>
5+
#include <string.h>
6+
7+
typedef struct SLinkedListNode {
8+
void* value;
9+
struct SLinkedListNode* next;
10+
} SLinkedListNode;
11+
12+
struct SLinkedList {
13+
size_t size;
14+
SLinkedListNode* head;
15+
SLinkedListNode* tail;
16+
};
17+
18+
SLinkedList* slinkedlist_new() {
19+
SLinkedList* list = malloc(sizeof(SLinkedList));
20+
if (list == NULL) return NULL;
21+
22+
list->size = 0;
23+
list->head = NULL;
24+
list->tail = NULL;
25+
26+
return list;
27+
}
28+
29+
size_t slinkedlist_size(SLinkedList* list) { return list->size; }
30+
31+
short slinkedlist_empty(SLinkedList* list) { return list->size == 0; }
32+
33+
void* slinkedlist_at(SLinkedList* list, int index) {
34+
if (index < 0 || index >= list->size) return NULL;
35+
36+
SLinkedListNode* node = list->head;
37+
int i = 0;
38+
while (node != NULL && i < index) {
39+
node = node->next;
40+
i++;
41+
}
42+
43+
if (node == NULL) return NULL;
44+
45+
return node->value;
46+
}
47+
48+
void slinkedlist_push_front(SLinkedList* list, const void* item) {
49+
SLinkedListNode* node = malloc(sizeof(SLinkedListNode));
50+
if (node == NULL) return;
51+
52+
node->value = (void*)item;
53+
node->next = list->head;
54+
55+
if (list->head == NULL) {
56+
list->head = node;
57+
list->tail = node;
58+
} else {
59+
list->head = node;
60+
}
61+
62+
list->size++;
63+
}
64+
65+
void* slinkedlist_pop_front(SLinkedList* list) {
66+
if (list->head == NULL) return NULL;
67+
68+
void* value = list->head->value;
69+
SLinkedListNode* next = list->head->next;
70+
71+
free(list->head);
72+
73+
list->head = next;
74+
75+
if (list->head == NULL) list->tail = NULL;
76+
77+
list->size--;
78+
79+
return value;
80+
}
81+
82+
void slinkedlist_push_back(SLinkedList* list, const void* item) {
83+
SLinkedListNode* node = malloc(sizeof(SLinkedListNode));
84+
if (node == NULL) return;
85+
86+
node->value = (void*)item;
87+
node->next = NULL;
88+
89+
if (list->tail == NULL) {
90+
list->head = node;
91+
list->tail = node;
92+
} else {
93+
list->tail->next = node;
94+
list->tail = node;
95+
}
96+
97+
list->size++;
98+
}
99+
100+
void* slinkedlist_pop_back(SLinkedList* list) {
101+
if (list->tail == NULL) return NULL;
102+
103+
void* value = list->tail->value;
104+
if (list->head == list->tail) {
105+
free(list->head);
106+
list->head = NULL;
107+
list->tail = NULL;
108+
list->size--;
109+
return value;
110+
}
111+
112+
SLinkedListNode* prev = list->head;
113+
while (prev->next != list->tail) {
114+
prev = prev->next;
115+
}
116+
117+
free(list->tail);
118+
list->tail = prev;
119+
list->tail->next = NULL;
120+
list->size--;
121+
122+
return value;
123+
}
124+
125+
void* slinkedlist_front(SLinkedList* list) {
126+
if (list->head == NULL) return NULL;
127+
128+
return list->head->value;
129+
}
130+
131+
void* slinkedlist_back(SLinkedList* list) {
132+
if (list->tail == NULL) return NULL;
133+
134+
return list->tail->value;
135+
}
136+
137+
void slinkedlist_insert(SLinkedList* list, int index, const void* item) {
138+
if (index < 0 || index > list->size) return;
139+
140+
if (index == 0) {
141+
slinkedlist_push_front(list, item);
142+
} else if (index == list->size) {
143+
slinkedlist_push_back(list, item);
144+
} else {
145+
SLinkedListNode* prev = list->head;
146+
int i = 0;
147+
while (prev != NULL && i < index - 1) {
148+
prev = prev->next;
149+
i++;
150+
}
151+
152+
if (prev == NULL) return;
153+
154+
SLinkedListNode* node = malloc(sizeof(SLinkedListNode));
155+
if (node == NULL) return;
156+
157+
node->value = (void*)item;
158+
node->next = prev->next;
159+
prev->next = node;
160+
161+
if (node->next == NULL) list->tail = node;
162+
163+
list->size++;
164+
}
165+
}
166+
167+
void slinkedlist_erase(SLinkedList* list, int index) {
168+
if (index < 0 || index >= list->size) return;
169+
170+
if (index == 0) {
171+
slinkedlist_pop_front(list);
172+
} else if (index == list->size - 1) {
173+
slinkedlist_pop_back(list);
174+
} else {
175+
SLinkedListNode* prev = list->head;
176+
int i = 0;
177+
while (prev != NULL && i < index - 1) {
178+
prev = prev->next;
179+
i++;
180+
}
181+
182+
if (prev == NULL) return;
183+
184+
SLinkedListNode* target = prev->next;
185+
if (target == NULL) return;
186+
187+
prev->next = target->next;
188+
if (target->next == NULL) list->tail = prev;
189+
190+
free(target);
191+
list->size--;
192+
}
193+
}
194+
195+
void* slinkedlist_value_n_from_end(SLinkedList* list, int n) {
196+
if (n < 0 || n >= list->size) return NULL;
197+
198+
SLinkedListNode* first = list->head;
199+
int i = 0;
200+
while (first != NULL && i < list->size - n - 1) {
201+
first = first->next;
202+
i++;
203+
}
204+
205+
if (first == NULL) return NULL;
206+
207+
return first->value;
208+
}
209+
210+
void slinkedlist_reverse(SLinkedList* list) {
211+
if (list->head == NULL || list->head->next == NULL) {
212+
return;
213+
}
214+
215+
SLinkedListNode* new_tail = list->head;
216+
SLinkedListNode* prev = NULL;
217+
SLinkedListNode* current = list->head;
218+
SLinkedListNode* next = NULL;
219+
220+
while (current != NULL) {
221+
next = current->next;
222+
current->next = prev;
223+
prev = current;
224+
current = next;
225+
}
226+
227+
list->head = prev;
228+
list->tail = new_tail;
229+
}
230+
231+
void slinkedlist_remove_value(SLinkedList* list, const void* value) {
232+
SLinkedListNode* prev = NULL;
233+
SLinkedListNode* current = list->head;
234+
while (current != NULL && current->value != value) {
235+
prev = current;
236+
current = current->next;
237+
}
238+
239+
if (current == NULL) return;
240+
241+
if (prev == NULL) {
242+
slinkedlist_pop_front(list);
243+
} else {
244+
prev->next = current->next;
245+
if (current->next == NULL) list->tail = prev;
246+
free(current);
247+
list->size--;
248+
}
249+
}
250+
251+
void slinkedlist_free(SLinkedList* list) {
252+
SLinkedListNode* current = list->head;
253+
while (current != NULL) {
254+
SLinkedListNode* next = current->next;
255+
free(current);
256+
current = next;
257+
}
258+
free(list);
259+
}

c/tests/BUILD.bazel

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,12 @@ cc_test(
1717
"@googletest//:gtest_main",
1818
],
1919
)
20+
21+
cc_test(
22+
name = "slinkedlist_test",
23+
srcs = ["slinkedlist_test.cc"],
24+
deps = [
25+
"//c/src/linkedlist:slinkedlist",
26+
"@googletest//:gtest_main",
27+
],
28+
)

0 commit comments

Comments
 (0)