Added more list functions and examples
This commit is contained in:
1 parent
964ececf0b
commit
bc46ace086
5 files changed
+438
-6
No files matched your search
@@ -43,6 +43,7 @@ A contiguous growable array. Elements can be added and removed from both ends of
|
||||
### <span id="list_function_index"> Defined Functions </span>
|
||||
|
||||
* [\_new()](#list_new)
|
||||
* [\_new\_from()](#list_new_from)
|
||||
* [\_clear()](#list_clear)
|
||||
* [\_free()](#list_free)
|
||||
* [\_push\_front()](#list_push_front)
|
||||
@@ -53,12 +54,17 @@ A contiguous growable array. Elements can be added and removed from both ends of
|
||||
* [\_pop\_back()](#list_pop_back)
|
||||
* [\_push\_if()](#list_push_if)
|
||||
* [\_pop\_if()](#list_pop_if)
|
||||
* [\_prepend()](#list_prepend)
|
||||
* [\_insert()](#list_insert)
|
||||
* [\_append()](#list_append)
|
||||
* [\_remove()](#list_remove)
|
||||
* [\_front()](#list_front)
|
||||
* [\_get()](#list_get)
|
||||
* [\_back()](#list_back)
|
||||
* [\_empty()](#list_empty)
|
||||
* [\_full()](#list_full)
|
||||
* [\_count()](#list_count)
|
||||
* [\_fits()](#list_fits)
|
||||
* [\_capacity()](#list_capacity)
|
||||
* [\_iter\_new()](#list_iter_new)
|
||||
* [\_iter\_start()](#list_iter_start)
|
||||
@@ -89,6 +95,28 @@ Allocates and returns a new list with an internal capacity of `size`. If allocat
|
||||
|
||||
* O(1)
|
||||
|
||||
## [<span id="list_new_from"> \_new\_from() </span>](#list_function_index)
|
||||
|
||||
Allocates and returns a new list from an already existing array. The list internal buffer's size will match the size of the given array.
|
||||
|
||||
#### Declaration
|
||||
|
||||
> `FMOD SNAME *PFX##_new_from(V *elements, size_t size);`
|
||||
|
||||
#### Parameters
|
||||
|
||||
1. `V *elements` - Array of elements to be added to the list.
|
||||
2. `size_t size` - Size of the array of elements.
|
||||
|
||||
#### Returns
|
||||
|
||||
1. `SNAME *` - A pointer to a heap allocated list with the given elements.
|
||||
2. `NULL` - If allocation fails, or if size equals `0`.
|
||||
|
||||
#### Complexity
|
||||
|
||||
* O(1)
|
||||
|
||||
## [<span id="list_clear"> \_clear() </span>](#list_function_index)
|
||||
|
||||
Removes all elements in the list but does not frees the list structure.
|
||||
@@ -303,6 +331,99 @@ Removes an element from a given index if the condition evaluates to true.
|
||||
|
||||
* O(n)
|
||||
|
||||
## [<span id="list_prepend"> \_prepend() </span>](#list_function_index)
|
||||
|
||||
Adds to the front of the list an array of elements with a given size.
|
||||
|
||||
#### Declaration
|
||||
|
||||
> `FMOD bool PFX##_prepend(SNAME *_list_, V *elements, size_t size);`
|
||||
|
||||
#### Parameters
|
||||
|
||||
1. `SNAME *_list_` - Target list.
|
||||
2. `V *elements` - Array of elements to be added.
|
||||
3. `size_t size` - The size of the array of elements.
|
||||
|
||||
#### Returns
|
||||
|
||||
1. `true` - If the elements were successfully added to the list.
|
||||
2. `false` - If buffer reallocation failed, or if `size` parameter equals `0`.
|
||||
|
||||
#### Complexity
|
||||
|
||||
* O(n<sup>2</sup>)
|
||||
|
||||
## [<span id="list_insert"> \_insert() </span>](#list_function_index)
|
||||
|
||||
Adds to the specified list an array of elements with a given size to a specific index. The first element of the array of elements will be positioned at that index.
|
||||
|
||||
#### Declaration
|
||||
|
||||
> `FMOD bool PFX##_insert(SNAME *_list_, V *elements, size_t size, size_t index);`
|
||||
|
||||
#### Parameters
|
||||
|
||||
1. `SNAME *_list_` - Target list.
|
||||
2. `V *elements` - Array of elements to be added.
|
||||
3. `size_t size` - The size of the array of elements.
|
||||
4. `size_t index` - Where the array of elements are to be inserted.
|
||||
|
||||
#### Returns
|
||||
|
||||
1. `true` - If the elements were successfully added to the list.
|
||||
2. `false` - If buffer reallocation failed, if `size` parameter equals `0`, or if the index is greater than `count`.
|
||||
|
||||
#### Complexity
|
||||
|
||||
* O(n<sup>2</sup>)
|
||||
|
||||
## [<span id="list_append"> \_append() </span>](#list_function_index)
|
||||
|
||||
Adds to the back of the list an array of elements with a given size.
|
||||
|
||||
#### Declaration
|
||||
|
||||
> `FMOD bool PFX##_append(SNAME *_list_, V *elements, size_t size);`
|
||||
|
||||
#### Parameters
|
||||
|
||||
1. `SNAME *_list_` - Target list.
|
||||
2. `V *elements` - Array of elements to be added.
|
||||
3. `size_t size` - The size of the array of elements.
|
||||
|
||||
#### Returns
|
||||
|
||||
1. `true` - If the elements were successfully added to the list.
|
||||
2. `false` - If buffer reallocation failed, or if `size` parameter equals `0`.
|
||||
|
||||
#### Complexity
|
||||
|
||||
* O(n)
|
||||
|
||||
## [<span id="list_remove"> \_remove() </span>](#list_function_index)
|
||||
|
||||
Removes a sequence of elements starting at `from` up to `to`. Both indexes are inclusive.
|
||||
|
||||
#### Declaration
|
||||
|
||||
> `FMOD bool PFX##_remove(SNAME *_list_, size_t from, size_t to);`
|
||||
|
||||
#### Parameters
|
||||
|
||||
1. `SNAME *_list_` - Target list.
|
||||
2. `V *elements` - Array of elements to be added.
|
||||
3. `size_t size` - The size of the array of elements.
|
||||
|
||||
#### Returns
|
||||
|
||||
1. `true` - If the elements were successfully removed from the list.
|
||||
2. `false` - If `from` is greater than `to`, or if `to` is greater than or equal to `count`.
|
||||
|
||||
#### Complexity
|
||||
|
||||
* O(n)
|
||||
|
||||
## [<span id="list_front"> \_front() </span>](#list_function_index)
|
||||
|
||||
Returns the first element (located at index `0`) if the list is not empty.
|
||||
@@ -430,6 +551,28 @@ Returns the amount of elements in the list.
|
||||
|
||||
* O(1)
|
||||
|
||||
## [<span id="list_fits"> \_fits() </span>](#list_function_index)
|
||||
|
||||
Returns true if a given size fits into the list internal buffer without triggering it to be reallocated.
|
||||
|
||||
#### Declaration
|
||||
|
||||
> `FMOD bool PFX##_fits(SNAME *_list_, size_t size);`
|
||||
|
||||
#### Parameters
|
||||
|
||||
1. `SNAME *_list_` - Target list.
|
||||
2. `size_t size` - Size of anything.
|
||||
|
||||
#### Returns
|
||||
|
||||
1. `true` - If the given size fits into the internal buffer of the list.
|
||||
2. `false` - If the given size doesn't fit into the internal buffer of the list.
|
||||
|
||||
#### Complexity
|
||||
|
||||
* O(1)
|
||||
|
||||
## [<span id="list_capacity"> \_capacity() </span>](#list_function_index)
|
||||
|
||||
Returns the internal buffer's current capacity.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# List examples
|
||||
|
||||
Currently none
|
||||
* list.c - Example of using a list and its iterator.
|
||||
* string.c - How to treat a list as a mutable string.
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* list.c
|
||||
*
|
||||
* Creation Date: 08/04/2019
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "list.h"
|
||||
|
||||
LIST_GENERATE(l, list, /* FMOD */, int)
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
// Create a list with internal capacity of 100
|
||||
list *my_list = l_new(100);
|
||||
|
||||
// - push_front (index: 0) [Complexity: O(N)]
|
||||
// - push (index: give) [Complexity: O(N)*]
|
||||
// - push_back (index: count) [Complexity: O(1)]
|
||||
//
|
||||
// - pop_front (index: 0) [Complexity: O(N)]
|
||||
// - pop (index: given) [Complexity: O(N)*]
|
||||
// - push_back (index: count - 1) [Complexity: O(1)]
|
||||
//
|
||||
// *average
|
||||
//
|
||||
// Average list Input/Output: O(N)
|
||||
|
||||
for (int i = 0; i < 200; i++)
|
||||
{
|
||||
// Add elements to the list
|
||||
l_push_back(my_list, i);
|
||||
}
|
||||
|
||||
// Erase all values from the list
|
||||
l_clear(my_list);
|
||||
|
||||
// Now that list is empty, add only even numbers
|
||||
for (int i = 0; i < 200; i++)
|
||||
{
|
||||
// Add even numbers to a given index. In this case they are being added
|
||||
// to the end of the list (count index == push_back). With a condition
|
||||
// of being even (i % 2 == 0)
|
||||
l_push_if(my_list, i, l_count(my_list), i % 2 == 0);
|
||||
}
|
||||
|
||||
// Iterator
|
||||
list_iter iter;
|
||||
int result, sum = 0;
|
||||
size_t index;
|
||||
|
||||
// Iterate over each element starting from the start (iter_new positions
|
||||
// the iterator to the start of the list) until the end of the list.
|
||||
for (l_iter_new(&iter, my_list); !l_iter_end(&iter);)
|
||||
{
|
||||
// Here index corresponds to the position of the result relative to all
|
||||
// other elements in the iteration. It is only a coincidence that the
|
||||
// index here is the same as the result's position in the list.
|
||||
l_iter_next(&iter, &result, &index);
|
||||
|
||||
// Do whatever you want with result and index, e.g.
|
||||
sum += result * index;
|
||||
}
|
||||
|
||||
// Release resources
|
||||
l_free(my_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* string.c
|
||||
*
|
||||
* Creation Date: 08/04/2019
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "list.h"
|
||||
|
||||
LIST_GENERATE(str, string, /* FMOD */, char)
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
// How to treat a list as a mutable string without \0 at the end
|
||||
char *example1 = "Lorem ipsum";
|
||||
char *example2 = "dolor sit amet";
|
||||
char *example3 = "consectetur";
|
||||
|
||||
string *my_str = str_new_from(example2, strlen(example2));
|
||||
|
||||
// Add a single character to the front of the list
|
||||
str_push_front(my_str, ' ');
|
||||
|
||||
// Add a sequence of characters to the front of the list
|
||||
str_prepend(my_str, example1, strlen(example1));
|
||||
|
||||
// Add a charater to the back of the list
|
||||
str_push_back(my_str, ' ');
|
||||
|
||||
// Add a sequence of characters to the back of the list
|
||||
str_append(my_str, example3, strlen(example3));
|
||||
|
||||
// Iterate through each letter and print it
|
||||
string_iter iter;
|
||||
str_iter_new(&iter, my_str);
|
||||
size_t index;
|
||||
char result;
|
||||
|
||||
for (str_iter_tostart(&iter); !str_iter_end(&iter);)
|
||||
{
|
||||
str_iter_next(&iter, &result, &index);
|
||||
putchar(result);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
// You can also print it reversed
|
||||
for (str_iter_toend(&iter); !str_iter_start(&iter);)
|
||||
{
|
||||
str_iter_prev(&iter, &result, &index);
|
||||
putchar(result);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
// Now remove the first letter supposing we don't know where it starts
|
||||
for (size_t i = 0; i < str_count(my_str); i++)
|
||||
{
|
||||
// Find first white space
|
||||
if (str_get(my_str, i) == ' ')
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we know where the first word is, remove it, including the
|
||||
// extra space. [from, to] are inclusive.
|
||||
str_remove(my_str, 0, index);
|
||||
|
||||
// Print it once again
|
||||
for (str_iter_tostart(&iter); !str_iter_end(&iter);)
|
||||
{
|
||||
str_iter_next(&iter, &result, &index);
|
||||
putchar(result);
|
||||
}
|
||||
|
||||
printf("\nString length: %lu\n", str_count(my_str));
|
||||
|
||||
return 0;
|
||||
}
|
||||
+136
-5
@@ -61,6 +61,7 @@
|
||||
typedef struct SNAME##_iter_s SNAME##_iter; \
|
||||
\
|
||||
FMOD SNAME *PFX##_new(size_t size); \
|
||||
FMOD SNAME *PFX##_new_from(V *elements, size_t size); \
|
||||
FMOD void PFX##_clear(SNAME *_list_); \
|
||||
FMOD void PFX##_free(SNAME *_list_); \
|
||||
FMOD bool PFX##_push_front(SNAME *_list_, V element); \
|
||||
@@ -71,12 +72,17 @@
|
||||
FMOD bool PFX##_pop_back(SNAME *_list_); \
|
||||
FMOD bool PFX##_push_if(SNAME *_list_, V element, size_t index, bool condition); \
|
||||
FMOD bool PFX##_pop_if(SNAME *_list_, size_t index, bool condition); \
|
||||
FMOD bool PFX##_prepend(SNAME *_list_, V *elements, size_t size); \
|
||||
FMOD bool PFX##_insert(SNAME *_list_, V *elements, size_t size, size_t index); \
|
||||
FMOD bool PFX##_append(SNAME *_list_, V *elements, size_t size); \
|
||||
FMOD bool PFX##_remove(SNAME *_list_, size_t from, size_t to); \
|
||||
FMOD V PFX##_front(SNAME *_list_); \
|
||||
FMOD V PFX##_get(SNAME *_list_, size_t index); \
|
||||
FMOD V PFX##_back(SNAME *_list_); \
|
||||
FMOD bool PFX##_empty(SNAME *_list_); \
|
||||
FMOD bool PFX##_full(SNAME *_list_); \
|
||||
FMOD size_t PFX##_count(SNAME *_list_); \
|
||||
FMOD bool PFX##_fits(SNAME *_list_, size_t size); \
|
||||
FMOD size_t PFX##_capacity(SNAME *_list_); \
|
||||
\
|
||||
FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target); \
|
||||
@@ -90,7 +96,7 @@
|
||||
/* SOURCE ********************************************************************/
|
||||
#define LIST_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
|
||||
\
|
||||
FMOD bool PFX##_grow(SNAME *_list_); \
|
||||
FMOD bool PFX##_grow(SNAME *_list_, size_t required); \
|
||||
\
|
||||
FMOD SNAME *PFX##_new(size_t size) \
|
||||
{ \
|
||||
@@ -123,6 +129,28 @@
|
||||
return _list_; \
|
||||
} \
|
||||
\
|
||||
FMOD SNAME *PFX##_new_from(V *elements, size_t size) \
|
||||
{ \
|
||||
if (size == 0) \
|
||||
return NULL; \
|
||||
\
|
||||
SNAME *_list_ = PFX##_new(size); \
|
||||
\
|
||||
if (!_list_) \
|
||||
return NULL; \
|
||||
\
|
||||
for (size_t i = 0; i < size; i++) \
|
||||
{ \
|
||||
if (!PFX##_push_back(_list_, elements[i])) \
|
||||
{ \
|
||||
PFX##_free(_list_); \
|
||||
return NULL; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return _list_; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_clear(SNAME *_list_) \
|
||||
{ \
|
||||
memset(_list_->buffer, 0, sizeof(V) * _list_->capacity); \
|
||||
@@ -140,7 +168,7 @@
|
||||
{ \
|
||||
if (PFX##_full(_list_)) \
|
||||
{ \
|
||||
if (!PFX##_grow(_list_)) \
|
||||
if (!PFX##_grow(_list_, _list_->count + 1)) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
@@ -175,7 +203,7 @@
|
||||
\
|
||||
if (PFX##_full(_list_)) \
|
||||
{ \
|
||||
if (!PFX##_grow(_list_)) \
|
||||
if (!PFX##_grow(_list_, _list_->count + 1)) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
@@ -195,7 +223,7 @@
|
||||
{ \
|
||||
if (PFX##_full(_list_)) \
|
||||
{ \
|
||||
if (!PFX##_grow(_list_)) \
|
||||
if (!PFX##_grow(_list_, _list_->count + 1)) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
@@ -272,6 +300,101 @@
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_prepend(SNAME *_list_, V *elements, size_t size) \
|
||||
{ \
|
||||
if (size == 0) \
|
||||
return false; \
|
||||
\
|
||||
if (!PFX##_fits(_list_, size)) \
|
||||
{ \
|
||||
if (!PFX##_grow(_list_, _list_->count + size)) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
for (size_t i = _list_->count; i > 0; i--) \
|
||||
{ \
|
||||
_list_->buffer[i + size - 1] = _list_->buffer[i - 1]; \
|
||||
} \
|
||||
\
|
||||
for (size_t i = 0; i < size; i++) \
|
||||
{ \
|
||||
_list_->buffer[i] = elements[i]; \
|
||||
} \
|
||||
\
|
||||
_list_->count += size; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_insert(SNAME *_list_, V *elements, size_t size, size_t index) \
|
||||
{ \
|
||||
if (size == 0 || index > _list_->count) \
|
||||
return false; \
|
||||
\
|
||||
if (index == 0) \
|
||||
return PFX##_prepend(_list_, elements, size); \
|
||||
else if (index == _list_->count) \
|
||||
return PFX##_append(_list_, elements, size); \
|
||||
else \
|
||||
{ \
|
||||
if (!PFX##_fits(_list_, size)) \
|
||||
{ \
|
||||
if (!PFX##_grow(_list_, _list_->count + size)) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
for (size_t i = _list_->count; i >= index; i--) \
|
||||
{ \
|
||||
_list_->buffer[i + size] = _list_->buffer[i]; \
|
||||
} \
|
||||
\
|
||||
for (size_t i = index, j = 0; j < size; i++, j++) \
|
||||
{ \
|
||||
_list_->buffer[i] = elements[j]; \
|
||||
} \
|
||||
\
|
||||
_list_->count += size; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_append(SNAME *_list_, V *elements, size_t size) \
|
||||
{ \
|
||||
if (size == 0) \
|
||||
return false; \
|
||||
\
|
||||
if (!PFX##_fits(_list_, size)) \
|
||||
{ \
|
||||
if (!PFX##_grow(_list_, _list_->count + size)) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
for (size_t i = _list_->count, j = 0; j < size; i++, j++) \
|
||||
{ \
|
||||
_list_->buffer[i] = elements[j]; \
|
||||
} \
|
||||
\
|
||||
_list_->count += size; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_remove(SNAME *_list_, size_t from, size_t to) \
|
||||
{ \
|
||||
if (from > to || to >= _list_->count) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = from, j = to + 1; i < _list_->count; i++, j++) \
|
||||
{ \
|
||||
_list_->buffer[i] = _list_->buffer[j]; \
|
||||
} \
|
||||
\
|
||||
_list_->count -= to - from + 1; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD V PFX##_front(SNAME *_list_) \
|
||||
{ \
|
||||
if (PFX##_empty(_list_)) \
|
||||
@@ -314,15 +437,23 @@
|
||||
return _list_->count; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_fits(SNAME *_list_, size_t size) \
|
||||
{ \
|
||||
return _list_->count + size <= _list_->capacity; \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_capacity(SNAME *_list_) \
|
||||
{ \
|
||||
return _list_->capacity; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_grow(SNAME *_list_) \
|
||||
FMOD bool PFX##_grow(SNAME *_list_, size_t required) \
|
||||
{ \
|
||||
size_t new_capacity = _list_->capacity * 2; \
|
||||
\
|
||||
if (new_capacity < required) \
|
||||
new_capacity = required; \
|
||||
\
|
||||
V *new_buffer = realloc(_list_->buffer, sizeof(V) * new_capacity); \
|
||||
\
|
||||
if (!new_buffer) \
|
||||
|
||||
Reference in new issue
Block a user