[C++ implementa algoritmo recursivo, ordenación por fusión y ordenación por montón]

1. Algoritmo recursivo

Cuando necesitamos ejecutar un algoritmo repetidamente, usar un algoritmo recursivo puede ser una buena opción. En este algoritmo, una función se llama a sí misma hasta que se alcanza una determinada condición que detiene la recursividad . La recursividad es compatible con el lenguaje C++ Vamos a presentar en detalle cómo usar C++ para implementar algoritmos recursivos.

En este tutorial, presentaremos la implementación del algoritmo recursivo tomando la secuencia de Fibonacci como ejemplo.

La secuencia de Fibonacci, también conocida como secuencia de la sección áurea, fue introducida por el matemático Leonardo Fibonacci con el ejemplo de la cría de conejos, por lo que también se la denomina "secuencia de conejos". Es una secuencia de este tipo: 1, 1, 2, 3 , 5, 8, 13, 21, 34, ... En matemáticas, la sucesión de Fibonacci se define recursivamente de la siguiente manera: F (0)= 1, F (1)=1, F (n)= F (n - 1 ) + F (n - 2) ( norte ≥ 2, norte ∈ N*)

1. Definir la función

Primero, necesitamos definir una función para calcular el enésimo término de la secuencia de Fibonacci. Teniendo en cuenta que se conocen los elementos 0 y 1 de la secuencia de Fibonacci, podemos dividir la función en dos casos: cuando n es 0 o 1, devolvemos directamente el valor de n; de lo contrario, devolvemos Fibonacci La suma de los n-1 y n-2 términos en la secuencia de Natch. el código se muestra a continuación:

int fibonacci(int n) {
    
    
    if (n == 0 || n == 1) {
    
    
        return n;
    }
    else {
    
    
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
}

2. Función de prueba

Podemos usar esta función para probar, calculando los primeros términos de la secuencia de Fibonacci. Por ejemplo, podemos usar el siguiente código para calcular los primeros 10 términos de la sucesión de Fibonacci:

int main() {
    
    
    for (int i = 0; i < 10; i++) {
    
    
        cout << fibonacci(i) << " ";
    }
    return 0;
}

3. Analizar algoritmo recursivo

En este ejemplo, se puede usar un algoritmo recursivo para calcular el término n de la sucesión de Fibonacci, con la fórmula recursiva:

F(n) = F(n-1) + F(n-2)

Entre ellos, F(n) representa el enésimo elemento de la sucesión de Fibonacci. Cuando n=0 o 1, devolvemos directamente n.

Cabe señalar que en el algoritmo recursivo, se deben establecer las condiciones para terminar la recursividad. En este ejemplo, configuramos la recursividad para que termine cuando n=0 o 1. Si no se establece la condición para terminar la recursividad o si la condición de terminación se establece incorrectamente, la recurrencia continuará ejecutándose indefinidamente, lo que generará problemas como el desbordamiento de la pila.

4. Resumen

Este tutorial presenta los pasos básicos para implementar un algoritmo recursivo usando C++, tomando como ejemplo la secuencia de Fibonacci. Desde definir funciones, probar funciones hasta analizar algoritmos recursivos, este tutorial espera ayudarlo a comprender mejor el concepto de algoritmos recursivos y dominar sus métodos de implementación.

El código completo es el siguiente:

#include<iostream>
using namespace std;
int fibonacci(int n);
int main()
{
    
    
	for (int i = 0; i < 10; i++) {
    
    
        cout << fibonacci(i) << " ";
    }
    return 0;

}

int fibonacci(int n) {
    
    
    if (n == 0 || n == 1) {
    
    
        return n;
    }
    else {
    
    
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
}

2. Clasificación por combinación

Merge Sort (Merge Sort) es un algoritmo de divide y vencerás. Su idea básica es dividir recursivamente una matriz grande en dos matrices pequeñas hasta que ya no se pueda dividir, y luego fusionar estas pequeñas matrices en pares y fusionarlas continuamente. hasta que la matriz original esté completamente ordenada . La ordenación por combinación es estable, la complejidad temporal es estable en O(nlogn) y la complejidad espacial es O(n).

Los siguientes pasos introducirán la implementación detallada de la ordenación por fusión.

1. Dividir

Primero, la matriz que se va a ordenar se divide recursivamente en dos sub-matrices hasta que cada sub-matriz tenga un solo elemento. Esto significa que la matriz se ha descompuesto en n subarreglos de longitud 1.

2. Fusionar

Combine los subconjuntos de dos en dos para obtener n/2 subconjuntos ordenados, y luego vuelva a fusionar estos subconjuntos ordenados hasta que solo quede un conjunto ordenado de longitud n. Los pasos para fusionar dos subarreglos ordenados son:

(1) Cree una matriz vacía para almacenar los elementos combinados.

(2) Recorra las dos matrices ordenadas al mismo tiempo, compare sus primeros elementos y agregue los elementos más pequeños a la nueva matriz.

(3) Repita los pasos anteriores hasta que todos los elementos de una de las matrices se coloquen en la nueva matriz.

(4) Agregue todos los elementos en otra matriz directamente al final de la nueva matriz.

(5) Devuelve la nueva matriz.

3. Implementación de código de tipo de fusión

La siguiente es la implementación del código de ordenación por fusión:

void merge(int nums[], int left, int mid, int right) {
    
    
    /*将原数组分成两个部分,左半部分为[nums[left], nums[mid]],
    右半部分为[nums[mid + 1], nums[right]]*/
    int n1 = mid - left + 1;
    int n2 = right - mid;
    int L[n1], R[n2];
    for (int i = 0; i < n1; i++) {
    
    
        L[i] = nums[left + i];
    }
    for (int i = 0; i < n2; i++) {
    
    
        R[i] = nums[mid + 1 + i];
    }
    // 将两个数组合并为一个升序数组
    int i = 0, j = 0, k = left;
    while (i < n1 && j < n2) {
    
    
        if (L[i] <= R[j]) {
    
    
            nums[k++] = L[i++];
        }
        else {
    
    
            nums[k++] = R[j++];
        }
    }
    while (i < n1) {
    
    
        nums[k++] = L[i++];
    }
    while (j < n2) {
    
    
        nums[k++] = R[j++];
    }
}

void mergeSort(int nums[], int left, int right) {
    
    
    if (left < right) {
    
    
        int mid = left + (right - left) / 2;
        mergeSort(nums, left, mid);
        mergeSort(nums, mid + 1, right);
        merge(nums, left, mid, right);
    }
}

4. Código de prueba

Aquí hay un código de prueba:

int main() {
    
    
    int nums[] = {
    
    2, 5, 1, 6, 3, 8, 4, 7};
    int len=sizeof(nums)/sizeof(nums[0]);
    cout<<"排序前:";
	for (int i=0;i<len;i++) {
    
    
        cout << nums[i] << " ";
    } 
	mergeSort(nums, 0, len - 1);
    cout<<"\n排序后:"; 
	for (int i=0;i<len;i++) {
    
    
        cout << nums[i] << " ";
    }
    return 0;
}

En el código anterior, a partir de los datos de prueba {2, 5, 1, 6, 3, 8, 4, 7}, los datos ordenados obtenidos por combinación de clasificación son {1, 2, 3, 4, 5, 6, 7, 8}.

5. Resumen

Merge sort es un algoritmo de clasificación eficiente que divide recursivamente una matriz por la mitad y luego combina las dos mitades en una matriz ordenada. La clasificación se puede implementar de manera eficiente con datos a gran escala. Debe tenerse en cuenta que el proceso de implementación de la ordenación por combinación involucra una gran cantidad de punteros y bucles, y se debe tener más cuidado durante la implementación para evitar problemas como cruzar el límite.

6. Código completo

#include<iostream>
using namespace std;

void merge(int nums[], int left, int mid, int right) {
    
    
    /*将原数组分成两个部分,左半部分为[nums[left], nums[mid]],
    右半部分为[nums[mid + 1], nums[right]]*/
    int n1 = mid - left + 1;
    int n2 = right - mid;
    int L[n1], R[n2];
    for (int i = 0; i < n1; i++) {
    
    
        L[i] = nums[left + i];
    }
    for (int i = 0; i < n2; i++) {
    
    
        R[i] = nums[mid + 1 + i];
    }
    // 将两个数组合并为一个升序数组
    int i = 0, j = 0, k = left;
    while (i < n1 && j < n2) {
    
    
        if (L[i] <= R[j]) {
    
    
            nums[k++] = L[i++];
        }
        else {
    
    
            nums[k++] = R[j++];
        }
    }
    while (i < n1) {
    
    
        nums[k++] = L[i++];
    }
    while (j < n2) {
    
    
        nums[k++] = R[j++];
    }
}

void mergeSort(int nums[], int left, int right) {
    
    
    if (left < right) {
    
    
        int mid = left + (right - left) / 2;
        mergeSort(nums, left, mid);
        mergeSort(nums, mid + 1, right);
        merge(nums, left, mid, right);
    }
}
int main() {
    
    
    int nums[] = {
    
    2, 5, 1, 6, 3, 8, 4, 7};
    int len=sizeof(nums)/sizeof(nums[0]);
    cout<<"排序前:";
	for (int i=0;i<len;i++) {
    
    
        cout << nums[i] << " ";
    } 
	mergeSort(nums, 0, len - 1);
    cout<<"\n排序后:"; 
	for (int i=0;i<len;i++) {
    
    
        cout << nums[i] << " ";
    }
    return 0;
}

3. Ordenar montones

Heap sort es un algoritmo de clasificación basado en montón binario, su complejidad de tiempo es O (nlogn) y se usa ampliamente en aplicaciones prácticas. La idea básica de la clasificación del montón es crear la secuencia que se va a clasificar en un montón binario y luego sacar los elementos superiores del montón hasta que el montón esté vacío .

1. Definición de montón

Un montón es un árbol binario completo, que se divide en dos tipos: montón máximo y montón mínimo.

Montón máximo: el valor de cada nodo es mayor o igual que el valor de sus nodos secundarios izquierdo y derecho.

Montón mínimo: el valor de cada nodo es menor o igual que el valor de sus nodos secundarios izquierdo y derecho.

2. La idea básica de la clasificación de montones

La idea básica de la clasificación del montón es crear la secuencia que se va a clasificar en un montón binario y luego sacar los elementos superiores del montón hasta que el montón esté vacío. El proceso específico es el siguiente:

(1) Construya la secuencia que se ordenará en un montón máximo.

(2) Intercambie los elementos en la parte superior del montón con los elementos en la parte inferior del montón, elimine los elementos en la parte inferior del montón y reconstruya los elementos restantes en un montón máximo.

(3) Repita el paso (2) hasta que el montón esté vacío.

3. Implementación de la ordenación en montón

(1) Construya el montón más grande

El proceso de construcción del almacenamiento dinámico máximo puede adoptar un método ascendente, comenzando desde el último nodo que no sea hoja y ajustando secuencialmente cada nodo a su subárbol para convertirse en el almacenamiento dinámico máximo. La implementación específica es la siguiente:

void AdjustHeap(int arr[], int i, int n)
{
    
    
    int temp = arr[i];
    int j = 2 * i + 1;
    while (j < n)
    {
    
    
        if (j + 1 < n && arr[j + 1] > arr[j])
        {
    
    
            j++;
        }
        if (arr[j] > temp)
        {
    
    
            arr[i] = arr[j];
            i = j;
            j = 2 * i + 1;
        }
        else
        {
    
    
            break;
        }
    }
    arr[i] = temp;
}

void buildMaxHeap(int arr[], int n)
{
    
    
    for (int i = n / 2 - 1; i >= 0; i--)
    {
    
    
        AdjustHeap(arr, i, n);
    }
}

(2) Clasificación de montón

El proceso de implementación de heap sort es el siguiente:

void heapSort(int arr[], int n)
{
    
    
    buildMaxHeap(arr, n);
    for (int i = n - 1; i > 0; i--)
    {
    
    
        swap(arr[0], arr[i]);
        AdjustHeap(arr, 0, i);
    }
}

4. Optimización de la clasificación de montones

(1) Optimizar el proceso de creación de montones

En el proceso de construcción de un montón, para un nodo i, sus nodos secundarios izquierdo y derecho son 2i + 1 y 2i + 2 respectivamente.Si el valor mayor de los nodos secundarios izquierdo y derecho es mayor que el valor del nodo i, entonces el valor más grande debe combinarse con los intercambios de i-node, y luego continúa ajustándose hacia abajo. Este proceso se puede implementar con un bucle, lo que evita llamadas recursivas y mejora la eficiencia.

void AdjustHeap(int arr[], int i, int n)
{
    
    
    int temp = arr[i];
    for (int j = 2 * i + 1; j < n; j = 2 * j + 1)
    {
    
    
        if (j + 1 < n && arr[j + 1] > arr[j])
        {
    
    
            j++;
        }
        if (arr[j] > temp)
        {
    
    
            arr[i] = arr[j];
            i = j;
        }
        else
        {
    
    
            break;
        }
    }
    arr[i] = temp;
}

(2) Optimizar el proceso de clasificación

Durante el proceso de clasificación, cada vez que el elemento superior del montón se intercambia con el elemento inferior del montón, el tamaño del montón se reduce en 1 y luego el montón debe reajustarse. Sin embargo, dado que el elemento inferior del montón se ha cambiado a la parte superior del montón, y la parte por encima del elemento inferior del montón sigue siendo un montón máximo, el elemento superior del montón se puede ajustar directamente sin reconstruir todo el montón. , lo que puede reducir algunas operaciones innecesarias.

void heapSort(int arr[], int n)
{
    
    
    buildMaxHeap(arr, n);
    for (int i = n - 1; i > 0; i--)
    {
    
    
        swap(arr[0], arr[i]);
        AdjustHeap(arr, 0, i);
    }
}

5. La estabilidad de la clasificación en montón

Heap sort es un algoritmo de clasificación inestable, porque en el proceso de ajuste del montón, las posiciones de los mismos elementos pueden intercambiarse. Por ejemplo, para la secuencia {5, 2, 5, 1, 6, 2}, después de la clasificación del montón, puede convertirse en {1, 2, 2, 5, 5, 6}, donde ocurren las posiciones relativas de dos 2. Cambiar .

6. Código completo

#include<iostream>
using namespace std;
//构建最大堆 
void AdjustHeap(int arr[], int i, int n)
{
    
    
    int temp = arr[i];
    for (int j = 2 * i + 1; j < n; j = 2 * j + 1)
    {
    
    
        if (j + 1 < n && arr[j + 1] > arr[j])
        {
    
    
            j++;
        }
        if (arr[j] > temp)
        {
    
    
            arr[i] = arr[j];
            i = j;
        }
        else
        {
    
    
            break;
        }
    }
    arr[i] = temp;
}

void buildMaxHeap(int arr[], int n)
{
    
    
    for (int i = n / 2 - 1; i >= 0; i--)
    {
    
    
        AdjustHeap(arr, i, n);
    }
}
//堆排序 
void heapSort(int arr[], int n)
{
    
    
    buildMaxHeap(arr, n);
    for (int i = n - 1; i > 0; i--)
    {
    
    
        swap(arr[0], arr[i]);
        AdjustHeap(arr, 0, i);
    }
}

int main()
{
    
    
	int arr[]={
    
    4,6,3,7,2,9};
	int len=sizeof(arr)/sizeof(arr[0]);
	cout<<"原数组:"; 
	for(int i=0;i<len;i++){
    
    
		cout<<arr[i]<<" ";
	}	
	heapSort(arr,len);
	cout<<endl;
	cout<<"排序后:";
	for(int i=0;i<len;i++){
    
    
		cout<<arr[i]<<" ";
	}
 } 

Supongo que te gusta

Origin blog.csdn.net/qq_43884946/article/details/131186691
Recomendado
Clasificación