数据结构和算法 第一章 综述(2)

继承与多态

下面简要的提一下面向对象编程的两个重要特征:继承与多态

继承是指由基类扩展或派生形成的一个新类。这个扩展类拥有基类的所有属性,并加上了集中其他属性。例如,秘书类可能是冲一个更加一般化的雇员类派生而来,它也许会包括一个雇员类所缺少的字段:打字速度。

在Java语言中,继承又称为子类化(subclassing)。基类被称为父类,扩展类被称为子类。

继承可以方便地向一个现有的类中增加属性,这对于设计一个许多相关类的系统而言,是十分重要的。由于用途发生微小变化而需要重用类,而继承使这个工作变得十分简单,这是OOP的一个重要的优点。

多态指的是以相同的办法处理来自不同类的对象。为了使多态能够正常运行,这些不同的类必须从同一个基类中派生出来。实际上,多态经常指的是通过一种方法的调用,而实质是对不同的类的对象执行不同的方法。

例如,调用一个secretary对象中的display()方法会激活secretary类中的相应方法,当对一个manager对象进行调用时,便会激活manager类中的不同的显示方法。多态可以简化程序设计和编写,并使之更加清新。

对那些不熟悉继承和多态的人来说,可能会带来多余的麻烦。为了将注意力集中在数据结构和算法上,示例程序会尽量避免使用这些特性。继承和多态是OOP的重要且强大的特性,但它们对于数据结构和算法的解释并不是必须的。

软件工程

最近几年,在数据结构和算法的书中时兴将以软件工程为内容的一张作为开场白。我们简要的讨论一下软件工程,并简述它同接下来的学习内容是如何相关的。

软件工程研究的是由许多程序员参与的大型复杂的计算机程序的创建办法。它强调的是程序的整体设计和如何依照最终用户需求而进行设计的问题。软件工程关系着一个软件项目的整个什么周期,包括分析、设计、验证、编码、测试、生产和维护各阶段。

将软件工程与数据结构和算法的知识融合在一起对学生学习这两个不同的主题是否有帮助,现在还不得而知。除非参加一个大型的项目,否则软件工程相当抽象,很难被领悟。但是另一方面,数据结构和算法却是有关编程和数据存储的细致入微的基本规则。

对于C++程序员的Java

没有指针

Java 和 C++的最大不同就在于 Java 没有指针。对于一个 C++程序员来说,没有指针在最初看起来会很令人惊讶,程序离了指针怎么能运行呢?

无指针的代码编写了复杂的数据结构,这种方法不仅可能,而且事实上比使用 C++指针更简单。

其实,Java 只是摆脱了显式表露的指针,指针依旧以存储地址的形式埋藏在程序的深处。有时甚至可以说,在Java中,所有东西都是指针。这句话虽不是百分之一百的正确,但也差不多。下面来更仔细地讨论这个问题。

引用(reference)

Java 对基本数据类型(如int、float 和 double)的处理与对象的处理不同。请看下面两条语句∶
int intVar;// 一个叫做intVar的int变量
BankAcount bc1; // 对BankAccount对象的引用

在第一行语句中,一个被称为 intVar的存储地址保存了一个数值 127(假设这个值已经被放在那里)。然而,bcl 这个存储地址并没有保存BankAcount对象的数据。与第一句不同的是,它存储了一个 BankAcount 对象的地址,而这个对象实际上被存储在内存空间的其他某个地方。这个名称 bc1 是对象的一个引用,它并不是对象本身。

实际上,如果 bcl 没有被预先赋值为程序中某个指针预先指向的对象的话,它就不会成为引用。在赋值为某个对象之前,它保存一个被称做null的特殊对象的引用。同样,intVar 在它被赋指之前也不会保存数值。如果尝试使用一个没有被赋值的变量,编译器便会报错。

在 C++中的语句∶ BankAccount bc1;
实际上创建了一个对象;它留出了所有这个对象的数据的空间。在Java中,这条语句只创建了一个放置某一对象的存储地址的空间。可以将引用认为是普通变量语法中的指针。(C++也有引用变量,但它们必须用&符号显式说明。)

