没有合适的资源?快使用搜索试试~ 我知道了~
首页C++高级特性:数据结构与算法基础
C++高级特性:数据结构与算法基础
4星 · 超过85%的资源 需积分: 14 164 下载量 23 浏览量
更新于2024-07-21
4
收藏 16.73MB PDF 举报
"《数据结构算法与应用-C++语言描述(清晰版)》是一本专注于数据结构和算法的经典教材,特别强调在C++语言环境下进行教学。本书并非针对C++初学者,而是为有一定基础的读者设计,旨在提升他们在程序开发中的数据描述效率和算法设计能力。 首先,章节1介绍了C++的高级特性和编程技巧,包括参数传递方式(如传值、引用和常量引用)、函数返回方式(同样有多种形式),以及模板函数、递归函数、常量函数等。这些内容都是为了确保读者能够灵活运用C++进行高效编程。此外,还讲解了内存管理,如new和delete操作,以及异常处理机制,如try-catch-throw结构。 书中还通过实例演示了一维和二维数组的动态内存分配与释放、二次方程求解、生成所有元素排列和查找最大值等实用算法,有助于读者理解和实践。同时,作者强调了程序的质量评价标准,包括但不限于正确性、可读性、文档完备性、修改性、内存消耗、运行效率、通用性和跨平台兼容性,这些都是衡量一个高效程序的重要指标。 在预备知识部分,作者引导读者思考程序的各个层面,以全面评估其在实际应用中的表现。通过这样的方式,读者不仅能掌握C++语言的高级特性,还能培养出良好的编程习惯和工程思维,这对于在实际项目中解决复杂问题具有重要意义。随着后续章节的深入,更多的C++特性和高级概念将逐步展开,确保读者在数据结构和算法的世界中稳步前行。"
资源详情
资源推荐
题。例如,如果5 . 2 9 的计算机表示是5 . 2 8 9 9 9,那么加上0 . 0 0 1 将得到5 . 2 9 0 9 9 , 由此所计算出的
c e n t s就是2 9。
程序1-17 设置p r i v a t e 数据成员
bool Currency::Set(sign s, unsigned long d, unsigned int c)
{// 取值
if (c > 99) return false;
sgn = s; dollars = d; cents = c;
return true;
}
bool Currency::Set(float a)
{// 取值
if (a < 0) {sgn = minus; a = -a;}
else sgn = plus;
dollars = a; // 抽取整数部分
// 获取两个小数位
cents = (a + 0.005 - dollars) * 100;
return true;
}
程序1 - 1 8 给出了函数 A d d 的代码,该函数首先把要累加的两个货币数量转换成整数,如
$2.32 变成整数2 3 2,-$ 4 . 7 5变成整数-4 7 5 。请注意引用当前对象的数据成员与引用参数 x的
数据成员在语法上有所区别。 x . d o l l a r s 指定x 的数据成员dollars ,而当前对象使用d o l l a r s 时可
以直接引用d o l l a r s而不必在它的前面加上对象名。当函数 A d d终止时,局部变量 a 1 , a 2 , a 3 和a n s
被l o n g数据类型的析构函数删除,这些变量所占用的空间也将被释放。由于 C u r r e n c y对象a n s 将
被作为调用结果返回,因此必须把它复制到调用者的环境中,所以 A d d返回的是值。
程序1-18 累加两个C u r r e n c y
Currency Currency::Add(const Currency& x) const
{// 把 x累加到 * t h i s .
long a1, a2, a3;
Currency ans;
// 把当前对象转换成带符号的整数
a1 = dollars * 100 + cents;
if (sgn == minus) a1 = -a1;
// 把x转换成带符号的整数
a2 = x.dollars * 100 + x.cents;
if (x.sgn == minus) a2 = -a 2 ;
a3 = a1 + a2;
// 转换成 currency 形式
if (a3 < 0) {ans.sgn = minus; a3 = -a 3 ; }
else ans.sgn = plus;
ans.dollars = a3 / 100;
1 6 第一部分 预 备 知 识
下载
ans.cents = a3 - ans.dollars * 100;
return ans;
}
程序1 - 1 9给出了函数I n c r e m e n t和O u t p u t 的代码。在C + + 中,保留关键字t h i s用于指向当前对
象,*this 代表对象本身。看一下调用g . I n c r e m e n t ( h )。函数I n c r e m e n t的第一行调用了p u b l i c 成员
函数A d d ,它把x ( 这里是h) 加到当前对象上(这里是 g),所得结果被返回,并被赋给 * t h i s ,
* t h i s就是当前对象。由于该对象不是函数I n c r e m e n t 的局部对象,因此当函数结束时,该对象不
会自动被删除。所以可以返回一个引用。
程序1-19 Increment与O u t p u t
Currency& Currency::Increment(const Currency& x)
{// 增加量 x .
*this = Add(x);
return *this;
}
void Currency::Output () const
{// 输出currency 的值
if (sgn == minus) cout << '-';
cout << '$' << dollars << '.';
if (cents < 10) cout << "0";
cout << cents;
}
通过把C u r r e n c y类的成员变成私有(p r i v a t e ),我们可以拒绝用户访问这些成员,所以用户
不能使用如下的语句来改变这些成员的值:
h.cents = 20;
h.dollars = 100;
h.sgn = plus;
利用成员函数来设置数据成员的值可以确保数据成员拥有合法的值。构造函数和 S e t函数
已经做到了这一点,其他函数当然也应该保证数据成员的合法性。因此,在诸如 A d d 和O u t p u t
函数的代码中不必验证c e n t s 是否介于0到1 0 0 之间。如果数据成员被声明为 p u b l i c 成员,它们的
合法性将难以保证。用户可能会错误地把 c e n t s 设置成3 0 5,因而将导致一些函数(如 O u t p u t 函
数)产生错误结果,所以,所有的函数在处理任务之前都必须验证数据的合法性。这种验证将
会降低代码的执行速度,同时也使代码不够优雅。
程序1 - 2 0给出了类C u r r e n c y的应用示例。这段代码假定类定义及实现都在文件 c u r r 1 . h之中。
我们一般把类定义和类实现分放在不同的文件中,然而,这种分开放置的方法可能会对后续章
节中大量使用模板函数和模板类带来困难。
函数m a i n的第一行定义了四个C u r r e n c y类变量:g, h, i 和j。除h 具有初值$ 3 . 5 0外,构造函
数把它们都初始化为$ 0 . 0 0 。在接下来的两行中, g 和i 分别被设置成-$ 2 . 2 5 和-$ 6 . 4 5 ,之后
调用函数A d d把g 和h 加在一起,并把所返回的对象(值为$ 1 . 2 5)赋给j。为此,需使用缺省的
赋值过程把右侧对象的各数据成员分别复制到左侧对象相应的数据成员之中,复制的结果是使
j 具有值$ 1 . 2 5,这个值在下一行被输出。
第 1章 C ++程序设计 1 7
下载
下两行语句把i 累加到h 上,并输出i的新值-$ 2 . 9 5 。接下来的一行首先把 i和g加在一起,
然后返回一个临时对象(其值为- $ 5 . 2 0 ),此后,把h 加到这个临时对象上并返回一个新的临
时对象,其值为-$ 1 . 7 0 。新的临时对象被复制到 j 中,然后输出j 的值(为- $ 1 . 7 0)。注意‘.’
序列的处理顺序是从左到右。
接下来的一行语句首先使用 I n c r e m e n t 为i累加g,它返回一个引用给i。A d d把i和h的和返回
给j,最后输出j 的结果为-$ 1 . 7 0,i 的结果为-$ 5 . 2 0。
程序1-20 Currency类应用示例
#include <iostream.h>
#include "curr1.h"
void main (void)
{
Currency g, h(plus, 3, 50), i, j;
g.Set(minus, 2, 25);
i . S e t ( - 6 . 4 5 ) ;
j = h.Add(g);
j.Output(); cout << endl;
i . I n c r e m e n t ( h ) ;
i.Output(); cout << endl;
j = i.Add(g).Add(h);
j.Output(); cout << endl;
j = i.Increment(g).Add(h);
j.Output(); cout << endl;
i.Output(); cout << endl;
}
1.4.2 使用不同的描述方法
假定已经有许多应用采用了程序 1 - 1 5中所定义的C u r r e n c y类,现在我们想要对 C u r r e n c y类
的描述进行修改,使其应用频率最高的两个函数 A d d 和I n c r e m e n t可以运行得更快,从而提高应
用程序的执行速度。由于用户仅能通过 p u b l i c部分所提供的接口与 C u r r e n c y 类进行交互,因此
对p r i v a t e 部分的修改并不会影响应用代码的正确性。所以可以修改 p r i v a t e 部分而不会使应用发
生变化。
在C u r r e n c y对象新的描述中,仅有一个私有数据成员,其类型为 l o n g 。数1 3 2 代表$ 1 . 3 2 ,
而-2 0代表-$ 0 . 2 0 。程序1-21, 1-22, 1-23中给出了C u r r e n c y类的新的描述方法以及各成员函数的
具体实现。
注意,如果把新代码放在文件 c u r r 1 . h中,则可以运行程序1 - 2 0中的代码而不需要做任何修
改。对用户隐藏实现细节的一个重大好处在于可以用新的、更高效的描述来取代以前的描述而
不需要改变应用代码。
程序1-21 Currency类的新定义
class Currency {
p u b l i c :
// 构造函数
1 8 第一部分 预 备 知 识
下载
Currency(sign s = plus, unsigned long d = 0, unsigned int c = 0);
// 析构函数
~Currency() {}
bool Set(sign s, unsigned long d, unsigned int c);
bool Set(float a);
sign Sign() const
{if (amount < 0) return minus;
else return plus;}
unsigned long Dollars() const
{if (amount < 0) return (-amount) / 100;
else return amount / 100;}
unsigned int Cents() const
{if (amount < 0)
return -amount - Dollars() * 100;
else return amount - Dollars() * 100;}
Currency Add(const Currency& x) const;
Currency& Increment(const Currency& x)
{amount += x.amount; return *this;}
void Output() const;
p r i v a t e :
long amount;
} ;
程序1-22 新的构造函数及S e t函数
Currency::Currency(sign s, unsigned long d, unsigned int c)
{// 创建Currency 对象
if (c > 99)
{// 美分数目过多
cerr << "Cents should be < 100" << endl;
e x i t ( 1 ) ; }
amount = d * 100 + c;
if (s == minus) amount = -amount;
}
bool Currency::Set(sign s, unsigned long d,
unsigned int c)
{// 取值
if (c > 99) return false;
amount = d * 100 + c;
if (s == minus) amount = -amount;
return true;
}
bool Currency::Set(float a)
{// 取值
第 1章 C ++程序设计 1 9
下载
sign sgn;
if (a < 0) {sgn = minus; a = -a;}
else sgn = plus;
amount = (a + 0.001) * 100;
if (sgn == minus) amount = -amount;
return true;
}
程序1-23 函数A d d 和O u t p u t 的新代码
Currency Currency::Add(const Currency& x) const
{// 把x 累加至 * t h i s .
Currency y;
y.amount = amount + x.amount;
return y;
}
void Currency::Output() const
{ / /输出currency 的值
long a = amount;
if (a < 0) {cout << '-' ; a = -a;}
long d = a / 100; // 美元
cout << '$' << d << '.';
int c = a
-
d * 100; // 美分
if (c < 10) cout << "0";
cout << c;
}
1.4.3 操作符重载
C u r r e n c y类包含了几个与 C + + 标准操作符相类似的成员函数,例如, A d d 进行 +操作,
I n c r e m e n t 进行 + = 操作。直接使用这些标准的 C + + 操作符比另外定义新的函数(如 A d d ,
I n c r e m e n t)要自然得多。可以借助于操作符重载( operator overloading)的过程来使用+和+ = 。
操作符重载允许扩充现有C + + 操作符的功能,以便把它们直接应用到新的数据类型或类。
程序1 - 2 4给出了把A d d 和I n c r e m e n t 分别替换为+和+ =的类描述。O u t p u t 函数采用一个输出
流的名字作为参数。这些变化仅需修改 A d d 和O u t p u t 的代码(见程序1 - 2 3)。程序1 - 2 5 给出了修
改后的代码。在这个程序还给出了重载C + +流插入操作符< <的代码。
注意在C u r r e n c y 类中重载了流插入操作符,但没有定义相应的成员函数,而重载 +和+ = 时
则把它们定义为类成员。同样,也可以重载流抽取操作符 > >而不需要把它定义为类成员。请留
意,是函数O u t p u t支持了< <的重载。由于C u r r e n c y对象的p r i v a t e成员对于非类成员函数来说不
可访问(被重载的 < < 不是类成员,而 +是),所以,重载 < < 的代码不能引用对象 x的私有成员
(在< < 操作中x将被插入到输出流中)。特别地,下面的代码是错误的,因为成员 a m o u n t是不可
访问的。
// 重载< <
ostream& operator<< ( ostream& out, const Currency& x)
{ out << x.amount; return out; }
2 0 第一部分 预 备 知 识
下载
剩余541页未读,继续阅读
qq_15199143
- 粉丝: 1
- 资源: 8
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 前端面试必问:真实项目经验大揭秘
- 永磁同步电机二阶自抗扰神经网络控制技术与实践
- 基于HAL库的LoRa通讯与SHT30温湿度测量项目
- avaWeb-mast推荐系统开发实战指南
- 慧鱼SolidWorks零件模型库:设计与创新的强大工具
- MATLAB实现稀疏傅里叶变换(SFFT)代码及测试
- ChatGPT联网模式亮相,体验智能压缩技术.zip
- 掌握进程保护的HOOK API技术
- 基于.Net的日用品网站开发:设计、实现与分析
- MyBatis-Spring 1.3.2版本下载指南
- 开源全能媒体播放器:小戴媒体播放器2 5.1-3
- 华为eNSP参考文档:DHCP与VRP操作指南
- SpringMyBatis实现疫苗接种预约系统
- VHDL实现倒车雷达系统源码免费提供
- 掌握软件测评师考试要点:历年真题解析
- 轻松下载微信视频号内容的新工具介绍
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功