权当笔记!
(一)归并排序:
#include <stdio.h>
#include <stdlib.h>
#include <string>
typedef long long LL;
using namespace std;
/* T(n) = 2T(n/2) + ⊙(n) = nlog(n) */
void Merge_sort(int *A,int x,int y,int *t) /* x表示左闭,y表示右开 */
{
if(y - x > 1){
int m = x + (y - x) / 2;
int p = x,q = m,i = x;
Merge_sort(A, x, m, t);
Merge_sort(A, m, y, t);
while(p < m || q < y){
if(q >= y || (p < m && A[p] <= A[q]))
t[i++] = A[p++];
else t[i++] = A[q++];
}
for(i=x; i<y; i++)
A[i] = t[i];
}
}
int main()
{
int t[15];
int s[] = {4, 1, 7, 6, 3, 8, 2, 5, 0, 9};
Merge_sort(s, 0, 10, t);
int i;
for(i=0; i<10; i++)
printf("%d ", s[i]);
printf("\n");
return 0;
}
用递归体会一下其中的分治思想,当然也可以用while循环解决!
#include <stdio.h>
#include <stdlib.h>
#include <string>
typedef long long LL;
using namespace std;
/* T(n) = T(n/2) + ⊙(1) = log(n) */
int Binary_find(int key, int left, int right, int *a)
{
int mid = left + (right - left) / 2;
if(a[mid] == key) return mid;
else if(a[mid] > key) return Binary_find(key, left, mid - 1, a);
else if(a[mid] < key) return Binary_find(key, mid + 1, right, a);
}
int main()
{
int a[] = {1, 3, 4, 6, 7, 9, 12, 14, 23, 24};
int i;
int ans;
for(i=0; i<8; i++){
ans = Binary_find(a[i], 0, 7, a);
printf("%d\n", ans);
}
return 0;
}
(三)x的n次方:
库函数<math.h>里面的double pow(double x, double y) 更加完美,指数可以是浮点型。这里手写个double Pow(double x, int n)。
#include <stdio.h>
#include <stdlib.h>
#include <string>
typedef long long LL;
using namespace std;
/* T(n) = T(n/2) + ⊙(1) = log(n) */
double f(double x, int n)
{
if(1 == n) return x;
int mid = (n>>1);
double s = f(x, mid);
if(n & 1) return s * s * x;
else return s * s;
}
double Pow(double x, int n)
{
if(0 == x && n > 0) return 0.0;
else if(0 == n) return 1.0;
else if(n > 0) return f(x, n);
else if(n < 0) return (1/f(x, -n));
}
int main()
{
double x;
int n;
while(~scanf("%lf%d", &x, &n)){
printf("%0.6lf\n", Pow(x, n));
printf("%0.6lf\n", pow(x, n));
}
}
(四)斐波那契(Fibonacci)数列:
递归是最愚蠢的做法,迭代可以是 ⊙(n) 的复杂度,矩阵快速幂可达到 ⊙(log(n)) 的复杂度。
F(n) 表示第n个斐波那契数则有这样的关系:
矩阵 F(N+1) F(N) = 矩阵 1 1 的 N 次方
F(N) F(N-1) 1 0
可用数学归纳法证明。所以结果就是普通的矩阵快速幂。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <iostream>
using namespace std;
int cnt;
/* 时间复杂度为指数级 */
LL Fibonacci(int n)
{
cnt++;
if(1 == n || 2 == n) return 1;
else return Fibonacci(n - 1) + Fibonacci(n - 2);
}
/* T(n) = ⊙(n) */
LL Fibonacci1(int n)
{
LL a[100000];
a[1] = a[2] = 1;
int i;
for(i=3; i<=n; i++)
a[i] = a[i - 1] + a[i - 2];
return a[n];
}
typedef struct
{
LL a[2][2];
}Matrix;
Matrix A, B;
Matrix Matrix_mul(Matrix X, Matrix Y)
{
Matrix tmp;
memset(tmp.a, 0, sizeof(tmp));
int i,j,k;
for(i=0; i<2; i++)
for(j=0; j<2; j++)
for(k=0; k<2; k++)
tmp.a[i][j] += X.a[i][k] * Y.a[k][j];
return tmp;
}
/* T(n) = ⊙(logn) */
LL Fibonacci2(int n)
{
A.a[0][0] = 1;
A.a[0][1] = 1;
A.a[1][0] = 1;
A.a[1][1] = 0;
B.a[0][0] = 1;
B.a[0][1] = 0;
B.a[1][0] = 0;
B.a[1][1] = 1;
while(n)
{
if(n & 1) B = Matrix_mul(B, A);
A = Matrix_mul(A, A);
n >>= 1;
}
return B.a[0][0];
}
int main()
{
int i;
int text = 4;
LL ans = Fibonacci1(text);
//long begtime = clock();
FILETIME beg,end;
GetSystemTimeAsFileTime(&beg);
for(i=0; i<100000; i++)
Fibonacci2(text);
GetSystemTimeAsFileTime(&end);
long time = (end.dwLowDateTime-beg.dwLowDateTime);
//long endtime = clock();
//cout<<endtime - begtime<<endl;
cout << time <<endl;
cout << ans <<endl;
}
(五)斯特拉森(Strassen)矩阵乘法:
参考了网上的做法,重写了此矩阵乘法,用了一个4阶矩阵验证。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <iostream>
typedef long long LL;
using namespace std;
typedef int INT;
#define N 4
typedef struct matrix
{
INT a[N][N];
matrix()
{
memset(a, 0, sizeof(a));
}
}Matrix;
void Matrix_mul(const Matrix A, const Matrix B, Matrix &C)
{
memset(C.a, 0, sizeof(C.a));
int i,j,k;
for(i=0; i<2; i++)
for(j=0; j<2; j++)
for(k=0; k<2; k++)
C.a[i][j] += A.a[i][k] * B.a[k][j];
}
void Matrix_add(const int n, const Matrix A, const Matrix B, Matrix &C)
{
memset(C.a, 0, sizeof(C.a));
int i,j;
for(i=0; i<n; i++)
for(j=0; j<n; j++)
C.a[i][j] = A.a[i][j] + B.a[i][j];
}
void Matrix_sub(const int n, const Matrix A, const Matrix B, Matrix &C)
{
memset(C.a, 0, sizeof(C.a));
int i,j;
for(i=0; i<n; i++)
for(j=0; j<n; j++)
C.a[i][j] = A.a[i][j] - B.a[i][j];
}
void Strassen(INT n, const Matrix A, const Matrix B, Matrix &C)
{
Matrix A11, A12, A21, A22;
Matrix B11, B12, B21, B22;
Matrix C11, C12, C21, C22;
Matrix M1, M2, M3, M4, M5, M6, M7;
Matrix At, Bt, Mt, Mt1;
if(2 == n) Matrix_mul(A, B, C);
else{
n /= 2;
int i, j;
for(i=0; i<n; i++)
for(j=0; j<n; j++){
A11.a[i][j] = A.a[i][j];
A12.a[i][j] = A.a[i][j + n];
A21.a[i][j] = A.a[i + n][j];
A22.a[i][j] = A.a[i + n][j + n];
B11.a[i][j] = B.a[i][j];
B12.a[i][j] = B.a[i][j + n];
B21.a[i][j] = B.a[i + n][j];
B22.a[i][j] = B.a[i + n][j + n];
}
Matrix_sub(n, A12, A22, At);
Matrix_add(n, B21, B22, Bt);
Strassen(n, At, Bt, M1);
Matrix_add(n, A11, A22, At);
Matrix_add(n, B11, B22, Bt);
Strassen(n, At, Bt, M2);
Matrix_sub(n, A11, A21, At);
Matrix_add(n, B11, B12, Bt);
Strassen(n, At, Bt, M3);
Matrix_add(n, A11, A12, At);
Strassen(n, At, B22, M4);
Matrix_sub(n, B12, B22, Bt);
Strassen(n, A11, Bt, M5);
Matrix_sub(n, B21, B11, Bt);
Strassen(n, A22, Bt, M6);
Matrix_add(n, A21, A22, At);
Strassen(n, At, B11, M7);
/* sub_C */
Matrix_add(n, M6, M1, Mt);
Matrix_add(n, Mt, M2, Mt1);
Matrix_sub(n, Mt1, M4, C11);
Matrix_add(n, M5, M4, C12);
Matrix_add(n, M6, M7, C21);
Matrix_sub(n, M5, M3, Mt);
Matrix_add(n, Mt, M2, Mt1);
Matrix_sub(n, Mt1, M7, C22);
for(i=0; i<n; i++)
for(j=0; j<n; j++){
C.a[i][j] = C11.a[i][j];
C.a[i][j + n] = C12.a[i][j];
C.a[i + n][j] = C21.a[i][j];
C.a[i + n][j + n] = C22.a[i][j];
}
}
}
int main()
{
Matrix A, B, C;
A.a[0][0] = 1;
A.a[0][1] = 0;
A.a[0][2] = 2;
A.a[0][3] = 1;
A.a[1][0] = 0;
A.a[1][1] = 3;
A.a[1][2] = 1;
A.a[1][3] = 2;
A.a[2][0] = 0;
A.a[2][1] = 0;
A.a[2][2] = 2;
A.a[2][3] = 2;
A.a[3][0] = 2;
A.a[3][1] = 3;
A.a[3][2] = 0;
A.a[3][3] = 1;
B.a[0][0] = 2;
B.a[0][1] = 1;
B.a[0][2] = 0;
B.a[0][3] = 0;
B.a[1][0] = 0;
B.a[1][1] = 1;
B.a[1][2] = 1;
B.a[1][3] = 1;
B.a[2][0] = 1;
B.a[2][1] = 0;
B.a[2][2] = 2;
B.a[2][3] = 2;
B.a[3][0] = 3;
B.a[3][1] = 0;
B.a[3][2] = 2;
B.a[3][3] = 1;
Strassen(N, A, B, C);
int i,j;
for(i=0; i<N; i++){
for(j=0; j<N; j++)
printf("%-4d", C.a[i][j]);
printf("\n");
}
return 0;
}