Teste a complexidade de tempo de algoritmos, como busca binária e classificação por seleção direta

        1.
        Pesquisa binária Pesquisa binária, também conhecida como pesquisa binária, a premissa da pesquisa binária é que a tabela ou árvore linear foi classificada. Aqui, a tabela linear é tomada como exemplo. Supõe-se que a tabela linear foi classificada por palavras-chave e está aumentando Organizado ordenadamente.
        A ideia da pesquisa binária: deixe a tabela linear R [esquerda, direita] ser o intervalo de pesquisa atual, primeiro determine a posição do ponto médio do intervalo mid = (esquerda + direita) / 2 e, em seguida, compare o valor K a ser verificado com R [mid] A comparação de .key é a seguinte:
        1) Se K = R [mid] .key, então retorne diretamente o índice do elemento;
        2) Se K <R [mid] .key, então
            left = mid-1;
            mid = (esquerda + direita) / 2;
      pesquisa no intervalo da metade esquerda [esquerda, meio-1];
        3) Se K> R [meio] .tecla, então
            direita = meio + 1;
            meio = (esquerda + direita) / 2;
      Pesquise na metade direita do intervalo [esquerda, meio-1];
    4) Repita as etapas 2) e 3) até esquerda> direita, ou seja, o espaço de pesquisa passa a 0. Se encontrado, retorna o índice do elemento. Caso contrário, retorna -1.
    Pesquisa binária, a cada pesquisa, o intervalo de pesquisa é reduzido pela metade, então o algoritmo é muito rápido, a complexidade do tempo é O (log n) O (log \, n)O ( l o gn ) .
    // Pesquisa binária 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. Classificação por
    seleção O método básico de classificação por seleção é: cada etapa seleciona o registro com a menor palavra-chave dos registros a serem classificados e a ordem é colocada no final dos registros classificados até que todas as classificações sejam concluídas. A classificação de seleção inclui classificação de seleção direta e classificação de heap. Aqui está uma classificação de seleção direta.
    O processo de seleção direta e classificação é: suponha que os registros são colocados em R [0, n-1], R [0, i-1] é a área ordenada, R [i, n-1] é a área desordenada, e há Todas as palavras-chave na área de sequência são menores do que todas as palavras-chave na área de desordem. É necessário adicionar R [i] a R [0, i-1] para fazer R [0, i] ordenado. Aqui, cada passagem seleciona um registro R [k] com a menor chave da área desordenada R [i, n-1] e o troca por R [i]. Obviamente, R [0, i] torna-se Uma nova área ordenada.
    2.1) Use a estrutura para indicar a classificação de seleção direta


#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 uma matriz para indicar a classificação de seleção direta

//交换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. Escrevendo casos de teste para algoritmos
    3.1 Coloque todos os algoritmos em um espaço de comando, como o namespace MyAlgorithmTester, que é um arquivo de cabeçalho: 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 a função que gera o conjunto de dados no namespace MyUtil, que também é um arquivo de cabeçalho: 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) Escreva a função 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) Descrição do algoritmo
    a) findMax () Encontre o maior elemento no array.
    Este algoritmo, quando a quantidade de dados dobra, o consumo de tempo do algoritmo dobra, indicando que a complexidade de tempo do algoritmo é linear, ou seja, a complexidade de tempo de findMax () é O (n) O (n)O ( n )

Figura (1) findMax () Encontre o algoritmo do maior elemento

    b) selectionSort () seleciona e ordena diretamente
    a matriz . Quando a quantidade de dados dobra, o algoritmo leva 4 vezes mais tempo, indicando que a complexidade de tempo do algoritmo é do tipo exponencial, com um expoente de log 2 4 = 2 log_2 {4} = 2l o g24=2 , ou seja, a complexidade de tempo do algoritmo selectionSort () éO (n 2) O (n ^ 2)O ( n2 )

Figura (2) selectionSort () algoritmo de classificação de seleção direta

    c) binarySearch () executa a pesquisa binária na matriz
    . Quando a quantidade de dados dobra, o aumento demorado do algoritmo é muito pequeno, quase nenhum aumento. Pode-se inferir que a complexidade do tempo do algoritmo é O (log n) O (log \, n)O ( l o gn )

Figura (3) binarySearch () algoritmo de pesquisa binária

    c) mergeSort () funde e ordena
    o array . Quando a quantidade de dados dobra, o algoritmo leva um pouco mais de 2 vezes, indicando que a complexidade do algoritmo está entre O (n) O (n)O ( n ) ~O (n 2) O (n ^ 2)O ( n2 ), pode-se especular que a complexidade de tempo do algoritmo éO (nlog n) O (nlog \, n)O ( n l o gn )

Figura (4) algoritmo merge sort () mergeSort ()

        Referências:
        1. Exercícios de estrutura de dados e nível de análise B, Li Chunbao, 2006

Acho que você gosta

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