积累-数据结构与算法介绍

前言:
貌似程序员一直在说数据结构与算法,但是到底是什么才是数据结构与算法!?
以下是我自己整理的资料,对数据结构与算法有一个较为清晰的认识,希望能帮到大家。

一、 数据结构的分类与算法
1. 数据结构可以分为:
“数据的逻辑结构”:数据元素间的逻辑关系。
“数据的物理结构(存储结构)” :数据元素在内存中的存放方式。
2. 算法:
算法实际就是在具体的存储结构上,对数据元素进行的运算操作,如:检索、排序、插入、删除、修改等。

二、 图解
1. 数据的逻辑结构
这里写图片描述
2. 数据的存储结构
顺序存储:数据元素放在一片连续的存储单元中,逻辑上相邻的单元存放到计算机内存仍然相邻。
链接存储:所有数据元素存放在不连续的存储单元中,但元素之间的关系可以通过地址确定,逻辑上相邻的元素存放到计算机内存后不一定是相邻的。
索引存储:存放数据元素的同时,还要建立附加的索引表(关键字,地址),其中关键字是唯一能标识一个接点的数据项。
散列存储:通过构造散列函数,用函数的值来确定数据元素存放的地址。

  1. 数据的逻辑结构(现实中)采用哪种数据的存储结构(内存中),来适应开发中不同的情况,这就是数据结构!

三、 各种逻辑结构常用的哪种的存储结构,详解
1. 线性表
线性表是具有相同类型的n个(n>=0)个数据元素组成的有限序列。
存储方式
1.1 顺序存储
顺序存储以结点为单位,按结点在表中的次序依次存储,
结点在表中的逻辑次序和其在存储器中的物理次序一致。
如(array数据,arrayList等)
1.2 链式存储
每个表元素对应链表的一个结点,结点含有值域和链域。
值域用以存储表元素,链域用于存储结点后继结点的存储
地址,最后一个结点的链域为空,无后继结点。
如(linkedList)
1.3 顺序表(采用顺序存储的表)的优缺点
优点:适合随机存储和提取,直接找到第n个元素
缺点:插入、删除元素时,需移动大量数据,耗费大量时间。使用前需要一次性分配固定大小的内存空间,且容量难以扩充。
1.4 链表(采用链式存储的表)
1.线性表的链式存储表示,即用一组任意的存储单元存储线
性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。
• 在存储结构中,数据结点地址不连续,插入删除时不移动结点。
• 链表使用指向结点(结构类型)的指针,在执行期间,调用动态存储管理函v数,产生结点,回收结点。
• 访问结点时,使用一个“滑动”的访问指针P,从表头结点出发可以逐个访问表中所有节点

四、 栈(先进后出,后来居上)
• 栈(Stack)也是一种线性结构,它的逻辑结构和线性表相同。
• 栈是按照“先进后出”的规则来操作的。
• 栈是在表的一端进行插入和删除操作,允许插入和删除操作的一端称为栈顶(top),另一端称为栈底
• 当表中没有元素时称为空栈。
• 栈的插入操作,称为入栈(push)。
• 栈的删除操作,称为出栈(pop)。
• 栈按物理存储结构分:顺序栈和链式栈。
这里写图片描述

  1. 利用顺序存储方式实现的栈称为顺序栈。
  2. 利用链式存储结构实现的栈称为链栈。它的结构与链表类似,用linkstack来表示

五、队列(先进先出)
• 队列(Queue)是只允许在一端进行插入,而在另一端进行删
除的运算受限的线性表。
• 允许删除的一端称为队头(Front)。
• 允许插入的一端称为队尾(Rear)。
• 当队列中没有元素时称为空队列。
• 队列亦称作先进先出(First In First Out)的线性表,简称为FIFO。
这里写图片描述

• 顺序存储结构称为顺序队列
顺序存储结构是在内存中开辟一个连续的空间用来存储数
据,因此对于内存的需求和苛刻,必须是连续的空间。
• 链式存储结构简称为链队列
链式存储结构是采取链表指针来指示数据的存储位置,这
就可以是在内存中随意的存储,没有必须连续储存空间的
要求。

