public void node_free(int fidx, int size)
	{
		int idx, pidx = 0;
		FREE start;

		if (size <= 0 || fidx <= FREE_NODE) {
			System.err.println("node_free: wrong parameter");
			System.exit(0);
		}

		idx = free_head.next_idx;
		if (idx == FREE_NODE) {
			// if there was no free nodes, simply updates the header pointer with the new free node
			free_head.next_idx = fidx;					// the start index of free nodes		
			trie_buf[fidx].free.size = size;			// the size of free nodes
			trie_buf[fidx].free.next_idx = FREE_NODE;	// the end of the free node list
			return;
		}

		if (fidx < idx) {
			// the new free nodes are in front compared to the existing free node list
			free_head.next_idx	= fidx;
			if (idx == fidx + size) {
				// if they are consecutive, they are merged.
				trie_buf[fidx].free.size = size + trie_buf[idx].free.size;
				trie_buf[fidx].free.next_idx = trie_buf[idx].free.next_idx;
			} else {
				// if they are not consecutive, they are separated
				trie_buf[fidx].free.size = size;
				trie_buf[fidx].free.next_idx = idx;
			}
			return;
		}
		
		// checks the location of the existing free node list and merge them
		while (idx != FREE_NODE && idx < fidx) {
			pidx = idx;
			idx = trie_buf[idx].free.next_idx;
		}
		start = trie_buf[pidx].free;

		if (fidx + size == idx) {
			// free nodes in back
			size += trie_buf[idx].free.size;
			start.next_idx = trie_buf[idx].free.next_idx;
		}

		if (pidx + start.size == fidx) {
			// free nodes in front
			start.size += size;
		} else {
			// merges the free nodes
			trie_buf[fidx].free.size = size;
			trie_buf[fidx].free.next_idx = start.next_idx;
			start.next_idx = fidx;
		}
	}