Algorithm 4th 1.1 基础编程模型

1.1.5 数组
在Java中创建一个数组需要三步:声明,创建,初始化数组元素。
在Java数组中double类型变量默认初始值为0.0。数值类型的默认初始值为0,布尔型的默认初始值为false。
我们需要在运行时明确地创建数组的原因是Java编译器在编译时无法知道应该为数组预留多少空间(对原始类型则可以:int, double, boolean, char)
数组一经创建,其大小就是固定的。

double[] a = new double[N];//数组的初始化

典型的数组处理代码:

//找出数组中最大的元素
double max = a[0];
for(int i = 1; i < a.length; i++)
    if(a[i] > max)
        max = a[i];
//计算数组元素的平均值
int N = a.length;
double sum = 0.0;
for(int i = 0; i < N; i++)
    sum += a[i];
double average = sum/N;
//复制数组
int N = a.length;
double[] b = new double[N];
for(int i = 0; i < N; i++)
    b[i] = a[i];
//颠倒数组元素顺序
int N = a.length;
for(int i = 0; i < N/2; i++)
{
    double temp = a[i];
    a[i] = a[N-1-i];
    a[N-1-i] = temp;
}
//矩阵相乘(方阵) a[][] * b[][] = c[][]
int N = a.length;
double[][] c = new double[N][N];
for(int i = 0; i < N; i++)
    for(int j = 0; j < N; j++)
    {
        for(int k = 0; k < N; k++)
        c[i][j] += a[i][k] * b[k][j];
    }

起别名
请注意!如果我们将一个数组变量赋给另一个变量,那么这两个变量将会指向同一个数组,例如:

int[] a = new int[N];
a[i] = 1234;
int[] b = a;
b[i] = 5678;//此时a[i]也将变成5678

如果是想将数组复制一份,则应该按照上面的复制数组的代码,将a中的元素逐一复制到b中。

静态方法
static将这类方法和1.2节的实例方法区别开来。
典型静态方法的实现(表1.1.5):

//计算一个整数的绝对值
public static int abs(int x)
{
    if(x < 0) return -x;
    else return x;
}
//计算一个浮点数的绝对值
public static double abs(double x)
{
    if(x < 0.0) return -x;
    else return x;
}
//判定一个数是否为素数
public static boolean isPrime(int N)
{
    if(N < 2) return false;
    for(int i = 2; i*i<= N; i++)
        if(N % i == 0) return false;
    return true;
}
//计算平方根(牛顿迭代法)*****why???
public static double sqrt(double c)
{
    if(c < 0) return Double.NaN;
    double err = 1e-15;//1e-15就是一个科学记数法的数字1x10的-15次方
    double t = c;
    while(Math.abs(t-c/t) > error * t)
        t = (c/t + t) / 2.0;
    return t;
}
//计算直角三角形的斜边
public static double hypotenuse(double a, double b)
{return Math.sqrt(a*a,b*b);}
//计算调和级数(见表1.4.5)
public static double H(int N)
{
    double sum = 0.0;
    for(int i =1; i <= N; i++)
        sum += 1.0 / i;
    return sum;
}

递归
编写递归代码时最重要的有以下三点:
1. 递归总有一个最简单的情况——方法的第一条语句总是一个包含return的条件语句。
2. 递归调用总是去尝试解决一个规模更小的问题,这样递归才能收敛到最简单的情况。
3. 递归调用的父问题和尝试解决的子问题之间不应该有交集。(EX: 在二分查找的递归实现和快速排序的递归实现中,两个子问题各自操作的数组部分是不同的)

//二分查找的递归实现
public static int rank(int key, int[] a)
{return rank(key, a, 0, a.length - 1);}

public static int rank(int key, int[] a, int lo, int hi)
{   //如果key存在于a[]中,它的索引不会小于lo且不会大于hi

    if(lo>hi) return -1;
    int mid = lo + (hi-lo)/2;
    if(key < a[mid]) return rank(key, a, lo, mid - 1);
    else if(key > a[mid]) return rank(ket, a, mid+1, hi);
    else     return mid;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值