Commit e2999c7
Changed files (3)
src/01/05/doubly_linked_list.c
@@ -1,7 +1,15 @@
#include "doubly_linked_list.h"
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+/**
+ * The equivalent of a constructor
+ * to initialize a new node in a doubly linked list.
+ *
+ * @param data The data to initialize the head node with.
+ * @return new Node bound to the data specified
+ */
Node *initialize(int data) {
Node *node = malloc(sizeof(Node));
node->data = data;
@@ -10,21 +18,43 @@ Node *initialize(int data) {
return node;
}
-Node *add(Node *head, int data) {
- Node *tail;
+/**
+ * Returns the tail of the list.
+ *
+ * @param head The head of the linked list
+ * @return The tail of the linked list
+ */
+Node *tail(Node *head) {
Node *tmp = head;
-
while (tmp) {
if (!tmp->next)
break;
tmp = tmp->next;
}
- tail = tmp;
- tail->next = initialize(data);
- tail->next->prev = tail;
- return tail->next;
+ return tmp;
+}
+
+/**
+ * Adds data to the tail of a doubly linked list.
+ *
+ * @param head The head of the doubly linked list
+ * @param data The data to append to the list
+ * @return Returns the new node.
+ */
+Node *add(Node *head, int data) {
+ Node *t = tail(head);
+ t->next = initialize(data);
+ t->next->prev = t;
+ return t->next;
}
+/**
+ * Returns a specific node in the list by index starting from 0.
+ *
+ * @param from The node to start scanning from.
+ * @param index The zero based index of the node to retrieve.
+ * @return The node at the specified index.
+ */
Node *get(Node *from, int index) {
if (!from || index < 0)
return NULL;
@@ -36,6 +66,12 @@ Node *get(Node *from, int index) {
return from;
}
+/**
+ * Returns the number of items in the linked list.
+ *
+ * @param head The head of the linked list
+ * @return The number of items in the list.
+ */
static int size(Node *head) {
int i = 0;
for (Node *tmp = head; tmp && tmp != NULL; tmp = tmp->next)
@@ -43,6 +79,12 @@ static int size(Node *head) {
return i;
}
+/**
+ * Assigns the next pointer of a node.
+ *
+ * @param self The node struct to alter.
+ * @param other The other node to point to.
+ */
static void assign_next(Node *self, Node *other) {
if (self)
self->next = other;
@@ -51,6 +93,12 @@ static void assign_next(Node *self, Node *other) {
other->prev = self;
}
+/**
+ * Assigns the previous pointer of a node.
+ *
+ * @param self The node struct to alter.
+ * @param other The other node to point to.
+ */
static void assign_prev(Node *self, Node *other) {
if (self)
self->prev = other;
@@ -59,6 +107,12 @@ static void assign_prev(Node *self, Node *other) {
other->next = self;
}
+/**
+ * Reverses a linked list.
+ *
+ * @param head The head of the linked list.
+ * @return The new head of the linked list.
+ */
Node *reverse(Node *head) {
Node *tmp = NULL;
Node *current = head;
@@ -72,24 +126,59 @@ Node *reverse(Node *head) {
return tmp ? tmp->prev : head;
}
-static void print(Node *node) {
+/**
+ * Generates a string representation of the Node usable for printing to stdout
+ *
+ * @param node The node to represent as a string
+ * @return The string that represents the node
+ */
+char *to_s(Node *node) {
+ const int buffer_size = 32;
+ char *buffer = malloc(buffer_size);
+ memset(buffer, buffer_size, '\0');
+
if (node->prev && node->next)
- printf("(%d<%d>%d)", node->prev->data, node->data, node->next->data);
+ snprintf(buffer, buffer_size, "(%d<%d>%d) ", node->prev->data, node->data, node->next->data);
else if (node->next)
- printf("(nil<%d>%d)", node->data, node->next->data);
+ snprintf(buffer, buffer_size, "(nil<%d>%d) ", node->data, node->next->data);
else
- printf("(%d<%d>nil)", node->prev->data, node->data);
+ snprintf(buffer, buffer_size, "(%d<%d>nil) ", node->prev->data, node->data);
+ return buffer;
}
-void inspect(Node *node) {
- if (!node)
- return;
+/**
+ * Prints the previous, data and next pointers for a node
+ *
+ * @param node The node to print
+ */
+static void print(Node *node) {
+ char *message = to_s(node);
+ printf("%s", message);
+ free(message);
+}
- printf("[ ");
- while (node) {
- print(node);
- printf(" ");
- node = node->next;
+/**
+ * Iterates through each node in a linked list.
+ *
+ * @param self The node to start iterating from.
+ * @param block The callback function to invoke on each node.
+ */
+void each(Node *self, Visitor block) {
+ Node *tmp = self;
+
+ while (tmp) {
+ block(tmp);
+ tmp = tmp->next;
}
+}
+
+/**
+ * Renders a visual output of a full linked list.
+ *
+ * @param node The head of the linked list
+ */
+void inspect(Node *node) {
+ printf("[ ");
+ each(node, &print);
printf("]\n");
}
src/01/05/doubly_linked_list.h
@@ -5,6 +5,7 @@ struct node {
};
typedef struct node Node;
+typedef void (Visitor)(Node *);
Node *initialize(int data);
Node *add(Node *head, int data);
src/01/05/README.md
@@ -41,8 +41,8 @@ clang build/doubly_linked_list.o build/main.o -o build/program
Before:
[ (nil<0>0) (0<0>1) (0<1>2) (1<2>3) (2<3>4) (3<4>5) (4<5>6) (5<6>7) (6<7>8) (7<8>9) (8<9>nil) ]
Reversing...
- After:
- [ (nil<9>8) (9<8>7) (8<7>6) (7<6>5) (6<5>4) (5<4>3) (4<3>2) (3<2>1) (2<1>0) (1<0>0) (0<0>nil) ]
+After:
+ [ (nil<9>8) (9<8>7) (8<7>6) (7<6>5) (6<5>4) (5<4>3) (4<3>2) (3<2>1) (2<1>0) (1<0>0) (0<0>nil) ]
```
## Discussion