赋值
Java 中的赋值操作符与 C++中的不一样。在 C++中,这条语句∶ bc2= bc1;
将一个名为 bc1的对象的所有数据都拷贝到另一个名为 bc2 的对象中。
这条语句执行后,程序中有两个含有相同数据的对象。然而在Java中,这条相同的赋值语句只向 bc2中拷贝了bcl指向的存储地址,现在bcl 和bc2实际上指的是同一个对象,它们都是这个对象的引用。
如果对赋值操作符理解不深的话,上面的语句会让人感到困惑。在那条语句之后是下面两句∶ bc1.withdraw(21.00);和
bc2. withdraw(21.00);
这两次都是从同一个银行账户对象中取款的。
如果想从一个对象中复制数据到另一个对象中,必须保证在一开始就有两个不同的对象,然后分别拷贝每一个字段,等号是不起复制作用的。

new 操作符

在 Java中任何创建对象的工作都必须使用 new.但是 new在Java中返回一个引用,而不像C中返回一个指针。因此,指针并不需要使用 new。下面是创建对象的一种方法∶
Bankccount ba1;
ba1 = new BankAcount ();
取消指针意味着一个更安全的系统。程序员不可能找到 bal 的真实地址,也就不可能意外地破坏它。除非故意想做一些使系统混乱的事情,否则的话是不需要知道真实地址的。

用 new 向系统申请空间后,如何去释放那些不再使用的空间?在 C++中,可以使用 delete。在 Java中,则根本不需要对释放空间担心。Java每隔一段时间就会查看每一块由 new开辟的内存,看指向它的有效引用是否依旧存在。如果这个引用不存在,系统会自动将这块空间归入空闲内存区。这个过程被称为垃圾收集。

几乎所有的程序员在使用 C++过程中都会有忘记删除存储空间的经历,这会导致"存储泄漏"(memory leak)从而消耗系统资源,使程序处于不稳定的状态,甚至会导致系统崩溃。存储泄漏在 Java中不可能出现(或至少几乎没有)。

