算法设计与分析第一周

算法设计与分析

第1章 概述

1.1 算法的概念
1.1.1 什么是算法
算法是求解问题的一系列计算步骤,用来将输入数据转换成输出结果 :
在这里插入图片描述

如果一个算法对其每一个输入实例,都能输出正确的结果并停止,则称它是正确的。

算法设计应满足以下几条目标:
1.正确性:
  算法的正确性是指算法至少应该具有输入、输出和加入处理无歧义性、能正确反映问题的需求。能够得到问题的正确答案。 但是算法的“正确”通常在用法上有很大的差别,大体分为以下四个层次:
①算法程序没有语法错误。
②算法程序对于合法的输入数据能够产生满足要求的输出结果。
③算法程序对于非法的输入数据能够得到满足规格说明的结果。
④算法程序对于精心选择的,甚至刁难的测试数据都有满足要求的输出结果。
2.可使用性
3.可读性
算法设计另一目的是为了便于阅读,理解和交流
4.健壮性
  当输入数据不合法时,算法分也能作出相关处理而不是产生异常,崩溃或莫名其妙的结果。
5.高效率与低存储量需求
应该具备时间效率高和存储量低的特点。

算法具有以下5个重要特征:
1.有限性
2.确定性
3.可行性
4.输入性
5.输出性

1.1.2 算法描述
  通常用函数的返回值表示算法能否正确执行。
  有时当算法只有一个返回值或者返回值可以区分算法是否正确执行时,用函数返回来表示算法的执行结果,另外还可以带有形参表示算法的输入输出。
  在C语言中调用函数时只有从实参到形参的单向值传递,执行函数时若改变了形参而对应的实参不会同步改变。

例如,设计以下主函数调用上面的fun函数:
在这里插入图片描述
执行时发现输出结果为0,因为b对应的形参为s,fun执行后s=55,但s并没有回传给b。

在C语言中可以用传指针方式来实现形参的回传,但增加了函数的复杂性。

为此C++语言中增加了引用型参数的概念,引用型参数名前需加上&,表示这样的形参在执行后会将结果回传给对应的实参。上例采用C++语言描述算法如下所示。
在这里插入图片描述
当将形参s改为引用类型的参数后,执行时main函数的输出结果就正确了即输出55。

结论:在设计算法时,如果某个形参需要将执行结果回传给实参,需要将该形参设计为引用型参数。

1.1.3 算法和数据结构
算法与数据结构既有联系又有区别。
联系:数据结构是算法设计的基础。算法的操作对象是数据结构,在设计算法时,通常要构建适合这种算法的数据结构。数据结构设计主要是选择数据的存储方式,如确定求解问题中的数据采用数组存储还是采用链表存储等。算法设计就是在选定的存储结构上设计一个满足要求的好算法。

区别:数据结构关注的是数据的逻辑结构、存储结构以及基本操作,而算法更多的是关注如何在数据结构的基础上解决实际问题。算法是编程思想,数据结构则是这些思想的逻辑基础。

1.1.4 算法设计的基本步骤
在这里插入图片描述
1.2 算法分析
  算法分析是分析算法占用计算机资源的情况,所以算法分析的两个主要方面是分析算法的时间复杂度和空间复杂度。
1.2.1 算法时间复杂度分析
1.时间复杂度分析概述
  一个算法是由控制结构(顺序、分支和循环3种)和原操作(指固有数据类型的操作)构成的,算法的运行时间取决于两者的综合效果。
  设n为算法中的问题规模,通常用大O、大Ω和Θ等三种渐进符号表示算法的执行时间与n之间的一种增长关系。
分析算法时间复杂度的一般步骤 :
在这里插入图片描述
2. 渐进符号(O、Ω和Θ)
在这里插入图片描述
  大O符号用来描述增长率的上界,表示f(n)的增长最多像g(n) 增长的那样快,也就是说,当输入规模为n时,算法消耗时间的最大值。这个上界的阶越低,结果就越有价值,所以,对于10n2+4n+2,O(n2)比O(n4) 有价值。
   一个算法的时间用大O符号表示时,总是采用最有价值的g(n)表示,称之为“紧凑上界”或“紧确上界”。
 一般地,如果f(n)=amnm+am-1nm-1+…+a1n+a0,有f(n)=O(nm)。

在这里插入图片描述
  大Ω符号用来描述增长率的下界,表示f(n)的增长最少像g(n) 增长的那样快,也就是说,当输入规模为n时,算法消耗时间的最小值。
  与大O符号对称,这个下界的阶越高,结果就越有价值,所以,对于10n2+4n+2,Ω(n2)比Ω(n) 有价值。一个算法的时间用大Ω符号表示时,总是采用最有价值的g(n)表示,称之为“紧凑下界”或“紧确下界”。
  在这里插入图片描述
  一般地,如果f(n)=amnm+am-1nm-1+…+a1n+a0,有f(n)=(nm)。
  大Θ符号比大O符号和大Ω符号都精确,f(n)=Θ(g(n)),当且仅当g(n)既是f(n)的上界又是f(n)的下界。
在这里插入图片描述
3. 算法的最好、最坏和平均情况
在这里插入图片描述
在这里插入图片描述
4. 非递归算法的时间复杂度分析
在这里插入图片描述5. 递归算法的时间复杂度分析
  递归算法是采用一种分而治之的方法,把一个“大问题”分解为若干个相似的“小问题”来求解。
  对递归算法时间复杂度的分析,关键是根据递归过程建立递推关系式,然后求解这个递推关系式,得到一个表示算法执行时间的表达式,最后用渐进符号来表示这个表达式即得到算法的时间复杂度。