五、 非线性结构 树和二叉树
1. 树:
• 树形结构是一种典型的非线性结构。
• 相对于仅可以表示数据元素之间一对一关系的线性结构,树形结构可以表示数据元素间一对多的关系。
基本概念和基本术语
• 树是n(n>=0)个节点的有限集。
• n=0时为空树。
• 在非空树中,有且仅有一个根节点。
• n=1时,只有一个根节点,n>1时,根节点无前驱节点,其余节点只有一个前驱节点,其余节点是互不相交的有限集,其中每一个有限集是符合本定义的树,称为根的子树

  1. 二叉树:树的度小于等于2的树为二叉树。
    • 满二叉树:一棵二叉树中,所有分支结点都有左孩子
    和右孩子结点,并且叶子节点集中在树的最下面一层。

    这里写图片描述

• 完全二叉树
二叉树中,最多只有最下面2层的结点的度数可以小于2,并且最下面一层的叶子结点都依次排在该层最左边的位置上。
这里写图片描述

二叉树的遍历
• 二叉树的遍历是指按照某种顺序访问二叉树中的每个结点,使每个结点被访问一次且仅被访问一次。
• 遍历方法
1. 先序访问。
(1) 访问根结点;
(2) 先序遍历左子树;
(3) 先序遍历右子树。
2.中序访问。
(1) 中序遍历左子树;
(2) 访问根结点;
(3) 中序遍历右子树。
3.后续访问。
(1) 后序遍历左子树;
(2) 后序遍历右子树;
(3) 访问根结点。
这里写图片描述
• 树形结构是一类非常重要的非线性结构,它可以很好的描述客观世界中广泛存在的具有分支关系或层次特性的对象,因此在计算机领域里有着广泛应用,如操作系统中的文件管理、编译程序中的语法结构和数据库系统信息组织形式等。

六、算法之查找(Search)
• 查找(Search) :
确定一个已给的数据是否出现在某个数据元素集合中。
• 查找(Searching)的定义是:
给定一个值K,在含有n个结点的表中找出关键字等于给定值K的结点。若找到,则查找成功,返回该结点的信息或该结点在表中的位置;否则查找失败,返回相关的指示信息。
• 查找的方法
1. 顺序查找
2. 二分查找(折半查找)
3. 分块查找
4. 二叉树查找(BST、B-树、B+树、B*树)
5. 哈希查找
• 按查找表的结构可将查找表分为静态查找表和动态查找表两类。
• 静态查找静态查找表是仅仅进行查询和检索操作,不改变查找表中数据元素间的逻辑关系的查找。
静态查找法主要有:顺序查找,折半查找,分块查找等。
• 动态查找动态查找表是除了进行查询和检索操作外,还对查找表进行插入、删除操作的查找,动态地改变查找表中数据元素之间的逻辑关系。
动态查找法主要有:二叉树查找,哈希查找。

  1. 顺序查找优缺点
    • 优点:
    算法简单,且对表的结构无任何要求,顺序查找方法既适用于线性表的顺序存储结构,也适用于线性表的链式存储结构(使用单链表作存储结构时,扫描必须从第一个结点开始)。
    • 缺点:
    查找效率低,因此,当n较大时不宜采用顺序查找。

  2. 二分查找优缺点
    • 优点:二分查找的查找效率非常高
    • 缺点:二分查找只适用顺序存储结构。为保持表的有序性,在顺序结构里插入和删除都必须移动大量的结点。因此,二分查找特别适用于那种一经建立就很少改动、而又经常需要查找的线性表。对那些查找少而又经常需要改动的线性表,可采用链表作存储结构,进行顺序查找。链表上无法实现二分查找。
    • 二分查找过程可用二叉树来描述,我们把当前查找区间的中间位置上的记录作为根,左子表和右子表中的记录分别作为根的左子树和右子树,由此得到的二叉树,称为描述二分查找的判定树或比较树。

  3. 分块查找

  4. 把表长为n的关键字线性表分成b块,前b-1块记录个数为s=n/b,第b块的记录个数小于等于s。
  5. 保证在每一块中,结点的存放不一定有序,但块与块之间必须是分块有序的(假定按结点的关键字值递增有序)。即指后一个块中所有记录的关键字值都应比前一个块中所有记录的关键字值大。
  6. 建立一个索引表。索引表的每个元素对应一个块,其中包括该块内最大关键字值和块中第一个记录位置的地址指针。

