Red de conocimiento informático - Conocimiento del nombre de dominio - Programa de análisis de rendimiento para algoritmo de clasificación de emergencia

Programa de análisis de rendimiento para algoritmo de clasificación de emergencia

El conjunto completo de algoritmos de clasificación se adjunta con código C.

El algoritmo de clasificación es un algoritmo básico y de uso común. Debido a la gran cantidad de procesamiento en el trabajo real, el algoritmo de clasificación tiene altos requisitos en cuanto a la velocidad del algoritmo en sí. En términos generales, lo que llamamos rendimiento de un algoritmo se refiere principalmente a la complejidad del algoritmo, que generalmente se expresa mediante el método O. Lo explicaré en detalle más adelante.

Me gustaría presentar brevemente el algoritmo de clasificación y dar un resumen de este artículo.

Analizaré el algoritmo de simple a difícil según su complejidad.

La primera parte es un algoritmo de clasificación simple. Verá más adelante que la similitud entre ellos es que la complejidad del algoritmo es O (n * n) (debido a que no se usa palabra, no se pueden escribir superíndices ni subíndices).

La segunda parte es un algoritmo de clasificación avanzado con una complejidad de O(Log2(N)). Aquí solo se presenta un algoritmo. Varios otros algoritmos no se analizan aquí porque involucran los conceptos de árboles y montones.

La tercera parte es similar a pensar. Los dos algoritmos aquí no son los mejores (ni siquiera los más lentos), pero los algoritmos en sí son lo suficientemente extraños como para que valga la pena consultarlos (desde una perspectiva de programación). También nos permite entender este tema desde otra perspectiva.

La cuarta parte es mi postre para ti: clasificación rápida universal basada en plantillas. Debido a que es una función de plantilla, se puede ordenar cualquier tipo de datos (lo siento, algunos expertos del foro lo usaron).

Ahora comencemos:

Primero, un algoritmo de clasificación simple

Debido a que el programa es relativamente simple, no se agregan comentarios. Todos los programas proporcionan códigos de ejecución completos y están en mi entorno VC.

En todas partes. Dado que MFC y WINDOWS no están disponibles, no debería haber problemas en la plataforma BORLAND C.

Al final del código se proporciona un diagrama esquemático del proceso en ejecución, que espero sea útil para la comprensión.

1. Método de la burbuja:

Este es el algoritmo más lento más primitivo y conocido. Recibe su nombre porque parece funcionar burbujeando:

#include

void BubbleSort(int* pData, int Count)

