working on linked-lists (going to remove some functions)
parent
4c23dbaf59
commit
b257e21a15
|
@ -10,13 +10,10 @@
|
|||
#ifndef DATA_TYPES_h
|
||||
#define DATA_TYPES_h
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "data-types/linked-list.h"
|
||||
|
||||
#define bool _Bool
|
||||
#define true ((bool)1)
|
||||
#define false ((bool)0)
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* linked list
|
||||
*
|
||||
* Notes:
|
||||
* - When 'position' is used, it referes to the position of the node in the
|
||||
* list, not the node's offset. E.g. the node with position == 1 is the
|
||||
* first node in the list.
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
|
@ -13,13 +18,22 @@
|
|||
#include "linked-list.h"
|
||||
|
||||
|
||||
// convenience macros (undefined later)
|
||||
#define _NEW_STRUCT_POINTER(type, name) \
|
||||
struct type * name = (struct type *) malloc(sizeof(struct type))
|
||||
// local macros (undefined later)
|
||||
#define _NEW_POINTER(type, name) type * name = (type *) malloc(sizeof(type))
|
||||
#define _list_t linked_list_t
|
||||
#define _node_t linked_list_node_t
|
||||
#define _data_t LINKED_LIST_DATA_TYPE
|
||||
|
||||
|
||||
struct linked_list * linked_list_new(void) {
|
||||
_NEW_STRUCT_POINTER(linked_list, list);
|
||||
/*
|
||||
* new()
|
||||
*
|
||||
* Returns
|
||||
* - success: a pointer to a new linked list
|
||||
* - failure: NULL
|
||||
*/
|
||||
_list_t * linked_list_new(void) {
|
||||
_NEW_POINTER(_list_t, list);
|
||||
if (!list) return NULL;
|
||||
|
||||
list->head = NULL;
|
||||
|
@ -29,11 +43,15 @@ struct linked_list * linked_list_new(void) {
|
|||
return list;
|
||||
}
|
||||
|
||||
struct linked_list * linked_list_add_head(
|
||||
struct linked_list * list,
|
||||
LINKED_LIST_DATA_TYPE data ) {
|
||||
|
||||
_NEW_STRUCT_POINTER(linked_list_node, node);
|
||||
/*
|
||||
* add_head()
|
||||
*
|
||||
* Returns
|
||||
* - success: the pointer to the list that was passed
|
||||
* - failure: NULL
|
||||
*/
|
||||
_list_t * linked_list_add_head(_list_t * list, _data_t data) {
|
||||
_NEW_POINTER(_node_t, node);
|
||||
if (!node) return NULL;
|
||||
|
||||
node->data = data;
|
||||
|
@ -46,11 +64,15 @@ struct linked_list * linked_list_add_head(
|
|||
return list;
|
||||
}
|
||||
|
||||
struct linked_list * linked_list_add_tail(
|
||||
struct linked_list * list,
|
||||
LINKED_LIST_DATA_TYPE data ) {
|
||||
|
||||
_NEW_STRUCT_POINTER(linked_list_node, node);
|
||||
/*
|
||||
* add_tail()
|
||||
*
|
||||
* Returns
|
||||
* - success: the pointer to the list that was passed
|
||||
* - failure: NULL
|
||||
*/
|
||||
_list_t * linked_list_add_tail(_list_t * list, _data_t data) {
|
||||
_NEW_POINTER(_node_t, node);
|
||||
if (!node) return NULL;
|
||||
|
||||
node->data = data;
|
||||
|
@ -65,11 +87,18 @@ struct linked_list * linked_list_add_tail(
|
|||
return list;
|
||||
}
|
||||
|
||||
LINKED_LIST_DATA_TYPE linked_list_pop_head(struct linked_list * list) {
|
||||
/*
|
||||
* pop_head()
|
||||
*
|
||||
* Returns
|
||||
* - success: the data element of the first node of the list
|
||||
* - failure: (_data_t) 0
|
||||
*/
|
||||
_data_t linked_list_pop_head(_list_t * list) {
|
||||
if (list->number_of_elements == 0)
|
||||
return 0;
|
||||
return (_data_t) 0;
|
||||
|
||||
struct linked_list_node node = {
|
||||
_node_t node = {
|
||||
.data = list->head->data,
|
||||
.next = list->head->next
|
||||
};
|
||||
|
@ -87,15 +116,24 @@ LINKED_LIST_DATA_TYPE linked_list_pop_head(struct linked_list * list) {
|
|||
return node.data;
|
||||
}
|
||||
|
||||
// note: this function is inefficient for singly linked lists: it has O(n) time
|
||||
// instead of O(1) time like most of the other functions. but it's not needed
|
||||
// for implementing stacks or queues, so i don't anticipate it being used all
|
||||
// that much. it's here for completeness.
|
||||
LINKED_LIST_DATA_TYPE linked_list_pop_tail(struct linked_list * list) {
|
||||
/*
|
||||
* pop_tail()
|
||||
*
|
||||
* Returns
|
||||
* - success: the data element of the last node of the list
|
||||
* - failure: (_data_t) 0
|
||||
*
|
||||
* Note
|
||||
* - This function is inefficient for singly linked lists: it has O(n) time
|
||||
* instead of O(1) time like most of the other functions. But it's not
|
||||
* needed for implementing stacks or queues, so i don't anticipate it being
|
||||
* used all that much. It's here for completeness.
|
||||
*/
|
||||
_data_t linked_list_pop_tail(_list_t * list) {
|
||||
if (list->number_of_elements == 0)
|
||||
return 0;
|
||||
return (_data_t) 0;
|
||||
|
||||
struct linked_list_node node = {
|
||||
_node_t node = {
|
||||
.data = list->tail->data,
|
||||
.next = list->tail->next
|
||||
};
|
||||
|
@ -116,22 +154,62 @@ LINKED_LIST_DATA_TYPE linked_list_pop_tail(struct linked_list * list) {
|
|||
return node.data;
|
||||
}
|
||||
|
||||
LINKED_LIST_DATA_TYPE linked_list_read(
|
||||
struct linked_list * list,
|
||||
uint8_t position ) {
|
||||
|
||||
/*
|
||||
* read()
|
||||
*
|
||||
* Returns
|
||||
* - success: the data element at the given position
|
||||
* - failure: (_data_t) 0
|
||||
*/
|
||||
_data_t linked_list_read(_list_t * list, uint8_t position) {
|
||||
if (position < 1 || position > (list->number_of_elements))
|
||||
return 0;
|
||||
return (_data_t) 0;
|
||||
|
||||
struct linked_list_node * node = list->head;
|
||||
_node_t * node = list->head;
|
||||
for (uint8_t i=1; i<position; i++)
|
||||
node = node->next;
|
||||
|
||||
return node->data;
|
||||
}
|
||||
|
||||
struct linked_list * linked_list_copy(struct linked_list * list) {
|
||||
_NEW_STRUCT_POINTER(linked_list, copy);
|
||||
/*
|
||||
* insert()
|
||||
* - Insert a new node containing the given data such that it occupies the
|
||||
* given position in the list.
|
||||
*
|
||||
* Returns
|
||||
* - success: the pointer to the list that was passed
|
||||
* - failure: NULL
|
||||
*/
|
||||
_list_t * linked_list_insert(_list_t * list, _data_t data, uint8_t position) {
|
||||
if (position < 1 || position > (list->number_of_elements)+1)
|
||||
return NULL;
|
||||
|
||||
_NEW_POINTER(_node_t, new);
|
||||
if (!new) return NULL;
|
||||
|
||||
_node_t * prev = list->head;
|
||||
for (uint8_t i=0; i<position; i++)
|
||||
prev = prev->next;
|
||||
|
||||
new->data = data;
|
||||
new->next = prev->next;
|
||||
prev->next = new;
|
||||
|
||||
list->number_of_elements++;
|
||||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
* copy()
|
||||
*
|
||||
* Returns
|
||||
* - success: a new pointer to a copy of the list who's pointer was passed
|
||||
* - failure: NULL
|
||||
*/
|
||||
_list_t * linked_list_copy(_list_t * list) {
|
||||
_NEW_POINTER(_list_t, copy);
|
||||
if (!copy) return NULL;
|
||||
|
||||
for (uint8_t i=1; i<=(list->number_of_elements); i++)
|
||||
linked_list_add_tail(copy, linked_list_read(list, i));
|
||||
|
@ -139,18 +217,102 @@ struct linked_list * linked_list_copy(struct linked_list * list) {
|
|||
return copy;
|
||||
}
|
||||
|
||||
|
||||
// note: this is implemented inefficiently (using ...pop_head(), which does
|
||||
// extra work). but that makes things simpler, and i don't anticipate using it
|
||||
// all that often.
|
||||
void linked_list_free(struct linked_list * list) {
|
||||
/*
|
||||
* free()
|
||||
* - Free the memory allocated to all the nodes, then free the memory allocated
|
||||
* to the list.
|
||||
*
|
||||
* Note
|
||||
* - This is implemented inefficiently (using pop_head(), which does extra
|
||||
* work). But that makes things simpler, and i don't anticipate using it all
|
||||
* that often.
|
||||
*/
|
||||
void linked_list_free(_list_t * list) {
|
||||
while ((list->number_of_elements) > 0)
|
||||
linked_list_pop_head(list);
|
||||
|
||||
free(list);
|
||||
}
|
||||
|
||||
/*
|
||||
* slice_copy()
|
||||
* - Return the (copied) sublist
|
||||
*
|
||||
* Arguments
|
||||
* - start_position:
|
||||
* - the position of the first element to include in the slice
|
||||
* - or '0' for the beginning of the list
|
||||
* - end_position:
|
||||
* - the position of the last element to include in the slice
|
||||
* - or '0' for the end of the list
|
||||
*
|
||||
* Returns
|
||||
* - success: a copy of the portion of the list indicated
|
||||
* - failure: NULL
|
||||
*/
|
||||
_list_t * linked_list_slice_copy (
|
||||
_list_t * list,
|
||||
uint8_t start_position,
|
||||
uint8_t end_position ) {
|
||||
|
||||
// convenience macros (undefined here)
|
||||
#undef _NEW_STRUCT_POINTER
|
||||
if ( start_position > end_position ||
|
||||
end_position > (list->number_of_elements) )
|
||||
return NULL;
|
||||
|
||||
if (start_position == 0)
|
||||
start_position = 1;
|
||||
if (end_position == 0)
|
||||
end_position = list->number_of_elements;
|
||||
|
||||
_NEW_POINTER(_list_t, shallow_slice);
|
||||
if (!shallow_slice) return NULL;
|
||||
|
||||
shallow_slice->number_of_elements = end_position - start_position + 1;
|
||||
shallow_slice->head = list->head;
|
||||
for (uint8_t i=1; i<start_position; i++)
|
||||
shallow_slice->head = shallow_slice->head->next;
|
||||
shallow_slice->tail = shallow_slice->head;
|
||||
for (uint8_t i=1; i<(shallow_slice->number_of_elements); i++)
|
||||
shallow_slice->tail = shallow_slice->tail->next;
|
||||
|
||||
return linked_list_copy(shallow_slice);
|
||||
}
|
||||
|
||||
/*
|
||||
* slice()
|
||||
*/
|
||||
_list_t * linked_list_slice (
|
||||
_list_t * list,
|
||||
uint8_t start_position,
|
||||
uint8_t end_position ) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/*
|
||||
* remove()
|
||||
*/
|
||||
_list_t * linked_list_remove(_list_t * list, uint8_t position) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/*
|
||||
* find_first()
|
||||
*/
|
||||
uint8_t linked_list_find_first(_list_t * list, _data_t data) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/*
|
||||
* reverse()
|
||||
*/
|
||||
_list_t * linked_list_reverse(_list_t * list) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
// local macros (undefined here)
|
||||
#undef _NEW_POINTER
|
||||
#undef _list_t
|
||||
#undef _node_t
|
||||
#undef _data_t
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* linked list : exports
|
||||
*
|
||||
* Includes aliases to treat the list as a queue or stack.
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
|
@ -15,7 +13,7 @@
|
|||
#include "lib/data-types.h"
|
||||
|
||||
|
||||
// default list data type
|
||||
// default data type for the list
|
||||
#ifndef LINKED_LIST_DATA_TYPE
|
||||
#define LINKED_LIST_DATA_TYPE uint8_t
|
||||
#endif
|
||||
|
@ -27,60 +25,42 @@
|
|||
struct linked_list_node * next;
|
||||
};
|
||||
|
||||
struct linked_list{
|
||||
struct linked_list {
|
||||
uint8_t number_of_elements;
|
||||
struct linked_list_node * head;
|
||||
struct linked_list_node * tail;
|
||||
};
|
||||
|
||||
// typedefs
|
||||
typedef struct linked_list linked_list_t;
|
||||
typedef struct linked_list_node linked_list_node_t;
|
||||
|
||||
// functions
|
||||
struct linked_list * linked_list_new(void);
|
||||
struct linked_list * linked_list_add_head(
|
||||
struct linked_list * list,
|
||||
LINKED_LIST_DATA_TYPE data );
|
||||
struct linked_list * linked_list_add_tail(
|
||||
struct linked_list * list,
|
||||
LINKED_LIST_DATA_TYPE data );
|
||||
LINKED_LIST_DATA_TYPE linked_list_pop_head(struct linked_list * list);
|
||||
LINKED_LIST_DATA_TYPE linked_list_pop_tail(struct linked_list * list);
|
||||
LINKED_LIST_DATA_TYPE linked_list_read(
|
||||
struct linked_list * list,
|
||||
uint8_t position );
|
||||
struct linked_list * linked_list_copy(struct linked_list * list);
|
||||
void linked_list_free(struct linked_list * list);
|
||||
|
||||
|
||||
// typedefs, for user code
|
||||
typedef struct linked_list * linked_list_t;
|
||||
typedef struct linked_list_node * linked_list_node_t;
|
||||
|
||||
// aliases, for user code
|
||||
#define list_t linked_list_t
|
||||
#define list_new linked_list_new
|
||||
#define list_push linked_list_add_head
|
||||
#define list_append linked_list_add_tail
|
||||
#define list_pop linked_list_pop_head
|
||||
#define list_pop_tail linked_list_pop_tail
|
||||
#define list_read linked_list_read
|
||||
#define list_copy linked_list_copy
|
||||
#define list_free linked_list_free
|
||||
|
||||
#define queue_t list_t
|
||||
#define queue_new list_new
|
||||
#define queue_append list_append
|
||||
#define queue_pop list_pop
|
||||
#define queue_read list_read
|
||||
#define queue_copy list_copy
|
||||
#define queue_free list_free
|
||||
|
||||
#define stack_t list_t
|
||||
#define stack_new list_new
|
||||
#define stack_push list_push
|
||||
#define stack_pop list_pop
|
||||
#define stack_read list_read
|
||||
#define stack_copy list_copy
|
||||
#define stack_free list_free
|
||||
#define _list_t linked_list_t
|
||||
#define _data_t LINKED_LIST_DATA_TYPE
|
||||
_list_t * linked_list_new (void);
|
||||
_list_t * linked_list_add_head (_list_t * list, _data_t data);
|
||||
_list_t * linked_list_add_tail (_list_t * list, _data_t data);
|
||||
_data_t linked_list_pop_head (_list_t * list);
|
||||
_data_t linked_list_pop_tail (_list_t * list);
|
||||
_data_t linked_list_read (_list_t * list, uint8_t position);
|
||||
_list_t * linked_list_insert ( _list_t * list,
|
||||
uint8_t position,
|
||||
_data_t data );
|
||||
_list_t * linked_list_copy (_list_t * list);
|
||||
void linked_list_free (_list_t * list);
|
||||
|
||||
_list_t * linked_list_slice_copy ( _list_t * list,
|
||||
uint8_t start_position,
|
||||
uint8_t end_position );
|
||||
_list_t * linked_list_slice ( _list_t * list,
|
||||
uint8_t start_position,
|
||||
uint8_t end_position );
|
||||
_list_t * linked_list_remove (_list_t * list, uint8_t position);
|
||||
uint8_t linked_list_find_first (_list_t * list, _data_t data);
|
||||
_list_t * linked_list_reverse (_list_t * list);
|
||||
#undef _list_t
|
||||
#undef _data_t
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue