What is the most efficient way to access certain items in a SortedSet?

I want to use a sorted selection, but I can access the elements by index, i.e. I want something that has the characteristics of both a set and a list. Java.util.TreeSet is suitable for what I need, but does not allow index access.

I can present several options:

  • I could iterate through a TreeSet every time I needed a specific item.
  • I could support a TreeSet and generate a List from it when I needed to access a specific item.
  • Same as above, only cache the list until Set changes.
  • I could have a List and sort it myself when I needed to add an item.
  • and etc.

There are various tradeoffs between the various options. I hope someone can give me some good advice. To answer potential questions about “why would you ever want to do this?”, Read about the Apriori algorithm .

+2
source share
4 answers

I had the same problem. So I took the source code of java.util.TreeMap and wrote IndexedTreeMap . It implements my own IndexedNavigableMap :

public interface IndexedNavigableMap<K, V> extends NavigableMap<K, V> {
   K exactKey(int index);
   Entry<K, V> exactEntry(int index);
   int keyIndex(K k);
}

The implementation is based on updating the node weights in the red-black tree when it changes. Weight is the number of child nodes below a given node, plus one. For example, when a tree rotates left:

    private void rotateLeft(Entry<K, V> p) {
    if (p != null) {
        Entry<K, V> r = p.right;

        int delta = getWeight(r.left) - getWeight(p.right);
        p.right = r.left;
        p.updateWeight(delta);

        if (r.left != null) {
            r.left.parent = p;
        }

        r.parent = p.parent;


        if (p.parent == null) {
            root = r;
        } else if (p.parent.left == p) {
            delta = getWeight(r) - getWeight(p.parent.left);
            p.parent.left = r;
            p.parent.updateWeight(delta);
        } else {
            delta = getWeight(r) - getWeight(p.parent.right);
            p.parent.right = r;
            p.parent.updateWeight(delta);
        }

        delta = getWeight(p) - getWeight(r.left);
        r.left = p;
        r.updateWeight(delta);

        p.parent = r;
    }
  }

updateWeight :

   void updateWeight(int delta) {
        weight += delta;
        Entry<K, V> p = parent;
        while (p != null) {
            p.weight += delta;
            p = p.parent;
        }
    }

, , :

public K exactKey(int index) {
    if (index < 0 || index > size() - 1) {
        throw new ArrayIndexOutOfBoundsException();
    }
    return getExactKey(root, index);
}

private K getExactKey(Entry<K, V> e, int index) {
    if (e.left == null && index == 0) {
        return e.key;
    }
    if (e.left == null && e.right == null) {
        return e.key;
    }
    if (e.left != null && e.left.weight > index) {
        return getExactKey(e.left, index);
    }
    if (e.left != null && e.left.weight == index) {
        return e.key;
    }
    return getExactKey(e.right, index - (e.left == null ? 0 : e.left.weight) - 1);
}

:

    public int keyIndex(K key) {
    if (key == null) {
        throw new NullPointerException();
    }
    Entry<K, V> e = getEntry(key);
    if (e == null) {
        throw new NullPointerException();
    }
    if (e == root) {
        return getWeight(e) - getWeight(e.right) - 1;//index to return
    }
    int index = 0;
    int cmp;
    index += getWeight(e.left);

    Entry<K, V> p = e.parent;
    // split comparator and comparable paths
    Comparator<? super K> cpr = comparator;
    if (cpr != null) {
        while (p != null) {
            cmp = cpr.compare(key, p.key);
            if (cmp > 0) {
                index += getWeight(p.left) + 1;
            }
            p = p.parent;
        }
    } else {
        Comparable<? super K> k = (Comparable<? super K>) key;
        while (p != null) {
            if (k.compareTo(p.key) > 0) {
                index += getWeight(p.left) + 1;
            }
            p = p.parent;
        }
    }
    return index;
}

http://code.google.com/p/indexed-tree-map/

+1

:

  • , , FP-, ( ), , , , . Jiawei Han , Data Mining: Concepts and Techniques.

  • , ( , , - ). . : http://fimi.ua.ac.be/src/

  • , - List O(1), /. , - ( ).

+2

, Treeset apache API CollectionUtils.get()

0
source

I would look at LinkedHashSet . It supports the insertion order of a HashSet.

0
source

All Articles