Skip to content

Commit

Permalink
Linked list (#630)
Browse files Browse the repository at this point in the history
* Update tests

* Add list_count() example implementation

* Correct return types

* Add list_delete() example implementation

* [CI] Format C code

* [CI] Format C code

* Return void for functions that add list items

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
wolf99 and github-actions[bot] authored Mar 6, 2021
1 parent 78caeef commit 5943ba6
Show file tree
Hide file tree
Showing 6 changed files with 307 additions and 89 deletions.
51 changes: 43 additions & 8 deletions exercises/practice/linked-list/.meta/example.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ struct list_node {
struct list_node *prev, *next;
ll_data_t data;
};

struct list {
struct list_node *first, *last;
};
Expand Down Expand Up @@ -33,24 +34,33 @@ struct list *list_create(void)
return list;
}

bool list_is_empty(const struct list * list)
size_t list_count(const struct list * list)
{
assert(list);
return list->first == NULL;

size_t count = 0;
struct list_node *node = list->first;

while (node) {
++count;
node = node->next;
}

return count;
}

bool list_push(struct list * list, ll_data_t data)
void list_push(struct list *list, ll_data_t data)
{
assert(list);
struct list_node *node = list_node_create(list->last, NULL, data);
if (!node)
return NULL;
return;
list->last = node;
if (!list->first)
list->first = node;
else
node->prev->next = node;
return node;
return;
}

ll_data_t list_pop(struct list * list)
Expand All @@ -68,18 +78,18 @@ ll_data_t list_pop(struct list * list)
return result;
}

bool list_unshift(struct list * list, ll_data_t data)
void list_unshift(struct list *list, ll_data_t data)
{
assert(list);
struct list_node *node = list_node_create(NULL, list->first, data);
if (!node)
return NULL;
return;
list->first = node;
if (!list->last)
list->last = node;
else
node->next->prev = node;
return node;
return;
}

ll_data_t list_shift(struct list * list)
Expand All @@ -97,6 +107,31 @@ ll_data_t list_shift(struct list * list)
return result;
}

void list_delete(struct list *list, ll_data_t data)
{
assert(list);

struct list_node *node = list->first;

while (node) {
if (node->data == data) {
if (node == list->first)
list->first = node->next;
else
node->prev->next = node->next;

if (node == list->last)
list->last = node->prev;
else
node->next->prev = node->prev;

free(node);
return;
}
node = node->next;
}
}

void list_destroy(struct list *list)
{
if (!list)
Expand Down
23 changes: 13 additions & 10 deletions exercises/practice/linked-list/.meta/example.h
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
#ifndef LINKED_LIST_H
#define LINKED_LIST_H

#include <stdbool.h>
#include <stddef.h>

typedef int ll_data_t;
struct list;

// constructs a new (empty) list
struct list *list_create(void);

// checks if the list is empty
bool list_is_empty(const struct list *list);
// counts the items on a list
size_t list_count(const struct list *list);

// inserts item at back of list
bool list_push(struct list *list, ll_data_t item_data);
// inserts item at back of a list
void list_push(struct list *list, ll_data_t item_data);

// removes item from back of list
// removes item from back of a list
ll_data_t list_pop(struct list *list);

// inserts item at front of list
bool list_unshift(struct list *list, ll_data_t item_data);
// inserts item at front of a list
void list_unshift(struct list *list, ll_data_t item_data);

// removes item from front of list
// removes item from front of a list
ll_data_t list_shift(struct list *list);

// destroys the entire list
// deletes a node that holds the matching data
void list_delete(struct list *list, ll_data_t data);

// destroys an entire list
// list will be a dangling pointer after calling this method on it
void list_destroy(struct list *list);

Expand Down
58 changes: 58 additions & 0 deletions exercises/practice/linked-list/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
[canonical-tests]

# pop gets element from the list
"7f7e3987-b954-41b8-8084-99beca08752c" = true

# push/pop respectively add/remove at the end of the list
"c3f67e5d-cfa2-4c3e-a18f-7ce999c3c885" = true

# shift gets an element from the list
"00ea24ce-4f5c-4432-abb4-cc6e85462657" = true

# shift gets first element from the list
"37962ee0-3324-4a29-b588-5a4c861e6564" = true

# unshift adds element at start of the list
"30a3586b-e9dc-43fb-9a73-2770cec2c718" = true

# pop, push, shift, and unshift can be used in any order
"042f71e4-a8a7-4cf0-8953-7e4f3a21c42d" = true

# count an empty list
"88f65c0c-4532-4093-8295-2384fb2f37df" = true

# count a list with items
"fc055689-5cbe-4cd9-b994-02e2abbb40a5" = true

# count is correct after mutation
"8272cef5-130d-40ea-b7f6-5ffd0790d650" = true

# popping to empty doesn't break the list
"229b8f7a-bd8a-4798-b64f-0dc0bb356d95" = true

# shifting to empty doesn't break the list
"4e1948b4-514e-424b-a3cf-a1ebbfa2d1ad" = true

# deletes the only element
"e8f7c600-d597-4f79-949d-8ad8bae895a6" = true

# deletes the element with the specified value from the list
"fd65e422-51f3-45c0-9fd0-c33da638f89b" = true

# deletes the element with the specified value from the list, re-assigns tail
"59db191a-b17f-4ab7-9c5c-60711ec1d013" = true

# deletes the element with the specified value from the list, re-assigns head
"58242222-5d39-415b-951d-8128247f8993" = true

# deletes the first of two elements
"ee3729ee-3405-4bd2-9bad-de0d4aa5d647" = true

# deletes the second of two elements
"47e3b3b4-b82c-4c23-8c1a-ceb9b17cb9fb" = true

# delete does not modify the list if the element is not found
"7b420958-f285-4922-b8f9-10d9dcab5179" = true

# deletes only the first occurrence
"7e04828f-6082-44e3-a059-201c63252a76" = true
1 change: 1 addition & 0 deletions exercises/practice/linked-list/linked_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ struct list_node {
struct list_node *prev, *next;
ll_data_t data;
};

struct list {
struct list_node *first, *last;
};
23 changes: 13 additions & 10 deletions exercises/practice/linked-list/linked_list.h
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
#ifndef LINKED_LIST_H
#define LINKED_LIST_H

#include <stdbool.h>
#include <stddef.h>

typedef int ll_data_t;
struct list;

// constructs a new (empty) list
struct list *list_create(void);

// checks if the list is empty
bool list_is_empty(const struct list *list);
// counts the items on a list
size_t list_count(const struct list *list);

// inserts item at back of list
bool list_push(struct list *list, ll_data_t item_data);
// inserts item at back of a list
void list_push(struct list *list, ll_data_t item_data);

// removes item from back of list
// removes item from back of a list
ll_data_t list_pop(struct list *list);

// inserts item at front of list
bool list_unshift(struct list *list, ll_data_t item_data);
// inserts item at front of a list
void list_unshift(struct list *list, ll_data_t item_data);

// removes item from front of list
// removes item from front of a list
ll_data_t list_shift(struct list *list);

// destroys the entire list
// deletes a node that holds the matching data
void list_delete(struct list *list, ll_data_t data);

// destroys an entire list
// list will be a dangling pointer after calling this method on it
void list_destroy(struct list *list);

Expand Down
Loading

0 comments on commit 5943ba6

Please sign in to comment.