Algoritmos y estructuras de datos: explicación de los algoritmos

Este artículo presenta principalmente la teoría relacionada con el algoritmo, incluida la definición y las características del algoritmo, el cálculo de la complejidad del tiempo y el espacio, etc., una pequeña cantidad de código en este artículo.

Tabla de contenido

 Algoritmos y estructuras de datos

 Comparación de dos algoritmos

La acumulación del primer ciclo.

Sucesiones aritméticas de segunda clase

propiedades del algoritmo

de entrada y salida

Infinidad

Certeza

factibilidad

Requisitos de diseño de algoritmos

exactitud

legibilidad

robustez

Alta eficiencia de tiempo y bajo almacenamiento

Medidas de eficiencia algorítmica

Estadísticas después del hecho

Estimado por adelantado

Crecimiento asintótico de funciones

Avanzado

Complejidad del tiempo del algoritmo

Representación de la Complejidad del Tiempo

Varias complejidades de tiempo comunes

el peor de los casos y el caso promedio

Complejidad espacial algorítmica


 Algoritmos y estructuras de datos

        La estructura de datos es la relación orgánica entre los datos, y el algoritmo son los pasos de operación sobre los datos. Sin la relación orgánica entre los datos, el programa no se puede diseñar en absoluto. Debido a la estructura de datos, el algoritmo puede nacer. Por el contrario, los algoritmos son una condición para que se mantengan las estructuras de datos. Sin algoritmos, los datos no se pueden tratar con regularidad. Los datos solo colisionarán en desorden y las estructuras de datos desaparecerán. Los algoritmos se mueven absolutamente, las estructuras de datos son relativamente estáticas y las dos son inseparables;

        Los algoritmos son animados, pero las estructuras de datos son lentas. El desarrollo de algoritmos requiere el desarrollo de estructuras de datos, de lo contrario, dificultará el desarrollo de algoritmos. Tarde o temprano, el desarrollo de algoritmos inevitablemente romperá los grilletes de las estructuras de datos. El punto continúa el movimiento contradictorio.

 Comparación de dos algoritmos

Usamos el lenguaje C como demostración, escribimos un programa para calcular el valor acumulativo de 1 a 100

La acumulación del primer ciclo.

int i, sum = 0, n = 100;
for(i = 1; i <= n; i++)
{
	sum = sum + i;
}
printf("%d", sum);	

Es un ciclo muy simple, calculamos el valor de 1+2+3+...+100, este es el primer pensamiento de muchas personas, esta es de hecho una de las respuestas correctas, pero es realmente bueno escribir como ¿este? ¿Es lo suficientemente eficiente?

Sucesiones aritméticas de segunda clase

El famoso matemático Gauss tiene otra solución:

Expresado en código es:

int sum = 0, n = 100;
sum = (1 + n) * n / 2;
printf("%d", sum);

        forma más sencilla y eficiente. En comparación con el primer tipo de acumulación y cálculo de bucles cien veces, la idea de usar la secuencia aritmética solo se calcula una vez. ¿Qué pasa si queremos sumar hasta mil? ¿Qué hay de diez mil? ¿Qué tal 100 millones? El cálculo aritmético está destinado a ahorrar muchos recursos informáticos y tiempo.

propiedades del algoritmo

Cinco propiedades básicas de los algoritmos: entrada, salida, finitud, determinismo y viabilidad

Un algoritmo siempre debe terminar después de ejecutar un número finito de pasos, y cada paso debe completarse en un tiempo finito.

de entrada y salida

Un algoritmo tiene cero o más entradas y un algoritmo tiene al menos una o más salidas.

Infinidad

El algoritmo debe poder finalizar automáticamente después de ejecutar un número finito de pasos sin un ciclo infinito, y un paso debe completarse en un tiempo aceptable.

Certeza

Cada paso del algoritmo tiene un significado claro y sin ambigüedades.

factibilidad

Cada paso del algoritmo debe ser factible, es decir, cada paso se completa ejecutando un número finito de veces.

Requisitos de diseño de algoritmos

Los algoritmos no son únicos. Puede haber múltiples soluciones para el mismo problema. Los algoritmos no tienen respuestas estándar, entonces, ¿cómo juzgar si un algoritmo es bueno o malo? Un buen algoritmo debe tener algunos requisitos:

exactitud

El algoritmo debe tener al menos una entrada, salida y procesamiento inequívocos, puede reflejar correctamente las necesidades del problema y puede obtener la respuesta correcta al problema.

