算法的优化(C语言描述)

算法的优化

  算法的优化分为全局优化和局部优化两个层次。全局优化也称为结构优化,主要是从基本控制结构优化、算法、数据结构的选择上考虑;局部优化即为代码优化,包括使用尽量小的数据类型、优化表达式、优化赋值语句、优化函数参数、全局变量及宏的使用等内容。

  一、全局优化

    1.优化算法设计

      例如,在排序中用快速排序或者堆排序代替插入排序或冒泡排序;用较快的折半查找代替顺序查找法等,都可以极大地提高程序的执行效率。

    2.优化数据结构

      例如在一堆随机存放的数中使用了大量的插入和删除指令,那么使用链表要快得多。数组和指针具有十分密切的关系,一般来说,指针比较灵活简洁,而数组比较直观,容易理解。在许多情况下,可以用指针运算代替数组,这样做常常能产生又快又短的代码,并且运行速度快,占用空间少。

    3.优化选择结构

      ①嵌套if语句的使用。当if结构中要判断的并列条件较多的时候,最好将它们拆分成多个if语句结构,然后嵌套在一起,就可以减少不必要的判断。

      ②嵌套switch语句的使用。switch语句中的case很多时,为了减少比较次数,可以把大switch语句转化为嵌套switch语句。把频率较高的case标号放在一个switch语句中,而发生频率较低的case标号则放到另一个switch语句当中。

      ③给switch语句中的case排序。根据发生的可能性对case的值排序,最有可能的放在第一位就可以使选择过程更合理,从而提高了效率。

    4.优化循环结构

      提高程序效率的核心是对影响代码执行速度的关键程序段进行优化。在任何程序中,最影响代码速度的往往是循环结构,特别是多层嵌套的循环结构。掌握循环优化的的各种实用技术是提高程序效率的关键。

      常用的循环优化技术如下:

      ①降价策略。通过算法分析我们知道算法的事件复杂度主要是由循环嵌套的层数决定的,所以,算法中如果能够减少循环嵌套的层数,如将双重循环改写成单循环,则从事件复杂度上可达到降价的目的。

      ②加速原理。是指将循环体内的选择结构去掉,则加速循环结构的执行效率。

      ③代码外提。是指将循环体中与循环变量无关的运算提出,并将其放到循环之外,以避免每次循环过程中的重复操作。

      ④变换循环控制条件。当某循环变量在循环体中除自身引用外,已不再控制循环过程时,可以将其从循环中删去。

      ⑤合并循环。把两个或两个以上的循环合并放到一个循环里,这样会加快速度。使用循环虽然简单,但是使用不当,往往可能带来很大的性能影响。原则是将问题充分分解为小的循环,不在循环内的多余的工作(如赋值、常量计算等),避免死循环。还可以考虑将循环改为非循环来提高效率。

  二、局部优化

    1.使用尽量小的数据类型

      能够使用字符型(char)定义的变量,就不要使用整型(int)变量来定义;能够使用整型变量定义的变量就不要使用长整型(long int),能不使用浮点型(float)就不要使用浮点型变量。当然,在定义变量后不要超过变量的作用范围,如果超过变量的范围赋值,C编译器并不报错,但程序运行结果却错了,而且这样的错误很难发现。

    2.优化表达式

      对于一个表达式中各种运算执行的优先顺序不太明确或容易混淆的地方,应当采用圆括号明确指定他们的优先顺序。一个表达式通常不能写的太复杂,如果表达式太复杂,时间久了,自己也不容易看得懂,不利于以后的维护。

    3.使用自增、自减和复合赋值运算符

      通常使用自增、自减运算符和复合赋值表达式(如a-=1及a+=1等)都能够生成高质量的程序代码,编译器通常都能够生成inc和dec之类的指令,而使用a=a+1或a=a-1之类的指令,有很多C编译器都会生成二到三个字节的指令。

    4.使用运算量较小(但功能相同)的表达式代替复杂的表达式可以减少运算的强度。例如平方运算:a=pow(b,2.0)优化为:a=b*b。

    5.避免浮点运算。C语言中的浮点型float和双精度型double运算比短整型、整型、长整型运算要慢得多,因此避免浮点运算就非常有必要。

    6.优化赋值语句。在代码中,若一个变量经赋值后在后面语句的执行过程中不再引用,则这一赋值语句就称为无用赋值,可以不用。当赋值语句中出现多个已知量的运算时,可以将其合并成一个值,减少程序执行过程中重复计算的工作量。

    7.优化函数参数。在C语言中,调用函数的第一步是传递参数给寄存器或堆栈。当函数的参数很多时,就要调用大量的堆栈空间,开销会很大。当结构作为函数参数传递的内容时,编译器的第一步操作是把整个结构复制到堆栈,这种情况下堆栈空间的使用会非常大。此外,如果结构作为函数返回值,调用程序会把堆栈空间保留,把结构地址传递给函数同时调用函数,接着把函数返回。最后,调用程序需要把堆栈空间清除,并把返回的结构拷贝到第二个结构当中。这样代码和堆栈的开销就会非常惊人。因此应禁止传递结构,一般用结构指针作为函数的参数,来避免这种开销。

    8.宏的使用

    在程序设计过程中,对于经常使用的一些常数,如果将它直接写到程序中去,一旦常数的数值发生变化,就必须逐个找出程序中所有的常数,并逐一进行修改,这样必然会降低程序的可维护性。因此,应该采用预处理命令中的宏定义,而且还可以避免输入错误。

    宏定义除了一些大家所熟知的好处外,如可以提高程序的清晰性、可读性,便于修改移植等,还有一个很妙的地方:利用宏定义来代替函数可以提高程序设计的效率。

算法优化中的注意事项:

    1.程序的优化以不破坏程序的可读性、可理解性为原则。

    2.如果将程序的执行效率纳入软件的整个生命周期来考虑,为提高单个程序的效率而花费大量的开发时间往往得不偿失,在下列情况下,程序的优化才有意义。

      ①首先保证程序的正确性和健壮性,然后才考虑优化。

      ②严重影响效率的程序才值得优化。例如系统反复调用的核心模块,无关大局的模块没有优化的价值。

摘自《算法设计方法与优化》

      

      

算法的优化(C语言描述),布布扣,bubuko.com

时间: 2024-12-24 22:11:24

算法的优化(C语言描述)的相关文章

《算法精解 C语言描述》

算法设计的一般方法 随机法依赖于随机数的统计特性.一个应用随机法的例子是快速排序. 分治法 动态规划 贪心法 近似法——旅行商问题 指针 在C语言中,通常声明一个void指针来表示泛型指针. 对于泛型指针来说类型转换非常重要,因为只有告诉泛型指针通过何种类型来访问地址时,泛型指针才能正确取到值.这是由于泛型指针不会告诉编译器它指向的是何种类型数据,因此编译器不知道多少个字节要被访问.也不知道应该如何解析字节. 函数指针是指向可执行代码段或调用可执行代码段的信息块的指针. 例如,在下面一段代码中,

数据结构、算法与应用c++语言描述--1.5习题总结

习题1-5:编写一个函数iota,实现a[i]=a[i]+value(0<=i<n) 思路1:这个题目看起来非常简单,就是给每一个数组元素再加上一个值就可以了.这里面涉及到了判断数组的边界,毕竟数组传给函数的时候会退化成指针.因此当然的联想到1-2习题的方式,采用引用传递的方式实现. 实现1: template <class T> void iota_error(T &a,const T & value) {// Set a[i] = a[i] + value, 0

《数据结构与算法分析:C语言描述》复习——第十章“算法设计技巧”——Alpha-Beta剪枝

2014.07.08 22:43 简介: “搜索”与“剪枝”几乎是如影随形的.此处的“搜索”指的是带有回溯算法的深度优先搜索. 在之前的“Minimax策略”中我们给出了一个三连棋的程序,运行后你就知道计算一步棋要花多少时间. 为了计算最优的一步棋,我们可能需要递归9万多次.如果毫无疑问这种阶乘式的穷举过程必须通过剪枝来加速. 本篇介绍一种用于Minimax策略的剪枝思路——α-β剪枝. 剪枝的英语是pruning,所以不要想当然说成trimming. 图示: 在上一篇讲解Minimax策略的博

基于BP神经网络的简单字符识别算法自小结(C语言版)

本文均属自己阅读源码的点滴总结,转账请注明出处谢谢. 欢迎和大家交流.qq:1037701636 email:[email protected] 写在前面的闲话: 自我感觉自己应该不是一个很擅长学习算法的人,过去的一个月时间里因为需要去接触了BP神经网络.在此之前一直都认为算法界的神经网络.蚁群算法.鲁棒控制什么的都是特别高大上的东西,自己也就听听好了,未曾去触碰与了解过.这次和BP神经网络的邂逅,让我初步掌握到,理解透彻算法的基本原理与公式,转为计算机所能识别的代码流,这应该就是所谓的数学和计

《数据结构与算法分析:C语言描述》复习——第五章“堆”——二叉堆

2014.06.15 22:14 简介: 堆是一种非常实用的数据结构,其中以二叉堆最为常用.二叉堆可以看作一棵完全二叉树,每个节点的键值都大于(小于)其子节点,但左右孩子之间不需要有序.我们关心的通常只有堆顶的元素,而整个堆则被封装起来,保存在一个数组中. 图示: 下图是一个最大堆: 实现: 优先队列是STL中最常用的工具之一,许多算法的优化都要利用堆,使用的工具就是优先队列.STL中的优先队列通过仿函数来定义比较算法,此处我偷懒用了“<”运算符.关于使用仿函数的好处,我之后如果有时间深入学习S

《数据结构与算法分析:C语言描述》复习——第四章“树”——AVL树

2014.06.15 16:22 简介: AVL树是一种高度平衡的二叉搜索树,其命名源自于联合发明算法的三位科学家的名字的首字母.此处“平衡”的定义是:任意节点的左右子树的高度相差不超过1.有了这个平衡的性质,使得AVL树的高度H总是接近log(N),因此各种增删改查的操作的复杂度能够保证在对数级别.没有bad case是AVL树与普通的二叉搜索树的最大区别.为了实现平衡性质,我们需要记录每个节点的高度(或者平衡因子)来检测不平衡的情况.为了修正高度不平衡,需要用到“旋转”的方法,分为单旋转和双

《数据结构与算法分析—C语言描述》pdf

下载地址:网盘下载 内容简介 编辑 <数据结构与算法分析:C语言描述(原书第2版)>内容简介:书中详细介绍了当前流行的论题和新的变化,讨论了算法设计技巧,并在研究算法的性能.效率以及对运行时间分析的基础上考查了一些高级数据结构,从历史的角度和近年的进展对数据结构的活跃领域进行了简要的概括.由于<数据结构与算法分析:C语言描述(原书第2版)>选材新颖,方法实用,题例丰富,取舍得当.<数据结构与算法分析:C语言描述(原书第2版)>的目的是培养学生良好的程序设计技巧和熟练的算

《数据结构与算法分析:C语言描述》复习——第六章“排序”——冒泡排序

2014.06.17 01:04 简介: 冒泡排序是O(n^2)级别的交换排序算法,原理简单,属于必知必会的基础算法之一. 思路: 排序要进行N轮,每一轮从尾部逐个向前扫描,遇到逆序对就进行交换.确保每一轮把最小的元素交换到前面去.这个过程好比水中的气泡向上飘,所以叫冒泡排序.代码非常简单,所以语言描述反而显得麻烦了. 实现: 1 // My implementation for bubble sort. 2 #include <iostream> 3 #include <vector&

java算法插入排序优化代码

原文:java算法插入排序优化代码 代码下载地址:http://www.zuidaima.com/share/1550463280630784.htm 一个细节让插入排序更具效率 运行此方法需要为main方法传递参数 package com.zuidaima.sort; /** *@author www.zuidaima.com **/ public class TestSort { public static void main(String args[]){ int l = args.len