Menu
×
   ❮   
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP C C++ C# AWS W3.CSS HOW TO BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS DSA TYPESCRIPT ANGULAR ANGULARJS GIT POSTGRESQL MONGODB ASP AI R GO KOTLIN SWIFT SASS VUE GEN AI SCIPY CYBERSECURITY DATA SCIENCE INTRO TO PROGRAMMING HTML & CSS BASH RUST TOOLS

C Tutorial

C HOME C Intro C Get Started C Syntax C Output C Comments C Variables C Data Types C Type Conversion C Constants C Operators C Booleans C If...Else C Switch C While Loop C For Loop C Break/Continue C Arrays C Strings C User Input C Memory Address C Pointers

C Functions

C Functions C Function Parameters C Scope C Function Declaration C Functions Challenge C Math Functions C Inline Functions C Recursion C Function Pointers

C Files

C Create Files C Write To Files C Read Files

C Structures

C Structures C Structs Challenge C Nested Structures C Structs & Pointers C Unions C typedef C Struct Padding

C Enums

C Enums

C Memory

C Memory Management

C Errors

C Errors C Error Challenge C Debugging C NULL C Error Handling C Input Validation

C More

C Date C Random Numbers C Macros C Organize Code C Storage Classes C Bitwise Operators C Fixed-width Integers

C DSA

C DSA Intro C Searching C Sorting C Stacks C Queues C Linked Lists C Trees C Big O

C Projects

C Projects

C Cert

C Certificate

C Reference

C Reference C Keywords C <stdio.h> C <stdlib.h> C <string.h> C <math.h> C <ctype.h> C <time.h>

C Examples

C Examples C Real-Life Examples C Exercises C Quiz C Code Challenges C Practice Problems C Compiler C Syllabus C Study Plan C Interview Q&A

C DSA Trees

Share

What is a Tree?

Like a linked list, a tree stores values in nodes that are connected with pointers. But in a tree, one node can point to several nodes.

A few words you will see a lot:

  • Root - the node at the top
  • Child - a node directly below another node (its parent)
  • Leaf - a node with no children

Binary Search Trees

In a binary tree, each node has at most two children: a left child and a right child.

A binary search tree (BST) adds one simple rule:

  • Smaller values go to the left.
  • Bigger values go to the right.
A binary search tree. The root is 50. Its left child is 30, with children 20 and 40. Its right child is 70, with children 60 and 80. Smaller values are always on the left, and bigger values on the right. root smaller bigger 50 30 70 20 40 60 80

Check the rule yourself: every value to the left of 50 is smaller than 50, and every value to the right is bigger. The same is true for 30 and 70.

This rule makes it very fast to find values. You will see why soon!


Create a Tree Node

A tree node looks like a linked list node, but with two pointers instead of one:

Example

struct Node {
  int data;
  struct Node *left;  // Smaller values
  struct Node *right; // Bigger values
};

Here is one node, with its two pointers:

One tree node. It has a data value, 50, and two pointers. left points to a node with a smaller value, 30. right points to a node with a bigger value, 70. left data right 50 30 70 smaller bigger

Insert Values

To insert a value, start at the root:

  1. If the value is smaller, go left. If it is bigger, go right.
  2. Repeat until you find an empty spot (NULL).
  3. Put the new node there.

"Repeat the same steps on a smaller part" is a perfect job for recursion. The insert() function calls itself on the left or right side.

We also add a function that prints the tree in order: first everything on the left, then the node itself, then everything on the right. Watch what happens:

Example

#include <stdio.h>
#include <stdlib.h>

struct Node {
  int data;
  struct Node *left;
  struct Node *right;
};

struct Node *createNode(int value) {
  struct Node *newNode = malloc(sizeof(struct Node));
  if (newNode == NULL) {
    printf("Memory allocation failed\n");
    exit(1);
  }
  newNode->data = value;
  newNode->left = NULL;
  newNode->right = NULL;
  return newNode;
}

struct Node *insert(struct Node *root, int value) {
  // Found an empty spot: put the new node here
  if (root == NULL) {
    return createNode(value);
  }
  if (value < root->data) {
    root->left = insert(root->left, value);   // Go left
  } else {
    root->right = insert(root->right, value); // Go right
  }
  return root;
}

void printInOrder(struct Node *root) {
  if (root == NULL) {
    return;
  }
  printInOrder(root->left);  // First, everything smaller
  printf("%d ", root->data); // Then this node
  printInOrder(root->right); // Then everything bigger
}

