




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
14:38:371C++程序设计教程(第二版)第六章性能Chapter6
Performance
14:38:372提高性能的意义:
性能对提高编程能力举足轻重如何提高性能?
以合理使用资源为前提,尽快完成任务的能力称为效率.效率影响性能,提高效率就能提高性能学习目标:
1.
扩展视野,对同一问题的不同要求,模仿各种编程技巧与空间布局策略,予以应对.从而对各种不同的问题,亦能应变自如
2.掌握测试性能的方法,学会测算时/空交换的代价,客观评估自身的编程能力14:38:373第六章内容
内联函数(InlineFunctions)
数据结构(DataStructures)
算法(Algorithms)
数值计算(NumericalComputation)STL算法(STLAlgorithms)
动态内存(DynamicMemory)
低级编程(LowerProgramming)
14:38:3741.内联函数(InlineFunctions)做法:将一些反复被执行的简单语句序列做成小函数用法:在函数声明前加上inline关键字作用:不损害可读性又能提高性能14:38:375//==================================#include<iostream>boolisDigit(char);//小函数intmain(){
for(charc;cin>>c&&c!='\n';)
if(isDigit(c))std::cout<<“Digit.\n";
elsestd::cout<<“NonDigit.\n";}//---------------------------------boolisDigit(charch){
returnch>='0'&&ch<='9'?1:0;}//=================================频繁调用的函数:用昂贵的开销换取可读性14:38:376//================================#include<iostream>intmain(){
for(charc;cin>>c&&c!='\n';)
if(ch>='0'&&ch<='9'?1:0)std::cout<<“Digit.\n";
else
std::cout<<“NonDigit.\n";}//===============================内嵌代码:开销虽少,但可读性差14:38:377内联方式:开销少,可读性也佳//==================================#include<iostream>inlineboolisDigit(char);//小函数intmain(){
for(charc;cin>>c&&c!='\n';)
if(isDigit(c))std::cout<<"Digit.\n";
else
std::cout<<"NonDigit.\n";}//---------------------------------boolisDigit(charch){
returnch>='0'&&ch<='9'?1:0;}//=================================内联标记放在函数声明的前面14:38:378内联函数的使用经验:函数体适当小,且无循环或开关语句,这样就使嵌入工作容易进行,不会破坏原调用主体.如:排序函数不能内联程序中特别是在循环中反复执行该函数,这样就使嵌入的代码利用率较高.如:上例中的isDigit函数程序并不多处出现该函数调用,这样就使嵌入工作量相对较少,代码量也不会剧增14:38:379//======================================#include<iostream>#include<time>usingnamespacestd;//--------------------------------------intcalc1(inta,intb){returna+b;}inlineintcalc2(inta,intb){returna+b;}//--------------------------------------intmain(){
intx[1000],y[1000],z[1000];clock_tt=clock();
for(inti=0;i<1000*1000*1000;++i)z[i]=calc1(x[i%1000],y[i%1000]);cout<<(clock()-t)/CLK_TCK<<“withoutinline\n";t=clock();
for(inti=0;i<1000*1000*1000;++i)z[i]=calc2(x[i%1000],y[i%1000]);cout<<(clock()-t)/CLK_TCK<<“withinline\n";}//=====================================性能测试初记时末记时非内联函数内联函数14:38:3710结果分析:内联用与不用差很多结论:应尽量将函数改造成可内联性质,提高性能E:\ch06>f0605↙8.281withoutinline2.437withinline14:38:37112.数据结构(DataStructures)揭示:将数据结构实现为数据类型是编程的高级境界,STL容器就是系统提供的现成数据结构做法:充分和合理使用STL容器,简化复杂问题,提高编程效率与程序性能14:38:3712问题:有许多序列,每个序列都等待验证是否可从顺序数列经过栈操作而得.例如:顺序数列1,2,3,4,5
待验证序列3,2,1,5,4
待验证序列5,3,4,2,114:38:3713采用不同的数据结构#include<fstream>#include<iostream>#include<sstream>//栈方式:
#include<stack>//向量方式:#include<vector>usingnamespacestd;14:38:3714栈方式//=============================intmain(){ifstreamin("rail.txt");
for(intn,line=0;in>>n&&n&&in.ignore();){cout<<(line++?"\n":"");
for(strings;getline(in,s)&&s!="0";){istringstreamsin(s);stack<int>st;
for(intlast=0,coach;sin>>coach;st.pop()){
for(intp=last+1;p<=coach;++p)st.push(p);
if(last<coach)last=coach;
if(st.top()!=coach)break;}cout<<(!sin?"Yes\n":"No\n");}}}//=============================栈中若不存在读入的元素,则应入栈创建栈读入元素不在栈顶即为失败退栈即逐个逐个过14:38:3715向量方式//================================intmain(){ifstreamin("rail.txt");
for(intn,line=0;in>>n&&n&&in.ignore();){cout<<(line++?"\n":"");
for(strings;getline(in,s)&&s!="0";){istringstreamsin(s);vector<int>st;
for(intlast=0,coach;sin>>coach;st.pop_back())){
for(intp=last+1;p<=coach;++p)st.push_back(p);
if(last<coach)last=coach;
if(st.back()!=coach)break;}cout<<(!sin?"Yes\n":"No\n");}}}//=================================模仿栈操作14:38:3716结论不同的数据结构有不同的操作和性能应学习使用不同数据结构的经验14:38:37173.算法(Algorithms)揭示:确定了数据结构之后,所采用的算法将直接决定程序的性能;任何语言都有个性,算法的选择使用是灵巧运用语言的艺术,充分发挥语言的优势是活用算法的根本做法:培养经验,用测试的办法对算法进行选择14:38:3718问题:已知不太大的正整数n(n≤46),求Fibonacci数列
0112358132134……的第n项的值.对于后面的四种算法:
unsignedfibo1(unsignedn);unsignedfibo2(unsignedn);unsignedfibo3(unsignedn);unsignedfibo4(unsignedn);如何选择其中之一.第0项第1项第2项14:38:3719算法1:递归法
优点:算法简单,容易编程
缺点:栈空间负担过重,调用开销过大unsignedfibo1(unsignedn){
if(n<=1)returnn;returnfibo1(n-1)+fibo1(n-2);}n=0或114:38:3720算法2:迭代法
优点:节省空间,节省时间
缺点:编程相对复杂unsignedfibo2(unsignedn){
intc=n;
for(inta=0,b=1,i=2;i<=n;++i)c=a+b,a=b,b=c;
returnc;}14:38:3721算法3:向量迭代法
优点:节省时间
缺点:n越大,占用堆空间越多unsignedfibo3(unsignedn){vector<unsigned>v(n+1,0);v[1]=1;
for(unsignedi=2;i<=n;++i)v[i]=v[i-1]+v[i-2];
returnv[n];}14:38:3722算法4:直接计算法
优点:节省时间
缺点:引入了浮点计算unsignedfibo4(unsignedn){
return
(pow((1+sqrt(5.0))/2,n)–pow((1–sqrt(5.0))/2,n))/sqrt(5.0);}14:38:3723fibo1:只在示意性编程中使用,但并不是否定一切递归法fibo2:在讲究性能的场合中使用,它省空间省时间,但在n很大的场合中,性能比不上fibo4fibo3:可以数组代替向量,提高低级编程的性能,它易编易用,还可以读取中间项的值,但在一味追求性能的场合中,比不上fibo2fibo4:在n不太大时,与fibo2相当,在n趋向很大时,其性能优势便充分体现14:38:37244.数值计算(NumericalComputation)揭示:在近似计算中,除了计算范围与终止计算条件外,还涉及逼近的快慢,这与算法有很大关系,选择成熟的算法具有决定性作用做法:了解各种数值计算算法的特点及使用场合,有的放矢解决实际问题14:38:3725数值计算的参数描述template<classT>//T为赖以计算的数系
Tmethod(//method为某种算法
Ta,//左边界
Tb,
//右边界
constTEpsilon,//终止条件
T(*f)(T)
//求值数学函数);14:38:3726矩形法doublerectangle(doublea,doubleb,constdoubleEps,double(*f)(double)){
doublew=b-a,sN=w*(f(a)+f(b))/2,sO=0;
for(intn=1;abs(sN-sO)>=Eps;n*=2){sO=sN;sN=0;
for(inti=0;i<n;++i)sN+=f(a+w*(i+0.5)/n);sN*=w/n;}
returnsN;}小矩形逐个求和前后两次小矩形和的差14:38:3727辛普生法
doublesimpson(doublea,doubleb,
constdoubleEps,double(*f)(double)){
doubleI2n=0,h=b-a,T2n=h*(f(a)+f(b))/2,In=T2n,Tn;
for(intn=1;abs(I2n–In)>Eps;n+=n,h/=2.0){In=I2n;Tn=T2n;//In老积分值
doublesigma=0;
for(intk=0;k<n;k++)sigma+=f(a+(k+0.5)*h);T2n=(Tn+h*sigma)/2;I2n=(4*T2n-Tn)/3;//I2n新积分值
}
returnI2n;}小矩形求和辛普生处理前后两次辛普生值的差14:38:3728性能比较求同样的数学函数,区间和精度矩阵法比辛普生法多循环许多次14:38:37295.标准C++算法(StandardC++Algorithms)揭示:标准C++提供了诸多算法,这些算法的组合构成了许多问题的解,对算法的准确了解是编程能力的一大体现做法:吃透标准C++算法,灵活运用之14:38:3730容器的区间表示vector<int>a(10);//下面表示待处理的元素vector<int>b(a.begin()+1,a.begin()+7);0123456789首尾待处理的元素14:38:3731逐一读入两个01字串,比较是否含有相同元素intmain(){ifstreamin("string.txt");
for(strings,t;in>>s>>t;){
比较输出yes
或no}}14:38:3732分别排序,直接加以字串比较是直截了当的思路:for(strings,t;in>>s>>t;){sort(s.begin(),s.end());sort(t.begin(),t.end());cout<<(s==t?"yes\n":"no\n");}C++标准算法14:38:3733避免排序,分别统计两个字串中01的个数则性能更优:
(排序至少做O(nlogn)数量级运算,统计只做O(n)数量级运算)for(strings,t;in>>s>>t;){
ints1=count(s.begin(),s.end(),’1’);
ints0=count(s.begin(),s.end(),’0’);
intt1=count(t.begin(),t.end(),’1’);
intt0=count(t.begin(),t.end(),’0’);cout<<(s1==t1&&s0==t0?"yes\n":"no\n");}C++标准算法14:38:3734字串中非0即1的特征,可以避免多余的统计,进一步提高性能:for(strings,t;in>>s>>t;){
ints1=count(s.begin(),s.end(),’1’);
intt1=count(t.begin(),t.end(),’1’);cout<<(s1==t1&&s.length()==t.length()?"yes\n":"no\n");}C++标准算法14:38:37356.动态内存(DynamicMemory)揭示:许多问题不知道数据量的大小,需要所运用的数据结构具有扩容能力;许多问题要求时间性能甚于空间占用.充分利用堆空间(动态内存)是解决这些问题的关键做法:理解堆空间的使用场合,学习堆空间的使用方法14:38:3736使用容器,便是自动使用堆内存例如,从abc.txt中读取诸段落:
ifstreamin("abc.txt");vector<string>ps;
//ps.reserve(1100);可以预留
for(strings;getline(in,s);)ps.push_back(s);预留是减小频繁扩容造成的数据移动开销14:38:3737若每个数据的处理,都要用到已经处理的数据时,保存历史数据,则可以改善时间性能例如,统计一亿之内的素数个数(原始版):
boolisPrime(intn){
intsqrtn=sqrt(n*1.0);
for(inti=2;i<=sqrtn;++i)
if(n%i==0)returnfalse;
return
true;}//--------------------------intmain(){
intnum=0;
for(inti=2;i<=100000000;++i)
if(isPrime(i))num++;cout<<num<<endl;}//--------------------------14:38:3738空间换时间版intmain(){bitset<100000000>*p=newbitset<100000000>;p->set();
for(inti=2;i<=10000;++i)
if(p->test(i))
for(intj=i*i;j<p->size();j+=i)p->reset(j);
intnum=0;
for(inti=2;i<100000000;++i)
if(p->test(i))num++;cout<<num<<endl;
delete[]p;}在空间中统计完成每个元素的标记14:38:37397.低级编程(LowerProgramming)揭示:通过无原则的代码优化来简化程序的执行步骤,从而提高性能.它会影响可读性,并需要对程序的内存布局有深刻的了解,这一般是编程课的后继学习内容做法:尽量去掉组织程序所花费的代价:少用调用频繁的函数;通过指针间访数据;尽可能不用类;无原则数据共享;用C库不用C++库14:38:3740低级编程版:
逐一读入两个01字串,比较是否含有相同元素intcnt(char*a){
intnum=0;
while(*a)if(*a++=='1')num++;
returnnum;}//----
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 个人与公司投资合作合同范本2025
- 包装材料供应合同
- 证券交易合同格式规范
- 车辆过户合同协议书模板
- 商业综合体给排水工程清包合同范本
- 版临时电力施工合作合同
- 出口代理合同模板
- 旅行期间的紧急情况应对准备加强考核试卷
- 农村集体经济组织可持续发展能力评价与实践考核试卷
- 咖啡馆行业品牌延伸策略考核试卷
- 小学生守则、日常行为规范教育实施方案
- 湖南省六年级上册数学期末试卷(含答案)
- 部编版小学六年级道德与法治下册课堂达标检测试卷全册含答案
- 岩土工程中的非线性问题分析
- 他们创造了数学:50位著名数学家的故事
- 《普洱茶的定义》课件
- 2023山东经贸职业学院教师招聘考试真题题库
- 《定向运动》教学大纲(含课程思政要素)
- 学技能如何打逃生绳结固定绳结
- 内浮顶储罐检修安全规范
- 特殊教育:康复训练课程标准(年版)
评论
0/150
提交评论