https://github.com/janinawibker/alt-stdlib
An alternative to the standard library data structures and some other utilities for C++
https://github.com/janinawibker/alt-stdlib
alternative c cpp standard-library
Last synced: 2 months ago
JSON representation
An alternative to the standard library data structures and some other utilities for C++
- Host: GitHub
- URL: https://github.com/janinawibker/alt-stdlib
- Owner: JaninaWibker
- License: mit
- Created: 2021-05-08T21:55:54.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2025-03-14T17:18:31.000Z (3 months ago)
- Last Synced: 2025-03-14T18:37:18.967Z (3 months ago)
- Topics: alternative, c, cpp, standard-library
- Language: C++
- Homepage:
- Size: 71.3 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# alternative stdlib
> **WIP**
This is intended to be a replacement for some of the standard library data structures as well as (maybe) other utilities (such as optionals).
This project is heavily inspired by [stb](https://github.com/nothings/stb), [serenityOS](https://github.com/SerenityOS/serenity), my operating systems and my algorithms class at university.
Included data structures:
- [unbounded array](#unbounded-array)
- [hashtable](#hashtable)
- [hashmap](#hashmap)
- [minheap](#minheap)
- [unionfind](#unionfind)## building and running tests
Unit tests exist (for almost all data structures) and can be compiled using the `./build.sh`-file.
This is only a minimal wrapper around G++ (or rather `$CXX`), nothing complicated is done there.> There will be a lot of warnings because the coding style is more c-like than normal c++, I'll maybe fix this in the future.
The resulting `test` executable can be run and will print the output of the unit tests, the first failing test halts the program.
## components
### (unbounded) array
An unbounded array implementation with a growth factor of 2.
> *TODO*
### hashtable
A hashtable implementation based on a unique technique taking inspiration from both doubly-linked lists and linear probing.
> The hashtable uses doubly-linked lists for saving values with hashes that clash but instead of allocating these elements randomly using malloc this is done manually.
> The twist is that all elements are allocated inside of the hashtable itself using a freelist which also spans across the hashtable containing all currently free "slots"
> Whenever a slot needs to be used it is unhooked from the freelist; whenever a slot is free'd it is returned to the freelist**hashtableinit**: Create a new hashtable
Create a new hashtable using an initial capacity and a given hash function
Use as follows (`[x]` marks things to replace):
```c
auto hash = []([your type] x) -> int { [your hash implementation] };
auto ht = hashtableinit<[your type], decltype(hash)>([initial capacity], hash);
````hashtable hashtableinit(size_t capacity, H hash)`
**hashtablefree**: Free hashtable
`void hashtablefree(hashtable* ht)`
**::resize**: Resize the hashtable
This can be called manually but will also be called internally whenever needed.
It might be useful to call this if you already know that you'll add a specific amount of items soon.`void hashtable::resize(size_t new_size)`
**::dbg**: Print debug information about the state of the hashtable
`void hashtable::dbg()`
**::dbg**: Print debug information about the state of the hashtable
Includes a name which will be displayed alongside the debug information to tell debug logs apart.
`void hashtable::dbg(char* name)`
**::ins**: Insert something into the hashtable
If the element already exists it will be overwritten.
Handles hash collisions.`T hashtable::ins(T value)`
**::del**: Delete something from the hashtable
Returns wether or not the action was successful.
Handles hash collisions.`bool hashtable::del(T value)`
**::fnd**: Search for a value in the hashtable
`T hashtable::fnd(T value)`
**::fnd**: Search for a value in the hashtable by predicate
> **Warning**: Expensive action
`T hashtable::fnd(F&& pred)`
**::has**: Check if the hashtable contains a value
`bool hashtable::has(T value)`
**::has**: Check if the hashtable contains a value by predicate lambda
> **Warning**: Expensive action
`bool hashtable::has(F&& pred)`
**::each**: Iterate through all elements
Iterate through all elements of the hashtable and call fn for every one of them> **Warning**: Expensive action
`void hashtable::each(F&& fn)`
**::clr**: Clear out all elements of the hashtable
> **Warning**: Expensive action
`void hashtable::clr()`
**::filter**: Filter hashtable elements
Takes a predicate lambda which decides which elements can stay and which get removed.
> **Warning**: Expensive action
`void hashtable::filter(F&& pred)`
**::cat**: Concatenate hashtables
Combine another hashtable with the current oneThis goes through all elements of the other hashtable and adds the elements to the current one.
> **Warning**: Expensive action
`void hashtable::cat(hashtable other)`
### hashmap
A hashmap implementation based on the hashtable implementation inspired by doubly-linked lists, linear probing and freelists.
**hashmapinit**: Create hashmap
`hashmap hashmapinit(size_t capacity, H hash)`
**hashmapfree**: Free hashmap
`void hashmapfree(hashmap* hm)`
**::resize**: Resize the hashmap
This can be called manually but will also be called internally whenever needed.
It might be useful to call this if you already know that you'll add a specific amount of items soon.`void hashmap::resize(size_t new_size)`
**::dbg**: Print debug information about the state of the hashmap
`void hashmap::dbg()`
**::dbg**: Print debug information about the state of the hashmap
Includes a name which will be displayed alongside the debug information to tell debug logs apart.
`void hashmap::dbg(char* name)`
**::ins**: Insert something into the hashmap
If an element with the same key already exists it will be overwritten.
Handles hash collisions.`V hashmap::ins(K key, V value)`
**::del**: Delete something from the hashmap by key
Returns the value of the deleted element.
Handles hash collisions.`V hashmap::del(K key)`
**::fnd**: Search for a value in the hashmap (by key)
`V hashmap::fnd(K key)`
**::fnd**: Search for a value in the hashmap by predicate (called with both key and value)
> **Warning**: Expensive action
`template V hashmap::fnd(F&& pred)`
**::has**: Check if the hashmap contains a value (by key)
`bool hashmap::has(K key)`
**::has**: Check if the hashmap contains a value by predicate lambda (called with both key and value)
> **Warning**: Expensive action
`template bool hashmap::has(F&& pred)`
**::each**: Iterate through all elements of the hashmap and call fn for every one of them (with both key and value)
> **Warning**: Expensive action
`template void hashmap::each(F&& fn)`
**::clr**: Clear out all elements of the hashmap
> **Warning**: Expensive action
`void hashmap::clr()`
**::filter**: Filter hashmap elements.
Takes a predicate lambda which decides which elements can stay and which get removed (called with both key and value).
> **Warning**: Expensive action
`template void hashmap::filter(F&& pred)`
**::cat**: Merge another hashmap with the current one
This goes through all elements of the other hashmap and adds the elements to the current one.
> **Warning**: Expensive action
`void hashmap::cat(hashmap other)`
### minheap
A minheap implementation.
**minheapinit**: Create a new minheap using an initial capacity.
`template static minheap minheapinit(size_t capacity)`
**minheapfree**: Free minheap
`template void minheapfree(minheap heap)`
**::resize**: Resize the minheap
This can be called manually but will also be called internally whenever needed.
It might be useful to call this if you already know that you'll add a specific amount of items soon.`template void minheap::resize(size_t new_size)`
**::dbg**: Print debug information about the state of the minheap
`template void minheap::dbg()`
**::dbg**: Print debug information about the state of the minheap
Includes a name which will be displayed alongside the debug information to tell debug logs apart.
`template void minheap::dbg(char* name)`
**::insert**: Insert something into the minheap
O(log n)
`template void minheap::insert(T el)`
**::sift_up**: Correct minheap invariant from the bottom up
Mostly used internally.
It is assumed that the minheap invariant holds true everywhere except at m_data[i]`template void minheap::sift_up(size_t i)`
**::sift_down**: Correct minheap invariant from the top down
Mostly used internally.
It is assumed that the minheap invariant holds true everywhere except at L_CHILD(i) and R_CHILD(i).`template void minheap::sift_down(size_t i)`
**::min**: Get the minimum element of the minheap
O(1)
`template T minheap::min()`
**::delete_min**: Delete minimum element of minheap and return it
O(log n)
`template T minheap::delete_min()`
### unionfind
A union-find implementation using union-by-rank and path-compression.
**unionfindinit**: Create a new unionfind data structure with a given size
> **Warning**: The size cannot be changed later on.
**unionfindfree**:: Free unionfind
**::_union**: Join two partitions together
Can be called using any element of a partition, doesn't need to be the root element / representative element of the partition.
Returns wether or not the two partitions did get joined together (only 'fails' if they already are the same)
`bool unionfind::_union(size_t a, size_t b)`
**::find**: Find the partition (identified by a representative element) of the given element
Time complexity: O(α(n)) amortized with α being the inverse Ackerman function (inverse of A(n, n)).
This can effectively be ignored as it's value is below 5 for almost all practical values of n.`size_t unionfind::find(size_t a)`
**::non_destructive_find**: Like find but does not mutate the data structure
> **Warning**: only useful for testing, performance is bad.
`size_t unionfind::non_destructive_find(size_t a)`
**::dbg**: Print debug information about the state of the union find structure
`void unionfind::dbg()`
**::dbg**: Print debug information about the state of the union find structure
Includes a name which will be displayed alongside the debug information to tell debug logs apart.
`void unionfind::dbg(char* name)`