一、算法的基本定义
1、有穷性
2、确定性:对于每种情况下所应执行的操作,在算法中都有确切的规定,不会产生二义性,使算法的执行者或者阅读者都能明确其含义及如何执行
3、可行性
4、输入
5、输出
二、算法的评价标准
1、正确性
2、可读性
3、健壮性
4、高效性
三、算法的时间复杂度
一个语句的重复执行次数称作语句频度
T(n) = O(f(n))
它表示随着问题规模n的增大,算法的执行时间的增长率和f(n)的增长率相同,称作算法的渐进时间复杂度,简称时间复杂度
常见的时间复杂度按数量级递增排列依次为:
常量阶O(1)<对数阶O(log2n)<线性阶O(n)<线性对数阶O(nlog2n)<平方阶O(n2)<立方阶O(n3)<k次方阶O(nk)<指数阶O(2n)
四、算法的空间复杂度
空间复杂度作为算法所需存储空间的量度。
五、顺序表和链表的比较
1、空间性能的比较:
顺序表的存储空间必须预先分配,元素的个数扩充收到一定限制,易造成存储空间浪费或空间溢出现象;
而链表不需要为其预先分配空间,只要内存空间允许,链表中的元素个数就没有限制。
因此,当线性表的长度变化较大,难以预估存储规模时,宜采用链表作为存储结构。
2、存储密度的定义
存储密度 = 数据元素本身占用的存储量 / 结点结构占用的存储量
顺序表的存储密度为1,单链表的存储空间利用率仅为50%
因此:当线性表的长度变化不大,易于事先确定其大小时,为了节约存储空间,宜采用顺序表作为存储结构。
3、时间性能比较:
(1)存取元素的效率:
顺序表时间复杂度为O(1)
链表时间复杂度为O(n)
因此若线性表的主要操作是和元素位置紧密相关的这类取值操作,很少做插入或删除时,宜采用顺序表作为存储结构。
(2)插入和删除操作的效率
对于链表,在确定插入或删除的位置后,插入或删除无需移动数据,只需要修改指针即可时间复杂度为O(1)
对于顺序表,则在进行插入或删除时,平均要移动表中近一半的结点,时间复杂度为O(n)
因此:对于频繁进行插入或删除操作的线性表,宜采用链表作为存储结构。
六、栈和队列的比较
栈后进先出
队列先进先出
七、递归算法
Hanoi塔问题:可以使用递归解决
递归的效率分析:
时间复杂度:使用递归方法解决Hanoi塔问题时时间复杂度为O(2n)
空间复杂度为O(n)
八、二叉树的性质和存储结构
二叉树的性质:
1、在二叉树的第i层上至多有2i-1结点(i>=1)
2、深度为k的二叉树至多有2k-1个结点(k>=1)
3、对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点数为n2 ,则n0 = n2+1。
4、完全二叉树即缺了部分的满二叉树,缺少的部分为连续的右边。
二叉树的存储结构:
顺序存储结构:顺序存储结构只适合完全二叉树。其他的二叉树则有点浪费空间
一般二叉树适合链式存储结构。
遍历二叉树:
前序遍历:根结点=》左结点=》右结点
中序遍历:左结点=》根结点=》右结点
后序遍历:左结点=》右结点=》根结点
无论哪种遍历:时间复杂度均为O(n),空间复杂度为O(n)
由二叉树的先序遍历和中序遍历或者后序遍历和中序遍历均可以唯一的确定一棵二叉树。
但是先序遍历和后序遍历不可以唯一确定一棵二叉树。
九、哈夫曼树及哈夫曼编码
哈夫曼树又称最优树,是一类带权路径长度最短的树,生成哈夫曼树算法是一种典型的贪心法。
用途:哈夫曼编码。?
哈夫曼编码的性质:
哈夫曼编码是前缀编码。
哈夫曼编码是最优前缀编码。
十、图的遍历
1、广度优先遍历
(1)从图中某个顶点v出发,访问v
(2)依次访问v的各个未曾访问过的邻接点。
(3)分别从这些邻接点出发依次访问它们的琳接点,并使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问。重复步骤3,直至图中所有已被访问的顶点的邻接点都被访问到。
使用邻接矩阵存储时,时间复杂度为O(n2);当以邻接表做存储数据结构时,时间复杂度为O(n+e)
2、深度优先遍历
(1)从图中某个顶点v出发,访问v。
(2)找到刚访问过的顶点的第一个未被访问的邻接点,访问该顶点。以该顶点为新顶点,重复此步骤,直至刚访问过的顶点没有未被访问的邻接点为止。
(3)返回前一个访问过且仍有未被访问的邻接点的顶点,找出该顶点的下一个未被访问的邻接点,访问该顶点。
(4)重复步骤(2)(3),直至图中所有顶点都被访问过。搜索结束。
使用邻接矩阵存储时,时间复杂度为O(n2);当以邻接表做存储数据结构时,时间复杂度为O(n+e)
十一、最小生成树
普里姆算法(加点法):时间复杂度为O(n2)与边数无关
克鲁思卡尔算法(加边法):时间复杂度为O(elog2e)与网中边数e有关,更适合求稀疏网的最小生成树。
十二、最短路径
迪杰斯特拉算法:找到从源点到某一个特定终点的最短路径,时间复杂度O(n2)
弗洛伊德算法
如果是求每一对顶点之间的最短路径,则有两种方法:
其一、是分别以图中的每个顶点作为源点共调用n次迪杰斯特拉算法;
其二、是使用弗洛伊德算法。
两种算法的时间复杂度均为O(n3),但后者形式较简单
十三、线性表的查找
顺序查找:从表的一端开始,依次将记录的关键字和给定的值进行比较,若相等,则查找成功。反之,扫描整个表后仍未找到关键字和给定值相等的记录,则查找失败。时间复杂度为O(n)
折半查找:二分查找。时间复杂度为O(log2n)。但折半查找只使用于有序表,且限于顺序存储结构。
分块查找:索引顺序查找,性能介于顺序查找和折半查找。
分块查找的优点:插入删除数据比较容易,不需要进行大量移动。如果线性表既要快速查找,又要经常动态变化,则采用分块查找。
分块查找的缺点:要增加一个索引表的存储空间并对初始索引表进行排序运算。
十四、插入排序
直接插入排序:基本操作是将一条记录插入到已排好序的有序表中,从而得到一个新的、记录数增1的有序表。时间复杂度为O(n2),空间复杂度为O(1)。适用于顺序结构和链式结构。比较适合于初始记录基本有序的情况,当初始记录无序,n较大时,此算法时间复杂度较高。
折半插入排序:只适用于顺序结构时间复杂度和空间复杂度与直接插入排序相同。但是折半查找比顺序查找快,所以就平均性能来说,折半插入排序优于直接插入排序。
十五、堆排序
堆排序的运行时间主要耗费在建初堆和调整堆时进行反复的“筛选”上。
堆排序的最坏情况下时间复杂度为O(nlog2n)。空间复杂度为O(1),只能用于顺序结构,不能用于链式结构。
堆排序图解:可以查看https://www.cnblogs.com/chengxiao/p/6129630.html