diff --git a/tp4/lib_conjunto.c b/tp4/lib_conjunto.c
index 4515ee5dcdd7c1db59c97feafb3f565668e7e4e5..9bc64e231aeb3fafba4b1c451107676d1df605af 100644
--- a/tp4/lib_conjunto.c
+++ b/tp4/lib_conjunto.c
@@ -3,14 +3,23 @@
 #include "lib_conjunto.h"
 
 /* retorna a posicao de um elemento em um conjunto ([0..card-1]).
- * como um conjunto nao necessariamente eh ordenado, eh uma busca linear.
+ * como estamos trabalhando com conjuntos ordenados, eh uma busca binaria.
  * se o elemento nao esta no conjunto, retorna -1. */
 int busca_cjt(conjunto_t *c, int elemento) {
-	int pos = 0;
-	while (pos < cardinalidade_cjt(c) && c->v[pos] != elemento)
-		pos++;
+	int inicio = 0;
+	int fim = cardinalidade_cjt(c) - 1;
+	int meio = fim / 2;
+
+	while (inicio <= fim && c->v[meio] != elemento) {
+		if (elemento > c->v[meio]) {
+			inicio = meio + 1;
+		} else {
+			fim = meio - 1;
+		}
+		meio = (inicio + fim) / 2;
+	}
 
-	return pos >= cardinalidade_cjt(c) ? -1 : pos;
+	return inicio > fim ? -1 : meio;
 }
 
 conjunto_t *cria_cjt(int max) {
@@ -49,18 +58,23 @@ int insere_cjt(conjunto_t *c, int elemento) {
 	if (pertence_cjt(c, elemento))
 		return 1;
 
-	c->v[cardinalidade_cjt(c)] = elemento;
+	int i = cardinalidade_cjt(c);
+	while (i > 0 && c->v[i - 1] > elemento) {
+		c->v[i] = c->v[i - 1];
+		i--;
+	}
+	
+	c->v[i] = elemento;
 	c->card++;
 	return 1;
 }
 
 int retira_cjt(conjunto_t *c, int elemento) {
-	int pos = busca_cjt(c, elemento);
-	if (pos == -1)
+	if (!(pertence_cjt(c, elemento)))
 		return 0;
 
 	int i;
-	for(i = pos; i < cardinalidade_cjt(c)-1; i++) {
+	for(i = busca_cjt(c, elemento); i < cardinalidade_cjt(c)-1; i++) {
 		c->v[i] = c->v[i + 1];
 	}
 
@@ -104,10 +118,13 @@ conjunto_t *interseccao_cjt(conjunto_t *c1, conjunto_t *c2) {
 	if ( !(inter = cria_cjt(c1->max)) )
 		return NULL;
 	
+	conjunto_t **menor_cjt = cardinalidade_cjt(c1) < cardinalidade_cjt(c2) ? &c1 : &c2;
+	conjunto_t **maior_cjt = cardinalidade_cjt(c1) > cardinalidade_cjt(c2) ? &c1 : &c2;
+
 	int i;
-	for (i = 0; i < cardinalidade_cjt(c1); i++) {
-		if (pertence_cjt(c2, c1->v[i]))
-			insere_cjt(inter, c1->v[i]);
+	for (i = 0; i < cardinalidade_cjt(*menor_cjt); i++) {
+		if (pertence_cjt(*maior_cjt, (*menor_cjt)->v[i]))
+			insere_cjt(inter, (*menor_cjt)->v[i]);
 	}
 
 	return inter;
@@ -118,19 +135,32 @@ conjunto_t *uniao_cjt(conjunto_t *c1, conjunto_t *c2) {
 	if ( !(uniao = cria_cjt(c1->max)) )
 		return NULL;
 
-	/* para nao ter que alocar um conjunto novo, a funcao usa ponteiros para
-	 * ponteiro de conjunto */
 	conjunto_t **menor_cjt = cardinalidade_cjt(c1) < cardinalidade_cjt(c2) ? &c1 : &c2;
 	conjunto_t **maior_cjt = cardinalidade_cjt(c1) > cardinalidade_cjt(c2) ? &c1 : &c2;
+	
+	while (c1->ptr < cardinalidade_cjt(c1) && c2->ptr < cardinalidade_cjt(c2)) {
+		if (c1->v[c1->ptr] == c2->v[c2->ptr]) {
+			insere_cjt(uniao, c1->v[c1->ptr]);
+			c1->ptr++;
+			c2->ptr++;
+		} else {
+			if (c1->v[c1->ptr] < c2->v[c2->ptr]) {
+				insere_cjt(uniao, c1->v[c1->ptr]);
+				c1->ptr++;
+			} else {
+				insere_cjt(uniao, c2->v[c2->ptr]);
+				c2->ptr++;
+			}
+		}
+	}
 
 	int i;
-	for (i = 0; i < cardinalidade_cjt(*menor_cjt); i++) {
-		insere_cjt(uniao, c1->v[i]);
-		insere_cjt(uniao, c2->v[i]);
+	for (i = cardinalidade_cjt(*menor_cjt); i < cardinalidade_cjt(*maior_cjt); i++) {
+		insere_cjt(uniao, (*maior_cjt)->v[i]);
 	}
 
-	for (; i < cardinalidade_cjt(*maior_cjt); i++)
-		insere_cjt(uniao, (*maior_cjt)->v[i]);
+	inicia_iterador_cjt(c1);
+	inicia_iterador_cjt(c2);
 
 	return uniao;
 }
@@ -172,53 +202,16 @@ conjunto_t *cria_subcjt_cjt(conjunto_t *c, int n) {
 	return sub;
 }
 
-/* funcao auxiliar para a ordenacao */
-void troca(int *a, int *b) {
-	int temp = *a;
-	*a = *b;
-	*b = temp;
-}
-
-/* implementacao do bubble sort */
-conjunto_t *ordena_cjt(conjunto_t *c) {
-	conjunto_t *ord;
-	if ( !(ord = copia_cjt(c)) )
-		return NULL;
-
-	int tam = cardinalidade_cjt(ord);
-	int trocou = 1;
-	int i;
-	while (trocou) { 	/* trocou eh uma flag para sair do loop quando ja */
-		trocou = 0;		/* estiver ordenado (nao trocou = ordenado)       */
-		for (i = 0; i < tam-1; i++) {
-			if (ord->v[i+1] < ord->v[i]) {
-				troca(&ord->v[i+1], &ord->v[i]);
-				trocou = 1;
-			}
-		}
-		tam--;
-	}
-	return ord;
-}
-
 void imprime_cjt(conjunto_t *c) {
 	if (vazio_cjt(c)) {
 		printf("Conjunto vazio.\n");
 		return;
 	}
 
-	conjunto_t *ord;
-	if ( !(ord = ordena_cjt(c)) ) {
-		printf("Erro na alocacao do conjunto.");
-		return;
-	}
-
 	int i;
-	for (i = 0; i < cardinalidade_cjt(ord)-1; i++)
-		printf("%d ", ord->v[i]);
-	printf("%d\n", ord->v[cardinalidade_cjt(ord)-1]);
-	
-	destroi_cjt(ord);
+	for (i = 0; i < cardinalidade_cjt(c)-1; i++)
+		printf("%d ", c->v[i]);
+	printf("%d\n", c->v[cardinalidade_cjt(c)-1]);
 }
 
 void inicia_iterador_cjt(conjunto_t *c) {