path compression and union by rank