Skip to content

Commit

Permalink
:)
Browse files Browse the repository at this point in the history
  • Loading branch information
LauraCD2 committed Jul 25, 2023
1 parent 60d5070 commit 212ef48
Showing 1 changed file with 296 additions and 28 deletions.
324 changes: 296 additions & 28 deletions taller_arboles/ArbolBinario.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -14,38 +14,306 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 16,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Recorrido en Preorden: [1, 3, 5, 7, 8]\n",
"Recorrido por Niveles: [1, 3, 7, 5, 8]\n",
"Después de eliminar 3:\n",
"Recorrido en Preorden: [1, 8, 5, 7, 8]\n",
"Recorrido por Niveles: [1, 8, 7, 5, 8]\n"
]
}
],
"source": [
"# 1. Realice la implementación en Python de un montículo usando árboles binarios. Debe tener las siguientes funciones: Crear el montículo, insertar un elemento, eliminar elemento, recorrido en preorden y por niveles.\n",
"\n",
"# Importar librerias\n",
"import matplotlib.pyplot as plt\n",
"\n",
"# Clase Nodo\n",
"def crearNodo(dato):\n",
" return [dato, None, None]\n",
"\n",
"# Clase Arbol\n",
"def crearArbol():\n",
" return None\n",
"\n",
"# Funcion para insertar un elemento \n",
"def insertar(arbol, dato):\n",
" if arbol == None:\n",
" return crearNodo(dato)\n",
" else:\n",
" datoRaiz = arbol[0]\n",
" if dato < datoRaiz:\n",
" hijoIzquierdo = arbol[1]\n",
" arbol[1] = insertar(hijoIzquierdo, dato)\n",
"class NodoMonticulo:\n",
" def __init__(self, valor):\n",
" self.valor = valor\n",
" self.izquierda = None\n",
" self.derecha = None\n",
"\n",
"\n",
"class MonticuloMinimo:\n",
" def __init__(self):\n",
" self.raiz = None\n",
"\n",
" def insertar(self, valor):\n",
" if not self.raiz:\n",
" self.raiz = NodoMonticulo(valor)\n",
" else:\n",
" self._insertar_recursivo(self.raiz, valor)\n",
"\n",
" def _insertar_recursivo(self, nodo_actual, valor):\n",
" if not nodo_actual.izquierda:\n",
" nodo_actual.izquierda = NodoMonticulo(valor)\n",
" elif not nodo_actual.derecha:\n",
" nodo_actual.derecha = NodoMonticulo(valor)\n",
" else:\n",
" hijoDerecho = arbol[2]\n",
" arbol[2] = insertar(hijoDerecho, dato)\n",
" return arbol\n",
" altura_izquierda = self._obtener_altura(nodo_actual.izquierda)\n",
" altura_derecha = self._obtener_altura(nodo_actual.derecha)\n",
"\n",
" if altura_izquierda <= altura_derecha:\n",
" self._insertar_recursivo(nodo_actual.izquierda, valor)\n",
" else:\n",
" self._insertar_recursivo(nodo_actual.derecha, valor)\n",
"\n",
" self._ajustar_monticulo(nodo_actual)\n",
"\n",
" def _obtener_altura(self, nodo):\n",
" if not nodo:\n",
" return 0\n",
" return 1 + max(self._obtener_altura(nodo.izquierda), self._obtener_altura(nodo.derecha))\n",
"\n",
" def _ajustar_monticulo(self, nodo):\n",
" if not nodo:\n",
" return\n",
"\n",
" if nodo.izquierda and nodo.izquierda.valor < nodo.valor:\n",
" nodo.valor, nodo.izquierda.valor = nodo.izquierda.valor, nodo.valor\n",
" self._ajustar_monticulo(nodo.izquierda)\n",
"\n",
" if nodo.derecha and nodo.derecha.valor < nodo.valor:\n",
" nodo.valor, nodo.derecha.valor = nodo.derecha.valor, nodo.valor\n",
" self._ajustar_monticulo(nodo.derecha)\n",
"\n",
" def eliminar(self, valor):\n",
" if not self.raiz:\n",
" return\n",
"\n",
" if self.raiz.valor == valor:\n",
" ultimo_nodo = self._obtener_ultimo_nodo()\n",
" if ultimo_nodo:\n",
" self.raiz.valor = ultimo_nodo.valor\n",
" self._eliminar_ultimo_nodo()\n",
" else:\n",
" self._eliminar_recursivo(self.raiz, valor)\n",
"\n",
" def _eliminar_recursivo(self, nodo_actual, valor):\n",
" if not nodo_actual:\n",
" return\n",
"\n",
" if nodo_actual.izquierda and nodo_actual.izquierda.valor == valor:\n",
" ultimo_nodo = self._obtener_ultimo_nodo()\n",
" if ultimo_nodo:\n",
" nodo_actual.izquierda.valor = ultimo_nodo.valor\n",
" self._eliminar_ultimo_nodo()\n",
" elif nodo_actual.derecha and nodo_actual.derecha.valor == valor:\n",
" ultimo_nodo = self._obtener_ultimo_nodo()\n",
" if ultimo_nodo:\n",
" nodo_actual.derecha.valor = ultimo_nodo.valor\n",
" self._eliminar_ultimo_nodo()\n",
" else:\n",
" self._eliminar_recursivo(nodo_actual.izquierda, valor)\n",
" self._eliminar_recursivo(nodo_actual.derecha, valor)\n",
"\n",
" def _obtener_ultimo_nodo(self):\n",
" if not self.raiz:\n",
" return None\n",
"\n",
" cola = [self.raiz]\n",
" ultimo_nodo = None\n",
"\n",
" while cola:\n",
" ultimo_nodo = cola.pop(0)\n",
" if ultimo_nodo.izquierda:\n",
" cola.append(ultimo_nodo.izquierda)\n",
" if ultimo_nodo.derecha:\n",
" cola.append(ultimo_nodo.derecha)\n",
"\n",
" return ultimo_nodo\n",
"\n",
" def _eliminar_ultimo_nodo(self):\n",
" if not self.raiz:\n",
" return\n",
"\n",
" cola = [self.raiz]\n",
" nodo_padre = None\n",
" ultimo_nodo = None\n",
"\n",
" while cola:\n",
" nodo_padre = cola.pop(0)\n",
" if nodo_padre.izquierda:\n",
" ultimo_nodo = nodo_padre.izquierda\n",
" cola.append(nodo_padre.izquierda)\n",
" if nodo_padre.derecha:\n",
" ultimo_nodo = nodo_padre.derecha\n",
" cola.append(nodo_padre.derecha)\n",
"\n",
" if ultimo_nodo:\n",
" if nodo_padre.izquierda == ultimo_nodo:\n",
" nodo_padre.izquierda = None\n",
" else:\n",
" nodo_padre.derecha = None\n",
"\n",
" self._ajustar_monticulo(self.raiz)\n",
"\n",
" def recorrido_preorden(self):\n",
" resultado = []\n",
" self._recorrido_preorden_recursivo(self.raiz, resultado)\n",
" return resultado\n",
"\n",
" def _recorrido_preorden_recursivo(self, nodo, resultado):\n",
" if not nodo:\n",
" return\n",
" resultado.append(nodo.valor)\n",
" self._recorrido_preorden_recursivo(nodo.izquierda, resultado)\n",
" self._recorrido_preorden_recursivo(nodo.derecha, resultado)\n",
"\n",
" def recorrido_por_niveles(self):\n",
" resultado = []\n",
" if not self.raiz:\n",
" return resultado\n",
"\n",
" cola = [self.raiz]\n",
"\n",
" while cola:\n",
" nodo = cola.pop(0)\n",
" resultado.append(nodo.valor)\n",
"\n",
" if nodo.izquierda:\n",
" cola.append(nodo.izquierda)\n",
" if nodo.derecha:\n",
" cola.append(nodo.derecha)\n",
"\n",
" return resultado\n",
"\n",
"\n",
"# Ejemplo de uso:\n",
"if __name__ == \"__main__\":\n",
" monticulo = MonticuloMinimo()\n",
" monticulo.insertar(5)\n",
" monticulo.insertar(3)\n",
" monticulo.insertar(8)\n",
" monticulo.insertar(1)\n",
" monticulo.insertar(7)\n",
"\n",
" print(\"Recorrido en Preorden:\", monticulo.recorrido_preorden()) \n",
" print(\"Recorrido por Niveles:\", monticulo.recorrido_por_niveles()) \n",
"\n",
" monticulo.eliminar(3)\n",
" print(\"Después de eliminar 3:\")\n",
" print(\"Recorrido en Preorden:\", monticulo.recorrido_preorden()) \n",
" print(\"Recorrido por Niveles:\", monticulo.recorrido_por_niveles()) \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Árbol de Huffman:\n",
"El árbol de Huffman es un tipo especial de árbol binario completo y óptimo que se utiliza en compresión de datos. Fue propuesto por David A. Huffman en 1952. El objetivo principal del árbol de Huffman es comprimir datos de manera eficiente asignando códigos binarios de longitud variable a diferentes caracteres en función de su frecuencia de aparición en el conjunto de datos.\n",
"\n",
"Funcionamiento del árbol de Huffman:\n",
"\n",
"Cálculo de frecuencias: Se comienza con el conjunto de datos que se desea comprimir y se calcula la frecuencia de aparición de cada caracter en el conjunto.\n",
"\n",
"Creación de nodos hoja: Cada caracter se convierte en un nodo hoja del árbol de Huffman. Estos nodos hoja contienen la frecuencia del caracter y el propio caracter.\n",
"\n",
"Construcción del árbol: Se crea un árbol binario completo ordenando los nodos hoja en orden ascendente según sus frecuencias. Se toman los dos nodos con menor frecuencia y se combinan en un nuevo nodo cuya frecuencia es la suma de las frecuencias de los nodos anteriores. Este nuevo nodo se inserta nuevamente en la lista ordenada.\n",
"\n",
"Repetición del paso 3: Se repite el paso 3 hasta que todos los nodos estén unidos en un único nodo raíz. En este punto, el árbol de Huffman está construido.\n",
"\n",
"Asignación de códigos: Se asignan códigos binarios a cada caracter recorriendo el árbol de Huffman desde la raíz hasta cada nodo hoja. Los caminos hacia la izquierda se etiquetan con \"0\" y hacia la derecha con \"1\". Los códigos asignados a los caracteres se almacenan en una tabla de códigos.\n",
"\n",
"Compresión de datos: Finalmente, se reemplazan los caracteres originales en el conjunto de datos con sus códigos binarios correspondientes y se genera la secuencia de bits comprimida."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Datos codificados: 111100001010111110111100011001111010110111000011111001000100010011011001001111101011010110000001100010110010011111000011011100110011100110111010\n",
"Datos decodificados: este_es_un_ejemplo_de_arbol_de_huffman\n"
]
}
],
"source": [
"import heapq\n",
"from collections import defaultdict, Counter\n",
"\n",
"class Nodo:\n",
" def __init__(self, caracter, frecuencia):\n",
" self.caracter = caracter\n",
" self.frecuencia = frecuencia\n",
" self.izquierda = None\n",
" self.derecha = None\n",
"\n",
" def __lt__(self, otro):\n",
" return self.frecuencia < otro.frecuencia\n",
"\n",
"def construir_arbol_huffman(datos):\n",
" frecuencia_caracter = Counter(datos)\n",
" cola_prioridad = [Nodo(caracter, frecuencia) for caracter, frecuencia in frecuencia_caracter.items()]\n",
" heapq.heapify(cola_prioridad)\n",
"\n",
" while len(cola_prioridad) > 1:\n",
" nodo_izquierdo = heapq.heappop(cola_prioridad)\n",
" nodo_derecho = heapq.heappop(cola_prioridad)\n",
"\n",
" nodo_combinado = Nodo(None, nodo_izquierdo.frecuencia + nodo_derecho.frecuencia)\n",
" nodo_combinado.izquierda = nodo_izquierdo\n",
" nodo_combinado.derecha = nodo_derecho\n",
"\n",
" heapq.heappush(cola_prioridad, nodo_combinado)\n",
"\n",
" return cola_prioridad[0]\n",
"\n",
"def construir_codigos_huffman(nodo, codigo_actual=\"\", codigos={}):\n",
" if nodo is None:\n",
" return\n",
"\n",
" if nodo.caracter:\n",
" codigos[nodo.caracter] = codigo_actual\n",
"\n",
" construir_codigos_huffman(nodo.izquierda, codigo_actual + \"0\", codigos)\n",
" construir_codigos_huffman(nodo.derecha, codigo_actual + \"1\", codigos)\n",
"\n",
" return codigos\n",
"\n",
"def codificar_huffman(datos):\n",
" if not datos:\n",
" raise ValueError(\"Los datos de entrada están vacíos.\")\n",
"\n",
" raiz_arbol = construir_arbol_huffman(datos)\n",
" codigos = construir_codigos_huffman(raiz_arbol)\n",
"\n",
" datos_codificados = \"\".join(codigos[caracter] for caracter in datos)\n",
" return datos_codificados, raiz_arbol\n",
"\n",
"def decodificar_huffman(datos_codificados, raiz_arbol):\n",
" datos_decodificados = \"\"\n",
" nodo_actual = raiz_arbol\n",
"\n",
" for bit in datos_codificados:\n",
" if bit == \"0\":\n",
" nodo_actual = nodo_actual.izquierda\n",
" else:\n",
" nodo_actual = nodo_actual.derecha\n",
"\n",
" if nodo_actual.caracter:\n",
" datos_decodificados += nodo_actual.caracter\n",
" nodo_actual = raiz_arbol\n",
"\n",
" return datos_decodificados\n",
"\n",
" "
"# Ejemplo de uso:\n",
"if __name__ == \"__main__\":\n",
" datos = \"este_es_un_ejemplo_de_arbol_de_huffman\"\n",
" \n",
" datos_codificados, raiz_arbol = codificar_huffman(datos)\n",
" print(\"Datos codificados:\", datos_codificados)\n",
" \n",
" datos_decodificados = decodificar_huffman(datos_codificados, raiz_arbol)\n",
" print(\"Datos decodificados:\", datos_decodificados)\n"
]
}
],
Expand Down

0 comments on commit 212ef48

Please sign in to comment.