数据结构和算法
数据结构和算法经常拿到一起谈,两者之间有什么联系呢?
在算法设计时先要确定相应的数据结构,而在讨论一种数据结构时也必然会涉及实现一定功能的算法。
算法
算法是解决某一特定问题的具体步骤的描述,是指令的有限序列。
评价一个算法的好坏一般从四个方面进行:
- 正确性
- 运行时间
- 占用空间
- 易读性
在竞赛中,尤其要注意算法耗费的储存空间是否到达上限。
数据结构
基础的数据结构,包括线性表(栈、队列、链表)以及树、图。
线性表
线性表是最简单、最基本、也是最常用的一种线性结构,它是具有相同数据类型的n个数据元素的有限序列,有两种存储方式:顺序存储和链式存储。
顺序表
顺序表:线性表的顺序存储是指在内存中用地址连续的一块存储空间顺序存放线性表的各元素,用这种存储形式存储的线性表称为顺序表。
顺序表的简单数组实现:
顺序表的初始化:
顺序表的初始化即构造一个空表,这对表是一个加工型的运算,因此,将L设为指针参数,首先动态分配存储空间,然后,将表中last指针置为-1,表示表中没有数据元素。
顺序表插入运算图示:
顺序表删除运算图示:
顺序表按值查找:
线性表中的按值查找是指在线性表中查找与给定值x相等的数据元素。在顺序表中完成该运算最简单的方法是:从第一个元素a1起依次和x比较,直到找到一个与x相等的数据元素,则返回它在顺序表中的存储下标或序号;或者查遍整个表都没有找到与x相等的元素,返回-1。
顺序表在进行元素的插入和删除操作时,会引起大量数据的移动,数据处理比较复杂。为了解决这些问题,有一种称为链表的数据结构。
链表
链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行过程中动态的生成。每个结点包括两个部分:一个是存储数据元素的数据域(元素本身);另一个是存储下一个结点地址的指针域(记录下一个数据的地址)。
链表对于数据插入、删除不需要移动数据元素,只需要修改”链“,但是链表由于增加了结点的指针域,空间开销比较大。
单向链表
用一组任意的存储单元存储线性表的数据元素,利用指针实现了用不相邻的存储单元存放逻辑上相邻的元素。
单链表的删除结点操作可以通过修改一个指针来实现。
插入操作如下图所示:
单向链表在查找元素的时候,从某个结点出发只能顺指针往后去寻查其他的结点,为了克服单链表的单向性的缺点,产生了双向链表。
双向链表
双向链表在每个结点前再加一个指向前驱的指针域,结点的结构如下图所示:
双向链表增加了对空间的需求,使得插入和删除的运行时间多了一倍,但是它却简化了删除操作,因为使用一个指向前驱元的指针来访问关键字就不是必须的。
循环链表
对于单链表,最后一个结点的指针域是空的,如果把该链表头指针置入该指针域,则使得链表头尾结点相连,就构成了单循环链表。
栈和队列
栈和队列是两类特殊的线性表,对它们进行插入和删除元素时只能在表的两端进行。
栈:限定仅在表尾进行插入或删除操作的线性表,表尾-栈顶,表头-栈底,不含元素的空表称空栈。是符合“后进先出”规则的数据结构。
队列:队列是限定只能在表的一端进行插入,在表的另一端进行删除的线性表。
队尾-允许插入的一端
队头-允许删除的一端
树和二叉树
树是n个节点的有限集,在任意一棵非空树中:(1)有且仅有一个特定的称为根的节点(2)当n>1时,其余节点可分为m个互不相交的有限集T1,T2,…,Tm,其中每一个集合本身又是一棵树,并且称为根的子树。
树的特点:
1.树的根结点没有前驱结点,除根结点以外的所有结点有且只有一个前驱结点。
2.树的所有结点可以有零个或多个后继结点。
- 节点的度:节点拥有的子树被称为节点的度
- 叶子或终端节点:度为0的节点
- 节点的孩子:节点的子树的根
- 孩子的双亲:该节点
- 兄弟:同一个双亲的孩子
- 节点的祖先:从根到该节点所经分支上的所有节点
二叉树:是一种树型结构,其中每个节点至多有两棵子树(即二叉树中不存在度大于2的节点),二叉树的子树有左右之分,其次序不能任意颠倒。
- 二叉树的路径长度PL:从树根到每一个叶结点的路径长度之和
- 结点的权:将树中结点赋予一个有某种意义的实数
- 结点的带权路径长度:是该结点到树根之间的路径长度与结点上权的乘积
- 二叉树的带权路径长度:树中所有叶子结点的带权路径长度之和
哈夫曼树(HUFFMAN)
又称最优二叉树,指对于一组带有确定权值的叶结点构造的具有最小带权路径长度的二叉树
根据哈夫曼树的定义,一棵二叉树要使其WPL值最小,必须使权值越大的叶结点越靠近根结点,而权值越小的叶结点越远离根结点。
图
图的简单描述
图G是由两个集合V(G)和E(G)组成的,记为G = (V, E)
,其中:V(G)是顶点的非空有限集,E(G)是边的有限集合,边是顶点的无序对或有序对。
有向图中的E(G)是有向边的有限集合,无向图中的E(G)是边的有限集合。
5. 权:与图的边或弧相关的数据信息
6. 网:带权的图
7. 子图:如果图G(V,E)和G1(V1,E1)满足:
8. V1是V的子集,E1是E的子集,则称G1为G的子图。
无向图中,顶点的度为与每个顶点相连的边数;
有向图中,顶点的度分为入度和出度
- 入度:以该顶点为头的弧的数目
- 出度:以该顶点为尾的弧的数目
- 路径:路径是顶点的序列
- 路径长度:沿路径边的数目或沿路径各边权值之和
- 简单路径:序列中顶点不重复出现的路径
- 回路:顶点序列中存在vp = vq的路径
- 简单回路:除了第一个顶点和最后一个顶点外,其余顶点不重复出现的回路
- 连通:从顶点V到顶点W有一条路径,则说V和W是连通的
- 强连通图:有向图中,如果任意一对顶点Vi和Vj间存在一条从Vi到Vj的路径和一条从Vj到Vi的路径,则称G是强连通图
图的存储结构
- 邻接矩阵:表示顶点间相联关系的矩阵
定义:设G = (V, E)
是有n>=1个顶点的图,G的邻接矩阵A是具有以下性质的n阶方阵
- 邻接表(Adjacency List):图的一种顺序存储和链式存储结合的存储方法。对于图G中的每个顶点vi,将所有邻接于vi的顶点vj链成一个单链表,这个单链表就称为顶点vi的邻接表,再将所有点的邻接表表头放到数组中,就构成了图的邻接表。
本篇博文参考资料:
《算法竞赛入门经典》
浙江大学数据结构课件