[bug+docs] add docs + fix error in getMax (#579)

* add docs + fix error in getMax

* fix clang-tidy alerts and errors

* rearrange comments

* allow subfolders in data_structure

* set pointer to NULL after purge
This commit is contained in:
Krishna Vedala 2020-07-22 08:37:28 -04:00 committed by GitHub
parent 83a8239805
commit 296f3d00d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 119 additions and 54 deletions

View File

@ -142,7 +142,7 @@ jobs:
print(f"{len(space_files)} files contain space or dash characters:") print(f"{len(space_files)} files contain space or dash characters:")
print("\n".join(space_files) + "\n") print("\n".join(space_files) + "\n")
nodir_files = [file for file in cpp_files if file.count(os.sep) != 1 and "project_euler" not in file] nodir_files = [file for file in cpp_files if file.count(os.sep) != 1 and "project_euler" not in file and "data_structure" not in file]
if nodir_files: if nodir_files:
print(f"{len(nodir_files)} files are not in one and only one directory:") print(f"{len(nodir_files)} files are not in one and only one directory:")
print("\n".join(nodir_files) + "\n") print("\n".join(nodir_files) + "\n")

View File

@ -1,29 +1,30 @@
/**
* @file
* @brief A basic unbalanced binary search tree implementation in C.
* @details The implementation has the following functionalities implemented:
* - Insertion
* - Deletion
* - Search by key value
* - Listing of node keys in order of value (from left to right)
*/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
/* A basic unbalanced binary search tree implementation in C, with the following /** Node, the basic data structure in the tree */
functionalities implemented:
- Insertion
- Deletion
- Search by key value
- Listing of node keys in order of value (from left to right)
*/
// Node, the basic data structure in the tree
typedef struct node typedef struct node
{ {
// left child struct node *left; /**< left child */
struct node *left; struct node *right; /**< right child */
int data; /**< data of the node */
// right child
struct node *right;
// data of the node
int data;
} node; } node;
// The node constructor, which receives the key value input and returns a node /** The node constructor, which receives the key value input and returns a node
// pointer * pointer
* @param data data to store in a new node
* @returns new node with the provided data
* @note the node must be deleted before program terminates to avoid memory
* leaks
*/
node *newNode(int data) node *newNode(int data)
{ {
// creates a slug // creates a slug
@ -37,61 +38,82 @@ node *newNode(int data)
return tmp; return tmp;
} }
// Insertion procedure, which inserts the input key in a new node in the tree /** Insertion procedure, which inserts the input key in a new node in the tree
* @param root pointer to parent node
* @param data value to store int he new node
* @returns pointer to parent node
*/
node *insert(node *root, int data) node *insert(node *root, int data)
{ {
// If the root of the subtree is null, insert key here // If the root of the subtree is null, insert key here
if (root == NULL) if (root == NULL)
{
root = newNode(data); root = newNode(data);
// If it isn't null and the input key is greater than the root key, insert }
// in the right leaf
else if (data > root->data) else if (data > root->data)
{
// If it isn't null and the input key is greater than the root key,
// insert in the right leaf
root->right = insert(root->right, data); root->right = insert(root->right, data);
// If it isn't null and the input key is lower than the root key, insert in }
// the left leaf
else if (data < root->data) else if (data < root->data)
{ // If it isn't null and the input key is lower than the root key, insert
// in the left leaf
root->left = insert(root->left, data); root->left = insert(root->left, data);
}
// Returns the modified tree // Returns the modified tree
return root; return root;
} }
// Utilitary procedure to find the greatest key in the left subtree /** Utilitary procedure to find the greatest key in the left subtree
* @param root pointer to parent node
* @returns pointer to parent node
*/
node *getMax(node *root) node *getMax(node *root)
{ {
// If there's no leaf to the right, then this is the maximum key value // If there's no leaf to the right, then this is the maximum key value
if (root->right == NULL) if (root->right != NULL)
{
return getMax(root->right);
}
return root; return root;
else
root->right = getMax(root->right);
} }
// Deletion procedure, which searches for the input key in the tree and removes /** Deletion procedure, which searches for the input key in the tree and removes
// it if present * it if present
* @param root pointer to parent node
* @param data value to search for int the node
* @returns pointer to parent node
*/
node *delete (node *root, int data) node *delete (node *root, int data)
{ {
// If the root is null, nothing to be done // If the root is null, nothing to be done
if (root == NULL) if (root == NULL)
{
return root; return root;
// If the input key is greater than the root's, search in the right subtree }
else if (data > root->data) else if (data > root->data)
{ // If the input key is greater than the root's, search in the right
// subtree
root->right = delete (root->right, data); root->right = delete (root->right, data);
// If the input key is lower than the root's, search in the left subtree }
else if (data < root->data) else if (data < root->data)
{ // If the input key is lower than the root's, search in the left subtree
root->left = delete (root->left, data); root->left = delete (root->left, data);
// If the input key matches the root's, check the following cases }
// termination condition
else if (data == root->data) else if (data == root->data)
{ {
// Case 1: the root has no leaves, remove the node // If the input key matches the root's, check the following cases
// termination condition
if ((root->left == NULL) && (root->right == NULL)) if ((root->left == NULL) && (root->right == NULL))
{ { // Case 1: the root has no leaves, remove the node
free(root); free(root);
return NULL; return NULL;
} }
// Case 2: the root has one leaf, make the leaf the new root and remove
// the old root
else if (root->left == NULL) else if (root->left == NULL)
{ { // Case 2: the root has one leaf, make the leaf the new root and
// remove
// the old root
node *tmp = root; node *tmp = root;
root = root->right; root = root->right;
free(tmp); free(tmp);
@ -104,10 +126,10 @@ node *delete (node *root, int data)
free(tmp); free(tmp);
return root; return root;
} }
// Case 3: the root has 2 leaves, find the greatest key in the left
// subtree and switch with the root's
else else
{ { // Case 3: the root has 2 leaves, find the greatest key in the left
// subtree and switch with the root's
// finds the biggest node in the left branch. // finds the biggest node in the left branch.
node *tmp = getMax(root->left); node *tmp = getMax(root->left);
@ -120,30 +142,55 @@ node *delete (node *root, int data)
return root; return root;
} }
// Search procedure, which looks for the input key in the tree and returns 1 if /** Search procedure, which looks for the input key in the tree and returns 1 if
// it's present or 0 if it's not in the tree * it's present or 0 if it's not in the tree
* @param root pointer to parent node
* @param data value to store int he new node
* @returns 0 if value not found in the nodes
* @returns 1 if value was found
*/
int find(node *root, int data) int find(node *root, int data)
{ {
// If the root is null, the key's not present // If the root is null, the key's not present
if (root == NULL) if (root == NULL)
{
return 0; return 0;
// If the input key is greater than the root's, search in the right subtree }
else if (data > root->data) else if (data > root->data)
{
// If the input key is greater than the root's, search in the right
// subtree
return find(root->right, data); return find(root->right, data);
// If the input key is lower than the root's, search in the left subtree }
else if (data < root->data) else if (data < root->data)
{
// If the input key is lower than the root's, search in the left subtree
return find(root->left, data); return find(root->left, data);
// If the input and the root key match, return 1 }
else if (data == root->data) else if (data == root->data)
{
// If the input and the root key match, return 1
return 1; return 1;
} }
else
{ // unknown result!!
return 0;
}
}
// Utilitary procedure to measure the height of the binary tree /** Utilitary procedure to measure the height of the binary tree
* @param root pointer to parent node
* @param data value to store int he new node
* @returns 0 if value not found in the nodes
* @returns height of nodes to get to data from parent node
*/
int height(node *root) int height(node *root)
{ {
// If the root is null, this is the bottom of the tree (height 0) // If the root is null, this is the bottom of the tree (height 0)
if (root == NULL) if (root == NULL)
{
return 0; return 0;
}
else else
{ {
// Get the height from both left and right subtrees to check which is // Get the height from both left and right subtrees to check which is
@ -154,27 +201,40 @@ int height(node *root)
// The final height is the height of the greatest subtree(left or right) // The final height is the height of the greatest subtree(left or right)
// plus 1(which is the root's level) // plus 1(which is the root's level)
if (right_h > left_h) if (right_h > left_h)
{
return (right_h + 1); return (right_h + 1);
}
else else
{
return (left_h + 1); return (left_h + 1);
} }
} }
}
// Utilitary procedure to free all nodes in a tree /** Utilitary procedure to free all nodes in a tree
* @param root pointer to parent node
*/
void purge(node *root) void purge(node *root)
{ {
if (root != NULL) if (root != NULL)
{ {
if (root->left != NULL) if (root->left != NULL)
{
purge(root->left); purge(root->left);
}
if (root->right != NULL) if (root->right != NULL)
{
purge(root->right); purge(root->right);
}
free(root); free(root);
root = NULL; // reset pointer
} }
} }
// Traversal procedure to list the current keys in the tree in order of value /** Traversal procedure to list the current keys in the tree in order of value
// (from the left to the right) * (from the left to the right)
* @param root pointer to parent node
*/
void inOrder(node *root) void inOrder(node *root)
{ {
if (root != NULL) if (root != NULL)
@ -185,7 +245,8 @@ void inOrder(node *root)
} }
} }
void main() /** Main funcion */
int main()
{ {
// this reference don't change. // this reference don't change.
// only the tree changes. // only the tree changes.
@ -218,7 +279,9 @@ void main()
root = delete (root, data); root = delete (root, data);
} }
else else
{
printf("Tree is already empty!\n"); printf("Tree is already empty!\n");
}
break; break;
case 3: case 3:
@ -240,4 +303,6 @@ void main()
// deletes the tree from the heap. // deletes the tree from the heap.
purge(root); purge(root);
return 0;
} }