un algoritmo es un procedimiento específico para resolver un problema computacional bien definido. El desarrollo y análisis de Algoritmos es fundamental para todos los aspectos de la informática: inteligencia artificial, bases de datos, gráficos, redes, sistemas operativos, seguridad, etc. El desarrollo de Algoritmos es más que solo programación., Requiere una comprensión de las alternativas disponibles para resolver un problema computacional, incluido el hardware, la red, el lenguaje de programación y las limitaciones de rendimiento que acompañan a cualquier solución en particular. También requiere entender lo que significa que un algoritmo sea «correcto» en el sentido de que resuelve completa y eficientemente el problema en cuestión.

una noción de acompañamiento es el diseño de una estructura de datos particular que permite que un algoritmo se ejecute de manera eficiente., La importancia de las estructuras de datos se deriva del hecho de que la memoria principal de un ordenador (donde se almacenan los datos) es lineal, que consiste en una secuencia de células de memoria que están numeradas en serie 0, 1, 2,…. Por lo tanto, la estructura de datos más simple es una matriz lineal, en la que los elementos adyacentes se numeran con «índices» enteros consecutivos y el valor de un elemento se accede por su índice único. Una matriz se puede usar, por ejemplo, para almacenar una lista de nombres, y se necesitan métodos eficientes para buscar y recuperar eficientemente un nombre particular de la matriz., Por ejemplo, ordenar la lista en orden alfabético permite utilizar la llamada técnica de búsqueda binaria, en la que el resto de la lista a buscar en cada paso se reduce a la mitad. Esta técnica de búsqueda es similar a buscar un nombre en particular en una guía telefónica. Saber que el libro está en orden alfabético permite pasar rápidamente a una página que está cerca de la página que contiene el nombre deseado. Se han desarrollado muchos algoritmos para ordenar y buscar listas de datos de manera eficiente.,

aunque los elementos de datos se almacenan de forma consecutiva en la memoria, pueden vincularse entre sí mediante punteros (esencialmente, direcciones de memoria almacenadas con un elemento para indicar dónde se encuentran el siguiente elemento o elementos de la estructura) para que los datos se puedan organizar de manera similar a aquellos en los que se accederá a ellos. La estructura más simple de este tipo se denomina lista vinculada, en la que se puede acceder a los elementos almacenados sin distinción en un orden predeterminado siguiendo los punteros de un elemento de la lista al siguiente., La lista puede ser circular, con el último elemento apuntando al primero, o cada elemento puede tener punteros en ambas direcciones para formar una lista doblemente vinculada. Se han desarrollado algoritmos para manipular eficientemente tales listas mediante la búsqueda, inserción y eliminación de elementos.

Los punteros también proporcionan la capacidad de implementar estructuras de datos más complejas. Un gráfico, por ejemplo, es un conjunto de nodos (elementos) y enlaces (conocidos como bordes) que conectan pares de elementos., Tal gráfico podría representar un conjunto de ciudades y las carreteras que las unen, el diseño de los elementos del circuito y los cables de conexión en un chip de memoria, o la configuración de las personas que interactúan a través de una red social. Los algoritmos típicos de gráficos incluyen estrategias de recorrido de gráficos, como Cómo seguir los enlaces de nodo a nodo (tal vez buscando un nodo con una propiedad particular) de manera que cada nodo se visite solo una vez. Un problema relacionado es la determinación del camino más corto entre dos nodos dados en un gráfico arbitrario. (Ver teoría de grafos.,) Un problema de interés práctico en los Algoritmos de red, por ejemplo, es determinar cuántos enlaces «rotos» se pueden tolerar antes de que las comunicaciones comiencen a fallar. Del mismo modo, en el diseño de chip de integración a gran escala (VLSI) es importante saber si el gráfico que representa un circuito es plano, es decir, si se puede dibujar en dos dimensiones sin que se crucen los enlaces (los cables se toquen).

la complejidad (computacional) de un algoritmo es una medida de la cantidad de recursos informáticos (tiempo y espacio) que un algoritmo en particular consume cuando se ejecuta., Los científicos informáticos utilizan medidas matemáticas de complejidad que les permiten predecir, antes de escribir el código, qué tan rápido se ejecutará un algoritmo y cuánta memoria requerirá. Tales predicciones son guías importantes para los programadores que implementan y seleccionan algoritmos para aplicaciones del mundo real.,

la complejidad computacional es un continuo, en el que algunos algoritmos requieren tiempo lineal (es decir, el tiempo requerido aumenta directamente con el número de elementos o nodos en la lista, gráfico o red que se procesa), mientras que otros requieren tiempo cuadrático o incluso exponencial para completarse (es decir, el tiempo requerido aumenta con el número de elementos al cuadrado o con el exponencial de ese número). En el extremo más lejano de este continuo se encuentran los turbios mares de problemas insolubles, aquellos cuyas soluciones no se pueden aplicar de manera eficiente., Para estos problemas, los científicos de la computación buscan encontrar algoritmos heurísticos que casi puedan resolver el problema y ejecutarse en una cantidad de tiempo razonable.

aún más lejos están aquellos problemas algorítmicos que se pueden declarar pero no se pueden resolver; es decir, se puede probar que no se puede escribir ningún programa para resolver el problema. Un ejemplo clásico de un problema algorítmico irresoluble es el problema de detención, que establece que no se puede escribir ningún programa que pueda predecir si cualquier otro programa se detiene o no después de un número finito de pasos., La irresolubilidad del problema de la detención tiene una incidencia práctica inmediata en el desarrollo de software. Por ejemplo, sería frívolo tratar de desarrollar una herramienta de software que predice si otro programa que se está desarrollando tiene un bucle infinito en él (aunque tener una herramienta de este tipo sería inmensamente beneficioso).