《算法》BEYOND 部分程序 part 2

Posted cuancuancuanhao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《算法》BEYOND 部分程序 part 2相关的知识,希望对你有一定的参考价值。

? 书中第六章部分程序,加上自己补充的代码,包括快速傅里叶变换,多项式表示

● 快速傅里叶变换,需要递归

  1 package package01;
  2 
  3 import edu.princeton.cs.algs4.StdOut;
  4 import edu.princeton.cs.algs4.StdRandom;
  5 import edu.princeton.cs.algs4.Complex;
  6 
  7 public class class01 
  8 {
  9     private static final Complex ZERO = new Complex(0, 0);
 10     private static final double EPSILON = 1e-8;
 11     private class01() { }
 12 
 13     public static Complex[] fft(Complex[] x)// 正向傅里叶变换
 14     {
 15         int n = x.length;
 16         if (n == 1)
 17             return new Complex[] {x[0]};
 18         if (n % 2 != 0)
 19             throw new IllegalArgumentException("n != 2^k");
 20 
 21         Complex[] temp = new Complex[n/2], result = new Complex[n];
 22         for (int k = 0; k < n/2; k++)       // 偶数项和奇数分别递归
 23             temp[k] = x[2*k];
 24         Complex[] q = fft(temp);
 25         for (int k = 0; k < n/2; k++)
 26             temp[k] = x[2*k + 1];
 27         Complex[] r = fft(temp);
 28         for (int k = 0; k < n/2; k++)       // 合并
 29         {
 30             double kth = -2 * k * Math.PI / n;
 31             Complex wk = new Complex(Math.cos(kth), Math.sin(kth));
 32             result[k]       = q[k].plus(wk.times(r[k]));
 33             result[k + n/2] = q[k].minus(wk.times(r[k]));
 34         }
 35         return result;
 36     }
 37 
 38     public static Complex[] ifft(Complex[] x)// 傅里叶反变换,共轭、正变换、再共轭,最后除以项数
 39     {
 40         int n = x.length;
 41         Complex[] result = new Complex[n], temp;
 42         for (int i = 0; i < n; i++)
 43             result[i] = x[i].conjugate();
 44         result = fft(result);
 45         for (int i = 0; i < n; i++)
 46             result[i] = result[i].conjugate();
 47         for (int i = 0; i < n; i++)
 48             result[i] = result[i].scale(1.0 / n);
 49         return result;
 50     }
 51 
 52     public static Complex[] cconvolve(Complex[] x, Complex[] y)// 环形卷积
 53     {
 54         if (x.length != y.length)
 55             throw new IllegalArgumentException("x.length != y.length");
 56         int n = x.length;
 57         Complex[] a = fft(x), b = fft(y), c = new Complex[n];
 58         for (int i = 0; i < n; i++)
 59             c[i] = a[i].times(b[i]);
 60         return ifft(c);
 61     }
 62 
 63     public static Complex[] convolve(Complex[] x, Complex[] y)// 线性卷积,后一半垫 0
 64     {
 65         if (x.length != y.length)
 66             throw new IllegalArgumentException("x.length != y.length");
 67         Complex[] a = new Complex[2 * x.length], b = new Complex[2 * y.length];
 68         for (int i = 0; i < x.length; i++)
 69             a[i] = x[i];
 70         for (int i = x.length; i < 2*x.length; i++)
 71             a[i] = ZERO;
 72         for (int i = 0; i < y.length; i++)
 73             b[i] = y[i];
 74         for (int i = y.length; i < 2*y.length; i++)
 75             b[i] = ZERO;
 76         return cconvolve(a, b);
 77     }
 78 
 79     private static void show(Complex[] x, String title)
 80     {
 81         StdOut.printf("%s
-------------------
",title);
 82         for (int i = 0; i < x.length; i++)
 83             StdOut.println(x[i]);
 84         StdOut.println();
 85     }
 86 
 87     public static void main(String[] args)
 88     {
 89         int n = 16;
 90         Complex[] x = new Complex[n];
 91         for (int i = 0; i < n; i++)
 92             x[i] = new Complex(StdRandom.uniform(-1.0, 1.0), 0);
 93 
 94         show(x, "x");
 95         Complex[] y = fft(x);
 96         show(y, "y = fft(x)");
 97         Complex[] z = ifft(y);
 98         show(z, "z = ifft(y)");
 99         Complex[] c = cconvolve(x, x);
100         show(c, "c = cconvolve(x, x)");
101         Complex[] d = convolve(x, x);
102         show(d, "d = convolve(x, x)");
103     }
104 }

● 多项式表示

  1 package package01;
  2 
  3 import edu.princeton.cs.algs4.StdOut;
  4 
  5 public class class01
  6 {
  7     private int[] coef;                 // 系数列表
  8     private int degree;                 // 次数
  9 
 10     public class01(int a, int b)        // 建立单项式 a*x^b
 11     {
 12         coef = new int[b + 1];
 13         coef[b] = a;
 14         reduce();
 15     }
 16 
 17     private void reduce()               // 记录多项式的次数
 18     {
 19         degree = -1;
 20         for (int i = coef.length - 1; i >= 0; i--)
 21         {
 22             if (coef[i] != 0)
 23             {
 24                 degree = i;
 25                 return;
 26             }
 27         }
 28     }
 29 
 30     public int degree()
 31     {
 32         return degree;
 33     }
 34 
 35     public class01 plus(class01 that)   // p(x) + q(x),把系数从低次项向高次项各加一遍
 36     {
 37         class01 poly = new class01(0, Math.max(degree, that.degree));
 38         for (int i = 0; i <= degree; i++)
 39             poly.coef[i] = coef[i];
 40         for (int i = 0; i <= that.degree; i++)
 41             poly.coef[i] += that.coef[i];
 42         poly.reduce();
 43         return poly;
 44     }
 45 
 46     public class01 minus(class01 that)
 47     {
 48         class01 poly = new class01(0, Math.max(degree, that.degree));
 49         for (int i = 0; i <= degree; i++)
 50             poly.coef[i] = coef[i];
 51         for (int i = 0; i <= that.degree; i++)
 52             poly.coef[i] -= that.coef[i];
 53         poly.reduce();
 54         return poly;
 55     }
 56 
 57     public class01 times(class01 that)
 58     {
 59         class01 poly = new class01(0, degree + that.degree);
 60         for (int i = 0; i <= degree; i++)
 61         {
 62             for (int j = 0; j <= that.degree; j++)
 63                 poly.coef[i + j] += (coef[i] * that.coef[j]);
 64         }
 65         poly.reduce();
 66         return poly;
 67     }
 68 
 69     public class01 compose(class01 that)// p(q(x)),用了秦九韶
 70     {
 71         class01 poly = new class01(0, 0);
 72         for (int i = degree; i >= 0; i--)
 73         {
 74             class01 term = new class01(coef[i], 0);
 75             poly = term.plus(that.times(poly));
 76         }
 77         return poly;
 78     }
 79 
 80     public class01 differentiate()      // p‘(x)
 81     {
 82         if (degree == 0)
 83             return new class01(0, 0);
 84         class01 poly = new class01(0, degree - 1);
 85         poly.degree = degree - 1;
 86         for (int i = 0; i < degree; i++)
 87             poly.coef[i] = (i + 1) * coef[i + 1];
 88         return poly;
 89     }
 90 
 91     public int evaluate(int x)          // p(x) /. {x->a}
 92     {
 93         int p = 0;
 94         for (int i = degree; i >= 0; i--)
 95             p = coef[i] + (x * p);
 96         return p;
 97     }
 98 
 99     public int compareTo(class01 that)
100     {
101         if (degree < that.degree)
102             return -1;
103         if (degree > that.degree)
104             return +1;
105         for (int i = degree; i >= 0; i--)
106         {
107             if (coef[i] < that.coef[i])
108                 return -1;
109             if (coef[i] > that.coef[i])
110                 return +1;
111         }
112         return 0;
113     }
114 
115     @Override
116         public String toString()
117     {
118         if (degree == -1)
119             return "0";
120         if (degree == 0)
121             return "" + coef[0];
122         if (degree == 1)
123             return coef[1] + "x + " + coef[0];
124         String s = coef[degree] + "x^" + degree;
125         for (int i = degree - 1; i >= 0; i--)
126         {
127             if (coef[i] == 0)
128                 continue;
129             if (coef[i]  > 0)
130                 s += " + " + (coef[i]);
131             if (coef[i]  < 0)
132                 s += " - " + (-coef[i]);
133             s += (i == 1) ? "x" : ("x^" + i);
134         }
135         return s;
136     }
137 
138     public static void main(String[] args)
139     {
140         class01 zero = new class01(0, 0);
141         class01 p1 = new class01(4, 3);
142         class01 p2 = new class01(3, 2);
143         class01 p3 = new class01(1, 0);
144         class01 p4 = new class01(2, 1);
145         class01 p = p1.plus(p2).plus(p3).plus(p4);   // 4x^3 + 3x^2 + 1
146 
147         class01 q1 = new class01(3, 2);
148         class01 q2 = new class01(5, 0);
149         class01 q = q1.plus(q2);                     // 3x^2 + 5
150 
151         StdOut.println("zero(x)     = " + zero);
152         StdOut.println("p(x)        = " + p);
153         StdOut.println("q(x)        = " + q);
154         StdOut.println("p(x) + q(x) = " + p.plus(q));
155         StdOut.println("p(x) * q(x) = " + p.times(q));
156         StdOut.println("p(q(x))     = " + p.compose(q));
157         StdOut.println("p(x) - p(x) = " + p.minus(p));
158         StdOut.println("0 - p(x)    = " + zero.minus(p));
159         StdOut.println("p(3)        = " + p.evaluate(3));
160         StdOut.println("p‘(x)       = " + p.differentiate());
161         StdOut.println("p‘‘(x)      = " + p.differentiate().differentiate());
162     }
163 }

 

以上是关于《算法》BEYOND 部分程序 part 2的主要内容,如果未能解决你的问题,请参考以下文章

《算法》BEYOND 部分程序 part 1

《算法》第五章部分程序 part 2

《算法》第三章部分程序 part 2

《算法》第六章部分程序 part 7

《算法》第五章部分程序 part 1

《算法》第三章部分程序 part 4