1. sort
Principio del algoritmo
std::sort
Es 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::sort
Al 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:
- 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.
- 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.
- 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.
- 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::sort
La 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::sort
se 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. sort
Uso 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::sort
para 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 iteradoresfirst
ylast
, 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::sort
que 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 esO(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 deO(n^2)
, pero esto rara vez sucede. - Requisitos de contenedor: se puede utilizar para contenedores estándar (
std::sort
comostd::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::deque
std::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 utilizarstd::stable_sort
el 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.