数据结构与算法分析(JAVA语言描述)第一章

第一章 引论

1.1 本书讨论的内容

现在解决很多问题的方法很多,在许多问题中,一个重要的观念是写出一个程序不够,如果这个程序在很大的数据集上运行,那么运行时间就成了很重要的问题。这本书看到对于大量输入如何估计运行时间,尤其是如何在未编码的情况下比较两个程序的运行时间,以及彻底改变程序速度以及确定程序平静的方法。这些方法将是我们能够发现需要我们集中精力努力优化的代码段。

1.2数学知识复习

主要介绍简单的公式,知识范围包括指数,对数,级数,模运算,以及引出归纳法和反证法证明定理的方式,这里不在介绍,主要是因为公式太难编辑,而且定理比较简单有兴趣的可以自行翻阅电子版查看。

1.3递归简论

使用一些小例子引出递归的4大原则:

1、基准情形。必须总要有某些基准情形,他无需递归就能解出(出口)

2、不断推进。对于那些需要递归求解的情形,每一次递归调用都必须朝向一种基准情形推进。

3、设计法则。假设所有的递归调用都能运行。(不必考虑计算机处理细节)

4、合成效益法则。在求解一个问题的同一实例时,切勿在不同的递归调用中做重复性的工作。(后面章节证明)

隐藏知识:mod例程非常耗时,建议使用 *10

1.4实现泛型构件pre-Java5

面向对象的一个重要的目标是代码重用。支持这个目标一个重要的机制就是泛型机制:如果除去对象的基本类型外,实现方法是相同的,那我们就可以用泛型实现来描述这种基本的功能。

1.4.1使用Object表示泛型

注意两个细节:

1)为了访问这种对象的一个特定方法,注意强制转换成正确的类型。

2)第二个重要的细节是不能使用基本类型。

1.4.2基本类型的包装

Java中我们已经看到,虽然每一个引用类型都和object相容,但是8种基本类型却不行。Java为8种基本类型提供对应的包装类。每一个包装对象都是不可变的(也就是状态不可变),存储原值并提供一种方法重新得到该值。

1.4.3使用接口类型表示泛型(不重要)

如果基本的代码是类型无关的,可以考虑用接口实现。

1.4.4数组类型的兼容性

语言设计中困难之一是处理集合类型的继承问题。

设Employee IS-A person 那么是不是Employee[] IS-A Person[] 呢? 乍一看,应该是的。

那么我们来考虑存在Student IS-A Person,有以下2条赋值语句:

Person[] arr = new Employee[5];

arr[0] = new Student(...);

两句都编译,而arr[0]实际上是引用一个Employee,可是Student IS-Not-A Employee。两者产生了类型混乱。运行时系统不能抛出ClassCastException异常,因为不存在类型转换。

避免这种问题最容易的方法最简单的方法就是指定这些数组不是类型兼容的。可是在Java中数组确实类型兼容的。这种叫做协变数组类型。每个数组都明了它所允许存储的对象的类型。如果将一个不兼容的类型插入到数组中,那么虚拟机将抛出一个ArrayStoreException异常。

1.5 利用JAVA5泛型特性实现泛型构件

1.5.1 简单的泛型类和接口

当指定一个泛型类时,类的声明则包含一个或多个类型参数,这些参数被放在类名后面。也可以声明接口是泛型的。

1.5.2 自动装箱/拆箱

如果一个int型变量被传递到需要一个Integer对象的地方,那么,编译器将在幕后插入一个对Integer构造方法的调用。这叫做自动装箱。而如果 Integer对象被放到需要int型变量的地方,则编译器将在幕后插入一个队intValue方法的调用,这就叫做自动拆箱。

1.5.3 菱形运算符

Java7之后增加了一种新的语言特性

//Java7之前
List<Integer> list =  new ArrayList<Integer>();

//Java7之后
List<Integer> list =  new ArrayList<>();

1.5.4带有限制的通配符

Java中数组是协变的,但是集合不是。Collection<Square> IS-NOT-A Collection<Shape>

现在的问题是,泛型集合不是协变的,而数组是协变的。若无附加的语法,则用户就会避免使用集合,因为失去协变性使得代码缺少灵活性。Java5使用通配符来弥补这个不足。

Collection<T>

Collection<? extends Shape>

 1.5.5 泛型static方法

泛型方法特别像是泛型类,因为类型参数表使用相同的语法。在泛型方法中的类型参数位于返回类型之前。

//声明泛型类
public static <AnyType> boolean contains(Anytype[] arr,Anytype x){}

1.5.6 类型限界

为了确定传参类型,在尖括号中对参数类型指定必须具有的性质。

例如

public static <AnyType extends Comparable<? super Anytype>> AnyType findMax(AnyType[] arr){}

1.5.7 类型擦除

泛型类可以由编译器通过所谓的类型擦除过程转变为非泛型类。编译器生成一种与泛型类同名的原始类,但是类型参数都被删去了,类型变量由他们的类型限界代替。如果使用一个泛型类而不带类型参数,那么使用的是原始类。

1.5.8对于泛型的限制

基本类型不能用做类型参数。

instanceof检测和类型转换工作只对原始类型进行。

static标注的泛型类,static域在各个泛型实例中共享。

不能创建一个泛型类型的实例。 T obj = new T(); //是违法的

也不能创建泛型类型的数组 T[] arr = new T[10];  //是违发的

 1.6函数对象

一种将函数作为参数传递的独创方法是注意到对象既包含数据也包含方法,于是我们可以定义一个没有数据而只有一个方法的类,并传递该类的一个实例。事实上一个函数放在一个对象内部而被传递。这样的对象通常叫做函数对象。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值