《算法》BEYOND 部分程序 part 2
▶ 书中第六章部分程序,加上自己补充的代码,包括快速傅里叶变换,多项式表示
● 快速傅里叶变换,需要递归
package package01; import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;
import edu.princeton.cs.algs4.Complex; public class class01
{
private static final Complex ZERO = new Complex(0, 0);
private static final double EPSILON = 1e-8;
private class01() { } public static Complex[] fft(Complex[] x)// 正向傅里叶变换
{
int n = x.length;
if (n == 1)
return new Complex[] {x[0]};
if (n % 2 != 0)
throw new IllegalArgumentException("n != 2^k"); Complex[] temp = new Complex[n/2], result = new Complex[n];
for (int k = 0; k < n/2; k++) // 偶数项和奇数分别递归
temp[k] = x[2*k];
Complex[] q = fft(temp);
for (int k = 0; k < n/2; k++)
temp[k] = x[2*k + 1];
Complex[] r = fft(temp);
for (int k = 0; k < n/2; k++) // 合并
{
double kth = -2 * k * Math.PI / n;
Complex wk = new Complex(Math.cos(kth), Math.sin(kth));
result[k] = q[k].plus(wk.times(r[k]));
result[k + n/2] = q[k].minus(wk.times(r[k]));
}
return result;
} public static Complex[] ifft(Complex[] x)// 傅里叶反变换,共轭、正变换、再共轭,最后除以项数
{
int n = x.length;
Complex[] result = new Complex[n], temp;
for (int i = 0; i < n; i++)
result[i] = x[i].conjugate();
result = fft(result);
for (int i = 0; i < n; i++)
result[i] = result[i].conjugate();
for (int i = 0; i < n; i++)
result[i] = result[i].scale(1.0 / n);
return result;
} public static Complex[] cconvolve(Complex[] x, Complex[] y)// 环形卷积
{
if (x.length != y.length)
throw new IllegalArgumentException("x.length != y.length");
int n = x.length;
Complex[] a = fft(x), b = fft(y), c = new Complex[n];
for (int i = 0; i < n; i++)
c[i] = a[i].times(b[i]);
return ifft(c);
} public static Complex[] convolve(Complex[] x, Complex[] y)// 线性卷积,后一半垫 0
{
if (x.length != y.length)
throw new IllegalArgumentException("x.length != y.length");
Complex[] a = new Complex[2 * x.length], b = new Complex[2 * y.length];
for (int i = 0; i < x.length; i++)
a[i] = x[i];
for (int i = x.length; i < 2*x.length; i++)
a[i] = ZERO;
for (int i = 0; i < y.length; i++)
b[i] = y[i];
for (int i = y.length; i < 2*y.length; i++)
b[i] = ZERO;
return cconvolve(a, b);
} private static void show(Complex[] x, String title)
{
StdOut.printf("%s\n-------------------\n",title);
for (int i = 0; i < x.length; i++)
StdOut.println(x[i]);
StdOut.println();
} public static void main(String[] args)
{
int n = 16;
Complex[] x = new Complex[n];
for (int i = 0; i < n; i++)
x[i] = new Complex(StdRandom.uniform(-1.0, 1.0), 0); show(x, "x");
Complex[] y = fft(x);
show(y, "y = fft(x)");
Complex[] z = ifft(y);
show(z, "z = ifft(y)");
Complex[] c = cconvolve(x, x);
show(c, "c = cconvolve(x, x)");
Complex[] d = convolve(x, x);
show(d, "d = convolve(x, x)");
}
}
● 多项式表示
package package01; import edu.princeton.cs.algs4.StdOut; public class class01
{
private int[] coef; // 系数列表
private int degree; // 次数 public class01(int a, int b) // 建立单项式 a*x^b
{
coef = new int[b + 1];
coef[b] = a;
reduce();
} private void reduce() // 记录多项式的次数
{
degree = -1;
for (int i = coef.length - 1; i >= 0; i--)
{
if (coef[i] != 0)
{
degree = i;
return;
}
}
} public int degree()
{
return degree;
} public class01 plus(class01 that) // p(x) + q(x),把系数从低次项向高次项各加一遍
{
class01 poly = new class01(0, Math.max(degree, that.degree));
for (int i = 0; i <= degree; i++)
poly.coef[i] = coef[i];
for (int i = 0; i <= that.degree; i++)
poly.coef[i] += that.coef[i];
poly.reduce();
return poly;
} public class01 minus(class01 that)
{
class01 poly = new class01(0, Math.max(degree, that.degree));
for (int i = 0; i <= degree; i++)
poly.coef[i] = coef[i];
for (int i = 0; i <= that.degree; i++)
poly.coef[i] -= that.coef[i];
poly.reduce();
return poly;
} public class01 times(class01 that)
{
class01 poly = new class01(0, degree + that.degree);
for (int i = 0; i <= degree; i++)
{
for (int j = 0; j <= that.degree; j++)
poly.coef[i + j] += (coef[i] * that.coef[j]);
}
poly.reduce();
return poly;
} public class01 compose(class01 that)// p(q(x)),用了秦九韶
{
class01 poly = new class01(0, 0);
for (int i = degree; i >= 0; i--)
{
class01 term = new class01(coef[i], 0);
poly = term.plus(that.times(poly));
}
return poly;
} public class01 differentiate() // p'(x)
{
if (degree == 0)
return new class01(0, 0);
class01 poly = new class01(0, degree - 1);
poly.degree = degree - 1;
for (int i = 0; i < degree; i++)
poly.coef[i] = (i + 1) * coef[i + 1];
return poly;
} public int evaluate(int x) // p(x) /. {x->a}
{
int p = 0;
for (int i = degree; i >= 0; i--)
p = coef[i] + (x * p);
return p;
} public int compareTo(class01 that)
{
if (degree < that.degree)
return -1;
if (degree > that.degree)
return +1;
for (int i = degree; i >= 0; i--)
{
if (coef[i] < that.coef[i])
return -1;
if (coef[i] > that.coef[i])
return +1;
}
return 0;
} @Override
public String toString()
{
if (degree == -1)
return "0";
if (degree == 0)
return "" + coef[0];
if (degree == 1)
return coef[1] + "x + " + coef[0];
String s = coef[degree] + "x^" + degree;
for (int i = degree - 1; i >= 0; i--)
{
if (coef[i] == 0)
continue;
if (coef[i] > 0)
s += " + " + (coef[i]);
if (coef[i] < 0)
s += " - " + (-coef[i]);
s += (i == 1) ? "x" : ("x^" + i);
}
return s;
} public static void main(String[] args)
{
class01 zero = new class01(0, 0);
class01 p1 = new class01(4, 3);
class01 p2 = new class01(3, 2);
class01 p3 = new class01(1, 0);
class01 p4 = new class01(2, 1);
class01 p = p1.plus(p2).plus(p3).plus(p4); // 4x^3 + 3x^2 + 1 class01 q1 = new class01(3, 2);
class01 q2 = new class01(5, 0);
class01 q = q1.plus(q2); // 3x^2 + 5 StdOut.println("zero(x) = " + zero);
StdOut.println("p(x) = " + p);
StdOut.println("q(x) = " + q);
StdOut.println("p(x) + q(x) = " + p.plus(q));
StdOut.println("p(x) * q(x) = " + p.times(q));
StdOut.println("p(q(x)) = " + p.compose(q));
StdOut.println("p(x) - p(x) = " + p.minus(p));
StdOut.println("0 - p(x) = " + zero.minus(p));
StdOut.println("p(3) = " + p.evaluate(3));
StdOut.println("p'(x) = " + p.differentiate());
StdOut.println("p''(x) = " + p.differentiate().differentiate());
}
}
《算法》BEYOND 部分程序 part 2的更多相关文章
- 信号量和PV操作写出Bakery算法的同步程序
面包店烹制面包及蛋糕,由n个销售员卖出.当有顾客进店购买面包或蛋糕时,应先在取号机上取号,然后等待叫号,若有销售员空闲时便叫下一号,试用信号量和PV操作写出Bakery算法的同步程序. 设计要求 1) ...
- GMM算法的matlab程序
GMM算法的matlab程序 在“GMM算法的matlab程序(初步)”这篇文章中已经用matlab程序对iris数据库进行简单的实现,下面的程序最终的目的是求准确度. 作者:凯鲁嘎吉 - 博客园 h ...
- GMM算法的matlab程序(初步)
GMM算法的matlab程序 在https://www.cnblogs.com/kailugaji/p/9648508.html文章中已经介绍了GMM算法,现在用matlab程序实现它. 作者:凯鲁嘎 ...
- KFCM算法的matlab程序(用FCM初始化聚类中心)
KFCM算法的matlab程序(用FCM初始化聚类中心) 在“聚类——KFCM”这篇文章中已经介绍了KFCM算法,现在用matlab程序对iris数据库进行实现,用FCM初始化聚类中心,并求其准确度与 ...
- KFCM算法的matlab程序
KFCM算法的matlab程序 在“聚类——KFCM”这篇文章中已经介绍了KFCM算法,现在用matlab程序对iris数据库进行简单的实现,并求其准确度. 作者:凯鲁嘎吉 - 博客园 http:// ...
- FCM算法的matlab程序2
FCM算法的matlab程序2 在“FCM算法的matlab程序”这篇文章中已经用matlab程序对iris数据库进行实现,并求解准确度.下面的程序是另一种方法,是最常用的方法:先初始化聚类中心,在进 ...
- FCM算法的matlab程序
FCM算法的matlab程序 在“FCM算法的matlab程序(初步)”这篇文章中已经用matlab程序对iris数据库进行简单的实现,下面的程序最终的目的是求准确度. 作者:凯鲁嘎吉 - 博客园 h ...
- K-means算法的matlab程序
K-means算法的matlab程序 在“K-means算法的matlab程序(初步)”这篇文章中已经用matlab程序对iris数据库进行简单的实现,下面的程序最终的目的是求准确度. 作者:凯鲁嘎吉 ...
- FCM算法的matlab程序(初步)
FCM算法的matlab程序 在https://www.cnblogs.com/kailugaji/p/9648430.html文章中已经介绍了FCM算法,现在用matlab程序实现它. 作者:凯鲁嘎 ...
- K-means算法的matlab程序(初步)
K-means算法的matlab程序 在https://www.cnblogs.com/kailugaji/p/9648369.html 文章中已经介绍了K-means算法,现在用matlab程序实现 ...
随机推荐
- Windows消息【一】 消息队列
看了MSDN后,以下是我个人的理解! 消息能够被分为「队列化消息」和「非队列化消息」. 队列化消息是指当程序发生某事件时,由Windows主动捕获并把消息放入系统消息队列中,而程序在运行时会初始化一个 ...
- mysql 高可用架构
什么是高可用 不可用出现的情况 如何实现高可用 第一种方法 第二种方法 MMM 和 MHA MHA更好的处理方式 安装步骤 优缺点 读写分离
- GoJS拖动设计
http://192.168.0.149:8035/gojs/intro/groups.html http://192.168.0.149:8035/gojs/intro/ports.html htt ...
- Memcached 集群架构方面的问题 [z]
集群架构方面的问题 memcached是怎么工作的? Memcached的神奇来自两阶段哈希(two-stage hash).Memcached就像一个巨大的.存储了很多<key,v ...
- 无法清除cookie中的属性值之对解决问题的思考
关于如何快速解决一个自己知识以外的问题的思考 做好任何事情都是讲究方法的,这是我健身之后的一个领悟,用正确的方式做事,自己的付出才能有价值. 首先分析问题: 比如我想清除cookie里面的token, ...
- java设计模式-Iterator
Iterator模式 主要是用在容器的遍历上,其他的地方都不怎么用:理解一下,会用了就可以了: 1.背景 请动手自己写一个可以动态添加对象的容器: 代码: ArrayList.java(是自己实现 ...
- Springboot监控之一:SpringBoot四大神器之Actuator之2--覆盖修改spring cloud的默认的consul健康检查规则
微服务网关是socket长连接与支付公司对接,该网关需要提供http接口给内部系统调用,当socket没有建立连接时(网关服务的高可用是haProxy搭建的,有些服务的socket可能未连上支付公司) ...
- folly无锁队列,尝试添加新的函数
1. folly是facebook开源的关于无锁队列的库,实现过程很精妙.folly向队列中添加节点过程,符合标准库中的队列的设计,而取出节点的过程,则会造成多个线程的分配不均.我曾经试着提供一次 取 ...
- 在Ubuntu16.04下面安装asterisk网络电话交换机服务器
在Ubuntu下面需要安装 apt install libncurses5-dev uuid-dev libjansson-dev libxml2-dev libsqlite3-dev 去官网下载包h ...
- redis-5.0.3集群搭建
首先部署redis-5.0.3,请参考我的另一篇文章 https://www.cnblogs.com/djlsunshine/p/10592174.html 启动redis服务 # redis-ser ...