7

i know how to build it with n insertions ( each with O(log(n)) efficiency ) (n*log(n)) overall ,i also know that the equivalent structure of 2-3-4 tree can also be build with linear time from sorted array. can anyone please provide a simple explanation about the red-black version?

Michael G
  • 1,190
  • 8
  • 12

4 Answers4

11

No matter what kind of BST you are going to build. The algorithm will be the same. Only need to build balanced binary tree.

  1. Place middle element to the current position
  2. Place [begin; middle) elements to the left subtree.
  3. Place (middle; end) elements to the right subtree.

This is O(N) algorithm. It can be shown, that the result tree will be balanced.

We have balanced tree, so by definition:

length(longest path) - length(shortest path) <= 1

So you need to mark all nodes as black, except the deepest nodes in the tree (mark them as red).

SashaMN
  • 708
  • 5
  • 16
4

A complete binary tree of height H has 2^H-1 nodes.

To make a red black tree from a sorted list:

  1. Remove every second item from the list until you have 2^H-1 items remaining for some H. Note that you will always have enough.
  2. Build a complete tree out of the remaining items, all black.
  3. Now attach all the items you removed to the tree. Each item will be a red node, attached to whichever of the black nodes around its proper position is a leaf.

The easiest way to do step (3) is just to do a pre-order traversal of the tree, attaching new red nodes to every black leaf until you run out of items.

NOTE: Sasha's algorithm also works, but this one obviously works.

Matt Timmermans
  • 53,709
  • 3
  • 46
  • 87
0

From a functional data structure perspective: there is a paper for Constructing Red-Black Trees, which discovered the pattern of continuous insertion and related it to 1-2 number system.

It's a fun read.

junjiah
  • 318
  • 2
  • 7
0

For a working example implemented in Java, you may want to check out the method buildFromSorted(int level, int lo, int hi, int redLevel, ...) in Java.util.TreeMap.

One more comment about Java in particular: Unfortunately, if you have your own data structured in a sorted manner (e.g. as sorted ArrayLists), it is not so easy to get it into a TreeMap in a linear manner. One possibility however is to create your own implementation of a SortedMap or NavigableMap which is backed up by an ArrayList internally. Then it is possible to use this constructor to efficiently construct the TreeMap:

    MySortedMap myMap = new MySortedMap(keyArray, valueArray);
    new TreeMap<K, V> (myMap)

Here is some sample code for doing so:

    public class MySortedMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V> {

        private ArrayList<K> keyArray;
        private ArrayList<V> valueArray;

        public Set<Map.Entry<K,V>> entrySet() {
            return new EntrySet();
        }

        class EntryIterator implements Iterator<Map.Entry<K,V>> {

            int i;

            public EntryIterator () {
                i = 0;
            }


            @Override
            public boolean hasNext() {
                if (i < keyArray.size()) {
                    return true;
                } else {
                    return false;
                }
            }

            @Override
            public Map.Entry<K,V> next() {
                if (hasNext()) {
                    Map.Entry<K,V> en = new Entry<K,V> (keyArray.get(i), valueArray.get(i));
                    i++;
                    return en;
                } else {
                    return null;
                }
            }
        }

        final class Entry<K,V> implements Map.Entry<K,V> {
            K key;
            V value;

            @Override
            public K getKey() {
                return key;
            }

            @Override
            public V getValue() {
                return value;
            }

            @Override
            public V setValue(V value) {
                this.value = value;
                return value;
            }

            public Entry(K key, V value) {
                this.key = key;
                this.value = value;
            }
        }

        class EntrySet extends AbstractSet<Map.Entry<K,V>> {
            public Iterator<Map.Entry<K,V>> iterator() {
                return new EntryIterator();
            }

            public int size() {
                return keyArray.size();
            }

            
        }

        public MySortedMap (ArrayList<K> keyArray, ArrayList<V> valueArray) {
            if (keyArray.size() != valueArray.size()) {
                throw new RuntimeException("Key and value arrays must have the same length!");
            }

            this.keyArray = keyArray;
            this.valueArray = valueArray;
        }

        ... some unused methods ...
    }
Rauni Lillemets
  • 2,299
  • 1
  • 26
  • 39