Pruebe la complejidad temporal de algoritmos como la búsqueda binaria y la clasificación por selección directa

        1.
        Búsqueda binaria Búsqueda binaria, también conocida como búsqueda binaria, la premisa de la búsqueda binaria es que la tabla lineal o el árbol se han ordenado. Aquí, la tabla lineal se toma como ejemplo. Se supone que la tabla lineal se ha ordenado por palabras clave y va aumentando Dispuesto ordenadamente.
        La idea de la búsqueda binaria: Deje que la tabla lineal R [izquierda, derecha] sea el intervalo de búsqueda actual, primero determine la posición del punto medio del intervalo mid = (izquierda + derecha) / 2, y luego compare el valor K que se comprobará con R [mid] La comparación de .key es la siguiente:
        1) Si K = R [mid] .key, entonces devuelve directamente el índice del elemento;
        2) Si K <R [mid] .key, entonces
            left = mid-1;
            mid = (izquierda + derecha) / 2;
      buscar en el intervalo de la mitad izquierda [izquierda, mitad-1];
        3) Si K> R [mitad] .key, entonces
            derecha = mitad + 1;
            mitad = (izquierda + derecha) / 2;
      Busque en la mitad derecha del intervalo [izquierda, mitad-1];
    4) Repita los pasos 2) y 3) hasta izquierda> derecha, es decir, el espacio de búsqueda se convierte en 0. Si lo encuentra, devuelve el índice del elemento. De lo contrario, devuelve -1.
    Búsqueda binaria, cada búsqueda, el intervalo de búsqueda se reduce a la mitad, por lo que el algoritmo es muy rápido, la complejidad del tiempo es O (log n) O (log \, n)O ( l o gn ) .
    // Búsqueda binaria binarySearch ()

	int binarySearch(int arr[], int n, int target) {
    
    
		int left = 0, right = n-1;
		while (left <= right) {
    
    
			int mid = (left+right)/2;
			if(arr[mid] == target)
				return mid;

			if(arr[mid] > target)
				right = mid - 1;
			else
				left = mid + 1;
		}
		return -1;
	}

    2.
    Clasificación por selección El método básico de clasificación por selección es: cada paso selecciona el registro con la palabra clave más pequeña de los registros que se van a clasificar, y el orden se coloca al final de los registros clasificados hasta que se completan todas las clasificaciones. La clasificación por selección incluye la clasificación por selección directa y la clasificación por montón. Aquí hay una clasificación de selección directa.
    El proceso de selección y ordenación directa es: supongamos que los registros se colocan en R [0, n-1], R [0, i-1] es el área ordenada, R [i, n-1] es el área desordenada, y hay Todas las palabras clave del área de secuencia son más pequeñas que todas las palabras clave del área de trastornos. Es necesario agregar R [i] a R [0, i-1] para hacer que R [0, i] esté ordenado. Aquí, cada pasada selecciona un registro R [k] con la clave más pequeña del área desordenada R [i, n-1] y lo intercambia con R [i]. Obviamente, R [0, i] se convierte en Una nueva zona ordenada.
    2.1) Utilice la estructura para indicar el tipo de selección directa


#define MaxSize 100
typedef int KeyType;
typedef char ElemType;
typedef struct{
    
    
	KeyType  key;       //关键字域
	ElemType data[10];  //其他数据域
}SqList;

void SelectSort(SqList R[], int n) {
    
    
	int i, j, k;
	SqList tmp;
	for (i = 0; i < n - 1; j++) {
    
    
		k = i;
		for (j = i + 1; j < n; j++) {
    
    
			if (R[j].key < R[k].key)
				k = j;
		}

		tmp = R[i];
		R[i] = R[k];
		R[k] = tmp;
	}
}

    2.2 Use una matriz para indicar el orden de selección directa

//交换a和b 方法一
void swapValue(int &a, int &b) {
    
    
	int tmp = a;
	a = b;
	b = tmp;
}

//交换a和b 方法二
void swapValue2(int &a, int &b) {
    
    
	a = a + b;
	b = a - b;
	a = a - b;	
}


//直接选择排序
void selectionSort(int arr[], int n) {
    
    
	for (int i = 0; i < n - 1; i++) {
    
    
		int minIndex = i;
		for (int j = i + 1; j < n; j++) {
    
    
			if (arr[j] < arr[minIndex]) {
    
    
				minIndex = j;
			}
		}
		swapValue(arr[i], arr[minIndex]);
	}
}

    3. Escribir casos de prueba para algoritmos
    3.1 Ponga todos los algoritmos en un espacio de comandos, como el espacio de nombres MyAlgorithmTester, que es un archivo de encabezado: MyAlgorithm.h
    //MyAlgorithm.h

