[Clase pequeña del algoritmo de habla] Utilice el método de dividir y conquistar (basado en la idea de fusionar y ordenar) para encontrar el número inverso de una permutación (O (n ^ 2) → O (n log n))

Inserte la descripción de la imagen aquí

Método de dividir y conquistar para encontrar el número ordinal inverso

Conocimiento previo: fusionar y ordenar.
Hemos demostrado la exactitud del tipo de combinación. Siempre que el algoritmo de clasificación de combinación se modifique ligeramente, la complejidad temporal de encontrar el número inverso de una permutación se puede reducir de O (n ^ 2) a O (n log⁡n).
Divida un arreglo P en dos partes P_1 y P_2 de la manera más uniforme posible. Entonces, el número de secuencia
inverso de P τ§ = τ (P_1) + τ (P_2) + τ_Merge
Obviamente, τ (P_1) y τ (P_2) respectivamente representan los números de secuencia inversa en el rango de P_1 y P_2 que se resuelven de forma recursiva. Y τ_Merge cubrirá todos los casos perdidos, es decir, los dos elementos a_i, a_j que forman el par de orden inverso (a_i, a_j), i <j, a_i> a_j satisfacen a_i∈P_1, a_j∈P_2.
En el proceso de fusión y clasificación, el paso de fusionar dos secuencias ordenadas (ascendentes) es:
establecer una secuencia temporal t para fusionar.
Los punteros i y j apuntan al comienzo de las dos submatrices respectivamente. El rango de la subsecuencia es _begin a _mid, _mid + 1 a _end.
Tome constantemente un elemento de cada una de las dos submatrices (es decir, los elementos apuntados por los punteros i y j) para comparar, coloque el número más pequeño en la matriz t, y el puntero correspondiente se incrementa (cuando los dos elementos son igual, la dirección se compara de forma predeterminada El número en la matriz inferior, es decir, el número al que apunta i se pone en t). Cuando se elimina una de las subsecuencias, el ciclo finaliza.
Copie todos los elementos de la subsecuencia cuyos elementos no se han llevado a la secuencia t.
Suponga que los dos números extraídos de la secuencia de números ordinales P_1 y P_2 de longitud myn son x_i, y_j respectivamente, y los subíndices representan sus posiciones en la secuencia de números ordinales. Si x_i> y_j se encuentra en cada comparación, y se sabe que la secuencia está en orden ascendente, entonces
x_k> y_j, k = i, i + 1, ..., m, x_k∈P_1, y_j∈P_2
significa que m se encuentra -i + 1 pares en orden inverso. Es decir, τ_Merge = m-i + 1.
Código:

template<class _Ty> size_t merge(_Ty* _begin, _Ty* _mid, _Ty* _end) {
    
    
	const auto l = _end - _begin + 1; size_t tau = 0;
	_Ty* t = new _Ty[l], * i = _begin, * j = _mid + 1, * k = t;
	while (i <= _mid && j <= _end) {
    
    
		if (*i <= *j) {
    
     *k = *i; ++i; ++k; }
		else {
    
     *k = *j; ++j; ++k; tau += _mid - i + 1; }
	}
	while (i <= _mid) {
    
     *k = *i; ++i; ++k; }
	while (j <= _end) {
    
     *k = *j; ++j; ++k; }
	std::copy(t, t + l, _begin);
	delete[] t;
	return tau;
}

template<class _Ty> size_t inversion_count(_Ty* _begin, _Ty* _end) {
    
    
	size_t tau = 0;
	if (_begin < _end) {
    
    
		_Ty* _mid = _begin + (_end - _begin) / 2;
		tau += inversion_count(_begin, _mid);
		tau += inversion_count(_mid + 1, _end);
		tau += merge(_begin, _mid, _end);
	}
	return tau;
}

Supongo que te gusta

Origin blog.csdn.net/COFACTOR/article/details/109005737
Recomendado
Clasificación