天天看點

算法導論第四章練習題4.1-1題目描述代碼

題目描述

  • 在你的計算機上實作最大子數組問題的暴力算法和遞歸算法。請指出多大的問題規模n0是性能交叉點——從此之後遞歸算法将擊敗暴力算法?

代碼

#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <assert.h>

using namespace std;

void generateRandomArray(int arr[], int n, int rangeL, int rangeR);//生成包含n個數的随機數組
vector<int> bruteSearch(int arr[], size_t n);//暴力搜尋算法
vector<int> recursiveSearch(int arr[], int low, int high);//遞歸算法
vector<int> crossSubarray(int arr[], int low, int mid, int high);//用于求解遞歸算法中最大子字元串跨越中點的情況

int main() {
	constexpr unsigned n = 1000000;
	cout << "輸入規模為:" << n << endl;
	static int arr[n];
	generateRandomArray(arr, n, -100, 100);

	clock_t start2, finish2;
	vector<int> ans2;
	start2 = clock();
	ans2 = recursiveSearch(arr, 0, n - 1);
	finish2 = clock();
	cout << "The answer of recursive search is:" << endl;
	for (auto &c : ans2) {
		cout << c << endl;
	}
	cout << "運作時間為:" << (double)(finish2 - start2) / CLOCKS_PER_SEC << endl;
	cout << "---------------------------------------" << endl;

	clock_t start1, finish1;
	vector<int> ans1;
	start1 = clock();
	ans1 = bruteSearch(arr, n);
	finish1 = clock();
	cout << "The answer of brute search is:" << endl;
	for (auto &c : ans1) {
		cout << c << endl;
	}
	cout << "運作時間為:" << (double)(finish1 - start1) / CLOCKS_PER_SEC << endl;
	cout << "---------------------------------------" << endl;
};

void generateRandomArray(int arr[], int n, int rangeL, int rangeR) {
	assert(rangeL <= rangeR);
	// srand(time(NULL)); // 随機種子
	for (int i = 0; i < n - 1; i++)
		arr[i] = rand() % (rangeR - rangeL + 1) + rangeL;
}

vector<int> bruteSearch(int arr[], size_t n) {
	int max_sum = INT_MIN;
	int left = 0;
	int right = 0;
	for (size_t i = 0; i != n - 1; ++i) {
		int sum = 0;
		for (size_t j = i; j != n; ++j) {
			sum += arr[j];
			if (sum > max_sum) {
				max_sum = sum;
				left = i;
				right = j;
			}
		}
	}
	return { left, right, max_sum};
}

vector<int> crossSubarray(int arr[], int low, int mid, int high) {
	int left_sum = INT_MIN;
	int max_left = 0;
	int max_right = 0;
	int sum = 0;
	for (int i = mid; i >= low; --i) {
		sum += arr[i];
		if (sum > left_sum) {
			left_sum = sum;
			max_left = i;
		}
	}
	int right_sum = INT_MIN;
	sum = 0;
	for (int i = mid + 1; i <= high; ++i) {
		sum += arr[i];
		if (sum > right_sum) {
			right_sum = sum;
			max_right = i;
		}
	}
	return { max_left, max_right, left_sum + right_sum };
}

vector<int> recursiveSearch(int arr[], int low, int high) {
	if (high == low) {
		return { low, high, arr[low] };
	}
	else {
		int mid = (low + high) / 2;
		vector<int> vec_left = recursiveSearch(arr, low, mid);
		vector<int> vec_right = recursiveSearch(arr, mid+1, high);
		vector<int> vec_cross = crossSubarray(arr, low, mid, high);
		if (vec_left[2] >= vec_right[2] && vec_left[2] >= vec_cross[2])
			return vec_left;
		else if (vec_right[2] >= vec_left[2] && vec_right[2] >= vec_cross[2])
			return vec_right;
		else return vec_cross;
	}
}
           
  • 實驗發現,n<10000時,暴力搜尋算法性能更好,n=10000時,兩種算法性能相當,n>10000時,遞歸算法開始展現出明顯優勢
  • 實驗結果如下;
算法導論第四章練習題4.1-1題目描述代碼
算法導論第四章練習題4.1-1題目描述代碼
算法導論第四章練習題4.1-1題目描述代碼
算法導論第四章練習題4.1-1題目描述代碼
算法導論第四章練習題4.1-1題目描述代碼

繼續閱讀