1.2.2 算法空间复杂度分析
  一个算法的存储量包括形参所占空间和临时变量所占空间。在对算法进行存储空间分析时,只考察临时变量所占空间。

  
  
1.3 算法设计工具―STL
  STL主要由container(容器)、algorithm(算法)和iterator(迭代器)三大部分构成,容器用于存放数据对象(元素),算法用于操作容器中的数据对象。
在这里插入图片描述
1.3.1 STL概述

  1. 什么是STL容器
      一个STL容器就是一种数据结构,如链表、栈和队列等,这些数据结构在STL中都已经实现好了,在算法设计中可以直接使用它们。
    在这里插入图片描述
    为此,使用STL时必须将下面的语句插入到源代码文件开头:
      using namespace std;
    这样直接把程序代码定位到std命名空间中。
  2. 什么是STL算法
      STL算法是用来操作容器中数据的模板函数,STL提供了大约100个实现算法的模版函数。例如,STL用sort()来对一个vector中的数据进行排序,用find()来搜索一个list中的对象。
      STL算法部分主要由头文件algorithm 、numeric和functional组成。
  3. 什么是STL迭代器
    STL迭代器用于访问容器中的数据对象。
    每个容器都有自己的迭代器,只有容器自己才知道如何访问自己的元素。
    迭代器像C/C++中的指针,算法通过迭代器来定位和操作容器中的元素。
    常用的迭代器有:
    iterator:指向容器中存放元素的迭代器,用于正向遍历容器中的元素。
    const_iterator:指向容器中存放元素的常量迭代器,只能读取容器中的元素。
    reverse_iterator:指向容器中存放元素的反向迭代器,用于反向遍历容器中的元素。
    const_reverse_iterator:指向容器中存放元素的常量反向迭代器,只能读取容器中的元素。
    1.3.2 常用的STL容器
    1.顺序容器
    1)vector(向量容器)
    它是一个向量类模板。向量容器相当于数组。
    用于存储具有相同数据类型的一组元素,可以从末尾快速的插入与删除元素,快速地随机访问元素,但是在序列中间插入、删除元素较慢,因为需要移动插入或删除处后面的所有元素。
    2)string(字符串容器)
    string是一个保存字符序列的容器,所有元素为字符类型,类似vector。
    除了有字符串的一些常用操作以外,还有包含了所有的序列容器的操作。字符串的常用操作包括增加、删除、修改、查找比较、连接、输入、输出等。
    关联容器。
    3)deque(双端队列容器)
    它是一个双端队列类模板。双端队列容器由若干个块构成,每个块中元素地址是连续的,块之间的地址是不连续的,有一个特定的机制将这些块构成一个整体。可以从前面或后面快速插入与删除元素,并可以快速地随机访问元素,但删除元素较慢。
    4)list(链表容器)
    它是一个双链表类模板。可以从任何地方快速插入与删除。它的每个结点之间通过指针链接,不能随机访问元素。

2 关联容器
1)set(集合容器)/ multiset(多重集容器)
   set和multiset都是集合类模板,其元素值称为关键字。set中元素的关键字是唯一的,multiset中元素的关键字可以不唯一,而且默认情况下会对元素按关键字自动进行升序排列。
  查找速度比较快,同时支持集合的交、差和并等一些集合上的运算,如果需要集合中的元素允许重复那么可以使用multiset。
2)map(映射容器)/ multimap(多重映射容器)
   map和multimap都是映射类模板。映射是实现关键字与值关系的存储结构,可以使用一个关键字key来访问相应的数据值value。
   在set/multiset中的key和value都是key类型,而key和value是一个pair类结构。
pair类结构的声明形如:
在这里插入图片描述
4. 适配器容器
1)stack(栈容器)它是一个栈类模板,和数据结构中的栈一样,具有后进先出的特点。栈容器默认的底层容器是deque。也可以指定其他底层容器。

2)queue(队列容器)
它是一个队列类模板,和数据结构中的队列一样,具有先进先出的特点。不允许顺序遍历,没有begin()/end()和rbegin()/rend()这样的用于迭代器的成员函数。

3)priority_queue(优先队列容器)
它是一个优先队列类模板。优先队列是一种具有受限访问操作的存储结构,元素可以以任意顺序进入优先队列。
一旦元素在优先队列容器中,出队操作将出队列最高优先级元素。

1.3.3 STL在算法设计中的应用

  1. 存放主数据
    算法设计重要步骤是设计数据的存储结构,除非特别指定,程序员可以采用STL中的容器存放主数据,选择何种容器不仅要考虑数据的类型,还有考虑数据的处理过程。
    例如,字符串可以采用string或者vector来存储,链表可以采用list来存储。

  2. 存放临时数据
    在算法设计中,有时需要存放一些临时数据。通常的情况是,如果后存入的元素先处理,可以使用stack栈容器;
    如果先存入的元素先处理,可以使用queue队列容器;如果元素处理顺序按某个优先级进行,可以使用priority_queue优先队列容器。

  3. 检测数据元素的唯一性
    可以使用map容器或者哈希表容器检测数据元素是否唯一或者存放累计个数。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值