@Override
    public List<T> search(final T source, final T target) {
        checkNotNull(source, "Source is null.");
        checkNotNull(target, "Target is null.");
        parentMapA.clear();
        parentMapB.clear();
        
        parentMapA.put(source, null);
        parentMapB.put(target, null);
        
        Deque<T> queueA = new LinkedList<T>();
        Deque<T> queueB = new LinkedList<T>();
        
        queueA.addLast(source);
        queueB.addLast(target);
        
        while (queueA.size() != 0 && queueB.size() != 0) {
            T current = queueA.removeFirst();
            
            if (parentMapB.containsKey(current)) {
                return tracebackPathBidirectional(current, 
                                                  parentMapA, 
                                                  parentMapB);
            }
            
            for (final T neighbour : current) {
                if (parentMapA.containsKey(neighbour) == false) {
                    parentMapA.put(neighbour, current);
                    queueA.addLast(neighbour);
                }
            }
            
            current = queueB.removeFirst();
            
            if (parentMapA.containsKey(current)) {
                return tracebackPathBidirectional(current, 
                                                  parentMapA,
                                                  parentMapB);
            }
            
            for (final T neighbour : current) {
                if (parentMapB.containsKey(neighbour) == false) {
                    parentMapB.put(neighbour, current);
                    queueB.addLast(neighbour);
                }
            }
        }
        
        return Collections.<T>emptyList();
    }