Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Linked vs Dynamic Array

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.

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;
}

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List