参数
在 C++中,指针经常被用来在函数之间传递对象,从而避免拷贝一个大的对象的系统开销。在 Java中,对象经常以引用的形式传递。这种方法同样避免了对象的拷贝;
void method1()
{
BankAccount ba1 = new BankAccount (350.80);
method2(ba1));
void method2(BankAccount acct)
{
在上面的代码中,引用 bal 和 acct 都指向同一个对象。而在C++中,acct 则是从bal 拷贝而来的另一个对象。
然而,简单数据类型总是通过它的值来传递。即由方法创建一个新的变量,并将参数的值复制到这个新的变量中去。

相等与同一

在 Java中,对基本数据类型,可以通过相等操作符(==)来判断两个变量是否含有相同的值∶

int intVar1 = 27;
int intvar2= intVar1;
if(intvar1 =- intVar2)
System.out.print1n(“They’re equal”);

这同C 和 C++中的语法是一致的。但是在 Java中,由于关系操作符使用引用,所以它们在涉及到对象的判断时有些不同。当使用相等操作符(= =)判断类时,实际上判断的是类的引用是否一致,即它们是否指的是同一个对象∶

carPart cp1= new carPart(’“ferder”);
carPart cp2 = cp1;
if(cp1 == cp2)
System.out.println(“They’reIdontical”);

在 C+中,这个操作符会判断出两个对象是否含有相同的数据。如果在 Java中要判断两个对象中是否含有相同的数据,则要使用 Object 类中的 equals()方法∶

carPart cp1 = new carPart(‘render");
carPart op2= cp1;
if( cp1.0quals(cp2) )
System.out.println("They’re equal’);

能够使用这个方法是因为 Java中所有类都是从 Object 类中派生而来的。

重载操作符

Java 中没有重载操作符。在 C++中,可以重新定义+、*、=及大多数其他操作符,以便使它们在特定的类中达到不同的效果。在 Java中,任何类似的重新定义都是不可能的,而可以使用命名的方法,例如 add()或其他名字。

基本变量类型

下表 是在 Java 中的基本或内置的变量类型。

在这里插入图片描述与C 和 C+用整数类型来表示真/假值不同的是,Java中的 boolean 型是一个独立的类型。 char(字符)型是无符号的,采用两个字节的空间来表示 Unicode 字符集,这个字符集可以处理国际通用的字符。

在C 和 C++中 int 型的大小可能不同,这取决于它们运行的计算机环境;在 Java中,一个 int型的变量永远是 32 位。

float 型变量的字面表达用F做后缀(例如,3.14159F);double 型变量的字面表达不需要后缀。 long型变量的字面表达用 L 徽后缀(例如,45L);其他整型的字面表达不需要后缀。

Java 与C 和 C++相比,属于强类型语言。在其他语言中可以由系统自动进行的转换,在 Java中却需要显式的转换(explicit cast)。

所有不包括在上表 中的类型,例如 String,都是类。

输入/输出

随着 Java的进化,输入输出也在跟着发生变化。对于类似书中即将出现的控制台模式的示例程序,输入输出可以用一些看起来比较笨拙但却很有效的方法。它们同C++中广泛应用的cout 和 cin以及 C 中的 prinf()和 scanf()截然不同。

若是用 Java软件开发环境工具集(SDK)的较早级本实现输入输出例程routine),那么在源程序的最开始需要有一行∶
import jar.io,";
现在只有当有输入时,才需要这一行语句。

输出
可以通过下面的语句输出任何基本类型数据(数字和字符),String类也可以;
Syste.out.print(var); // 显示var,不换行
Systen.out.printIn(var); //显示var,换行
print()方法将光标停在同一行上∶而 println()方法将光标移至下一行的开始。
在 SDK的老版本中,System.ou.prin()实际上并没有向屏幕上写任何东西,它的后面必须紧接一句System.outprintIn()或 Sysem.out,flush()才能将缓冲区中的所有东西显示出来。但是在现在的服本中,它会直接显示出来。

参数可以用好几个变量,中间用加号连接即可。假设下句中的 ans 值为 33∶
Systen.oxt.println("The amswer is’ + ans);
输出为∶
Tne answr is 33输入字符串
输入比输出更棘手。通常希望程序读入的所有值都被当作一个String类。如果输入的实际上是其他的东西,如一个字母或数字,就还得需要将 Strig类转换为希望的类型,正如我们所注意到的,有输入过程的程序的开始必须包括下条语句∶inport jave.io.*;
如果没有的话,编译器便不能识别如IOExeption和 InputStremReader 这样的实体。

字符串输入很复杂。下面的方法返回用户输入的字符串;

public static String getString()thrws IOException
{
InputStreamReader isr = new InputStrearAeader(System,in);
BufferedRoader br = new BufferedReader(isr);
String s= br.readLine();
return s;
}

这个方法返回一个 String类对象,它由从键盘输入的字符组成,通过回车键终止。现在并不需要对 InputStreamReader 和 BufferedReader 类的细节知道得太多。

除了引入java.io.*,还需要像上面的代码一样,为所有的输入方法加上 throwsIOException。事实上,所有方法,臂如 main(),凡是要调用任何输入方法的,就需要在其中加上 throwsIOException.

输入字符

当程序用户输入一个字符时(输入指键入一些字母并按下回车键),他有可能输入一个或输入多于一个(错误)的字符,因此最安全的读入一个字符的方法是,先读入一个字符串,再通过charAt()方法摘取它的第一个字符∶

public static char getChar()throws IOException
{
String s = getString();
return s.charAt(0);
}

String类的 charAt()方法返回一个 String 类对象中某个特定位置的字符,在上面的例子中,是第一个字符,号码是 0。这个方法避免了无关的字符留在输入的缓存中,正是无关的字符导致后续的输入总是出现错误。

输入整数

读入数字需要得到一个 String类对象并用转换方法将其转成所需的类型。下面这个getInt()方法就是将 String 类对象转化成 int 型并返回∶

pubic int getint()throws IOException
{
String s =getString();
return Integer.parseInt(3);
}

Integer 类的 parselnt()方法将字符串转成 int 型。还有一个类似的例程——parseLong(),可以转成 long 型。
在 SDK 的老版本中,任何使用 parselnt()方法的程序开头都必须包括下条语句;
irport java.lang.Integer;
但现在已不是必需的了。
为了简单起见,示例程序中的输入例程没有加进任何纠错过程。用户可能正确输入,但也会有异常出现。在上面的代码中,异常会导致程序的终止。在正式的程序中应该在转换之前先分析输入的字符串,捕获所有异常并正确地处理它们。

输入浮点型数

输入浮点数和双精度数的处理方法和处理整数的方法几乎一样,但转换的过程更复杂。下面的代码可以读入一个双精度型数∶
puolic int getDouble() throws IOException
{
String s =getString();
double aDub = Double.value0f(s);
return aDub.doubleValue();
}

字符串先转换成一个Double 型的对象(D大写),它是double类型的"封装"类。然后 Double类的doubleValue()方法将这个对象转化成 double 型。
对于float型来说,同样有一个 Float类,其中同样也有valueOf()和 floatValue()这两个方法。

Java 数据结构的类库

Java.util 包中包含有诸如向量(一个可扩充的数组)、栈、库(dictionary)和哈希表等类型的数据结构。
如果想使用这些类,必须先加入 inport java.ut1l.*;
尽管重点不是介绍这些类库,不论是 Java 自带的还是第三方开发人员提供的类库,但这些类都是通用的,并经过了调试,它们为我们提供了丰富的资源。只有真正明白数据结构的基础,才能决定是应该写自己的类还是用别人的类。

小 结

数据结构是指数据在计算机内存空间中或磁盘中的组织形式,
正确选择数据结构会使程序的效率大大提高。
数据结构的例子有数组、栈和链表。
算法是完成特定任务的过程。
在 Java中,算法经常通过类的方法实现。
一些数据结构的用途是作为程序员的工具;它们帮助执行算法。
其他数据结构可以模拟现实世界中的情况,例如城市之间的电话线网。
数据库是指由许多类似的记录组成的数据存储的集合。
一条记录经常表示现实世界中的一个事物,例如一名雇员或一个汽车零件。
一条记录被分成字段。每个字段都存储了由这个记录所描述事物的一条特性。
一个关键字是一条记录中的一个字段,通过它可以对数据执行许多操作。例如,人事记录
可以通过 LastName 字段进行排序。
可以搜索数据库以便找到关键字字段有定值的所有记录,这个值被称为查找关键字。

问 题
下列问题作为读者的自测题。
1.对于许多数据结构来说,可以_____一条记录,可以____它,还可以_———它。
2.按照某种顺序对一个数据结构的内容进行重新排列被称为______。
3. 在数据库中,一个字段是 a.一条特殊的数据项。 b.-个特殊的对象。 c.一条记录的一部分, d.一个算法的一部分。
4.当查找一个特定的记录时,所使用的那个字段被称为_____。
5. 在面向对象程序设计中,一个对象
a.是一个类。
b.可能包含有数据和方法。 c. 是一个程序。 d.可能含有类。
6.一个类
a. 是许多对象的蓝图(blueprint)。 b.表示了一个特定的现实世界中的事物。 c. 在它的字段中可以保存特殊的值。 d.规定了一个方法的类型。
7.在Java中,声明(specify)一个类
a.创建了一个对象。 b.需要关键字 new。 c.创建了一个引用。 d.以上均不是。
8.当一个对象想做一些事情时,它使用一个
9.在Java中,访问一个类的方法要用_
10.在Java中,booean和 byte 是

答案
1.对于许多数据结构来说,可以插入一条记录,可以查找它,还可以删除它。
2.按照某种顺序对一个数据结构的内容进行重新排列被称为排序
3. 在数据库中,一个字段是c
a.一条特殊的数据项。 b.-个特殊的对象。 c.一条记录的一部分, d.一个算法的一部分。
4.当查找一个特定的记录时,所使用的那个字段被称为搜索关键字
5. 在面向对象程序设计中,一个对象b
a.是一个类。b.可能包含有数据和方法。 c. 是一个程序。 d.可能含有类。
6.一个类a
a. 是许多对象的蓝图(blueprint)。 b.表示了一个特定的现实世界中的事物。 c. 在它的字段中可以保存特殊的值。 d.规定了一个方法的类型。
7.在Java中,声明(specify)一个类d
a.创建了一个对象。 b.需要关键字 new。 c.创建了一个引用。 d.以上均不是。
8.当一个对象想做一些事情时,它使用一个方法
9.在Java中,访问一个类的方法要用==.(点)==
10.在Java中,booean和 byte 是数据类型

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值