这里写图片描述
优缺点:
1. 有索引作用,在表中插入或删除一个记录时,只要找到该记录所属的块,就在该块内进行插入和删除运算。
2. 因块内记录的存放是任意的,所以插入或删除比较容易,无须移动大量记录。
• 分块查找的缺点
分块查找的主要代价是增加一个辅助数组的存储空间(构建索引表)和将初始表分块排序的运算(实现分块有序)

二叉查找树(BST)
• 为什么用二叉树?
1. 当用线性表作为表的组织形式时,可以有三种查找法。其中以二分查找效率最高。
2. 但由于二分查找要求表中结点按关键字有序,且不能用链表作存储结构,因此,当表的插入或删除操作频繁时,为维护表的有序性,势必要移动表中很多结点。这种由移动结点引起的额外时间开销,就会抵消二分查找的优点。
3. 二分查找只适用于静态查找表。若要对动态查找表进行高效率的查找,可以使用二叉树查找,是一种动态查找法。
4. BST能用链表作存储结构,实际上就是将数据元素组织成二叉树形式,以达到与二分法相同的查找效率,而又具有链表的插入、删除操作的灵活性。
• 二叉查找树(BST)的定义
二叉查找树又称做二叉排序树或二叉搜索树,其定义为:二叉查找树或者是空树,或者是满足下面性质的二叉树。

这里写图片描述
这里写图片描述
小结
1. BST:二叉查找树,每个结点只存储一个关键字,等於则命中,小于走左结点,大于走右结点;
2. B-树:多路搜索树,每个结点存储M/2到M个关键字,非叶子结点存储指向关键字范围的子结点;所有关键字在整颗树中出现,且只出现一次,非叶子结点可以命中;
3. B+树:在B-树基础上,为叶子结点增加链表指针,所有关键字都在叶子结点中出现,非叶子结点作为叶子结点的索引;B+树总是到叶子结点才命中;
4. B*树:在B+树基础上,为非叶子结点也增加链表指针,将结点的最低利用率从1/2提高到2/3;

哈希查找
• 基本概念
1. 哈希表(Hash Table)又称散列表,是除顺序表存储结构、链接表存储结构和索引表存储结构之外的又一种存储线性表的存储结构。
2.哈希表主要目的是用于解决数据的快速定位问题。哈希表是种数据结构,它可以提供快速的插入操作和查找操作。
3.哈希表在所有的线性数据结构中,数组的定位速度最快,因为它可通过数组下标直接定位到相应的数组空间,就不需要一个个查找。
• 哈希表存储的基本思路
设要存储的对象个数为n,设置一个长度为m(m≥n)的连续内存单元;以线性表中每个对象的关键字ki(0≤i≤n-1)为自变量,通过一个称为哈希函数的函数h(ki),把ki映射为内存单元的地址(或称下标)h(ki),并把该对象存储在这个内存单元中。这样,h(ki)称为哈希地址(又称散列地址)。
把如此构造的线性表存储结构称为哈希表。
• 哈希冲突
1. 构造哈希表但是存在这样的问题,对于两个关键字ki和kj(i≠j),有ki≠kj(i≠j),但h(ki)=h(kj)。我们把这种现象叫做哈希冲突。
2. 通常把这种具有不同关键字而具有相同哈希地址的对象称做“同义词”,由同义词引起的冲突称作同义词冲突。
• 在哈希表存储结构的存储中,同义词冲突是很难避免的;
• 除非关键字的变化区间小于等于哈希地址的变化区间,而这种情况当关键字取值不连续时是非常浪费存储空间的。
• 通常的实际情况是关键字的取值区间远大于哈希地址的变化区间。
小结
1. 哈希函数是一个映象,即:将关键字的集合映射到某个地址集合上,它的设置很灵活,只要这个地址集合的大小不超出允许范围即可;
2. 由于哈希函数是一个压缩映象,因此,在一般情况下,很容易产生“冲突”现象,即:
key1   key2,而 f(key1) = f(key2)。
3. 很难找到一个不产生冲突的哈希函数。一般情况下,只能选择恰当的哈希函数,
使冲突尽可能少地产生。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章