public Itemsets runAlgorithm(String output, TransactionDatabase database, double minsupp) throws IOException {

        // if the user want to keep the result into memory
        if (output == null) {
            writer = null;
            frequentItemsets = new Itemsets("FREQUENT ITEMSETS");
        } else { // if the user want to save the result to a file
            frequentItemsets = null;
            writer = new BufferedWriter(new FileWriter(output));
        }

        // reset the number of itemset found to 0
        itemsetCount = 0;

        this.database = database;

        // record the start time
        startTimestamp = System.currentTimeMillis();

        // convert from an absolute minsup to a relative minsup by multiplying
        // by the database size
        this.minsupRelative = (int) Math.ceil(minsupp * database.size());

        // A set that will contains all transactions IDs
        Set<Integer> allTIDS = new HashSet<Integer>();

        // (1) First database pass : calculate tidsets of each item.

        int maxItemId = 0;
        // This map will contain the tidset of each item
        // Key: item   Value :  tidset
        final Map<Integer, Set<Integer>> mapItemCount = new HashMap<Integer, Set<Integer>>();
        // for each transaction
        for (int i = 0; i < database.size(); i++) {
            // add the transaction id to the set of all transaction ids
            allTIDS.add(i);
            // for each item in that transaction
            for (Integer item : database.getTransactions().get(i)) {
                // add the transaction ID to the tidset of that item
                Set<Integer> set = mapItemCount.get(item);
                if (set == null) {
                    set = new HashSet<Integer>();
                    mapItemCount.put(item, set);
                    // if the current item is larger than all items until                    
                    if (item > maxItemId) {
                        maxItemId = item;
                    }
                }
                set.add(i); // add tid to the tidset of the item
            }
        }
        
        // (2) create ITSearchTree with root node
        ITSearchTree tree = new ITSearchTree();
        // add the empty set
        ITNode root = new ITNode(new Itemset());
        // the empty set as all tids as its tidset
        root.setTidset(allTIDS);
        tree.setRoot(root);

        // (3) create childs of the root node.
        for (Entry<Integer, Set<Integer>> entry : mapItemCount.entrySet()) {
            // we only add nodes for items that are frequents
            if (entry.getValue().size() >= minsupRelative) {
                // create a new node for that item
                Itemset itemset = new Itemset();
                itemset.addItem(entry.getKey());
                ITNode newNode = new ITNode(itemset);
                // set its tidset as the tidset that we have calculated previously
                newNode.setTidset(entry.getValue());
                // set its parent as the root
                newNode.setParent(root);
                // add the new node as child of the root node
                root.getChildNodes().add(newNode);
            }
        }

        // save root node
        save(root);

        // for optimization
        sortChildren(root);

        // while there is at least one child node of the root
        while (root.getChildNodes().size() > 0) {
            // get the first child node
            ITNode child = root.getChildNodes().get(0);
            // extend it
            extend(child);
            // save it
            save(child);
            // delete it
            delete(child);
        }

        // close the output file if the result was saved to a file
        if (writer != null) {
            writer.close();
        }

        // record the end time for statistics
        endTime = System.currentTimeMillis();

        return frequentItemsets; // Return all frequent itemsets found!
    }