最大子陣列問題的暴力解法,遞迴解法,動態規劃解法和暴力-遞迴混合解法
阿新 • • 發佈:2018-12-12
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> #define SIZE 5000 #define RANDOM_LIMIT 50 #define THRESHOLD 22 #define TESTTIMES 100 double Myrandom(void){ int Sign = rand() % 2; return (rand() % RANDOM_LIMIT) / (100 * pow(-1,Sign + 2)); } struct SubArray{ int Left,Right; double Sum; }; typedef struct SubArray SubArray; SubArray BruteForceAlgorithm(double A[],int low,int high){ SubArray result; result.Left = result.Right = 0; result.Sum = (-1) * __DBL_MAX__; int i,j; for(i = low;i <= high;i++){ double CurrentSum = 0.0; for(j = i;j <= high;j++){ CurrentSum += A[j]; if(CurrentSum > result.Sum){ result.Sum = CurrentSum; result.Left = i; result.Right = j; } } } return result; } SubArray FindMaxCrossingSubarray(double A[],int low,int high,int mid){ SubArray result; double LeftSum = (-1)*__DBL_MAX__, RightSum = (-1)*__DBL_MAX__ ; int i; double CurrentSum; for(i = mid,CurrentSum = 0;i >= low;i--){ CurrentSum += A[i]; if(CurrentSum > LeftSum){ LeftSum = CurrentSum; result.Left = i; } } for(i = mid + 1,CurrentSum = 0;i <= high;i++){ CurrentSum += A[i]; if(CurrentSum > RightSum){ RightSum = CurrentSum; result.Right = i; } } result.Sum = LeftSum + RightSum; return result; } SubArray RecurrenceAlgorithm(double A[],int low,int high){ if(low == high){ SubArray result = {low,high,A[low]}; return result; } else{ int mid = (low + high) / 2; SubArray LeftMax = RecurrenceAlgorithm(A,low,mid); SubArray RightMax = RecurrenceAlgorithm(A,mid + 1,high); SubArray CrossMax = FindMaxCrossingSubarray(A,low,high,mid); if(LeftMax.Sum >= RightMax.Sum && LeftMax.Sum >= CrossMax.Sum) return LeftMax; else if(RightMax.Sum >= LeftMax.Sum && RightMax.Sum >= CrossMax.Sum) return RightMax; else return CrossMax; } } SubArray MixAlgorithm(double A[],int low,int high){ SubArray result; if(low - high <= THRESHOLD){ result = BruteForceAlgorithm(A,low,high); } else{ int mid = (low + high) / 2; SubArray LeftMax = RecurrenceAlgorithm(A,low,mid); SubArray RightMax = RecurrenceAlgorithm(A,mid + 1,high); SubArray CrossMAx = FindMaxCrossingSubarray(A,low,high,mid); if(LeftMax.Sum >= RightMax.Sum && LeftMax.Sum >= CrossMAx.Sum) result = LeftMax; else if(RightMax.Sum >= LeftMax.Sum && RightMax.Sum >= CrossMAx.Sum) result = RightMax; else result = CrossMAx; } return result; } SubArray DynamicAlgorithm(double A[],int low,int high){ SubArray result; result.Sum = (-1)*__DBL_MAX__; double BestSumFromHere = A[high]; int BestSumEnd = high,i; for(i = high - 1;i >= low;i--){ if(BestSumFromHere >= 0) BestSumFromHere += A[i]; else{ BestSumFromHere = A[i]; BestSumEnd = i; } if(BestSumFromHere > result.Sum){ result.Sum = BestSumFromHere; result.Right = i; result.Left = BestSumEnd; } } return result; } int main(void){ int j; int BruteTime = 0,RecurrTime = 0,DynamicTime = 0,MixTime = 0; for(j = 0;j < TESTTIMES;j++){ srand((unsigned int)time(NULL)); double TestData[SIZE]; SubArray BruteResult,RecurrResult,DynamicResult,MixResult; int i; for(i = 0;i < SIZE;i++) TestData[i] = Myrandom(); int BeginTime,EndTime; BeginTime = clock(); BruteResult = BruteForceAlgorithm(TestData,0,SIZE-1); EndTime = clock(); BruteTime += (EndTime - BeginTime); //printf("BruteForce time is: %dms\tResult is %d to %d, sum = %lf\n",EndTime - BeginTime,BruteResult.Left,BruteResult.Right,BruteResult.Sum); BeginTime = clock(); RecurrResult = RecurrenceAlgorithm(TestData,0,SIZE-1); EndTime = clock(); RecurrTime += (EndTime - BeginTime); //printf("Recurrence time is: %dms\tResult is %d to %d, sum = %lf\n",EndTime - BeginTime,RecurrResult.Left,RecurrResult.Right,RecurrResult.Sum); BeginTime = clock(); DynamicResult = RecurrenceAlgorithm(TestData,0,SIZE-1); EndTime = clock(); DynamicTime += (EndTime - BeginTime); //printf("Dynamicalg time is: %dms\tResult is %d to %d, sum = %lf\n",EndTime - BeginTime,DynamicResult.Left,DynamicResult.Right,DynamicResult.Sum); BeginTime = clock(); MixResult = MixAlgorithm(TestData,0,SIZE-1); EndTime = clock(); MixTime += (EndTime - BeginTime); } printf("BruteTimeAverage:\t %lf\n",BruteTime / (double)TESTTIMES); printf("RecurrTimeAverage:\t %lf\n",RecurrTime / (double)TESTTIMES); printf("DynamicTimeAverage:\t %lf\n",DynamicTime / (double)TESTTIMES); printf("MixTimeAverage:\t\t %lf\n",MixTime / (double)TESTTIMES); return 0; }