{

int iTemp

for(int I = 1; I = I; j -)

{

if(pData[j] 9, 10, 8, 7-> 8, 10, 9, 7-> 7, 10, 9, 8 (tres intercambios)

Segunda ronda: 7, 10, 9, 8-> 7, 9, 10, 8-> 7, 8, 10, 9 (intercambio dos veces)

Primera ronda: 7, 8, 10, 9-> 7, 8, 9, 10 (.

Número de ciclos: 6 veces

Número de intercambios: 6 veces

Otros:

Primera ronda: 8, 10, 7, 9-> 8, 10, 7, 9-> 7, 10, 8, 9-> 7, 10, 8, 9 (1 intercambio)

Segunda ronda: 7, 10, 8, 9-> 7, 8, 10, 9-> 7, 8, 10, 9 (1 intercambio)

Primera ronda: 7, 8, 10, 9- > 7, 8, 9, 10 (1 intercambio)

<. p>Número de ciclos: 6 veces

Número de intercambios: 3 veces

Desde la tabla de ejecución, el intercambio es casi tan malo como el burbujeo. De hecho, el número de bucles también lo es. 1/2 * (n-1) * n, por lo que la complejidad del algoritmo sigue siendo O (n * n. ). Debido a que no podemos proporcionar toda la información,

solo puedo decirle eso directamente. son igualmente malos en el intercambio (algunos casos ligeramente mejores, otros ligeramente peores).

3. Método de selección:

Ahora por fin podemos ver una pequeña esperanza: el método de selección, que mejora ligeramente el rendimiento (en algunos casos)

Este método es similar a nuestro hábito de clasificación manual: seleccione el valor más pequeño de los datos e intercámbielo con el primer valor, en la parte guardada.

Selecciona el más pequeño y cámbialo por el segundo, y así sucesivamente.

#include

void SelectSort(int* pData, int Count)

{

int iTemp

territorio iPos;

for(int I = 0; I < Count-1; i )

{

iTemp = pData

iPos = I;

for(int j = I 1; j 9, 10, 8, 7 (intercambio 1 vez) (bucle 1 vez)

Segunda ronda: 9, 10 , 8, 7-> 8, 9, 10, 7 (intercambiar 1 vez) (ciclo 2 veces)

Primera ronda: 8, 9, 10, 7-> 7, 8, 9, 10 ( Intercambio 1 vez) (Ciclo 3 veces)

Número de ciclos: 6 veces

Número de intercambios: 3 veces

Otros:

Primera ronda: 810, 7, 9-> 810, 7, 9 (intercambio 0 veces) (bucle 1 vez)

Segunda ronda: 8, 10, 7, 9-> 7, 8, 10 , 9 (intercambio 1 vez) (ciclo 2 veces)

Primera ronda: 7, 8, 10, 9-> 7, 8, 9, 10 (intercambio 1 vez) (ciclo 1 veces). /p>

Número de bucles: 4 veces

Número de intercambios: 2 veces

El análisis de comportamiento al final de lo anterior en realidad crea una ilusión, haciéndonos pensar Esto El algoritmo es el mejor entre los algoritmos simples, pero no lo es.

Debido a que el número de ciclos no es fijo, aún se puede usar el método O. De los resultados anteriores, se puede ver que el número de ciclos es el mejor. ciclos f (n) < =

1/2 * n *(n-1)< = 1/2 * n * n Entonces su complejidad sigue siendo O (n * n) (en realidad, si no fuera con el propósito de mostrar esta simplicidad,

Esto aún puede deducir el número de intercambios) Ahora mire los intercambios Por la apariencia, el número de intercambios es O(n) (la deducción es. similar

El método de selección), pero tenemos que hacer la misma cantidad de operaciones '=" que el bucle interno. Necesitamos tres '=" para hacer un intercambio normal.

Y obviamente hay más aquí, por lo que perdemos el tiempo.

Al final, personalmente creo que el método de selección es el mejor entre los algoritmos de clasificación simples.

2. algoritmo de clasificación:

Solo presentamos este algoritmo de clasificación avanzado, que también es el más rápido que conozco (según la información que he leído).

Todavía funciona como un binario. árbol Primero, seleccionamos un valor intermedio, usamos el valor medio de la matriz y luego colocamos el más pequeño a la izquierda y el más grande a la derecha (la implementación específica es encontrar). un par de ambos lados y luego intercambiar). Luego deja que ambas partes se separen

Utiliza este proceso (la forma más fácil: recursividad).

1. Ordenación rápida:

#include

void run(int* pData, int left, int right)

{

int i, j;

int medio, iTemp

i = izquierda

j = derecha

middle = pData[(left and right)/2] //Encontrar el valor medio

Hacer {

while((pData < middle) amp; amp(I < right) ))/ /Escanee números mayores que la mediana desde la izquierda.

i;

while((pData[j]> middle) amp; amp(j > left))//Escanea números mayores que el valor medio desde la derecha.

j-;

if(I < = j)//Encuentra un par de valores.

{

//Exchange

iTemp = pData

pData = pData[j];

pData [j]= iTemp;

i

j-;

}

} mientras(I < = j);/ / Deténgase (completar una vez) si los subíndices en ambos lados del escaneo están escalonados.

//Cuando la mitad izquierda tiene un valor (izquierda

if(left< j)

run(pData, left, j);

//Cuando la mitad derecha tiene un valor (right > i) , la mitad derecha es recursiva.

if(right>I)

run(pData, I, right);

}

void quick sort(int*); pData, int Count)

{

run(pData, 0, Count-1);

}

void main()

{

int data[] = {10, 9, 8, 7, 6, 5, 4};

Clasificación rápida (datos, 7) ;

for(int I = 0; I < 7; i )

cout < < datos

cout < < " \ n

}

No haremos análisis de comportamiento aquí, porque es muy simple. Analicemos el algoritmo directamente: primero considere la situación ideal

1. es una potencia de 2, por lo que siempre es divisible por 2. Supongamos que es la potencia k de 2, es decir, k = log2 (n) Cada vez que elegimos el valor es. exactamente el valor medio, de modo que la matriz se pueda dividir en partes iguales.

El primer nivel es recursivo, se repite n veces y el segundo nivel es 2 * (n/2)...

.

Entonces * *hay n 2 (. n/2) 4 (n/4) ... n * (n/n) = n n ... n = k * n = log2 (n) * n.

Entonces la complejidad del algoritmo es O (log2 (n) * n)

Otras situaciones solo serán peores que esta. El peor de los casos es que cada vez que se selecciona el valor medio, cambiará.p>

Método de intercambio (la situación es peor debido a la recursividad). Pero, ¿qué posibilidades hay de que esto suceda? Jaja, no necesitas preocuparte por este problema en absoluto. En este caso, la clasificación rápida siempre es mejor.

Si le preocupa este problema, puede utilizar la clasificación de montón. Es un algoritmo O (log2 (n) * n) estable, pero suele ser más lento.

Clasificación rápida (porque quieres reorganizar el montón).

En tercer lugar, otra clasificación

1. Burbujeo bidireccional:

Por lo general, el burbujeo es unidireccional, aquí es bidireccional, lo que significa que necesita trabajo. hacia atrás.

El código parece complicado y se puede entender con atención. Es una forma de oscilar hacia adelante y hacia atrás.

El autor que escribió este código cree que esto puede reducir parte de la comunicación debido al burbujeo (no lo creo, tal vez me equivoque).

De todos modos, creo que este es un código interesante y que vale la pena leer.

#include

void Bubble2Sort(int* pData, int Count)

{

int iTemp

int izquierda = 1;

int derecha = Contar-1;

int t; p>//Parte positiva

for(int I = derecha; i > = izquierda; i-)

{

if(pData data.m _ iIndex

}

/////////////////////////////////// ///////////////////////////////////////////////// // /////////////////////////////////////////

// Principal parte del programa

#include

#Contiene "MyData.h"

Plantilla

void run(T* pData , int izquierda, int derecha)

{

int i, j;

t, iTemp

i = izquierda

j = right;

//Todas las siguientes comparaciones llaman a nuestras funciones de operador sobrecargadas

middle = pData[(left and right)/2. Encuentra el valor medio

Haz {

while((pData < middle) amp; amp(I < right))//Escanea números mayores que el valor medio desde la izquierda <. /p>

i;

while((pData[j]> middle) amp; amp(j > left))//Escanea números mayores que el valor medio desde la derecha. p>j-;

if(I < = j)//Encontrar un par de valores

{

//Intercambiar

iTemp = pData

pData = pData[j];

pData[j]= iTemp;

i;

j-;

}

} while(I < = j); // Si los subíndices en ambos lados del escaneo están entrelazados, deténgase (completar una vez). //Cuando la mitad izquierda tiene un valor (izquierda

if(left< j)

run(pData, left, j);

//Cuando la mitad derecha tiene un valor (right > i) , la mitad derecha es recursiva.

if(right>I)

run(pData, I, right

}

Plantilla <); /p>

clasificación rápida nula (T* pData, int count)

{

run(pData, 0, Count-1);

}

void main()

{

CMyData datos[] = {

CMyData(8, "xulion"),

CMyData(7, "sanzoo"),

CMyData(6, "Wang Jun"),

CMyData(5, "VCKBASE"),

p>

CMyData(4, "jacky2000"),

CMyData(3, "cwally"),

CMyData(2, "VCUSER") ,

CMyData(1, " isdong ")

};

QuickSort(datos, 8);

for(int I = 0; yo < 8; yo )

cout