legibilidad

Fácil de leer, entender y comunicar.

robustez

Cuando los datos de entrada son ilegales, el algoritmo también puede realizar un procesamiento relevante en lugar de producir resultados anormales o inexplicables.

Alta eficiencia de tiempo y bajo almacenamiento

La eficiencia del tiempo se refiere al tiempo de ejecución de un algoritmo. La capacidad de almacenamiento se refiere principalmente a la memoria o espacio en el disco duro externo que ocupa el programa del algoritmo cuando se está ejecutando. El algoritmo de diseño debe tratar de cumplir con los requisitos de alta eficiencia de tiempo y baja capacidad de almacenamiento.

Medidas de eficiencia algorítmica

Estadísticas después del hecho

        Este método compara principalmente el tiempo de ejecución de los programas compilados por diferentes algoritmos mediante el uso de contadores de computadora a través de programas y datos de prueba diseñados, para determinar la eficiencia del algoritmo.

Las desventajas son: el programa debe escribirse con anticipación; depende más del hardware y el software de la computadora; el diseño de los datos de prueba es difícil.

Estimado por adelantado

Antes de compilar el programa de computadora, el algoritmo se estima de acuerdo con el método estadístico.

Se refieren principalmente a los siguientes factores:

  1. Estrategias y métodos adoptados por el algoritmo;
  2. La calidad del código generado por la compilación;
  3. El tamaño de entrada del problema;
  4. La velocidad a la que una máquina ejecuta instrucciones.

Tomemos como ejemplo el algoritmo de acumulación anterior:

1 + 2 + 3 + ... + 100 = ?



#循环累加
int i, sum = 0, n = 100;	/* 执行1次 */
for(i = 1; i <= n; i++)	/* 执行了n+1次 */
{
	sum = sum + i;			/* 执行n次 n次 n次! */
}
printf("%d", sum);			/* 执行1次 */



#等差数列
int sum = 0,n = 100;		/* 执行一次 */
sum = (1 + n) * n / 2;		/* 执行一次 */
printf("%d", sum);			/* 执行一次 */

Dos algoritmos, superior o inferior.

Crecimiento asintótico de funciones

Suponemos que hay dos algoritmos A y B

Un algoritmo calcula 2n+3 operaciones

El algoritmo B calcula 3n+1 operaciones

¿Cuál de los dos algoritmos es más rápido? Por supuesto que no necesariamente, porque:

frecuencia A(2n + 3 ) B( 3n + 1 )

norte = 1

5 4
norte = 2 7 7
norte = 3 9 10
norte = 10 23 31
n = 100 203 301

Cuando el número de veces es uno, la eficiencia del algoritmo A no es tan buena como la del algoritmo B, pero cuando n > 2, la eficiencia del algoritmo A es peor que la del algoritmo B, por lo que decimos que la eficiencia del algoritmo A es generalmente mejor que el algoritmo B.

Avanzado

        De hecho, es un problema de crecimiento de la función, aquí ignoramos las constantes, por lo que la forma en que juzgamos la eficiencia es dar prioridad al orden más alto de la función, seguido de los coeficientes y finalmente las constantes.

        Es decir, a medida que aumenta el número de veces n, un algoritmo será mejor o peor que otro algoritmo.

Complejidad del tiempo del algoritmo

        Complejidad del tiempo, también conocida como complejidad del tiempo, la complejidad del tiempo de un algoritmo es una función que describe cualitativamente el tiempo de ejecución del algoritmo. Esta es una función de la longitud de la cadena que representa el valor de entrada del algoritmo. La complejidad del tiempo a menudo se expresa en notación O grande, excluyendo los términos de orden inferior y los coeficientes principales de esta función. Al utilizar este enfoque, se puede decir que la complejidad del tiempo es asintótica, es decir, considere el caso en el que el tamaño del valor de entrada se acerca al infinito.

Representación de la Complejidad del Tiempo

        Como dijimos anteriormente, cuando n se vuelve más y más grande, las partes de bajo nivel, constante y coeficiente en la fórmula no afectarán su tendencia de crecimiento, por lo que puede ignorarlas directamente y solo registrar la magnitud más grande. Por lo tanto, cuando calculamos la complejidad del tiempo, solo debemos prestar atención al código con la mayor cantidad de bucles.

int sum = 0; //执行1次,忽略不计

