算法导论的第四章——分治策略,主要的算法为寻找最大子数组问题,还有矩阵乘法的Strassen算法,还有一些课后的练习题,主要讲了求解递归式的三种方法:代入法(感觉像是猜测,然后用数学归纳法验证),递归树法(比较的直观明了),主方法(给出了递归式的大部分通解)。现在把该chapter的所有涉及的算法都贴上来。
#include
using namespace std;
//this is the program that in order to find the max crossing subarray.
//in order to return the subarray's low bound and the high bound,
//i have to create a struct to contain all this information
//this is the constrction of the struct
template<class T>
struct SUB_Array {
int low;
int high;
T sum;
};
//this is the realization of FIND-MAX-CROSSING-SUBARRAY
template<class T>
SUB_Array<T> F_M_C_S(T* A, int low, int mid, int high)
{
T left_sum = -99999;
T sum = 0;
int max_left;
for (int i = mid; i >= low; i--)
{
sum += A[i];
if (sum > left_sum)
{
left_sum = sum;
max_left = i;
}
}
T right_sum = -9999999;
int max_right;
sum = 0;
for (int j = mid + 1; j <= high; j++)
{
sum += A[j];
if (sum > right_sum)
{
right_sum = sum;
max_right = j;
}
}
SUB_Array x;
x.low = max_left;
x.high = max_right;
x.sum = left_sum + right_sum;
return x;
}
//this is the FIND-MAXIMUM-SUBBARRAY
template<class T>
SUB_Array<T> F_M_S(T* A, int low, int high)
{
SUB_Array x,y,z;
if(high==low)
{
x.low = low;
x.high = high;
x.sum = A[low];
return x;
}
else
{
int mid = (low + high) / 2;
x = F_M_S(A, low, mid);
y = F_M_S(A, mid + 1, high);
z = F_M_C_S(A, low, mid, high);
if (x.sum >= y.sum&&x.sum >= z.sum)
return x;
else if (y.sum >= x.sum&&y.sum >= z.sum)
return y;
else
return z;
}
}
//solution to 4.1-2 . so i will use the violent way to solve the max subarray;
template<class T>
SUB_Array<T> Viol_Maxarray(T* A, int low, int high)
{
SUB_Array x;
T Max_sum = A[low];
int Max_low, Max_high;
for (int i = low; i <= high; i++)
{
T sum = 0;
for (int j = i; j <= high; j++)
{
sum += A[j];
if (sum > Max_sum)
{
Max_sum = sum;
Max_low = i;
Max_high = j;
}
}
}
x.sum = Max_sum;
x.low = Max_low;
x.high = Max_high;
return x;
}
//solution to 4.1-4
//in my opinion,i think the biggest subarray is that the sum must more than zero,and if the sum \
// is less than zero,it just returns the zero ,which means not have.
// and it is easy to change the program ,just use the upper program,and make the left_sum=0 ,right_sum=0;
//solution to 4.1-5
template<class T>
SUB_Array<T> Nrecurr_SUBARR(T* A, int low, int high)
{
SUB_Array x;
int t_high;
T Max_sum = A[low];
int t_low=low;
for (int i = low; i <= high; i++)
{
T sum = 0;
for (int j = i + 1; j >= t_low; j--)
{
sum += A[j];
if (sum > Max_sum)
{
Max_sum = sum;
t_low = j;
t_high = i + 1;
}
}
}
x.low = t_low;
x.high = t_high;
x.sum = Max_sum;
return x;
}
//this is the SQUARE-MATRIX-MULTIPLY
const int n = 4;
template<class T>
void SQMA_MUL(T a[n][n], T b[n][n], T c[n][n])
{
for(int i=0;ifor (int j = 0; j < n; j++)
{
c[i][j] = 0;
for (int k = 0; k < n; k++)
c[i][j] += a[i][k] * b[k][j];
}
}
//this is the Strassen meathod
//we just assure the input number is N*N,so i just split into n/2 * n/2.
//and i didn't have much more simple coded way to realize it.
//so i just use the ordinary way .
//there are several steps to make ahead,so it will be sort of simple.
const int Size = 4;
template<class T>
void Strassen(T a[Size][Size], T b[Size][Size], T c[Size][Size])
{
const int newsize = Size/2;
T S1[newsize][newsize] = { 0 }, S2[newsize][newsize] = { 0 }, S3[newsize][newsize] = { 0 };
T S4[newsize][newsize] = { 0 }, S5[newsize][newsize] = { 0 }, S6[newsize][newsize] = { 0 }, S7[newsize][newsize] = { 0 }, S8[newsize][newsize] = { 0 };
T S9[newsize][newsize] = { 0 }, S10[newsize][newsize] = { 0 };
for (int i = 0; i < newsize; i++)
for (int j = 0; j < newsize; j++)
{
S1[i][j] = b[i][j+newsize] - b[newsize + i][newsize + j];
S2[i][j] = a[i][j] + a[i][newsize + j];
S3[i][j] = a[newsize + i][j] + a[newsize + i][newsize + j];
S4[i][j] = b[newsize + i][j] - b[i][j];
S5[i][j] = a[i][j] + a[newsize + i][newsize + j];
S6[i][j] = b[i][j] + b[newsize + i][newsize + j];
S7[i][j] = a[i][newsize + j] - a[newsize + i][newsize + j];
S8[i][j] = b[newsize + i][j] + b[newsize + i][newsize + j];
S9[i][j] = a[i][j] - a[newsize + i][j];
S10[i][j] = b[i][j] + b[i][newsize + j];
}
T P1[newsize][newsize] = { 0 }, P2[newsize][newsize] = { 0 }, P3[newsize][newsize] = { 0 }, P4[newsize][newsize] = { 0 };
T P5[newsize][newsize] = { 0 }, P6[newsize][newsize] = { 0 }, P7[newsize][newsize] = { 0 };
for (int i = 0; i < newsize; i++)
for (int j = 0; j < newsize; j++)
{
for (int k = 0; k < newsize; k++)
{
P1[i][j] += a[i][k] * S1[k][j];
P2[i][j] += S2[i][k] * b[newsize + k][newsize + j];
P3[i][j] += S3[i][k] * b[k][j];
P4[i][j] += a[newsize + i][newsize + k] * S4[k][j];
P5[i][j] += S5[i][k] * S6[k][j];
P6[i][j] += S7[i][k] * S8[k][j];
P7[i][j] += S9[i][k] * S10[k][j];
}
}
for (int i = 0; i < newsize; i++)
for (int j = 0; j < newsize; j++)
{
c[i][j] = 0;
c[i][j] = P5[i][j] + P4[i][j] - P2[i][j] + P6[i][j];
c[i][newsize + j] = 0;
c[i][newsize + j] = P1[i][j] + P2[i][j];
c[i + newsize][newsize + j] = 0;
c[i + newsize][j + newsize] = P5[i][j] + P1[i][j] - P3[i][j] - P7[i][j];
c[newsize + i][j] = 0;
c[newsize + i][j] = P4[i][j] + P3[i][j];
}
}
int main()
{
//int A[16] = { 13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7 };
//SUB_Array x;
//x = F_M_S(A, 0, 15);
//x = Viol_Maxarray(A, 0, 15);
//x = Nrecurr_SUBARR(A, 0, 15);
//cout << x.low <<" "<< x.high <<" "<< x.sum << endl;
int a[4][4] = { 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2 };
int b[4][4] = { 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2 };
int c[4][4] = { 0 };
int d[4][4];
int e[2][2] = { 1,3,7,5 };
int f[2][2] = { 6,8,4,2 };
// SQMA_MUL(e, f, c);
SQMA_MUL(a, b, d);
Strassen<int>(a, b, c);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
cout << c[i][j] << " ";
cout << endl;
}
cout << endl;
for (int i = 0; i < n; i++)
{ for (int j = 0; j < n; j++)
cout << d[i][j] << " ";
cout << endl;
}
return 0;
}
总的算法就那么多,但是有些东西可以继续完善。有些函数的接口有待斟酌,还有就是Strassen算法,我感觉我的实现还是O(n^3),递归实现我暂时没有想出来。先上传了,等有思路在补上!欢迎大家提供思路,一起探讨~