1
Name:
Anonymous
2011-12-12 20:01
In consideration of modern architectures and memory layout, are linked data structures ever worth it?
It feels like an dynamic array is a lot better in every sense.
55
Name:
Anonymous
2011-12-13 19:25
I wrote a small test, everything is one giant file so FrozenVoid should be happy. I wrote it so that the structures are easily extensible with O(1) peek and size operations and O(n) contains.
#include <stdlib.h>
#include <stddef.h>
typedef int data_type;
#define DATA_TYPE_NULL ((data_type) -1)
#define DATA_TYPE_DEALLOCATOR(data)
/* array_stack */
#define REALLOC_SIZE(oldsize) (2*(oldsize) + 1)
typedef struct {
data_type * base;
data_type * read;
data_type * end;
} array_stack;
static inline array_stack *
array_stack_init (array_stack * self)
{
self->base = NULL;
self->read = self->base;
self->end = self->base + 0;
return self;
}
static inline array_stack *
array_stack_clear (array_stack * self)
{
while (self->base < self->read--)
DATA_TYPE_DEALLOCATOR(*self->read);
free(self->base);
return array_stack_init(self);
}
static inline data_type
array_stack_push (array_stack * self, data_type elem)
{
if (self->read == self->end) {
ptrdiff_t read_offset = (self->read - self->base);
ptrdiff_t size = (self->end - self->base);
self->base = realloc(self->base, REALLOC_SIZE(size) * sizeof(data_type));
self->read = self->base + read_offset;
self->end = self->base + REALLOC_SIZE(size);
if (self->base == NULL)
return DATA_TYPE_NULL;
}
return *self->read++ = elem;
}
static inline data_type
array_stack_pop (array_stack * self)
{
if (self->read == self->base)
return DATA_TYPE_NULL;
return *--self->read;
}
/* linked stack */
typedef struct {
struct linked_stack_node {
struct linked_stack_node * prev;
data_type elem;
} * head;
int size;
} linked_stack;
static inline struct linked_stack_node *
__linked_stack_node_init (struct linked_stack_node * self, data_type elem)
{
self->prev = NULL;
self->elem = elem;
return self;
}
static inline struct linked_stack_node *
__linked_stack_node_alloc (data_type elem)
{
struct linked_stack_node * node;
node = malloc(sizeof(node));
if (node == NULL)
return NULL;
return __linked_stack_node_init(node, elem);
}
static inline void
__linked_stack_node_destroy (struct linked_stack_node * self)
{
DATA_TYPE_DEALLOCATOR(self->elem);
free(self);
}
static inline linked_stack *
linked_stack_init (linked_stack * self)
{
self->head = NULL;
self->size = 0;
return self;
}
static inline linked_stack *
linked_stack_clear (linked_stack * self)
{
struct linked_stack_node * node;
while (self->head != NULL) {
node = self->head;
self->head = self->head->prev;
__linked_stack_node_destroy(node);
}
return linked_stack_init(self);
}
static inline data_type
linked_stack_push (linked_stack * self, data_type elem)
{
struct linked_stack_node * node;
node = __linked_stack_node_alloc(elem);
if (node == NULL)
return DATA_TYPE_NULL;
node->prev = self->head;
self->head = node;
self->size += 1;
return elem;
}
static inline data_type
linked_stack_pop (linked_stack * self)
{
struct linked_stack_node * node;
data_type elem;
if (self->head == NULL)
return DATA_TYPE_NULL;
elem = self->head->elem;
node = self->head;
self->head = self->head->prev;
__linked_stack_node_destroy(node);
self->size -= 1;
return elem;
}
/* testing */
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#define NUMBER_OF_OPERATIONS 100000000
static struct timeval time_buffer_start;
static struct timeval time_buffer_end;
static struct timeval time_buffer_res;
static time_t seed = 0;
static void
array_stack_test (void)
{
int i;
array_stack s;
array_stack_init(&s);
srand(seed);
for (i = 0; i < NUMBER_OF_OPERATIONS; i++)
rand() & 1 ? array_stack_push(&s, i) : array_stack_pop(&s);
array_stack_clear(&s);
}
static void
linked_stack_test (void)
{
int i;
linked_stack s;
linked_stack_init(&s);
srand(seed);
for (i = 0; i < NUMBER_OF_OPERATIONS; i++)
rand() & 1 ? linked_stack_push(&s, i) : linked_stack_pop(&s);
linked_stack_clear(&s);
}
#define test(implementation) \
do { \
gettimeofday(&time_buffer_start, NULL); \
implementation##_test(); \
gettimeofday(&time_buffer_end, NULL); \
\
timersub(&time_buffer_end, \
&time_buffer_start, \
&time_buffer_res); \
\
printf(#implementation ": %lu.%06lu seconds\n", \
time_buffer_res.tv_sec, \
time_buffer_res.tv_usec); \
} while (0)
int main (void)
{
seed = time(NULL);
test(array_stack);
test(linked_stack);
return 0;
}