Treap

A treap is a binary search tree that uses randomized priorities to be self-balancing in expectation. It combines properties of binary search trees and heaps.

Java example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Node {
  int key, priority, size; 
  Node left, right;

  public Node(int key) {
    this.key = key;
    priority = rand.nextInt();
    size = 1;
  }
}

Node insert(Node root, int key) {
  if (root == null) {
    return new Node(key);
  }
  
  if (key < root.key) {
    root.left = insert(root.left, key);
  } else {
    root.right = insert(root.right, key);
  }
  
  if (root.left != null && root.left.priority > root.priority) {
    // rotate right
  }

  if (root.right != null && root.right.priority > root.priority) {   
    // rotate left
  }

  // update size

  return root;
}

C++ example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
struct Node {
  int key, priority, size;
  Node *left, *right;

  Node(int k) : key(k) {
    priority = rand();
    size = 1;
  }
};

Node* insert(Node* root, int key) {
  if (root == nullptr) 
    return new Node(key);

  if (key < root->key) {
    root->left = insert(root->left, key); 
  } else {
    root->right = insert(root->right, key);
  }

  // rotations, size, etc

  return root;
}

Python example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import random

class Node:

  def __init__(self, key):
    self.key = key
    self.priority = random.random()
    self.size = 1
    self.left = None
    self.right = None

def insert(root, key):
  if root is None:
    return Node(key)

  if key < root.key:  
    root.left = insert(root.left, key)
  else:
    root.right = insert(root.right, key)

  # rotations, size, etc

  return root

Treaps provide average O(log n) time for operations with efficient priority-based balancing.

A Treap is a hybrid data structure that combines the properties of a binary search tree (BST) and a heap. In a Treap, each node has a key and a priority. The key follows the rules of a binary search tree, while the priority obeys the heap property. Specifically, keys are ordered just like in a BST, and priorities are organized so that parent nodes have higher priorities than their children. This dual structure guarantees that the Treap is balanced probabilistically, ensuring expected logarithmic time complexity for operations like insert, delete, and search.

Java Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import java.util.Random;

class Node {
    int key, priority;
    Node left, right;

    public Node(int key) {
        this.key = key;
        this.priority = new Random().nextInt(100);
    }
}

public class Treap {
    Node root;

    // Right Rotation
    public Node rightRotate(Node y) {
        Node x = y.left;
        y.left = x.right;
        x.right = y;
        return x;
    }

    // Left Rotation
    public Node leftRotate(Node x) {
        Node y = x.right;
        x.right = y.left;
        y.left = x;
        return y;
    }

    public Node insert(Node root, int key) {
        if (root == null) return new Node(key);

        if (key <= root.key) {
            root.left = insert(root.left, key);
            if (root.left.priority > root.priority) {
                root = rightRotate(root);
            }
        } else {
            root.right = insert(root.right, key);
            if (root.right.priority > root.priority) {
                root = leftRotate(root);
            }
        }

        return root;
    }
}

In Java, we define a Node class with key and priority fields. The Treap class contains methods for right and left rotations, and an insert method that considers both key and priority.

C++ Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <cstdlib>
#include <ctime>

struct Node {
    int key, priority;
    Node *left, *right;

    Node(int key) : key(key), priority(rand() % 100), left(nullptr), right(nullptr) {}
};

class Treap {
public:
    Node* root;

    Node* rightRotate(Node* y) {
        Node* x = y->left;
        y->left = x->right;
        x->right = y;
        return x;
    }

    Node* leftRotate(Node* x) {
        Node* y = x->right;
        x->right = y->left;
        y->left = x;
        return y;
    }

    Node* insert(Node* root, int key) {
        if (!root) return new Node(key);

        if (key <= root->key) {
            root->left = insert(root->left, key);
            if (root->left->priority > root->priority) {
                root = rightRotate(root);
            }
        } else {
            root->right = insert(root->right, key);
            if (root->right->priority > root->priority) {
                root = leftRotate(root);
            }
        }

        return root;
    }
};

In C++, we use a struct for Node and a class for Treap. The logic for rotations and insertions is similar to the Java implementation.

Python Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import random

class Node:
    def __init__(self, key):
        self.key = key
        self.priority = random.randint(0, 100)
        self.left = None
        self.right = None

class Treap:
    def __init__(self):
        self.root = None

    def right_rotate(self, y):
        x = y.left
        y.left = x.right
        x.right = y
        return x

    def left_rotate(self, x):
        y = x.right
        x.right = y.left
        y.left = x
        return y

    def insert(self, root, key):
        if root is None:
            return Node(key)

        if key <= root.key:
            root.left = self.insert(root.left, key)
            if root.left.priority > root.priority:
                root = self.right_rotate(root)
        else:
            root.right = self.insert(root.right, key)
            if root.right.priority > root.priority:
                root = self.left_rotate(root)

        return root

In Python, the Node and Treap classes are straightforward. The insert method is implemented recursively, just like in the Java and C++ versions.

The treap is useful for situations where you need both map (BST) and priority queue (heap) operations. It’s simple to implement, easy to understand, and the average-case time complexities are quite favorable.