Binary Tree :
If there are n
nodes, then in total there will be n-1
edges.
M
, J F B A are all ancestors.0
are called Leaf Nodes. Nodes whose degree > 0 are called Internal/Non-Leaf Nodes.A tree of degree 2. Every node can have maximum of 2 children.
If n
nodes are given, then
h
to the left side of the =
sign.Also called a Strict/Proper/Complete Binary Tree.
We can fill the elements in the array level-by-level, make sure to take into account empty nodes
1
, we can simply ignore the index 0
and start from 1
.Full / Strict BT : A binary tree of height h
having maximum number of nodes.
RKV Sir :
Fill Binary Tree / Strict Binary Tree : 0 or 2 Child Nodes of a parent
Complete Binary Tree : Left Aligned Nodes hone chahiye, i.e. left side se nodes fill/add honge.
h
can have maximum of Book Definition :
Preorder : NLR
Inorder : LNR
Postorder : LRN
Example :
-1
as input value will mean that the node is empty / it doesn't exist.Create Node Structure: Define a structure to represent each node in the binary tree. Each node should contain data and pointers to its left and right children.
Create Queue Structure: Define a structure to represent the queue. Each node in the queue will contain a pointer to a tree node and a pointer to the next node in the queue.
Enqueue Root: Create the root node of the binary tree and enqueue it into the queue.
Loop Until Queue is Empty:
Repeat: Repeat the above steps until the queue becomes empty.
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
typedef struct Node Node;
#define newNode (Node *)malloc(sizeof(Node))
/* -------------------- Queue Starts -------------------- */
struct Node
{
int data;
Node *lchild;
Node *rchild;
};
struct Queue
{
int size;
int front;
int rear;
Node **Q;
};
void createQueue(Queue *q, int size)
{
q->size = size;
q->front = 0; // front and rear should not be at -1 but at 0 instead
q->rear = 0;
q->Q = (Node **)malloc(size * sizeof(Node *)); // Array of pointers
}
void enqueue(Queue *q, Node *x)
{
if ((q->rear + 1) % (q->size) == q->front)
cout << "Queue is Full\n";
else
{
q->rear = (q->rear + 1) % (q->size);
q->Q[q->rear] = x;
}
}
Node *dequeue(Queue *q)
{
Node *x = NULL;
if (q->front == q->rear)
cout << "Queue is empty\n";
else
{
q->front = (q->front + 1) % (q->size);
x = q->Q[q->front];
}
return x;
}
void Display(Queue q)
{
int i = q.front + 1;
do
{
cout << q.Q[i];
i = (i + 1) % q.size;
} while (i != (q.rear + 1) % (q.size));
cout << endl;
}
int isEmpty(struct Queue q)
{
return q.front == q.rear;
}
/* --------------------- Queue Ends --------------------- */
struct Node *root = NULL;
void create()
{
struct Node *p, *t;
int x;
struct Queue q;
createQueue(&q, 100);
printf("Enter Root Value: ");
scanf("%d", &x);
root = newNode;
root->data = x;
root->lchild = root->rchild = NULL;
enqueue(&q, root);
while (!isEmpty(q))
{
p = dequeue(&q);
printf("enter left child of %d: ", p->data);
scanf("%d", &x);
if (x != -1)
{
t = newNode;
t->data = x;
t->lchild = t->rchild = NULL;
p->lchild = t;
enqueue(&q, t);
}
printf("enter right child of %d: ", p->data);
scanf("%d", &x);
if (x != -1)
{
t = newNode;
t->data = x;
t->lchild = t->rchild = NULL;
p->rchild = t;
enqueue(&q, t);
}
}
}
void preorder(Node *p)
{
if (p)
{
printf("%d", p->data);
preorder(p->lchild);
preorder(p->rchild);
}
}
void Inorder(struct Node *p)
{
if (p)
{
Inorder(p->lchild);
printf("%d ", p->data);
Inorder(p->rchild);
}
}
void Postorder(struct Node *p)
{
if (p)
{
Postorder(p->lchild);
Postorder(p->rchild);
printf("%d ", p->data);
}
}
int main()
{
create();
preorder(root);
return 0;
}
DIY : Easy hai
This is a little complex.
Nodes will be printed level by level from left to right.
If only one type of order is given then total number of possible tree formations are :
If Preorder + Postorder is given then more than one (i.e. 1+) trees are possible.
Preorder + Inorder and Postorder + Inorder will give only 1 tree structure.
Time Complexity is
Recursive Approach :
Iterative Approach :
RKV Sir Lab Question Code :
#include <stdio.h>
#include <stdlib.h>
typedef struct Node Node;
#define newNode (struct Node *)malloc(sizeof(struct Node))
// Similar to question 1
struct Node
{
int data;
struct Node *lchild;
struct Node *rchild;
};
struct Node *createNode(int data)
{
struct Node *p = newNode;
if (p != NULL)
{
p->data = data;
p->lchild = p->rchild = NULL;
}
return p;
}
struct Node *insertNode(struct Node *root, int data)
{
if (root == NULL)
{
root = createNode(data);
}
else if (data <= root->data) // Should be < and not<=
{
root->lchild = insertNode(root->lchild, data);
}
else // shoule be else if (data > root->data)
{
root->rchild = insertNode(root->rchild, data);
}
return root;
}
void inorderTraversal(struct Node *root)
{
if (root != NULL)
{
inorderTraversal(root->lchild);
printf("%d ", root->data);
inorderTraversal(root->rchild);
}
}
int main()
{
struct Node *root = NULL;
int elements[] = {13, 3, 4, 12, 14, 10, 5, 1, 8, 2, 7, 9, 11, 6, 18};
int n = sizeof(elements) / sizeof(elements[0]);
for (int i = 0; i < n; i++)
{
root = insertNode(root, elements[i]);
}
printf("BST before insertion: ");
inorderTraversal(root);
printf("\n");
// inserting nodes in the BST
root = insertNode(root, 16);
root = insertNode(root, 577);
printf("BST after insertion: ");
inorderTraversal(root);
printf("\n");
return 0;
}
struct Node *insertNode(struct Node *root, int data)
{
if (root == NULL)
root = createNode(data);
else if (data < root->data)
root->lchild = insertNode(root->lchild, data);
else if (data > root->data)
root->rchild = insertNode(root->rchild, data);
return root;
}
#include <iostream>
using namespace std;
class Node{
public:
Node* lchild;
int data;
Node* rchild;
};
class BST{
private:
Node* root;
public:
BST(){ root = nullptr; }
Node* getRoot(){ return root; }
void iInsert(int key);
void Inorder(Node* p);
Node* iSearch(int key);
Node* rInsert(Node* p, int key);
Node* rSearch(Node* p, int key);
Node* Delete(Node* p, int key);
int Height(Node* p);
Node* InPre(Node* p);
Node* InSucc(Node* p);
};
void BST::iInsert(int key) {
Node* t = root;
Node* p;
Node* r;
// root is empty
if (root == nullptr){
p = new Node;
p->data = key;
p->lchild = nullptr;
p->rchild = nullptr;
root = p;
return;
}
while(t != nullptr){
r = t;
if (key < t->data){
t = t->lchild;
} else if (key > t->data){
t = t->rchild;
} else {
return;
}
}
// Now t points at NULL and r points at insert location
p = new Node;
p->data = key;
p->lchild = nullptr;
p->rchild = nullptr;
if (key < r->data){
r->lchild = p;
} else {
r->rchild = p;
}
}
void BST::Inorder(Node* p) {
if (p){
Inorder(p->lchild);
cout << p->data << ", " << flush;
Inorder(p->rchild);
}
}
Node* BST::iSearch(int key) {
Node* t = root;
while (t != nullptr){
if (key == t->data){
return t;
} else if (key < t->data){
t = t->lchild;
} else {
t = t->rchild;
}
}
return nullptr;
}
Node* BST::rInsert(Node *p, int key) {
Node* t;
if (p == nullptr){
t = new Node;
t->data = key;
t->lchild = nullptr;
t->rchild = nullptr;
return t;
}
if (key < p->data){
p->lchild = rInsert(p->lchild, key);
} else if (key > p->data){
p->rchild = rInsert(p->rchild, key);
}
return p; // key == p->data?
}
Node* BST::rSearch(Node *p, int key) {
if (p == nullptr){
return nullptr;
}
if (key == p->data){
return p;
} else if (key < p->data){
return rSearch(p->lchild, key);
} else {
return rSearch(p->rchild, key);
}
}
Node* BST::Delete(Node *p, int key) {
Node* q;
if (p == nullptr){
return nullptr;
}
if (p->lchild == nullptr && p->rchild == nullptr){
if (p == root){
root = nullptr;
}
delete p;
return nullptr;
}
if (key < p->data){
p->lchild = Delete(p->lchild, key);
} else if (key > p->data){
p->rchild = Delete(p->rchild, key);
} else {
if (Height(p->lchild) > Height(p->rchild)){
q = InPre(p->lchild);
p->data = q->data;
p->lchild = Delete(p->lchild, q->data);
} else {
q = InSucc(p->rchild);
p->data = q->data;
p->rchild = Delete(p->rchild, q->data);
}
}
return p;
}
int BST::Height(Node *p) {
int x;
int y;
if (p == nullptr){
return 0;
}
x = Height(p->lchild);
y = Height(p->rchild);
return x > y ? x + 1 : y + 1;
}
Node* BST::InPre(Node *p) {
while (p && p->rchild != nullptr){
p = p->rchild;
}
return p;
}
Node* BST::InSucc(Node *p) {
while (p && p->lchild != nullptr){
p = p->lchild;
}
return p;
}
int main() {
BST bst;
// Iterative insert
bst.iInsert(10);
bst.iInsert(5);
bst.iInsert(20);
bst.iInsert(8);
bst.iInsert(30);
// Inorder traversal
bst.Inorder(bst.getRoot());
cout << endl;
// Iterative search
Node* temp = bst.iSearch(2);
if (temp != nullptr){
cout << temp->data << endl;
} else {
cout << "Element not found" << endl;
}
// Recursive search
temp = bst.rSearch(bst.getRoot(), 20);
if (temp != nullptr){
cout << temp->data << endl;
} else {
cout << "Element not found" << endl;
}
// Recursive insert
bst.rInsert(bst.getRoot(), 50);
bst.rInsert(bst.getRoot(), 70);
bst.rInsert(bst.getRoot(), 1);
bst.Inorder(bst.getRoot());
cout << "\n" << endl;
// Inorder predecessor and inorder successor
BST bs;
bs.iInsert(5);
bs.iInsert(2);
bs.iInsert(8);
bs.iInsert(7);
bs.iInsert(9);
bs.iInsert(1);
temp = bs.InPre(bs.getRoot());
cout << "InPre: " << temp->data << endl;
temp = bs.InSucc(bs.getRoot());
cout << "InSucc: " << temp->data << endl;
bs.Inorder(bs.getRoot());
cout << endl;
// Delete
bs.Delete(bs.getRoot(), 7);
bs.Inorder(bs.getRoot());
return 0;
}
To balance a node of an AVL tree we perform rotations.
Deletion from AVL tree is similar to Deletion from Binary Search Tree :
40
is inserted into the heap, but after insertion it no longer remains a Max Heap. Therefore we'll have to fix it.
40
with it's parent, for max heap if temp < A[i/2]
In heap we can only delete the largest element (we are talking about the max heap here) i.e. the root element. In other words only the highest priority element can be deleted from the heap.
We'll do the same thing in the array :
x
then move 5 at at the place of 40In array :
i
is the root, compare 2i and 2i+1 then compare the greater element with the parent and swap if child > root.#include <stdio.h>
#include <stdlib.h>
void swap(int *x, int *y)
{
int temp = *x;
*x = *y;
*y = temp;
}
void insert(int a[], int n)
{
int x = a[n];
int i = n;
while (i > 1 && a[i / 2] < x)
{
a[i] = a[i / 2];
i = i / 2;
}
a[i] = x;
}
int delete(int a[], int n)
{
int i = 1, j = 2 * i;
int x = a[i];
a[i] = a[n];
a[n] = x;
while (j < n - 1)
{
if (a[j + 1] > a[j])
j = j + 1;
if (a[j] > a[i])
{
swap(&a[i], &a[j]);
i = j;
j = 2 * i;
}
else
break;
}
return x;
}
int main()
{
int a[] = {0, 10, 20, 30, 25, 5, 40, 35};
for(int i =1; i<=7; i++)
insert(a, i);
for(int i = 7; i>=1; i--)
delete(a, i);
// Heap Sort
for(int i = 1; i<=7; i++)
printf("%d ", a[i]);
return 0;
}
create heap
we adjust from bottom to up and start from the first element of the array of binary tree where as in heapify
we adjust towards the bottom and start from the last element in the arraycreate heap
has O(n * log n)
time complexity.