一、程序的基本结构
1.顺序执行
2.循环结构
从数据结构方面看,涉及线性表的遍历和查找操作,一般都会用到循环结构,比如多项式求和算法和各种排序算法
如果算法操作的数据结构是二维数组,通常都会用到两重循环,但是也可以用单循环遍历二维数组
递归:递归通常可以用复杂一点的循环形式代替,特别是尾递归形式,可以直接替换成循环结构。递归结构一般由递归关系定义和递归终止条件组成
对于树和图,递归方法具有比循环形式更大的优势,eg:二叉树查找算法
尾递归的定义是一个函数里的最后一个动作是调用一个函数的情形,这个函数调用的返回值直接被当前函数作为返回值
上文的FindTNode()函数就是尾递归,可以很容易地将其转化为循环形式
递归结构的缺点:
3.分支和跳转结构
根据对条件的判断,选择合适的处理步骤,是算法实现过程中常用的逻辑
switch-case结构的优缺点:
二、算法与数据结构之间的关系
常说的数据结构主要包含了两层意思:
1)指相互之间存在某种特定关系的数据的集合
2)数据之间的相互关系,也就是数据的逻辑结构。eg:线性结构、关联结构(集合、映射),树形结构和图形结构
1.数组
2.链表
3.栈
4.队列
队列的应用:
1)可以在队列的两端都执行“入队”和“出队”cao'操作的双端队列(double-ended queue),给每个数据元素打上优先级标签的优先级队列(priority queue)
2)图的广度优先搜索算法,使用一个队列存放与当前搜索节点有边相连的所有邻接点
3)操作系统中的线程调度算法,使用带优先级的队列管理就绪线程列表,高优先级的线程插入在队列的前端,获得优先调度的机会(出队)。
4)队列也是不同速率的IO设备之间缓冲区管理的常用方式,eg:打印机打印速度比较慢,操作系统会为每个打印机维护一个打印队列,对不同进程提交的打印操作做入队管理,可以避免因一个大文件打印时间过长造成其它进程无法提交打印操作的问题
5)网络设备中也普遍使用队列来管理数据报文的发送和接收,以匹配不同速率的设备之间的数据传输
接下来是一些复杂数据结构
1 树
一些常用概念:
树的应用:
自由树与有序树
根据每个节点的子节点的数量,又可以将树分为二叉树和多叉树,B树就是一种典型的多叉树
有序的二叉树也被称之为二叉搜索树(binary search tree)或者二叉排序数(binary sort tree)
二叉查找树的特点有:
1)
)))
2)
3)
4)如果构造二叉查找树时依次插入的节点已经是有序的,则二叉树会退化为链表形式的单支树
这种情况的查找效率很下降,所以又设计了AVL树和红黑树(具有自平衡功能,保证二叉树始终是一颗平衡树)
二叉查找树的应用:
1)决策问题,可以使用二叉查找树构造决策树
2)统计问题,可以使用二叉查找树的形式组织各种信息数据节点
其它一些树
1)多叉树
用处:常用于文件管理系统和数据库系统,若遇到多路分支且有序的层次结构时,可以考虑用B树
2)区间树
用处:区间树常用于区间查询相关的问题,eg:各个区间之间是否存在重叠区域等问题
3)线段树
应用:
4)堆
5)字典树
2.集合
3.哈希表与映射
在C++ 的STL库中,
std::hash_map采用一个哈希函数实现从关键字到值的映射关系,数据的插入、删除和查找的时间复杂度都是O(1);
std::map则是采用红黑树实现关键字和值的存储,数据的插入、删除和查找的时间复杂度都是
哈希表的应用:
学生成绩管理系统会通过一个唯一分配的学号建立与具体学生信息的映射关系,可以通过学号查询和管理学生信息
4图
图的遍历方法:深度优先搜索和广度优先搜索
1)
深度优先搜索的伪代码
//从第v个定点出发递归地深度优先遍历图G
void DFS(Graph G,int v)
{
visitfunction(v);//访问v点,并将其标记为访问过的节点
for_each(vi:v的所有邻接点)//遍历v的所有邻接点
{
if(vi没有被访问过)
DFS(G,vi);
}
}
2)
伪代码
void BFS(Graph G,int v)
{
for_each(vi:v的所有邻接点)//遍历v的所有邻接点
{
if(vi木有被访问过)
{
visitfunction(vi);//访问v点
enqueue(q,vi);//vi入队
}
}
while(!queueempty(q))//如果队列q不为空
{
dequeue(q,u);//将队头元素出队并置为u
BFS(G,u);
}
}
应用: