aboutsummaryrefslogtreecommitdiff
path: root/sem3/algo/mm2/linked/llist.c
blob: e4166ee75837065ddca1deadfc4660fb416f6062 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include "llist.h"

#include <string.h>
#include <stdio.h>

#define OUT_OFF_BOUNDS 2

void llist_init(llist_t *list)
{
    /* Zero out structure */
    list->head = list->root = NULL;

    list->len = 0;
}

void llist_append(llist_t *list, int val)
{
    /* Insert node after HEAD */
    list->head = node_insert(list->head, val);

    /* Check if was list is empty */
    if (list->len == 0) {
        /* Set root */
        list->root = list->head;
    }

    /* Increase count */
    list->len++;
}

node_t *llist_get_node(llist_t *list, unsigned int index)
{
    /* Check if we have it */
    if (index >= list->len) {
        return NULL;
    }

    /* Find the best way to go down the list */
    int direc = index > (list->len / 2) ? -1 : 1;

    /* Setup start location */
    int pos = direc > 0 ? 0 : list->len - 1;
    node_t *node = direc > 0 ? list->root : list->head;

    /* Go to index */
    while (pos != index) {
        /* TODO kinda risky, we trust our math and len */
        node = direc > 0 ? node->next : node->prev;

        pos += direc;
    }

    return node;
}

int llist_get(llist_t *list, unsigned int index)
{
    /* Get node */
    node_t *node = llist_get_node(list, index);
    if (node == NULL) {
        /* Yes i know this is stupid */
        return -1;
    }

    /* Return value */
    return node->val;
}

int llist_pop(llist_t *list, unsigned int index)
{
    /* Get node */
    node_t *node = llist_get_node(list, index);
    if (node == NULL) {
        /* Yes i know this is stupid */
        return -1;
    }

    /* Update root and head if we delete it */
    if (node == list->root) {
        list->root = node->next;
    }
    if (node == list->head) {
        list->head = node->prev;
    }

    /* Keep len up to date */
    list->len--;

    /* Delete stuff */
    return node_pop(node);
}