Work on collections
This commit is contained in:
parent
ad459c3b85
commit
8660ff8bad
4 changed files with 184 additions and 125 deletions
49
collections/collections.h
Normal file
49
collections/collections.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
// vim: set et sw=4 ts=4 tw=80:
|
||||
#ifndef COLLECTIONS_H_INCLUDED
|
||||
#define COLLECTIONS_H_INCLUDED
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Doubly linked list
|
||||
*/
|
||||
|
||||
typedef struct dl_node {
|
||||
void* element;
|
||||
struct dl_node* prev;
|
||||
struct dl_node* next;
|
||||
} dl_node_t;
|
||||
|
||||
typedef struct dl_list {
|
||||
dl_node_t* first;
|
||||
} dl_list_t;
|
||||
|
||||
extern size_t dl_list_length(const dl_list_t* self);
|
||||
extern dl_node_t* dl_list_ith(const dl_list_t* self, const size_t position);
|
||||
extern dl_node_t* dl_list_ith_or_last(const dl_list_t* self,
|
||||
const size_t position, size_t* returned);
|
||||
|
||||
extern inline dl_node_t* dl_list_alloc_node(void* element);
|
||||
extern inline void dl_list_free_node(dl_node_t* node);
|
||||
|
||||
extern inline void dl_list_init(dl_list_t* list);
|
||||
extern inline void dl_list_destroy(dl_list_t* list);
|
||||
|
||||
extern size_t dl_list_copy_slice(const dl_list_t* self, dl_list_t* destination,
|
||||
const size_t from, const size_t to);
|
||||
|
||||
extern int dl_list_insert(dl_list_t* self, const size_t position,
|
||||
dl_node_t* node);
|
||||
extern dl_node_t* dl_list_remove(dl_list_t* self, const size_t position);
|
||||
|
||||
typedef struct vector {
|
||||
void** elements;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
} vector_t;
|
||||
|
||||
extern void vector_init(vector_t* self, const size_t initial_capacity);
|
||||
|
||||
#endif
|
115
collections/list.c
Normal file
115
collections/list.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
// vim: set ts=4 sw=4 tw=80 et:
|
||||
#include "./collections.h"
|
||||
|
||||
size_t dl_list_length(const dl_list_t* self) {
|
||||
size_t length = 0;
|
||||
dl_node_t* i = self->first;
|
||||
|
||||
while (i != NULL) {
|
||||
length++;
|
||||
i = i->next;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
dl_node_t* dl_list_ith(const dl_list_t* self, const size_t position) {
|
||||
size_t found;
|
||||
dl_node_t* elem = dl_list_ith_or_last(self, position, &found);
|
||||
return found != position ? NULL : elem;
|
||||
}
|
||||
|
||||
dl_node_t* dl_list_ith_or_last(const dl_list_t* self, const size_t position,
|
||||
size_t* returned) {
|
||||
dl_node_t* to_reach = self->first;
|
||||
size_t i;
|
||||
for (i = 0; i < position && to_reach->next != NULL; i++) {
|
||||
to_reach = to_reach->next;
|
||||
}
|
||||
*returned = i;
|
||||
return to_reach;
|
||||
}
|
||||
|
||||
inline dl_node_t* dl_list_alloc_node(void* element) {
|
||||
dl_node_t* node = malloc(sizeof(node));
|
||||
node->element = element;
|
||||
node->next = NULL;
|
||||
node->prev = NULL;
|
||||
}
|
||||
|
||||
inline void dl_list_free_node(dl_node_t* node) {
|
||||
if (node->element != NULL) {
|
||||
free(node->element);
|
||||
}
|
||||
free(node);
|
||||
}
|
||||
|
||||
inline void dl_list_init(dl_list_t* self) {
|
||||
self->first = NULL;
|
||||
}
|
||||
|
||||
inline void dl_list_destroy(dl_list_t* self) {
|
||||
while(self->first != NULL) {
|
||||
free(dl_list_remove(self, 0));
|
||||
}
|
||||
}
|
||||
|
||||
size_t dl_list_copy_slice(const dl_list_t* self, dl_list_t* destination,
|
||||
const size_t from, const size_t to) {
|
||||
if (from >= to) {
|
||||
return 0;
|
||||
}
|
||||
dl_list_destroy(destination);
|
||||
size_t start, i;
|
||||
dl_node_t* to_copy = dl_list_ith_or_last(self, to, &start);
|
||||
if (to_copy == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(i = start; i > from; i--) {
|
||||
dl_node_t* copied = malloc(sizeof(dl_node_t));
|
||||
memcpy(copied, self, sizeof(dl_node_t));
|
||||
dl_list_insert(destination, 0, copied);
|
||||
}
|
||||
|
||||
return start - from;
|
||||
}
|
||||
|
||||
int dl_list_insert(dl_list_t* self, const size_t position, dl_node_t* node) {
|
||||
if (position == 0) {
|
||||
node->next = self->first;
|
||||
node->prev = NULL;
|
||||
self->first = node;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dl_node_t* to_reach = dl_list_ith(self, position - 1);
|
||||
|
||||
if (to_reach == NULL) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
to_reach->next->prev = node;
|
||||
node->next = to_reach->next;
|
||||
node->prev = to_reach;
|
||||
to_reach->next = node;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dl_node_t* dl_list_remove(dl_list_t* self, const size_t position) {
|
||||
if(position == 0) {
|
||||
dl_node_t* to_remove = self->first;
|
||||
self->first = to_remove->next;
|
||||
return to_remove;
|
||||
}
|
||||
|
||||
dl_node_t* to_reach = dl_list_ith(self, position - 1);
|
||||
if (to_reach == NULL || to_reach->next == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dl_node_t* to_remove = to_reach->next;
|
||||
to_reach->next = to_reach->next->next;
|
||||
to_reach->next->prev = to_reach;
|
||||
return to_remove;
|
||||
}
|
20
collections/stack.c
Normal file
20
collections/stack.c
Normal file
|
@ -0,0 +1,20 @@
|
|||
// vim: set et sw=4 ts=4 tw=80:
|
||||
#include "./collections.h"
|
||||
|
||||
static inline void vector_expand(vector_t* self) {
|
||||
if (self->size >= self->capacity) {
|
||||
self->capacity *= 2;
|
||||
self->elements = realloc(self->elements,
|
||||
sizeof(void*) * self->capacity);
|
||||
}
|
||||
}
|
||||
|
||||
void vector_init(vector_t* self, const size_t initial_capacity) {
|
||||
self->elements = (void**) malloc(sizeof(void*) * initial_capacity);
|
||||
self->size = 0;
|
||||
self->capacity = initial_capacity;
|
||||
}
|
||||
|
||||
void vector_insert(vector_t* self, const size_t position, const void* element) {
|
||||
vector_expand(self);
|
||||
}
|
125
list.c
125
list.c
|
@ -1,125 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define TYPE int
|
||||
//A list is one of:
|
||||
// - (make-note element next)
|
||||
// - '() -> NULL
|
||||
|
||||
struct node {
|
||||
TYPE element;
|
||||
struct node* prev;
|
||||
struct node* next;
|
||||
};
|
||||
|
||||
typedef struct node node_t;
|
||||
|
||||
typedef struct {
|
||||
node* first;
|
||||
} list_t;
|
||||
|
||||
size_t list_length(const list_t* self) {
|
||||
size_t length = 0;
|
||||
node_t* i = self->first;
|
||||
|
||||
while (i != NULL) {
|
||||
length++;
|
||||
i = self->next;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
node_t* list_ith(const list_t* self, const size_t position) {
|
||||
size_t found;
|
||||
node_t* elem = list_ith_or_last(self, position, &found);
|
||||
return found != position ? NULL : elem;
|
||||
}
|
||||
|
||||
node_t* list_ith_or_last(const list_t* self, const size_t position,
|
||||
const size_t* returned) {
|
||||
node_t* to_reach = self->first;
|
||||
size_t i;
|
||||
for (i = 0; i < position && to_reach->next != NULL; i++) {
|
||||
to_reach = to_reach->next;
|
||||
}
|
||||
*returned = i;
|
||||
return to_reach;
|
||||
}
|
||||
|
||||
node_t* make_node(TYPE element) {
|
||||
node_t* node = malloc(sizeof(node));
|
||||
node->element = element;
|
||||
node->next = NULL;
|
||||
node->prev = NULL;
|
||||
}
|
||||
|
||||
void free_list(const list_t* list) {
|
||||
while(list->first != NULL) {
|
||||
free(list_remove(self, 0));
|
||||
}
|
||||
}
|
||||
|
||||
size_t list_copy_slice(const list_t* self, const list_t* destination,
|
||||
const size_t from, const size_t to) {
|
||||
if (from >= to) {
|
||||
return 0;
|
||||
}
|
||||
free_list(destination);
|
||||
size_t start, i;
|
||||
node_t* to_copy = list_ith_or_last(self, to, &start);
|
||||
if (to_copy == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(i = start; i > from; i--) {
|
||||
node_t* copied = malloc(sizeof(node_t));
|
||||
memcpy(copied, src, sizeof(node_t));
|
||||
list_insert(destination, 0, copied);
|
||||
}
|
||||
|
||||
return start - from;
|
||||
}
|
||||
|
||||
int list_insert(const list_t* self, const size_t position, const node_t* node) {
|
||||
if (self->first == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (position == 0) {
|
||||
node->next = self->first;
|
||||
node->prev = NULL;
|
||||
self->first = node;
|
||||
return 0;
|
||||
}
|
||||
|
||||
node_t* to_reach = list_ith(self, position - 1);
|
||||
|
||||
if (to_reach == NULL) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
to_reach->next->prev = node;
|
||||
node->next = to_reach->next;
|
||||
node->prev = to_reach;
|
||||
to_reach->next = node;
|
||||
return 0;
|
||||
}
|
||||
|
||||
node_t* list_remove(const list_t* self, const size_t position) {
|
||||
if(position == 0) {
|
||||
node_t* to_remove = self->first;
|
||||
self->first = to_remove->next;
|
||||
return to_remove;
|
||||
}
|
||||
|
||||
node_t* to_reach = list_ith(self, position - 1);
|
||||
if (to_reach == NULL || to_reach->next == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node_t* to_remove = to_reach->next;
|
||||
to_reach->next = to_reach->next->next;
|
||||
to_reach->next->prev = to_reach;
|
||||
return to_remove;
|
||||
}
|
Reference in a new issue