[C ++ STL] El principio y el uso del algoritmo de clasificación rápida (clasificación)

1. sortPrincipio del algoritmo

std::sortEs un algoritmo de clasificación proporcionado en la biblioteca estándar de C++ y utiliza un algoritmo de clasificación clásico: Quicksort (Quicksort) o una variante del mismo.

La clasificación rápida es un algoritmo de clasificación basado en la comparación. Al seleccionar continuamente un valor de pivote, la secuencia que se va a ordenar se divide en dos subsecuencias. Todos los elementos de una subsecuencia son menores o iguales que el valor de pivote, y todos los elementos de la otra subsecuencia son menores o iguales que el valor de pivote. El elemento es mayor que el valor base. Luego, las dos subsecuencias se ordenan de forma recursiva y finalmente dan como resultado una secuencia ordenada.

std::sortAl implementar la clasificación rápida, generalmente se combinan otras técnicas de optimización, como la clasificación por inserción o la clasificación en montón, para mejorar el rendimiento y la eficiencia del algoritmo.

Pasos básicos para una clasificación rápida:

  1. Elija un valor de pivote. Puede seleccionar el primer elemento, el último elemento, el elemento intermedio de la secuencia o un elemento aleatorio como valor base.
  2. Divida la secuencia en dos subsecuencias, de modo que todos los elementos de una subsecuencia sean menores o iguales que el valor de referencia y todos los elementos de la otra subsecuencia sean mayores que el valor de referencia.
  3. Ordene dos subsecuencias de forma recursiva, es decir, ordene las subsecuencias que son menores o iguales que el valor de referencia y las subsecuencias que son mayores que el valor de referencia.
  4. Fusione las dos subsecuencias ordenadas para obtener la secuencia ordenada final.

La clasificación rápida es un algoritmo de clasificación in situ cuya complejidad de tiempo promedio es O(nlogn), donde n es el tamaño de la secuencia que se va a ordenar. En el peor de los casos, la complejidad temporal de la clasificación rápida es O(n^2), pero la probabilidad del peor de los casos se puede reducir seleccionando racionalmente el valor de referencia.

std::sortLa implementación tiene en cuenta el rendimiento y la eficiencia en diferentes situaciones y puede variar entre diferentes compiladores e implementaciones de biblioteca. Por lo general, selecciona un algoritmo de clasificación apropiado según el tamaño de la secuencia, el tipo de datos y otros factores para lograr un mejor rendimiento. Para secuencias pequeñas, std::sortse puede utilizar la clasificación por inserción u otros algoritmos de clasificación simples, mientras que para secuencias grandes, normalmente se utiliza la clasificación rápida o una variante de la misma. Además, se pueden aceptar funciones o predicadosstd::sort de comparación personalizados para satisfacer diferentes necesidades de clasificación.

2. sortUso de algoritmos

Función: organizar los elementos en el contenedor (predeterminado en orden ascendente)

  • sort()Pertenece al algoritmo de cambio cualitativo.
Prototipo de función: ordenar (iterador inicio, iterador final, pred) explicar
Parámetro 1 iterador suplicar iniciar iterador
Parámetro 2 final del iterador iterador final
Parámetro 3 antes predicado

detalles:

Cuando se llama std::sortpara ordenar, utiliza un algoritmo de clasificación rápida de divide y vencerás, lo que significa que divide los elementos que se van a ordenar en subconjuntos más pequeños, luego ordena estos subconjuntos y los fusiona gradualmente, obteniendo finalmente resultados completamente ordenados.

  • Rango de clasificación:std::sort la clasificación es un rango, especificado por dos iteradores firsty last, que indica la posición inicial y final de la clasificación. La clasificación se aplicará a [first, last)los elementos dentro del rango.
  • Criterios de clasificación: de forma predeterminada, las comparaciones std::sortque utilizan <el operador se utilizan para determinar el orden de los elementos. Si desea ordenar según otros criterios, puede proporcionar una función de comparación personalizada o un objeto de función como tercer argumento opcional. Esta función de comparación u objeto de función debe aceptar dos argumentos y devolver un valor booleano que indique si el primer argumento debe aparecer antes del segundo argumento en la clasificación.
  • Complejidad temporal:std::sort utilizando el algoritmo de clasificación rápida, su complejidad temporal promedio es O(n log n), donde n es el número de elementos a ordenar. En el peor de los casos, la clasificación rápida tiene una complejidad temporal de O(n^2), pero esto rara vez sucede.
  • Requisitos de contenedor: se puede utilizar para contenedores estándar ( std::sortcomo std::vector,, etc.) y matrices ordinarias. La clasificación se realiza in situ, es decir, el orden de los elementos en el contenedor se modifica directamente sin crear un nuevo contenedor.std::dequestd::list
  • Tipos personalizables:std::sort no solo se pueden ordenar los tipos básicos (como enteros, números de punto flotante), sino también los tipos personalizados, siempre que el tipo personalizado admita operadores de comparación <o proporcione funciones de comparación personalizadas.
  • Invalidación de iteradores:std::sort los iteradores no se invalidan, lo que significa que los iteradores del contenedor original aún se pueden usar después de la clasificación.
  • Estabilidad:std::sort la estabilidad de la clasificación no está garantizada, es decir, el orden de elementos iguales puede cambiar después de la clasificación. Si necesita mantener sin cambios el orden de los elementos iguales, puede utilizar std::stable_sortel algoritmo.

