{"id":24876049,"url":"https://github.com/dook97/cdict","last_synced_at":"2025-06-22T01:33:46.764Z","repository":{"id":144027483,"uuid":"537050778","full_name":"Dook97/cdict","owner":"Dook97","description":"A generic ordered dictionary C library using AVL trees","archived":false,"fork":false,"pushed_at":"2024-04-16T21:03:31.000Z","size":203,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-27T02:45:35.736Z","etag":null,"topics":["data-structures","dictionary","tree"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Dook97.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-09-15T13:54:59.000Z","updated_at":"2023-01-02T19:31:24.000Z","dependencies_parsed_at":"2025-02-01T08:19:47.840Z","dependency_job_id":"a98fb5f8-c8ea-4567-91e4-0b914c1e3b7c","html_url":"https://github.com/Dook97/cdict","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Dook97/cdict","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dook97%2Fcdict","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dook97%2Fcdict/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dook97%2Fcdict/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dook97%2Fcdict/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Dook97","download_url":"https://codeload.github.com/Dook97/cdict/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dook97%2Fcdict/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261220249,"owners_count":23126719,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["data-structures","dictionary","tree"],"created_at":"2025-02-01T08:19:43.224Z","updated_at":"2025-06-22T01:33:41.752Z","avatar_url":"https://github.com/Dook97.png","language":"C","readme":"# AVL Tree Based Generic Dictionary Library\n\n**WARNING:** I wrote this library as an assignment during my 2nd year of uni\nwhich is why *I discourage you* from using it for any practical applications.\n\n## Brief Intro\n\nThe AVL Tree data structure is a flavor of the binary search tree with the\nadded ability of self-balancing. All basic operations are therefore guaranteed\nto be $O(\\log n)$, where $n$ is the number of elements inside the structure.\n\nThis implementation is generic. However due to the C language being limited in\nthis regard I had to use some non-standard language extensions. The library\ncompiles with `GCC v12.2.0` and `clang v14.0.6`. Other options were not tested.\n\n## Note on memory management\n\nThis library **does not** provide any memory handling facilities - that is left\ncompletely up to the user.\n\nThis means more work when using the library but also greater flexibility and\npossibly efficiency, which is a very C-spirited tradeoff to make I think 🙂\n\n## Note on internals\n\nIt should be obvious, but the user is **NOT** expected to directly access data\ninside the internal structures used by the library. A hellish landscape ripe\nwith segfaults surely awaits any programmer foolish enough to take on such\nendeavour.\n\nA less stringent warning applies to the use of any of the `*_impl` functions.\nThese only exist as infrastructure for the generic macros and there is little\nreason to use them, besides I suppose a very minor performance gain, which\nhowever would be payed for in increased code complexity and the loss of genericity.\n\n## Supporting Structures\n\n### Define a dictionary item type\n\nThe type can contain any members you wish and it has to contain *(at least)*\none `avl_node_t` member. If you wish to embed the structure in more than one\nAVL tree it has to contain one `avl_node_t` member for each.\n\nAn example typedef which will be used throughout the rest of the documentation:\n\n```c\ntypedef struct {\n    TKey key;\n    TValue value;\n    avl_node_t dict_data;\n} dict_item_t;\n```\n\n### Define a comparator function on `dict_item_t`\n\nIts signature has to be `int (*)(const void *, const void *)`, its arguments\ncan be safely expected to be non-null and it has to return:\n\n```\n\u003c0 if item1 \u003c item2\n 0 if item1 = item2\n\u003e0 if item1 \u003e item2\n```\n\nAn example comparator function assuming `TKey` is a numeric type:\n\n```c\nint dict_compare(const void *item1, const void *item2) {\n    assert(item1 != NULL \u0026\u0026 item2 != NULL);\n    TKey key1 = ((dict_item_t *)item1)-\u003ekey, key2 = ((dict_item_t *)item2)-\u003ekey;\n    return (key1 == key2) ? 0\n                          : (key1 \u003c key2) ? -1 : 1;\n}\n```\n\n### Define a dictionary type\n\nSimply call:\n\n```c\nAVL_DEFINE_ROOT(dict_t, dict_item_t);\n```\n\nThe arguments to this macro are:\n\n1. type which will represent your dictionary\n2. type of a dictionary item\n\n`dict_t` is now the type of your dictionary.\n\nInternally this is just a typedef, so it's ok to use in header files.\n\n## Interface\n\nnote: Where applicable the library functions return *typed pointers*, not `void *`\nas might be expected. This has the nice consequence of the user not having to\nexplicitly typecast, like:\n\n```c\n// find an item in the dictionary and directly change its value\navl_find(\u0026dict, \u0026dummy)-\u003evalue = 42;\n\n// this is unnecessary\n((dict_item_t *)avl_find(\u0026dict, \u0026dummy))-\u003evalue = 42;\n```\n\n### Creating new dictionary instances\n\nTo create a new dictionary instance use:\n\n```c\ndict_t dict = AVL_NEW(dict_t, dict_data, dict_compare);\n```\n\nThe arguments to the `AVL_NEW` macro are:\n\n1. dictionary type\n2. name of the `avl_node_t` member of a dictionary item\n3. pointer to a comparator function\n\n### Insert\n\nTo insert `dict_item_t item` into the dictionary instance `dict_t dict` use `avl_insert`\n\n```c\ndict_item_t *replaced = avl_insert(\u0026dict, \u0026item);\n```\n\n`avl_insert` places the item inside the dictionary **potentially replacing**\nany item defined equal by the comparator function.\n\nIt returns a typed pointer to the replaced item or `NULL` if no item was\nreplaced.\n\n### Find\n\nTo find an item in `dict_t dict` use `avl_find`\n\nYou need to create a dictionary item instance which is equal to the item you're\nlooking for as per your comparator function.\n\n```c\ndict_item_t dummy = { .key = 13 };\ndict_item_t *found = avl_find(\u0026dict, \u0026dummy);\n```\n\n`avl_find` returns a typed pointer to the found item or `NULL` if it wasn't found.\n\n### Delete\n\nTo delete an item equal to `dict_item_t dummy` from `dict_t dict` use `avl_delete`\n\n```c\ndict_item_t dummy = { .key = 13 };\ndict_item_t *deleted = avl_delete(\u0026dict, \u0026dummy);\n```\n\n`avl_delete` returns a typed pointer to the deleted item or `NULL` if the\nitem wasn't found in the dictionary.\n\n### Contains\n\nTo check wheter an item equal to `dict_item_t item` is present in `dict_t dict`\nuse `avl_contains`\n\n```c\nbool item_present = avl_contains(\u0026dict, \u0026item);\n```\n\n`avl_contains` returns `true` if item was found otherwise `false` (as per `stdbool.h`)\n\n### Min\n\nTo get minimal item from `dict_t dict` use `avl_min`\n\n```c\ndict_item_t *min = avl_min(\u0026dict);\n```\n\n`avl_min` returns a typed pointer to the minimal item in `dict`\n\n### Max\n\n`avl_max` is used analogously to `avl_min`\n\n### Next\n\nTo get the next item after `dict_item_t item` in order defined by the\ncomparator function use `avl_next`\n\n```c\ndict_item_t *next = avl_next(\u0026dict, \u0026item);\n```\n\n`item` doesn't have to be in the dictionary in order for `avl_next` to work.\nThis can be handy if you wish to find the lowest value above some threshold,\neg: *\"Which of our cutomers have recently turned 40?\"*\n\n`avl_next` returns a typed pointer to the next larger item in `dict`\n\n### Previous\n\n`avl_prev` is used analogously to `avl_next`\n\n## Iterators\n\n### Creating an iterator\n\nAn iterator is obtained via `avl_get_iterator`. The arguments to this macro are\nas follows:\n\n1. pointer to the dictionary structure\n2. lower bound of the iterator interval\n3. upper bound of the iterator interval\n4. **[OPTIONAL]** a macro specifying increasing or decreasing order\n\nIf a `NULL` is specified in place of one of the bounds the minimum and the\nmaximum dictionary items will be used for the lower and upper bounds\nrespectively.\n\nUse `AVL_ASCENDING` or `AVL_DESCENDING` to specify iteration order. If you\nleave the 4th argument out, ascending order is presumed.\n\nExample presuming `dict` contains items whose keys range from 1 to 100:\n\n```c\ndict_item_t lower = { .key = 13 };\ndict_item_t upper = { .key = 42 };\n\n/* get iterator over the interval 13..42 */\navl_iterator_t iterator = avl_get_iterator(\u0026dict, \u0026lower, \u0026upper);\n\n/* get iterator over the interval 42..13 */\navl_iterator_t reversed = avl_get_iterator(\u0026dict, \u0026lower, \u0026upper, AVL_DESCENDING);\n\n/* get iterator over the interval 1..42 */\navl_iterator_t half_open = avl_get_iterator(\u0026dict, NULL, \u0026upper);\n\n/* get iterator over the interval 1..100 */\navl_iterator_t open = avl_get_iterator(\u0026dict, NULL, NULL);\n\n/* empty iterator - legal but useless */\navl_iterator_t empty = avl_get_iterator(\u0026dict, \u0026upper, \u0026lower);\n```\n\n### Advancing an iterator\n\nTo advance an iterator use `avl_advance`\n\n```c\ndict_item_t *next = avl_advance(\u0026dict, \u0026iterator);\n```\n\n`avl_advance` returns a typed pointer to the next node yielded by the\niterator. If a `NULL` is returned it means the iterator has been depleted.\n\nThe state of the iterator is modified by calling this macro. If you only wish to\nget the next item without advancing the iterator use `avl_peek` which otherwise\nshares the same interface as `avl_advance`\n\n### Note on iterator invalidation\n\nIf the underlying dictionary gets modified after an iterator was created, the\niterator is considered invalidated and any operations performed on it have an\nundefined result.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdook97%2Fcdict","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdook97%2Fcdict","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdook97%2Fcdict/lists"}