#ifndef MY_ALGORITHM_H
#define MY_ALGORITHM_H

#include <iostream>
#include <cassert>
#include <cmath>

using namespace std;

#define min(a,b)  (((a)<(b))?(a):(b))

namespace MyAlgorithmTester {
    
    

	//O(logN)
	int binarySearch(int arr[], int n, int target) {
    
    
		int left = 0, right = n-1;
		while (left <= right) {
    
    
			int mid = (left+right)/2;
			if(arr[mid] == target)
				return mid;

			if(arr[mid] > target)
				right = mid - 1;
			else
				left = mid + 1;
		}
		return -1;
	}

	//O(N)
	int findMax(int arr[],int n) {
    
    
		assert(n > 0);
		int res = arr[0];
		for (int i=1;i<n;i++) {
    
    
			if(arr[i] > res)
				res = arr[i];
		}

		return res;
	}

	//O(NlogN)
	void __merge(int arr[],int left,int mid,int right, int aux[]) {
    
    
		int i = left,j = mid+1;
		for(int k=left; k<= right; k++) {
    
    
			if (i > mid) {
    
    
				arr[k] = aux[j];
				j++;
			}
			else if (j > right) {
    
    
				arr[k] = aux[i];
				i++;
			}
			else if (aux[i] < aux[j]) {
    
    
				arr[k] = aux[i];
				i++;
			}
			else {
    
    
				arr[k] =aux[j];
				j++;
			}		
		}
	}

	//自顶向上排序
	void mergeSort(int arr[], int n) {
    
    
		int *aux = new int[n];
		for (int i=0;i<n;i++) {
    
    
			aux[i] = arr[i];
		}

		for (int sz=1;sz<n;sz += sz) {
    
    
			for (int i=0; i < n; i += sz+sz) {
    
    
				__merge(arr,i,i+sz-1,min(i+sz+sz-1, n-1), aux);
			}
		}

		delete[] aux;
		return;
	}

	//O(N^2)
	void selectionSort(int arr[], int n) {
    
    
		for (int i=0;i<n-1; i++) {
    
    
			int minIndex = i;
			for (int j=i+1; j<n; j++) {
    
    
				if(arr[j] < arr[minIndex])
					minIndex = j;
			}
			swap(arr[i],arr[minIndex]);
		}
	}


}

#endif

    3.2) Coloque la función que genera el conjunto de datos en el espacio de nombres MyUtil, que también es un archivo de encabezado: MyUtil.h
    //MyUtil.h

#ifndef MY_UTIL_H
#define MY_UTIL_H

#include <iostream>
#include <cassert>
#include <ctime>
using namespace std;

namespace MyUtil {
    
    
	int *generateRandomArray(int n, int rangeL, int rangeR) {
    
    
		assert(n > 0 && rangeL <= rangeR );

		int *arr = new int[n];
		srand(time(NULL));
		for (int i = 0; i < n; i++) {
    
    
			arr[i] = rand() % (rangeR - rangeL + 1) + rangeL;
		}
		return arr;
	}

	int *generateOrderedArray(int n) {
    
    
		assert(n > 0);

		int *arr = new int[n];
		for (int i = 0; i < n; i++) {
    
    
			arr[i] = i;
		}
		return arr;
	}

}


#endif

    3.3) Escribe la función principal
    //main.cpp

#include "MyAlgorithm.h"
#include "MyUtil.h"

#include <cmath>
#include <ctime>
#include <windows.h>
using namespace std;

