@Override
    public void propagateQueries() {
        Set<Node> currentNodesSetTemp; // stores the new set of current nodes
        // while the "old" set of current nodes are being added to the
        // set of visited nodes.
        
        /* Does the following for each search query. */
        for (int iQuery = 0; iQuery < searchQueriesMap.size(); iQuery++) {
            final Query currentQuery = searchQueriesMap.get(iQuery);
            
            currentNodesSetTemp = new HashSet<Node>();  // stores the set of
            // nodes that receive the query during this propagation step and
            // will become the current nodes for the next propagation step
            
            /*
             * Checks to see if this is the first hop of the query. If so,
             * initialize the previous hop structure.
             */
            ArrayList<Integer> prevHopArrayList;
            
            if (currentQuery.isFirstHop()) {
                prevHopArrayList = new ArrayList<Integer>();
                
                currentQuery.getCurrentNodesPrevHopMap().put(-1,
                        prevHopArrayList);
            }
            
            /* Checks that the TTL for the current query has not expired. */
            if (ttlMap.get(currentQuery.getQueryID()) > 0) {
                
                /* Iterates over each node in the set of current nodes. */
                final Iterator<Node> itCurrentNodes =
                        currentQuery.getCurrentNodesSet().iterator();
                
                while (itCurrentNodes.hasNext()) {
                    final Node aCurrentNode = itCurrentNodes.next();
                    
                    /*
                     * Picks a random neighbour of the current node.
                     *
                     * NOTE: To pick a random neighbour except for the
                     * node that sent it the message, uncomment the do/while loop
                     * in the code below. This essentially means that the ranom walk
                     * has a memory of one hop.
                     *
                     * An exception is made if the degree of the current node is one,
                     * in which case it is allowed to send the query back to the
                     * previous hop so as to avoid deadlock.
                     */
                    Node aRandomNeighbour;
                    
//                    do {
                    aRandomNeighbour = aCurrentNode.pickRandomNeighbour();
//                    } while ((!currentQuery.getCurrentNodesPrevHopMap().get(-1)
//                        .isEmpty()) &&
//                        (currentQuery.getCurrentNodesPrevHopMap().get(-1)
//                            .get(0) == aRandomNeighbour.getNodeID()) &&
//                        (aCurrentNode.degree() > 1));
                    
                    /*
                     * Forwards the query (i.e. the selected neighbour becomes a
                     * current node).
                     */
                    currentNodesSetTemp.add(aRandomNeighbour);
                    
                    /* Adds the neighbour to the list of visited nodes. */
                    currentQuery.getVisitedNodesSet().add(aRandomNeighbour);
                    
                    /*
                     * Stores previous hop information.
                     *
                     * As the implementation of "currentNodesPrevHopMap"
                     * differs for each search type, the following search
                     * uses the following:
                     *
                     * Only the key "-1" is used to loop up the list of node IDs
                     * that make up the path from the current node right back to the
                     * source. The reason for using "-1" is to not confuse the
                     * implementation that flooding uses, which uses current node IDs
                     * to look up previous hop information. Newly visited nodes are
                     * added to the front of this list.
                     */
                    prevHopArrayList =
                            currentQuery.getCurrentNodesPrevHopMap().get(-1);
                    prevHopArrayList.add(0, aCurrentNode.getNodeID());
                    currentQuery.getCurrentNodesPrevHopMap().put(-1,
                            prevHopArrayList);
                    
                    /* Decrements TTL. */
                    ttlMap.put(iQuery, ttlMap.get(iQuery) - 1);
                    
                    /*
                     * Increments the total number of messages send since the
                     * beginning of the search.
                     */
                    nTotalMessages++;
                    
                }
                
                /* Updates the query after it has made its first hop. */
                if (currentQuery.isFirstHop()) {
                    currentQuery.setFirstHop(false);
                }
            }
            
            /*
             * Updates the current node sets with the temporary sets created
             * locally.
             */
            currentQuery.setCurrentNodesSet(currentNodesSetTemp);
        }
        
        /*
         * Increments the number of elapsed time steps since
         * the beginning of the search.
         */
        nTotalTime++;
        
        /* Updates the network panel and information display. */
        searchCoordinator.getNetworkPanel().repaint();
        searchCoordinator.getControlPanel().getInformationNumberOfTimeLabel()
                .setText(Integer.toString(nTotalTime));
        searchCoordinator.getControlPanel()
                .getInformationNumberOfMessagesLabel().setText(
                        Integer.toString(nTotalMessages));
    }