for (int i = 0; i < n; i++) {

sum += i; // 循环内执行次数最多,执行次数为n次,因此时间复杂度记为O(n)

}

return sum; //执行1次,忽略不计

}

Varias complejidades de tiempo comunes

Hay siete ejemplos más comunes que solemos encontrar, ordenados de mayor a menor en términos de eficiencia operativa:

  1. O(1) —  complejidad constante
  2. O(log n) —  complejidad logarítmica
  3. O(n) —  complejidad lineal
  4. O (n log n) -  complejidad log-lineal
  5. O (nᵏ) -  complejidad polinomial
  6. O(kⁿ) —  complejidad exponencial
  7. O(n!) —  complejidad factorial

        El tiempo de ejecución del algoritmo en el área sombreada en rojo aumenta drásticamente a medida que crece el tamaño de entrada. Por otro lado, los algoritmos en las áreas sombreadas en amarillo y verde no varían mucho en el tiempo de ejecución a medida que crece el tamaño de entrada, por lo que son más eficientes y manejan grandes cantidades de datos con facilidad. 

el peor de los casos y el caso promedio

muy simple

El primer paso, supongamos que tenemos una matriz de 100 números y quiero encontrar uno de ellos.

En el segundo paso, si puedo repetir el primer paso por innumerables rondas, por supuesto encontraré este número en varias posiciones, como la primera vez que lo encuentro o 35 veces, 76 veces, 83 veces, etc., luego en promedio en cada ronda encuentro el número Este número tomará 50 veces, que es el caso promedio.

En el tercer paso, por supuesto, también encontraremos que el peor de los casos es encontrar este número por centésima vez.

El tiempo promedio es nuestro tiempo esperado, pero nuestros algoritmos de evaluación tienden a tomar el peor de los casos.

Complejidad espacial algorítmica

       Para medir el tamaño del espacio de almacenamiento temporalmente ocupado por un algoritmo durante la operación, regístrelo como S(n)=O(f(n)). Por ejemplo, la complejidad temporal de la clasificación por inserción directa es O(n^2) y la complejidad espacial es O(1). El algoritmo recursivo general tendrá una complejidad espacial de O(n), porque la información de retorno debe almacenarse para cada recursión.

        La complejidad espacial S(n) de un algoritmo se define como el espacio de almacenamiento consumido por el algoritmo, que también es una función del tamaño del problema n. La complejidad del espacio asintótico también suele denominarse simplemente complejidad del espacio. Space Complexity (SpaceComplexity) es una medida del tamaño del espacio de almacenamiento ocupado temporalmente por un algoritmo durante la operación. El espacio de almacenamiento ocupado por un algoritmo en la computadora incluye tres aspectos : el espacio de almacenamiento ocupado por el propio algoritmo, el espacio de almacenamiento ocupado por los datos de entrada y salida del algoritmo y el espacio de almacenamiento ocupado temporalmente por el algoritmo durante la operación.

        Cuando escribimos código, podemos intercambiar espacio por tiempo, por ejemplo, para determinar si un determinado año es bisiesto, cada vez que damos un año, debemos calcular si es bisiesto o no.

        Otra forma es crear una matriz con 2022 elementos por adelantado y luego unir todos los años con los números marcados, si es un año bisiesto, el valor de este elemento de la matriz es 1, y si no lo es, el valor es 0 . De esta forma, lo que se llama juzgar si un determinado año es un año bisiesto se convierte en un problema de encontrar el valor de un determinado elemento de esta matriz.

El primer enfoque requiere mucho tiempo de computación . En el segundo método, nuestro cálculo se minimiza, pero los 0 y 1 de 2050 deben almacenarse en el disco duro o en la memoria, lo que requiere algo de espacio de almacenamiento .

Bienvenido a dar me gusta, recopilar y comentar en el área de comentarios, y reimprimir para indicar la fuente.

--------------------------------------------

Enlace de arriba:

Algoritmos y estructuras de datos - Introducción a las estructuras de datos Speedrun de estructura de datos. https://blog.csdn.net/qq_52213943/article/details/125676781

Enlaces a continuación:

Algoritmo y estructura de datos: tabla lineal y su código de volumen de estructura de almacenamiento secuencial. https://blog.csdn.net/qq_52213943/article/details/125709931

Supongo que te gusta

Origin blog.csdn.net/qq_52213943/article/details/125686761
Recomendado
Clasificación