int main() {
    
    

	//1) findMax 数据规模倍乘测试 
	//O(n)
	//for (int i = 10; i <= 26; i++) {
    
    
	//	int n = pow(2, i);
	//	int *arr = MyUtil::generateRandomArray(n, 0, 100000000);

	//	clock_t startTime = clock();
	//	MyAlgorithmTester::findMax(arr, n);
	//	clock_t endTime = clock();

	//	cout << "data size 2^" << i << " = " << n << "\t";
	//	cout << "Time cost: " << double(endTime - startTime) / CLOCKS_PER_SEC << endl;

	//	delete[] arr;
	//}

	//2) selectionSort 数据规模倍乘测试 
	//O(n^2)
	//cout << "Test for selectionSort:" << endl;
	//for (int i = 10; i <= 15; i++) {
    
    
	//	int n = pow(2, i);
	//	int *arr = MyUtil::generateRandomArray(n, 0, 100000000);

	//	clock_t startTime = clock();
	//	MyAlgorithmTester::selectionSort(arr, n);
	//	clock_t endTime = clock();

	//	cout << "data size 2^" << i << " = " << n << "\t";
	//	cout << "Time cost: " << double(endTime - startTime) / CLOCKS_PER_SEC << endl;

	//	delete[] arr;
	//}

	//3) binarySearch 数据规模倍乘测试 
	//O(logn)
	//cout << "Test for selectionSort:" << endl;
	//double run_time = 0;
	//LARGE_INTEGER time_start;
	//LARGE_INTEGER time_end;
	//double dqFreq;
	//LARGE_INTEGER freq;
	//QueryPerformanceFrequency(&freq);
	//dqFreq = (double)freq.QuadPart;

	//for (int i = 10; i <= 27; i++) {
    
    
	//	int n = pow(2, i);
	//	int *arr = MyUtil::generateRandomArray(n, 0, 100000000);		

	//	QueryPerformanceCounter(&time_start);
	//	MyAlgorithmTester::binarySearch(arr, n, 0);
	//	QueryPerformanceCounter(&time_end);
	//	run_time = 1000000 * (time_end.QuadPart - time_start.QuadPart) / dqFreq;
	//	cout << "data size 2^" << i << " = " << n << "\t";
	//	cout << "Time cost: " << run_time << endl;

	//	delete[] arr;
	//}

	//4) binarySearch 数据规模倍乘测试 
	//O(logn)
	cout << "Test for selectionSort:" << endl;
	double run_time = 0;
	LARGE_INTEGER time_start;
	LARGE_INTEGER time_end;
	double dqFreq;
	LARGE_INTEGER freq;
	QueryPerformanceFrequency(&freq);
	dqFreq = (double)freq.QuadPart;

	for (int i = 10; i <= 26; i++) {
    
    
		int n = pow(2, i);
		int *arr = MyUtil::generateRandomArray(n, 0, 100000000);

		QueryPerformanceCounter(&time_start);
		MyAlgorithmTester::mergeSort(arr, n);
		QueryPerformanceCounter(&time_end);
		run_time = 1000 * (time_end.QuadPart - time_start.QuadPart) / dqFreq;
		cout << "data size 2^" << i << " = " << n << "\t";
		cout << "Time cost: " << run_time << endl;

		delete[] arr;
	}



	system("pause");

	return 0;
}

    3.3) Descripción del algoritmo
    a) findMax () Encuentra el elemento más grande en la matriz.
    Este algoritmo, cuando la cantidad de datos se duplica, el consumo de tiempo del algoritmo se duplica, lo que indica que la complejidad temporal del algoritmo es lineal, es decir, la complejidad temporal de findMax () es O (n) O (n)O ( n )

Figura (1) findMax () Encuentra el algoritmo de elemento más grande

    b) selectionSort () selecciona y ordena directamente
    la matriz . Cuando la cantidad de datos se duplica, el algoritmo tarda 4 veces más, lo que indica que la complejidad temporal del algoritmo es de tipo exponencial, con un exponente de log 2 4 = 2 log_2 {4} = 2l o g24=2 , es decir, la complejidad de tiempo del algoritmo selectionSort () esO (n 2) O (n ^ 2)O ( n2 )

Figura (2) algoritmo de clasificación de selección directa selectionSort ()

    c) binarySearch () realiza una búsqueda binaria en la matriz
    . Cuando la cantidad de datos se duplica, el aumento del algoritmo que consume mucho tiempo es muy pequeño, casi ningún aumento. Se puede inferir que la complejidad del tiempo del algoritmo es O (log n) O (log \,norte)O ( l o gn )

Figura (3) algoritmo de búsqueda binaria binarySearch ()

    c) mergeSort () fusiona y ordena
    la matriz . Cuando la cantidad de datos se duplica, el algoritmo toma un poco más de 2 veces, lo que indica que la complejidad del algoritmo está entre O (n) O (n)O ( n ) ~O (n 2) O (n ^ 2)O ( n2 ), se puede especular que la complejidad temporal del algoritmo esO (nlog n) O (nlog \, n)O ( n l o gn )

Figura (4) algoritmo de clasificación de fusión mergeSort ()

        Referencias:
        1. Ejercicios de estructura de datos y nivel de análisis B, Li Chunbao, 2006

Supongo que te gusta

Origin blog.csdn.net/sanqima/article/details/107578007
Recomendado
Clasificación