void freeTree(struct Node *root) {
  if (root == NULL) {
    return;
  }
  freeTree(root->left);
  freeTree(root->right);
  free(root);
}

int main() {
  struct Node *root = NULL;
  int values[] = {50, 70, 30, 80, 20, 60, 40};
  int length = sizeof(values) / sizeof(values[0]);

  for (int i = 0; i < length; i++) {
    root = insert(root, values[i]);
  }

  printInOrder(root);
  printf("\n");

  freeTree(root);
  return 0;
}

Result:

20 30 40 50 60 70 80 
Try it Yourself »

Did you see that? We inserted the values in a mixed order, but they came out sorted! That is the magic of the binary search tree rule. These seven values build exactly the tree in the picture above.

Example Explained

  • insert() walks left or right until it reaches NULL, and creates the new node there.
  • printInOrder() prints the left side, then the node, then the right side. Because smaller values are always on the left, the output is sorted.
  • freeTree() frees both children first, then the node itself. If it freed the node first, it would lose the pointers to the children.

Run the simulation below to see how the code above works, one step at a time. The green line is the pointer that just changed:



Search the Tree

Searching works just like inserting. At each node, the rule tells you which way to go, so you never have to look at the other side.

Does that sound familiar? It is the same idea as binary search: every check skips a big part of the values that are left.

The program uses the same createNode(), insert() and freeTree() functions as before. The new part is search(), which uses a simple loop and prints every node it checks:

Example

#include <stdio.h>
#include <stdlib.h>

struct Node {
  int data;
  struct Node *left;
  struct Node *right;
};

struct Node *createNode(int value) {
  struct Node *newNode = malloc(sizeof(struct Node));
  if (newNode == NULL) {
    printf("Memory allocation failed\n");
    exit(1);
  }
  newNode->data = value;
  newNode->left = NULL;
  newNode->right = NULL;
  return newNode;
}

struct Node *insert(struct Node *root, int value) {
  if (root == NULL) {
    return createNode(value);
  }
  if (value < root->data) {
    root->left = insert(root->left, value);
  } else {
    root->right = insert(root->right, value);
  }
  return root;
}

// Returns 1 (true) if the value is in the tree
int search(struct Node *root, int value) {
  struct Node *current = root;
  while (current != NULL) {
    printf("Checking %d\n", current->data);
    if (value == current->data) {
      return 1;                 // Found it
    }
    if (value < current->data) {
      current = current->left;  // Go left
    } else {
      current = current->right; // Go right
    }
  }
  return 0; // Not found
}

void freeTree(struct Node *root) {
  if (root == NULL) {
    return;
  }
  freeTree(root->left);
  freeTree(root->right);
  free(root);
}

int main() {
  struct Node *root = NULL;
  int values[] = {50, 70, 30, 80, 20, 60, 40};
  int length = sizeof(values) / sizeof(values[0]);

  for (int i = 0; i < length; i++) {
    root = insert(root, values[i]);
  }

  if (search(root, 60)) {
    printf("60 was found!\n");
  } else {
    printf("60 was not found.\n");
  }

  freeTree(root);
  return 0;
}

Result:

Checking 50
Checking 70
Checking 60
60 was found!
Try it Yourself »

Only 3 checks to find 60! In a large, well-shaped tree with 1,000,000 values, you need only about 20 checks.

Run the simulation below to see how the code above works, one step at a time. Grey nodes are the ones the search never has to look at:


Summary

  • A tree stores values in nodes, and each node can have children. The top node is the root.
  • In a binary search tree, smaller values go left and bigger values go right.
  • Insert and search by going left or right at each node, until you find the spot or the value.
  • Printing a binary search tree "in order" gives you the values sorted.

You have now seen that some ways to store and search data are much faster than others. But how do programmers measure "fast"? Find out in the next chapter!


Free account

Track your progress

XP earned 0 Day streak 0 Spaces 0 League —

New

Learn in Adventure Mode W3Schools Adventure App

Coding fundamentals as bite-sized lessons and challenges.

×

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail:
sales@w3schools.com

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail:
help@w3schools.com

W3Schools is optimized for learning and training. Examples might be simplified to improve reading and learning. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using W3Schools, you agree to have read and accepted our terms of use, cookies and privacy policy.

Copyright 1999-2026 by Refsnes Data. All Rights Reserved. W3Schools is Powered by W3.CSS.