Created: 2023-10-02 22:21
Status: #concept
Subject: Programming
Tags: C Data Structure Linked List Tree Heap
Binary Tree
It is a Node-based hierarchal data structure where a single node branches out to two other nodes,
left
and right
.Subtypes of Binary Trees
The height of a binary tree is defined as the number of Edges from the root node to the deepest leaf node.
- Full or Perfect Binary Tree
- every node, except the Leaves, has exactly two children.
- it has
nodes, where h
is the height (number of edges to the leaf) of the tree.
- Complete Binary Tree
- every level of the tree is completely filled, except for the last level which can be partially filled.
- new nodes are inserted starting from the leftmost side of the last level.
- Balanced Binary Tree
- the height of the left & right subtrees of every node differ by at most
1
.
- the height of the left & right subtrees of every node differ by at most
Kinds of Traversals
These traversals allow us to list out or
printf
the elements of a tree.
- Depth-First Search (DFS)
- Breadth-First Search (BFS)
Array Implementation
An array can represent a tree, where the indices represent positon of the nodes of a tree and the elements are the values inside each node.
Let parent
, leftChild
, rightChild
, child
be valid indices of an array a
.
We can derive the formula to get the nodes like so:
leftChild = (2*parent) + 1
rightChild = (2*parent) + 2
parent = (child-1) / 2
#define MAX 10
typedef struct heap {
int arr[MAX];
int lastIndex;
} HeapType;
Since we always insert elements into the next available leaf node, this is a Complete Binary Tree.
Binary Search Trees
The node
.data
must be more than .left->data
and less than .right->data
.
- each node must have one parent, excluding the root node.
- these nodes are called "branches".
- each parent node can branch out UP TO 2 children nodes.
- a node with no children is called a "leaf".
typedef struct node {
int data;
struct node *left;
struct node *right;
} TreeNode, *Root;
Functions
// Creates a new TreeNode with data
TreeNode createNode(int data) {
TreeNode *newNode = malloc(sizeof(TreeNode));
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
// Finds the sum of all the data members of a Root
int sum(Root root) {
if (root == NULL) {
return 0;
}
return root->data + sum(root->left) + sum(root->right);
}
// Inserts a node in its proper position
void insert(Root *node, int data) {
if (*node == NULL) {
*node = createNode(data);
} else if (data < (*node)->elem) {
insert(&(*node)->LC, data);
} else {
insert(&(*node)->RC, data);
}
}
// Searches the tree for a target element
bool isMember(Node root, int target) {
if (root != NULL && target < root->elem) {
return isMember(root->LC, target);
} else if (root != NULL && target > root->elem) {
return isMember(root->RC, target);
} else {
return root == NULL ? false : true;
}
}
bool isMemberIterative(Node root, int target) {
while (root != NULL && root->elem != target) {
if (target < root->elem) {
root = root->LC;
} else {
root = root->RC;
}
}
return root == NULL ? false : true;
}
void delete(Node *root, int target) {
// first traverse to the node toDelete while keeping track of parent node
Node *trav;
for (trav = root; *trav != NULL && (*trav)->elem != target;) {
trav = (target < (*trav)->elem) ? &(*trav)->LC : &(*trav)->RC;
}
// trav is the node to delete
if (*trav != NULL) {
// node has two children
// SO, we swap the min((*trav)->RC) value with the node to delete
if ((*trav)->LC != NULL && (*trav)->RC != NULL) {
Node *min;
for (min = &(*trav)->RC; (*min)->LC != NULL; min = &(*min)->LC) {
// we are traversing until we reach the leaf node
}
// swap min value with node to delete
(*trav)->elem = (*min)->elem;
// free the min node
Node tmp = *min;
*min = NULL;
free(tmp);
}
// node to delete is a leaf node
// SO, just make parent point to NULL
else if ((*trav)->LC == NULL && (*trav)->RC == NULL) {
Node tmp = *trav;
*trav = NULL;
free(tmp);
}
// node to delete has one child
// SO, we let parent point to that child and then free the deleted node
else {
Node tmp = *trav;
*trav = (*trav)->LC != NULL ? (*trav)->LC : (*trav)->RC;
free(tmp);
}
}
}