非递归的快速傅立叶变换

快速傅里叶变换没什么好说的, 只是需要注意避免递归.

避免递归

上面那个递归版本的FFT实际上常数很大,因为要复制数组。我们观察一下递归树,假设这是一个长度为8的多项式。

+===============================================+
| 000   001   010   011   100   101   110   111 |
+-----------------------------------------------+
| 000   010   100   110 | 001   011   101   111 |
+-----------------------------------------------+
| 000   100 | 010   110 | 001   101 | 011   111 |
+-----------------------------------------------+
| 000 | 100 | 010 | 110 | 001 | 101 | 011 | 111 |
+===============================================+

实际上,从叶子往上做的话就是把每个数的二进制位颠倒过来。

 1 struct Complex
 2 {
 3   double real, imag;
 4   Complex(const double r = .0, const double i = .0): real(r), imag(i) { }
 5 };
 6 const Complex ZERO(.0, .0);
 7 inline Complex operator+(const Complex& lhs, const Complex& rhs) { return Complex(lhs.real+rhs.real, lhs.imag+rhs.imag); }
 8 inline Complex operator-(const Complex& lhs, const Complex& rhs) { return Complex(lhs.real-rhs.real, lhs.imag-rhs.imag); }
 9 inline Complex operator*(const Complex& lhs, const Complex& rhs) { return Complex(lhs.real*rhs.real-lhs.imag*rhs.imag, lhs.real*rhs.imag+lhs.imag*rhs.real); }
10 inline int bit_reverse(const int x, const int n)
11 {
12   int res = 0;
13   for (int i = 0; i < n; ++i)
14     res |= (x>>i&1)<<(n-i-1);
15   return res;
16 }
17 void fft(Complex y[], const Complex a[], const int n, const int rev)
18 {
19   const int len = 1<<n;
20   for (int i = 0; i < len; ++i) y[i] = a[bit_reverse(i, n)];
21   for (int d = 1; d <= n; ++d)
22   {
23     const int m = 1<<d;
24     const Complex wn(std::cos(2*PI/m*rev), std::sin(2*PI/m*rev));
25     for (int k = 0; k < len; k += m)
26     {
27       Complex w(1., .0);
28       for (int j = 0; j < m/2; ++j)
29       {
30         const Complex u = y[k+j], t = w*y[k+j+m/2];
31         y[k+j] = u+t, y[k+j+m/2] = u-t;
32         w = w*wn;
33       }
34     }
35   }
36   if (rev == -1)
37     for (int i = 0; i < len; ++i) y[i].real /= len, y[i].imag = .0;
38 }
39 void convolution(Complex c[], Complex a[], Complex b[], const int la, const int lb)
40 {
41   static Complex tmp1[MAXN], tmp2[MAXN];
42   int n = 0, len = 1<<n;
43   for (; len < 2*la || len < 2*lb; ++n) len <<= 1;
44   std::fill(a+la, a+len, ZERO);
45   std::fill(b+lb, b+len, ZERO);
46   fft(tmp1, a, n, 1);
47   fft(tmp2, b, n, 1);
48   for (int i = 0; i < len; ++i) tmp1[i] = tmp1[i]*tmp2[i];
49   fft(c, tmp1, n, -1);
50 }
原文地址:https://www.cnblogs.com/hatsuakiratenan/p/3132444.html