Ejemplo 1: ordenar en orden ascendente de forma predeterminada

#include <iostream>
#include <algorithm> //必须包含该头文件
#include <vector>
using namespace std;

//函数对象(仿函数)
class print
{
    
    
public:
	void operator()(int value)
	{
    
    
		cout << value << " ";
	}
};

void test01()
{
    
    
	vector<int> vec = {
    
    6, 9, 3, 4, 2, 7, 1, 5, 8};

	//排序前
	cout << "排序前:";
	for_each(vec.begin(), vec.end(), print());
	cout << endl;

	//排序后-升序
	cout << "排序后:";
	sort(vec.begin(), vec.end());   //默认升序
	for_each(vec.begin(), vec.end(), print());
	cout << endl;
}

int main()
{
    
    
	test01();
	system("pause");
	return 0;
}
//result
排序前:6 9 3 4 2 7 1 5 8
排序后:1 2 3 4 5 6 7 8 9

Ejemplo 2: uso de predicadosstd::greater<>

  • greater<>Es una clase de plantilla, que es un predicado binario (predicado binario), que se utiliza para comparar la relación de tamaño entre dos valores.
#include <iostream>
#include <algorithm> //必须包含该头文件
#include <vector>
using namespace std;

//函数对象(仿函数)
class print
{
    
    
public:
	void operator()(int value)
	{
    
    
		cout << value << " ";
	}
};

void test01()
{
    
    
	vector<int> vec = {
    
    6, 9, 3, 4, 2, 7, 1, 5, 8};

	//排序前
	cout << "排序前:";
	for_each(vec.begin(), vec.end(), print());
	cout << endl;

	//排序后-降序-添加谓词greater
	cout << "排序后:";
	sort(vec.begin(), vec.end(), greater<int>());
	for_each(vec.begin(), vec.end(), print());
	cout << endl;
}

int main()
{
    
    
	test01();
	system("pause");
	return 0;
}
//result
排序前:6 9 3 4 2 7 1 5 8
排序后:9 8 7 6 5 4 3 2 1

Ejemplo 3: clasificación de tipos personalizados

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

class goods
{
    
    
public:
    goods(string name, int price)
    {
    
    
        m_name = name;
        m_price = price;
    }

public:
    string m_name;
    int m_price;
};

// 自定义排序-根据商品价格升序
struct arrange
{
    
    
    bool operator()(const goods& value1, const goods& value2)
    {
    
    
        return value1.m_price < value2.m_price;
    }
};

class print
{
    
    
public:
    void operator()(const goods& value)
    {
    
    
        cout << "名称:" << value.m_name  << "\t价格:" << value.m_price << endl;
    }
};

void test01()
{
    
    
    goods goods1("可乐", 3);
    goods goods2("红牛", 5);
    goods goods3("脉动", 4);
    goods goods4("外星人", 6);
    goods goods5("雪碧", 3);
    goods goods6("哇哈哈", 2);

    vector<goods> vec;
    vec.push_back(goods1);
    vec.push_back(goods2);
    vec.push_back(goods3);
    vec.push_back(goods4);
    vec.push_back(goods5);
    vec.push_back(goods6);

    // 排序前
    cout << "排序前:" << endl;
    for_each(vec.begin(), vec.end(), print());
    cout << endl;

    // 排序后-升序-添加谓词arrange
    cout << "排序后:" << endl;
    sort(vec.begin(), vec.end(), arrange());
    for_each(vec.begin(), vec.end(), print());
    cout << endl;
}

int main()
{
    
    
    test01();
    system("pause");
    return 0;
}
//result
排序前:
名称:可乐      价格:3
名称:红牛      价格:5
名称:脉动      价格:4
名称:外星人    价格:6
名称:雪碧      价格:3
名称:哇哈哈    价格:2

排序后:
名称:哇哈哈    价格:2
名称:可乐      价格:3
名称:雪碧      价格:3
名称:脉动      价格:4
名称:红牛      价格:5
名称:外星人    价格:6

Resumen:std::sort Es un algoritmo de clasificación eficiente, versátil y flexible. Proporciona un buen rendimiento en la mayoría de los casos y se puede aplicar a diferentes tipos de contenedores y tipos personalizados. Sin embargo, para algunas necesidades especiales, como la necesidad de una clasificación estable o la clasificación de contenedores grandes, puede ser necesario elegir otro algoritmo de clasificación o utilizar una implementación de clasificación personalizada.


Si este artículo te resulta útil, ¡me gustaría recibir un Me gusta tuyo!

Insertar descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/AAADiao/article/details/131011879
Recomendado
Clasificación