java算法:一流的ADT
客户程序处理的应用越来越复杂,而ADT通过构建越来越强大的抽象层帮助管理创建客户程序的复杂性。在这个过程中,可能会出现隐患。一流数据类型是我们能在程序中使用的方式与使用基本数据类型的方式相同的数据类型。如果只能通过接口来访问,那就是一流的ADT。
写一个程序计算第N个单位根并把他们每个都提升到N次幂来检查计算。
例1:复数的ADT接口
- class Complex implements Cloneable{
- Complex(double re, double im)
- double re()
- double im()
- Complex mult(Comlex rhs)
- public Object clone()
- public String toString()
- }
class Complex implements Cloneable{
Complex(double re, double im)
double re()
double im()
Complex mult(Comlex rhs)
public Object clone()
public String toString()
}
例2:复数的ADT实现
- class Complex implements Cloneale{
- private double re, im;
- Complex(double re, double im){
- this.re = re;
- this.im = im;
- }
- double re(){
- return re;
- }
- double im(){
- return im;
- }
- void add(Complex rhs){
- re = re() + rhs.re();
- im = im() + rhs.im();
- }
- void mult(Complex rhs){
- double t = re();
- re = re() * rhs.re() - im() * rhs.im();
- im = t * rhs.im() + im() * rhs.re();
- }
- public String toString(){
- return re() + " " + im();
- }
- }
class Complex implements Cloneale{
private double re, im;
Complex(double re, double im){
this.re = re;
this.im = im;
}
double re(){
return re;
}
double im(){
return im;
}
void add(Complex rhs){
re = re() + rhs.re();
im = im() + rhs.im();
}
void mult(Complex rhs){
double t = re();
re = re() * rhs.re() - im() * rhs.im();
im = t * rhs.im() + im() * rhs.re();
}
public String toString(){
return re() + " " + im();
}
}
例3:复数驱动器(单位根)
- public class RootsOfUnity{
- public static void main(String args[]){
- int N = 100;
- System.out.println(N + " roots of unity.");
- for(int k = 0; k < N; k++){
- double x = Math.cos(2.0 * Math.PI * k / N);
- double y = Math.sin(2.0 * Math.PI * k / N);
- Complex c = new Complex(x,y);
- System.out.println(k + " : " + c);
- Complex z = (Complex)c.clone();
- for(int j = 0; j < N-1; j++){
- z.mult(c);
- }
- System.out.println(" " + z);
- }
- }
- }
public class RootsOfUnity{
public static void main(String args[]){
int N = 100;
System.out.println(N + " roots of unity.");
for(int k = 0; k < N; k++){
double x = Math.cos(2.0 * Math.PI * k / N);
double y = Math.sin(2.0 * Math.PI * k / N);
Complex c = new Complex(x,y);
System.out.println(k + " : " + c);
Complex z = (Complex)c.clone();
for(int j = 0; j < N-1; j++){
z.mult(c);
}
System.out.println(" " + z);
}
}
}
当使用静态的带有两个参数的方法时,每次执行算术运算以及扩展运算都不得不创建一个新的Complex,这可能留下很多要被垃圾收集器回收的对象。当使用类方法时,则不需要。
如计算:z的N次方:
- float z = t;
- for(int j = 0; j < N-1; j++){
- z *= t;
- }
float z = t;
for(int j = 0; j < N-1; j++){
z *= t;
}
如果是Complex对象:
- Complex z = t;
- for(int j = 0; j < N-1; j++){
- z.mult(t);
- }
Complex z = t;
for(int j = 0; j < N-1; j++){
z.mult(t);
}
在这里可能会犯错误,因为z和t是对同一个复数对象的引用,而不是不同复数的对象。结果不是z的N次方,而是z的平方的N次方。使用clone()很好的解决了这个问题。