From 0db4478ddffd25c27cf570098766892edf60f617 Mon Sep 17 00:00:00 2001 From: androvonx95 Date: Tue, 24 Jun 2025 23:32:51 +0530 Subject: [PATCH] Added the data structres back --- struct/avl.c | 236 +++++++++++++++++++++++++++++++++++++++++++ struct/avl.h | 80 +++++++++++++++ struct/bst.c | 132 ++++++++++++++++++++++++ struct/bst.h | 80 +++++++++++++++ struct/hash_table.c | 137 +++++++++++++++++++++++++ struct/hash_table.h | 83 +++++++++++++++ struct/heap.c | 199 ++++++++++++++++++++++++++++++++++++ struct/heap.h | 99 ++++++++++++++++++ struct/linked_list.c | 96 ++++++++++++++++++ struct/linked_list.h | 66 ++++++++++++ struct/queue.c | 149 +++++++++++++++++++++++++++ struct/queue.h | 90 +++++++++++++++++ struct/stack.c | 70 +++++++++++++ struct/stack.h | 63 ++++++++++++ 14 files changed, 1580 insertions(+) create mode 100644 struct/avl.c create mode 100644 struct/avl.h create mode 100644 struct/bst.c create mode 100644 struct/bst.h create mode 100644 struct/hash_table.c create mode 100644 struct/hash_table.h create mode 100644 struct/heap.c create mode 100644 struct/heap.h create mode 100644 struct/linked_list.c create mode 100644 struct/linked_list.h create mode 100644 struct/queue.c create mode 100644 struct/queue.h create mode 100644 struct/stack.c create mode 100644 struct/stack.h diff --git a/struct/avl.c b/struct/avl.c new file mode 100644 index 0000000..8d73eaf --- /dev/null +++ b/struct/avl.c @@ -0,0 +1,236 @@ +#include "avl.h" +#include + +#ifndef NULL +#define NULL ((void*)0) +#endif + +static int max(int a, int b) { + return (a > b) ? a : b; +} + +static int height(AVLNode* node) { + return node ? node->height : 0; +} + +static AVLNode* create_node(uint32_t key, void* value) { + AVLNode* node = (AVLNode*)kmalloc(sizeof(AVLNode)); + if (!node) return NULL; + + node->key = key; + node->value = value; + node->left = node->right = NULL; + node->height = 1; + return node; +} + +static AVLNode* right_rotate(AVLNode* y) { + AVLNode* x = y->left; + AVLNode* T2 = x->right; + + x->right = y; + y->left = T2; + + y->height = max(height(y->left), height(y->right)) + 1; + x->height = max(height(x->left), height(x->right)) + 1; + + return x; +} + +static AVLNode* left_rotate(AVLNode* x) { + AVLNode* y = x->right; + AVLNode* T2 = y->left; + + y->left = x; + x->right = T2; + + x->height = max(height(x->left), height(x->right)) + 1; + y->height = max(height(y->left), height(y->right)) + 1; + + return y; +} + +static int get_balance(AVLNode* node) { + if (!node) return 0; + return height(node->left) - height(node->right); +} + +static void free_node(AVLNode* node) { + if (!node) return; + if (node->value) kfree(node->value); + kfree(node); +} + +static void avl_node_destroy(AVLNode* node) { + if (!node) return; + avl_node_destroy(node->left); + avl_node_destroy(node->right); + free_node(node); +} + +void avl_init(AVLTree* tree) { + if (!tree) return; + tree->root = NULL; + tree->size = 0; +} + +void avl_destroy(AVLTree* tree) { + if (!tree) return; + avl_node_destroy(tree->root); + tree->root = NULL; + tree->size = 0; +} + +static AVLNode* avl_insert_node(AVLNode* node, uint32_t key, void* value, bool* inserted) { + if (!node) { + *inserted = true; + return create_node(key, value); + } + + if (key < node->key) { + node->left = avl_insert_node(node->left, key, value, inserted); + } else if (key > node->key) { + node->right = avl_insert_node(node->right, key, value, inserted); + } else { + // Duplicate keys not allowed + *inserted = false; + return node; + } + + node->height = 1 + max(height(node->left), height(node->right)); + + int balance = get_balance(node); + + // Left Left Case + if (balance > 1 && key < node->left->key) + return right_rotate(node); + + // Right Right Case + if (balance < -1 && key > node->right->key) + return left_rotate(node); + + // Left Right Case + if (balance > 1 && key > node->left->key) { + node->left = left_rotate(node->left); + return right_rotate(node); + } + + // Right Left Case + if (balance < -1 && key < node->right->key) { + node->right = right_rotate(node->right); + return left_rotate(node); + } + + return node; +} + +bool avl_insert(AVLTree* tree, uint32_t key, void* value) { + if (!tree || !value) return false; + bool inserted = false; + tree->root = avl_insert_node(tree->root, key, value, &inserted); + if (inserted) tree->size++; + return inserted; +} + +static AVLNode* min_value_node(AVLNode* node) { + AVLNode* current = node; + while (current && current->left) + current = current->left; + return current; +} + +static AVLNode* avl_remove_node(AVLNode* root, uint32_t key, bool* removed) { + if (!root) return NULL; + + if (key < root->key) { + root->left = avl_remove_node(root->left, key, removed); + } else if (key > root->key) { + root->right = avl_remove_node(root->right, key, removed); + } else { + *removed = true; + + // Node with one or no child + if (!root->left || !root->right) { + AVLNode* temp = root->left ? root->left : root->right; + if (!temp) { + // No child case + free_node(root); + return NULL; + } else { + // One child case + if (root->value) kfree(root->value); + *root = *temp; + kfree(temp); + return root; + } + } else { + // Node with two children + AVLNode* temp = min_value_node(root->right); + root->key = temp->key; + + if (root->value) kfree(root->value); + root->value = temp->value; + + // Remove the inorder successor, but avoid double free of value + bool dummy = false; + root->right = avl_remove_node(root->right, temp->key, &dummy); + } + } + + if (!root) return NULL; + + root->height = 1 + max(height(root->left), height(root->right)); + + int balance = get_balance(root); + + // Left Left Case + if (balance > 1 && get_balance(root->left) >= 0) + return right_rotate(root); + + // Left Right Case + if (balance > 1 && get_balance(root->left) < 0) { + root->left = left_rotate(root->left); + return right_rotate(root); + } + + // Right Right Case + if (balance < -1 && get_balance(root->right) <= 0) + return left_rotate(root); + + // Right Left Case + if (balance < -1 && get_balance(root->right) > 0) { + root->right = right_rotate(root->right); + return left_rotate(root); + } + + return root; +} + +bool avl_remove(AVLTree* tree, uint32_t key) { + if (!tree) return false; + bool removed = false; + tree->root = avl_remove_node(tree->root, key, &removed); + if (removed) tree->size--; + return removed; +} + +void* avl_get(const AVLTree* tree, uint32_t key) { + if (!tree) return NULL; + AVLNode* current = tree->root; + while (current) { + if (key == current->key) return current->value; + if (key < current->key) + current = current->left; + else + current = current->right; + } + return NULL; +} + +size_t avl_size(const AVLTree* tree) { + return tree ? tree->size : 0; +} + +bool avl_contains(const AVLTree* tree, uint32_t key) { + return avl_get(tree, key) != NULL; +} \ No newline at end of file diff --git a/struct/avl.h b/struct/avl.h new file mode 100644 index 0000000..7cad332 --- /dev/null +++ b/struct/avl.h @@ -0,0 +1,80 @@ +#pragma once + +#include +#include + +/* AVL Tree node structure */ +typedef struct AVLNode { + uint32_t key; + void* value; + struct AVLNode* left; + struct AVLNode* right; + int height; +} AVLNode; + +/* AVL Tree structure */ +typedef struct { + AVLNode* root; + size_t size; +} AVLTree; + +/* AVL Tree functions */ + +/** + * Initializes an empty AVL tree. + * + * @param tree Pointer to the AVLTree to initialize. + */ +void avl_init(AVLTree* tree); + +/** + * Destroys the AVL tree, freeing all nodes and values. + * + * @param tree Pointer to the AVLTree to destroy. + */ +void avl_destroy(AVLTree* tree); + +/** + * Inserts a key-value pair into the AVL tree. + * + * @param tree Pointer to the AVLTree. + * @param key The key to insert. + * @param value Pointer to the value associated with the key. + * @return true if insertion succeeded, false if key exists or allocation fails. + */ +bool avl_insert(AVLTree* tree, uint32_t key, void* value); + +/** + * Retrieves the value associated with a key. + * + * @param tree Pointer to the AVLTree. + * @param key The key to search. + * @return Pointer to value or NULL if not found. + */ +void* avl_get(const AVLTree* tree, uint32_t key); + +/** + * Removes a node with the given key from the AVL tree. + * + * @param tree Pointer to the AVLTree. + * @param key The key to remove. + * @return true if the node was found and removed, false otherwise. + */ +bool avl_remove(AVLTree* tree, uint32_t key); + +/** + * Returns the number of nodes in the AVL tree. + * + * @param tree Pointer to the AVLTree. + * @return Number of nodes. + */ +size_t avl_size(const AVLTree* tree); + +/** + * Checks if a key exists in the AVL tree. + * + * @param tree Pointer to the AVLTree. + * @param key The key to check. + * @return true if the key exists, false otherwise. + */ +bool avl_contains(const AVLTree* tree, uint32_t key); \ No newline at end of file diff --git a/struct/bst.c b/struct/bst.c new file mode 100644 index 0000000..30577c3 --- /dev/null +++ b/struct/bst.c @@ -0,0 +1,132 @@ +#include "bst.h" +#include + +static void bst_node_destroy(BSTNode* node) { + if (!node) return; + bst_node_destroy(node->left); + bst_node_destroy(node->right); + if (node->value) { + kfree(node->value); + } + kfree(node); +} + +void bst_init(BST* tree) { + if (!tree) return; + tree->root = NULL; + tree->size = 0; +} + +void bst_destroy(BST* tree) { + if (!tree) return; + bst_node_destroy(tree->root); + tree->root = NULL; + tree->size = 0; +} + +static BSTNode* bst_node_create(uint32_t key, void* value) { + BSTNode* node = (BSTNode*)kmalloc(sizeof(BSTNode)); + if (!node) return NULL; + node->key = key; + node->value = value; + node->left = NULL; + node->right = NULL; + return node; +} + +static BSTNode* bst_node_insert(BSTNode* root, uint32_t key, void* value, bool* inserted) { + if (!root) { + *inserted = true; + return bst_node_create(key, value); + } + if (key < root->key) { + root->left = bst_node_insert(root->left, key, value, inserted); + } else if (key > root->key) { + root->right = bst_node_insert(root->right, key, value, inserted); + } else { + // Duplicate key, do not insert + *inserted = false; + } + return root; +} + +bool bst_insert(BST* tree, uint32_t key, void* value) { + if (!tree || !value) return false; + bool inserted = false; + tree->root = bst_node_insert(tree->root, key, value, &inserted); + if (inserted) tree->size++; + return inserted; +} + +static void* bst_node_get(BSTNode* root, uint32_t key) { + if (!root) return NULL; + if (key == root->key) return root->value; + else if (key < root->key) return bst_node_get(root->left, key); + else return bst_node_get(root->right, key); +} + +void* bst_get(const BST* tree, uint32_t key) { + if (!tree) return NULL; + return bst_node_get(tree->root, key); +} + +static BSTNode* bst_node_find_min(BSTNode* node) { + while (node && node->left) { + node = node->left; + } + return node; +} + +static BSTNode* bst_node_remove(BSTNode* root, uint32_t key, bool* removed) { + if (!root) return NULL; + + if (key < root->key) { + root->left = bst_node_remove(root->left, key, removed); + } else if (key > root->key) { + root->right = bst_node_remove(root->right, key, removed); + } else { + // Found node to remove + *removed = true; + if (!root->left) { + BSTNode* right = root->right; + if (root->value) kfree(root->value); + kfree(root); + return right; + } else if (!root->right) { + BSTNode* left = root->left; + if (root->value) kfree(root->value); + kfree(root); + return left; + } else { + // Two children: find inorder successor (min in right subtree) + BSTNode* min_node = bst_node_find_min(root->right); + root->key = min_node->key; + + // Free old value and copy new value pointer + if (root->value) kfree(root->value); + root->value = min_node->value; + + // Remove the successor node but don't free value again + bool dummy = false; + root->right = bst_node_remove(root->right, min_node->key, &dummy); + } + } + return root; +} + +bool bst_remove(BST* tree, uint32_t key) { + if (!tree) return false; + bool removed = false; + tree->root = bst_node_remove(tree->root, key, &removed); + if (removed) tree->size--; + return removed; +} + +size_t bst_size(const BST* tree) { + return tree ? tree->size : 0; +} + +bool bst_contains(const BST* tree, uint32_t key) { + if (!tree) return false; + return bst_get(tree, key) != NULL; +} \ No newline at end of file diff --git a/struct/bst.h b/struct/bst.h new file mode 100644 index 0000000..df43053 --- /dev/null +++ b/struct/bst.h @@ -0,0 +1,80 @@ +#pragma once + +/* Includes */ +#include +#include + +/* Binary Search Tree node structure */ +typedef struct BSTNode { + uint32_t key; /* The key for the BST entry */ + void* value; /* Pointer to the stored value */ + struct BSTNode* left; /* Pointer to left child */ + struct BSTNode* right; /* Pointer to right child */ +} BSTNode; + +/* Binary Search Tree structure */ +typedef struct { + BSTNode* root; /* Pointer to the root node */ + size_t size; /* Current number of nodes in the tree */ +} BST; + +/* Binary Search Tree functions */ + +/** +* Initializes a new empty BST. +* +* @param tree Pointer to the BST structure to initialize. +*/ +void bst_init(BST* tree); + +/** +* Destroys the BST, freeing all nodes and their associated values. +* +* @param tree Pointer to the BST to destroy. +*/ +void bst_destroy(BST* tree); + +/** +* Inserts a key-value pair into the BST. +* +* @param tree Pointer to the BST. +* @param key The key to insert. +* @param value Pointer to the value to associate with the key. +* @return true if insertion was successful, false if the key already exists or on failure. +*/ +bool bst_insert(BST* tree, uint32_t key, void* value); + +/** +* Retrieves a value associated with a given key from the BST. +* +* @param tree Pointer to the BST. +* @param key The key to search for. +* @return Pointer to the stored value, or NULL if the key is not found. +*/ +void* bst_get(const BST* tree, uint32_t key); + +/** +* Removes a node by key from the BST. +* +* @param tree Pointer to the BST. +* @param key The key to remove. +* @return true if the key was found and removed, false otherwise. +*/ +bool bst_remove(BST* tree, uint32_t key); + +/** +* Returns the current number of nodes stored in the BST. +* +* @param tree Pointer to the BST. +* @return Number of nodes in the BST. +*/ +size_t bst_size(const BST* tree); + +/** +* Checks if a key exists in the BST. +* +* @param tree Pointer to the BST. +* @param key The key to look for. +* @return true if the key exists in the BST, false otherwise. +*/ +bool bst_contains(const BST* tree, uint32_t key); diff --git a/struct/hash_table.c b/struct/hash_table.c new file mode 100644 index 0000000..829b8f7 --- /dev/null +++ b/struct/hash_table.c @@ -0,0 +1,137 @@ +#include "hash_table.h" +#include // for kmalloc, kfree +#include // for memcpy +#include // for error logging if available + +// Simple hash function using FNV-1a +static inline uint32_t hash(uint32_t key, size_t bucket_count) { + const uint32_t FNV_PRIME = 0x100000001b3; + const uint32_t FNV_OFFSET = 0xcbf29ce484222325; + + uint32_t hash = FNV_OFFSET; + for (int i = 0; i < 8; i++) { + hash ^= (key >> (i * 8)) & 0xFF; + hash *= FNV_PRIME; + } + + return hash % bucket_count; +} + +void hash_table_init(HashTable* table, size_t bucket_count) { + if (!table || bucket_count == 0) return; + + table->buckets = (HashNode**)kmalloc(bucket_count * sizeof(HashNode*)); + if (!table->buckets) return; + + for (size_t i = 0; i < bucket_count; i++) { + table->buckets[i] = NULL; + } + + table->bucket_count = bucket_count; + table->size = 0; +} + +void hash_table_destroy(HashTable* table) { + if (!table) return; + + for (size_t i = 0; i < table->bucket_count; i++) { + HashNode* current = table->buckets[i]; + while (current) { + HashNode* next = current->next; + if (current->value) { + kfree(current->value); + } + kfree(current); + current = next; + } + } + + kfree(table->buckets); + table->buckets = NULL; + table->bucket_count = 0; + table->size = 0; +} + +bool hash_table_insert(HashTable* table, uint32_t key, void* value) { + if (!table || !value) return false; + + size_t index = hash(key, table->bucket_count); + HashNode* new_node = (HashNode*)kmalloc(sizeof(HashNode)); + if (!new_node) { + printk("hash_table_insert: kmalloc failed for new node\n"); + return false; + } + + new_node->key = key; + new_node->value = value; + new_node->next = table->buckets[index]; + table->buckets[index] = new_node; + table->size++; + + return true; +} + +void* hash_table_get(HashTable* table, uint32_t key) { + if (!table) return NULL; + + size_t index = hash(key, table->bucket_count); + HashNode* current = table->buckets[index]; + + while (current) { + if (current->key == key) { + return current->value; + } + current = current->next; + } + + return NULL; +} + +bool hash_table_remove(HashTable* table, uint32_t key) { + if (!table) return false; + + size_t index = hash(key, table->bucket_count); + HashNode* current = table->buckets[index]; + HashNode* prev = NULL; + + while (current) { + if (current->key == key) { + if (prev) { + prev->next = current->next; + } else { + table->buckets[index] = current->next; + } + + if (current->value) { + kfree(current->value); + } + kfree(current); + table->size--; + return true; + } + prev = current; + current = current->next; + } + + return false; +} + +size_t hash_table_size(const HashTable* table) { + return table ? table->size : 0; +} + +bool hash_table_contains(const HashTable* table, uint32_t key) { + if (!table) return false; + + size_t index = hash(key, table->bucket_count); + HashNode* current = table->buckets[index]; + + while (current) { + if (current->key == key) { + return true; + } + current = current->next; + } + + return false; +} \ No newline at end of file diff --git a/struct/hash_table.h b/struct/hash_table.h new file mode 100644 index 0000000..978fc5e --- /dev/null +++ b/struct/hash_table.h @@ -0,0 +1,83 @@ +#pragma once + +/* Includes */ +#include +#include + +/* Hash table node structure */ +typedef struct HashNode { + uint32_t key; /* The key for the hash table entry */ + void* value; /* Pointer to the stored value */ + struct HashNode* next; /* Pointer to next node in case of collision */ +} HashNode; + +/* Hash table structure */ +typedef struct { + HashNode** buckets; /* Array of pointers to bucket heads */ + size_t bucket_count; /* Number of buckets in the hash table */ + size_t size; /* Current number of entries in the table */ +} HashTable; + +/* Hash table functions */ + +/** + * Initializes a new hash table. + * + * @param table The hash table to initialize. + * @param bucket_count The number of buckets to create. + */ +void hash_table_init(HashTable* table, size_t bucket_count); + +/** + * Destroys the hash table and frees allocated memory. + * + * @param table The hash table to destroy. + */ +void hash_table_destroy(HashTable* table); + +/** + * Inserts a key-value pair into the hash table. + * + * @param table The hash table to insert into. + * @param key The key for the entry. + * @param value The value to store. + * @return true if the insertion was successful, false otherwise. + */ +bool hash_table_insert(HashTable* table, uint32_t key, void* value); + +/** + * Retrieves a value from the hash table by key. + * + * @param table The hash table to search. + * @param key The key to look up. + * @return A pointer to the stored value, or NULL if not found. + */ +void* hash_table_get(HashTable* table, uint32_t key); + +/** + * Removes a key-value pair from the hash table. + * + * @param table The hash table to modify. + * @param key The key to remove. + * @return true if the key was found and removed, false otherwise. + */ +bool hash_table_remove(HashTable* table, uint32_t key); + +/** + * Returns the current size of the hash table. + * + * @param table The hash table to check. + * @return The current number of entries in the table. + */ +size_t hash_table_size(const HashTable* table); + +/** + * Checks if a key exists in the hash table. + * + * @param table The hash table to check. + * @param key The key to look for. + * @return true if the key exists, false otherwise. + */ +bool hash_table_contains(const HashTable* table, uint32_t key); + +#endif // HASHTABLE_H \ No newline at end of file diff --git a/struct/heap.c b/struct/heap.c new file mode 100644 index 0000000..62f55b1 --- /dev/null +++ b/struct/heap.c @@ -0,0 +1,199 @@ +#include +#include +#include + +/* Helper function to swap two items in the heap */ +static void heap_swap(Heap* heap, unsigned int i, unsigned int j) { + void* temp = heap->items[i]; + heap->items[i] = heap->items[j]; + heap->items[j] = temp; +} + +/* Helper function to maintain heap property by bubbling up */ +static void heap_bubble_up(Heap* heap, unsigned int i) { + while (i > 0) { + unsigned int parent = PARENT(i); + if (heap->compare(heap->items[i], heap->items[parent]) > 0) { + heap_swap(heap, i, parent); + i = parent; + } else { + break; + } + } +} + +/* Helper function to maintain heap property by bubbling down */ +static void heap_bubble_down(Heap* heap, unsigned int i) { + while (true) { + unsigned int left = LEFT(i); + unsigned int right = RIGHT(i); + unsigned int largest = i; + + if (left < heap->size && + heap->compare(heap->items[left], heap->items[largest]) > 0) { + largest = left; + } + + if (right < heap->size && + heap->compare(heap->items[right], heap->items[largest]) > 0) { + largest = right; + } + + if (largest != i) { + heap_swap(heap, i, largest); + i = largest; + } else { + break; + } + } +} + +/* Initialize a new heap */ +void heap_init(Heap* heap, unsigned int item_size, unsigned int initial_capacity, + HeapCompareFunc compare) { + if (!heap || !compare || item_size == 0 || initial_capacity == 0) { + return; + } + + heap->items = kmalloc(initial_capacity * sizeof(void*)); + if (!heap->items) { + heap->capacity = 0; + heap->size = 0; + heap->item_size = 0; + heap->compare = NULL; + return; + } + + heap->capacity = initial_capacity; + heap->size = 0; + heap->item_size = item_size; + heap->compare = compare; +} + +/* Destroy a heap and free its memory */ +void heap_destroy(Heap* heap) { + if (!heap || !heap->items) { + return; + } + + // Free each item that was allocated by the heap + for (unsigned int i = 0; i < heap->size; i++) { + if (heap->items[i]) { + kfree(heap->items[i]); + } + } + + kfree(heap->items); + heap->items = NULL; + heap->capacity = 0; + heap->size = 0; + heap->item_size = 0; + heap->compare = NULL; +} + +/* Add an item to the heap */ +bool heap_insert(Heap* heap, void* item) { + if (!heap || !item || !heap->items || !heap->compare) { + return false; + } + + // Resize if needed + if (heap->size >= heap->capacity) { + unsigned int new_capacity = heap->capacity * 2; + void** new_items = kmalloc(new_capacity * sizeof(void*)); + + if (!new_items) { + return false; + } + + // Copy existing items + for (unsigned int i = 0; i < heap->size; i++) { + new_items[i] = heap->items[i]; + } + + // Free old memory and update + kfree(heap->items); + heap->items = new_items; + heap->capacity = new_capacity; + } + + // Allocate memory for the item and copy the content + void* new_item = kmalloc(heap->item_size); + if (!new_item) { + return false; + } + + memcpy(new_item, item, heap->item_size); + heap->items[heap->size] = new_item; + heap_bubble_up(heap, heap->size); + heap->size++; + + return true; +} + +/* Remove and return the root item from the heap */ +void* heap_extract(Heap* heap) { + if (!heap || heap_empty(heap)) { + return NULL; + } + + void* root = heap->items[0]; + heap->size--; + + if (heap->size > 0) { + heap->items[0] = heap->items[heap->size]; + heap->items[heap->size] = NULL; + heap_bubble_down(heap, 0); + } else { + heap->items[0] = NULL; + } + + return root; // Caller is responsible for freeing this memory +} + +/* Remove and free the root item from the heap */ +bool heap_extract_free(Heap* heap) { + if (!heap || heap_empty(heap)) { + return false; + } + + void* root = heap->items[0]; + heap->size--; + + if (heap->size > 0) { + heap->items[0] = heap->items[heap->size]; + heap->items[heap->size] = NULL; + heap_bubble_down(heap, 0); + } else { + heap->items[0] = NULL; + } + + if (root) { + kfree(root); + } + + return true; +} + +/* Peek at the root item without removing it */ +void* heap_peek(const Heap* heap) { + if (!heap || heap_empty(heap)) { + return NULL; + } + return heap->items[0]; +} + +/* Check if the heap is empty */ +bool heap_empty(const Heap* heap) { + return !heap || heap->size == 0; +} + +/* Get the current size of the heap */ +unsigned int heap_size(const Heap* heap) { + return heap ? heap->size : 0; +} + +/* Check if heap is valid/initialized */ +bool heap_is_valid(const Heap* heap) { + return heap && heap->items && heap->capacity > 0 && heap->compare != NULL; +} \ No newline at end of file diff --git a/struct/heap.h b/struct/heap.h new file mode 100644 index 0000000..fda921d --- /dev/null +++ b/struct/heap.h @@ -0,0 +1,99 @@ +#pragma once + +/* Includes */ +#include + +/* Comparison function type */ +typedef int (*HeapCompareFunc)(const void*, const void*); + +/* Heap structure */ +typedef struct { + void** items; /* Array of pointers to items */ + unsigned int capacity; /* Maximum number of items */ + unsigned int size; /* Current number of items */ + unsigned int item_size; /* Size of each item in bytes */ + HeapCompareFunc compare; /* Function to compare items */ +} Heap; + +/* Helper macros */ +#define PARENT(i) ((i - 1) / 2) +#define LEFT(i) (2 * i + 1) +#define RIGHT(i) (2 * i + 2) + +/* Heap functions */ + +/** +* Initializes a new heap. +* +* @param heap The heap to initialize. +* @param item_size The size of each item in bytes. +* @param initial_capacity The initial capacity of the heap. +* @param compare Function to compare items (should return <0, 0, >0 for max-heap). +*/ +void heap_init(Heap* heap, unsigned int item_size, unsigned int initial_capacity, + HeapCompareFunc compare); + +/** +* Destroys the heap and frees allocated memory. +* +* @param heap The heap to destroy. +*/ +void heap_destroy(Heap* heap); + +/** +* Adds an item to the heap (maintains heap property). +* +* @param heap The heap to add the item to. +* @param item The item to add (pointer to the item). +* @return true if the item was successfully added, false if there was an error. +*/ +bool heap_insert(Heap* heap, void* item); + +/** +* Removes and returns the root item from the heap (maintains heap property). +* NOTE: The caller is responsible for freeing the returned memory. +* +* @param heap The heap to remove the item from. +* @return A pointer to the removed item, or NULL if the heap is empty. +*/ +void* heap_extract(Heap* heap); + +/** +* Removes and frees the root item from the heap. +* +* @param heap The heap to remove the item from. +* @return true if an item was removed, false if the heap was empty. +*/ +bool heap_extract_free(Heap* heap); + +/** +* Returns the root item without removing it. +* +* @param heap The heap to peek at. +* @return A pointer to the root item, or NULL if the heap is empty. +*/ +void* heap_peek(const Heap* heap); + +/** +* Checks if the heap is empty. +* +* @param heap The heap to check. +* @return true if the heap is empty, false otherwise. +*/ +bool heap_empty(const Heap* heap); + +/** +* Returns the current size of the heap. +* +* @param heap The heap to check. +* @return The current number of items in the heap. +*/ +unsigned int heap_size(const Heap* heap); + +/** +* Checks if the heap is valid/initialized. +* +* @param heap The heap to check. +* @return true if the heap is valid, false otherwise. +*/ +bool heap_is_valid(const Heap* heap); \ No newline at end of file diff --git a/struct/linked_list.c b/struct/linked_list.c new file mode 100644 index 0000000..9ef5113 --- /dev/null +++ b/struct/linked_list.c @@ -0,0 +1,96 @@ +#include // for kmalloc, kfree, memcpy +#include // for memcmp + +void list_init(LinkedList* list, unsigned int item_size) { + if (!list || item_size == 0) return; + list->head = NULL; + list->tail = NULL; + list->size = 0; + list->item_size = item_size; +} + +void list_destroy(LinkedList* list) { + if (!list) return; + + ListNode* current = list->head; + while (current) { + ListNode* next = current->next; + if (current->data) { + kfree(current->data); + } + kfree(current); + current = next; + } + + list->head = NULL; + list->tail = NULL; + list->size = 0; + list->item_size = 0; +} + +bool list_append(LinkedList* list, const void* data) { + if (!list || !data) return false; + + ListNode* node = (ListNode*)kmalloc(sizeof(ListNode)); + if (!node) return false; + + void* data_copy = kmalloc(list->item_size); + if (!data_copy) { + kfree(node); + return false; + } + + memcpy(data_copy, data, list->item_size); + + node->data = data_copy; + node->next = NULL; + + if (!list->head) { + list->head = node; + list->tail = node; + } else { + list->tail->next = node; + list->tail = node; + } + + list->size++; + return true; +} + +bool list_remove(LinkedList* list, const void* data) { + if (!list || !data || !list->head) return false; + + ListNode* current = list->head; + ListNode* prev = NULL; + + while (current) { + if (memcmp(current->data, data, list->item_size) == 0) { + if (prev) { + prev->next = current->next; + } else { + list->head = current->next; + } + + if (current == list->tail) { + list->tail = prev; + } + + kfree(current->data); + kfree(current); + list->size--; + return true; + } + prev = current; + current = current->next; + } + + return false; +} + +bool list_empty(const LinkedList* list) { + return !list || list->size == 0; +} + +unsigned int list_size(const LinkedList* list) { + return list ? list->size : 0; +} \ No newline at end of file diff --git a/struct/linked_list.h b/struct/linked_list.h new file mode 100644 index 0000000..b9c6195 --- /dev/null +++ b/struct/linked_list.h @@ -0,0 +1,66 @@ +#pragma once + +#include + +/* Node structure */ +typedef struct ListNode { + void* data; + struct ListNode* next; +} ListNode; + +/* Linked list structure */ +typedef struct { + ListNode* head; + ListNode* tail; + unsigned int size; + unsigned int item_size; +} LinkedList; + +/** + * Initialize linked list. + * + * @param list Pointer to LinkedList to initialize + * @param item_size Size of data stored in each node (bytes) + */ +void list_init(LinkedList* list, unsigned int item_size); + +/** + * Destroy list, free all nodes and their data. + * + * @param list Pointer to LinkedList to destroy + */ +void list_destroy(LinkedList* list); + +/** + * Insert data at the end of the list. + * + * @param list Pointer to LinkedList + * @param data Pointer to data to insert + * @return true if success, false if memory allocation failed + */ +bool list_append(LinkedList* list, const void* data); + +/** + * Remove the first node with data matching `data` (using memcmp). + * + * @param list Pointer to LinkedList + * @param data Pointer to data to remove + * @return true if removed, false if not found + */ +bool list_remove(LinkedList* list, const void* data); + +/** + * Check if the list is empty. + * + * @param list Pointer to LinkedList + * @return true if empty, false otherwise + */ +bool list_empty(const LinkedList* list); + +/** + * Get the size of the list. + * + * @param list Pointer to LinkedList + * @return number of elements + */ +unsigned int list_size(const LinkedList* list); \ No newline at end of file diff --git a/struct/queue.c b/struct/queue.c new file mode 100644 index 0000000..133f59b --- /dev/null +++ b/struct/queue.c @@ -0,0 +1,149 @@ +#include +#include +#include + +/* Initialize a new queue */ +void queue_init(Queue* queue, unsigned int item_size, unsigned int initial_capacity) { + if (!queue || item_size == 0 || initial_capacity == 0) { + return; + } + + queue->items = kmalloc(initial_capacity * sizeof(void*)); + if (!queue->items) { + queue->capacity = 0; + queue->size = 0; + queue->head = 0; + queue->tail = 0; + queue->item_size = 0; + return; + } + + queue->capacity = initial_capacity; + queue->size = 0; + queue->head = 0; + queue->tail = 0; + queue->item_size = item_size; +} + +/* Destroy a queue and free its memory */ +void queue_destroy(Queue* queue) { + if (!queue || !queue->items) { + return; + } + + // Free each item that was allocated by the queue + for (unsigned int i = 0; i < queue->size; i++) { + unsigned int index = (queue->head + i) % queue->capacity; + if (queue->items[index]) { + kfree(queue->items[index]); + } + } + + kfree(queue->items); + queue->items = NULL; + queue->capacity = 0; + queue->size = 0; + queue->head = 0; + queue->tail = 0; + queue->item_size = 0; +} + +/* Add an item to the back of the queue */ +bool queue_enqueue(Queue* queue, void* item) { + if (!queue || !item || !queue->items) { + return false; + } + + /* Resize if needed */ + if (queue->size >= queue->capacity) { + unsigned int new_capacity = queue->capacity * 2; + void** new_items = kmalloc(new_capacity * sizeof(void*)); + + if (!new_items) { + return false; // Failed to allocate memory + } + + /* Copy existing items in order */ + for (unsigned int i = 0; i < queue->size; i++) { + unsigned int index = (queue->head + i) % queue->capacity; + new_items[i] = queue->items[index]; + } + + /* Free old memory and update */ + kfree(queue->items); + queue->items = new_items; + queue->capacity = new_capacity; + queue->head = 0; + queue->tail = queue->size; + } + + /* Allocate memory for the item and copy the content */ + void* new_item = kmalloc(queue->item_size); + if (!new_item) { + return false; // Failed to allocate memory + } + + memcpy(new_item, item, queue->item_size); + queue->items[queue->tail] = new_item; + + queue->tail = (queue->tail + 1) % queue->capacity; + queue->size++; + + return true; +} + +/* Remove and return the item from the front of the queue */ +void* queue_dequeue(Queue* queue) { + if (!queue || queue_empty(queue)) { + return NULL; + } + + void* item = queue->items[queue->head]; + queue->items[queue->head] = NULL; // Clear the pointer + queue->head = (queue->head + 1) % queue->capacity; + queue->size--; + + return item; // Caller is responsible for freeing this memory +} + +/* Peek at the front item without removing it */ +void* queue_peek(const Queue* queue) { + if (!queue || queue_empty(queue)) { + return NULL; + } + + return queue->items[queue->head]; +} + +/* Remove and free the item from the front of the queue */ +bool queue_dequeue_free(Queue* queue) { + if (!queue || queue_empty(queue)) { + return false; + } + + void* item = queue->items[queue->head]; + if (item) { + kfree(item); + } + + queue->items[queue->head] = NULL; + queue->head = (queue->head + 1) % queue->capacity; + queue->size--; + + return true; +} + +/* Check if the queue is empty */ +bool queue_empty(const Queue* queue) { + return !queue || queue->size == 0; +} + +/* Get the current size of the queue */ +unsigned int queue_size(const Queue* queue) { + return queue ? queue->size : 0; +} + +/* Check if queue is valid/initialized */ +bool queue_is_valid(const Queue* queue) { + return queue && queue->items && queue->capacity > 0; +} \ No newline at end of file diff --git a/struct/queue.h b/struct/queue.h new file mode 100644 index 0000000..3b372c8 --- /dev/null +++ b/struct/queue.h @@ -0,0 +1,90 @@ +#pragma once + +/* Includes */ +#include + +/* Queue structure */ +typedef struct { + void** items; /* Array of pointers to items */ + unsigned int capacity; /* Maximum number of items */ + unsigned int size; /* Current number of items */ + unsigned int head; /* Index of the head (front) */ + unsigned int tail; /* Index of the tail (back) */ + unsigned int item_size; /* Size of each item in bytes */ +} Queue; + +/* Queue functions */ + +/** +* Initializes a new queue. +* +* @param queue The queue to initialize. +* @param item_size The size of each item in bytes. +* @param initial_capacity The initial capacity of the queue. +*/ +void queue_init(Queue* queue, unsigned int item_size, unsigned int initial_capacity); + +/** +* Destroys the queue and frees allocated memory. +* +* @param queue The queue to destroy. +*/ +void queue_destroy(Queue* queue); + +/** +* Adds an item to the back of the queue. +* +* @param queue The queue to add the item to. +* @param item The item to add (pointer to the item). +* @return true if the item was successfully added, false if there was an error. +*/ +bool queue_enqueue(Queue* queue, void* item); + +/** +* Removes and returns the item from the front of the queue. +* NOTE: The caller is responsible for freeing the returned memory. +* +* @param queue The queue to remove the item from. +* @return A pointer to the removed item, or NULL if the queue is empty. +*/ +void* queue_dequeue(Queue* queue); + +/** +* Removes and frees the item from the front of the queue. +* +* @param queue The queue to remove the item from. +* @return true if an item was removed, false if the queue was empty. +*/ +bool queue_dequeue_free(Queue* queue); + +/** +* Peeks at the front item without removing it. +* +* @param queue The queue to peek at. +* @return A pointer to the front item, or NULL if the queue is empty. +*/ +void* queue_peek(const Queue* queue); + +/** +* Checks if the queue is empty. +* +* @param queue The queue to check. +* @return true if the queue is empty, false otherwise. +*/ +bool queue_empty(const Queue* queue); + +/** +* Returns the current size of the queue. +* +* @param queue The queue to check. +* @return The current number of items in the queue. +*/ +unsigned int queue_size(const Queue* queue); + +/** +* Checks if the queue is valid/initialized. +* +* @param queue The queue to check. +* @return true if the queue is valid, false otherwise. +*/ +bool queue_is_valid(const Queue* queue); \ No newline at end of file diff --git a/struct/stack.c b/struct/stack.c new file mode 100644 index 0000000..48fcb70 --- /dev/null +++ b/struct/stack.c @@ -0,0 +1,70 @@ +#include +#include +#include + +/* Initialize a new stack */ +void stack_init(Stack* stack, uint item_size, uint initial_capacity) { + stack->items = kmalloc(initial_capacity * sizeof(void*)); // Allocate space for the array of pointers + stack->capacity = initial_capacity; + stack->size = 0; + stack->item_size = item_size; +} + +/* Destroy a stack and free its memory */ +void stack_destroy(Stack* stack) { + // Free each item in the stack if they were dynamically allocated + for (uint i = 0; i < stack->size; i++) { + kfree(stack->items[i]); // Assuming items were allocated dynamically + } + kfree(stack->items); // Free the array of pointers + stack->items = NULL; + stack->capacity = 0; + stack->size = 0; + stack->item_size = 0; +} + +/* Add an item to the stack */ +bool stack_push(Stack* stack, void* item) { + /* Resize if needed */ + if (stack->size >= stack->capacity) { + uint new_capacity = stack->capacity * 2; + void** new_items = kmalloc(new_capacity * sizeof(void*)); + + /* Copy existing items */ + for (uint i = 0; i < stack->size; i++) { + new_items[i] = stack->items[i]; + } + + /* Free old memory and update */ + kfree(stack->items); + stack->items = new_items; + stack->capacity = new_capacity; + } + + /* Allocate memory for the item and copy the content */ + void* new_item = kmalloc(stack->item_size); + memcpy(new_item, item, stack->item_size); // Copy the item to allocated memory + stack->items[stack->size++] = new_item; // Add the item to the stack + + return true; +} + +/* Remove and return the top item from the stack */ +void* stack_pop(Stack* stack) { + if (stack_empty(stack)) { + return NULL; + } + + void* item = stack->items[--stack->size]; + return item; +} + +/* Check if the stack is empty */ +bool stack_empty(const Stack* stack) { + return stack->size == 0; +} + +/* Get the current size of the stack */ +uint stack_size(const Stack* stack) { + return stack->size; +} \ No newline at end of file diff --git a/struct/stack.h b/struct/stack.h new file mode 100644 index 0000000..73dc246 --- /dev/null +++ b/struct/stack.h @@ -0,0 +1,63 @@ +#pragma once + +/* Includes */ +#include + +/* Stack structure */ +typedef struct { + void** items; /* Array of pointers to items */ + unsigned int capacity; /* Maximum number of items */ + unsigned int size; /* Current number of items */ + unsigned int item_size; /* Size of each item in bytes */ +} Stack; + +/* Stack functions */ + +/** +* Initializes a new stack. +* +* @param stack The stack to initialize. +* @param item_size The size of each item in bytes. +* @param initial_capacity The initial capacity of the stack. +*/ +void stack_init(Stack* stack, unsigned int item_size, unsigned int initial_capacity); + +/** +* Destroys the stack and frees allocated memory. +* +* @param stack The stack to destroy. +*/ +void stack_destroy(Stack* stack); + +/** +* Pushes an item onto the stack. +* +* @param stack The stack to push the item onto. +* @param item The item to push (pointer to the item). +* @return true if the item was successfully pushed, false if there was an error. +*/ +bool stack_push(Stack* stack, void* item); + +/** +* Pops the top item from the stack. +* +* @param stack The stack to pop the item from. +* @return A pointer to the popped item, or NULL if the stack is empty. +*/ +void* stack_pop(Stack* stack); + +/** +* Checks if the stack is empty. +* +* @param stack The stack to check. +* @return true if the stack is empty, false otherwise. +*/ +bool stack_empty(const Stack* stack); + +/** +* Returns the current size of the stack. +* +* @param stack The stack to check. +* @return The current number of items in the stack. +*/ +unsigned int stack_size(const Stack* stack); \ No newline at end of file