An open API service indexing awesome lists of open source software.

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++

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 one

This 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)`