算法与数据结构

算法与数据结构

一、八大排序算法

冒泡排序算法:

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

简单选择排序:

​ 最简单的选择方法是顺序扫描序列中的元素,记住遇到的最小元素,在一次扫描过后,将其与最前面的尚未排序的元素交换位置;


直接插入排序:

​ 1. 先看第一个数,将数组划分为有序和无序部分

​ 2. 无序部分的首个插入到有序部分

​ 3. 重复第2步直到无序部分全部插入有序


快速排序:

​ (1)首先设定一个分界值,通过该分界值将数组分成左右两部分。(假设以首元素8为分界值,先从右往左找一个小于8的数,再从左往右找一个大于8的数,然后交换他们,一直这样进行,直到两边的指针指向同一个数据)

​ (2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于分界值,而右边部分中各元素都大于或等于分界值。

​ (3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。

​ (4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。


希尔排序:


堆排序:

归并排序:

基数排序:



二、八大数据结构

1、数组(Array)

数组是一种线性表的数据结构,连续的空间存储相同类型的数据;

线性表:是n个具有相同特性的数据元素的有限序列;

​ 优点:查询速度快。

​ 缺点:数组在创建时大小确定,无法扩容。数组只能存储一种类型的数据。添加、删除元素慢。

2、栈(Stock)

栈可以类比为水桶,只有一端能够进出,遵循先进后出的原则。

栈先进的元素进入栈底,读元素的时候从栈顶取元素。

3、队列(Queue)

类比水管,两端放开,一端入水,一端出水。

队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作。

4、链表(Linked List)

链表是一种线性表的链式存储方式,链表的内存是不连续的,前一个元素存储地址的下一个地址中存储的不一定是下一个元素。链表通过一个指向下一个元素地址的引用将链表中的元素串起来。

  • 单向链表:单向链表是最简单的链表形式。我们将链表中最基本的数据成为节点,每一个节点包含了数据块和指向下一个节点的指针。
  • 双向链表:顾名思义,双向链表就是由两个方向的链表。同单向链表不同,在双向链表中每一个节点不仅存储指向下一个节点的指针,而且存储指向前一个节点的指针。通过这种方式,能够通过在O(1)时间内通过目的节点直接找到前驱节点,但是同时会增加大量的指针存储空间。
  • 循环链表:它的特点是表中最后一个节点的指针域由NULL改为指向头结点或者线性表的第一个节点,整个链表形成一个环,就得到了循环链表。因此,在循环链表中,从链表的任意一个节点出发均可找到表中的其他节点。

5、哈希表(Hash)

哈希表也叫散列表,是一种可以通过关键码值(key-value)直接访问的数据结构,可以实现快速查询、插入、删除。

数组类型的数据结构在插入和删除时时间复杂度高;链表类型的数据结构在查询时时间复杂度高;而哈希表结合了数组与链表的优势;

在jdk8中,Java中经典的HashMap,由数组+链表或红黑树组成;

哈希函数在哈希表中起着关键作用,能够将任意长度的输入转为定长的输出(哈希值)。通过哈希函数,能够快速地对数据元素进行定位。

哈希值并不是具有唯一性,在某些情况下Hash值会冲突,HashMap在Hash冲突时,会将元素在数组的位置上添加链表元素节点,当链表长度达到8时,数组长度达到64时,链表会转换为红黑树。

Hash冲突:

根据key(键)即经过一个函数f(key)得到的结果最为地址去存放当前的key-value键值对(这个是hashmap的存值方式),但是却发现算出来的地址已经被占用了。这就是所谓的hash冲突。(即通过key的hash值,计算出来的地址已被占用)。

补充:^为Java中的异或运算 100^101 =>001(个人感觉好像是求两数差的绝对值)

6、堆(Heap)

堆可以被看成一个树的数组对象,具有如下特点:

  • 堆是一颗完全二叉树。
  • 最大堆/大根堆:某个节点的值不大于父节点的值。
  • 最小堆/小根堆:某个节点的值不小于父节点的值。

简单的来说堆实际上是一个数组,在物理结构(内存)中是连续存储的,但是逻辑上数据与数据之间的关系是一个二叉树

堆的性质

  • 堆中某个节点的值总是不大于或不小于其父节点的值
  • 堆总是一棵完全二叉树

在这里插入图片描述
在这里插入图片描述

7、图(Graph)

一个图就是一些顶点的集合,这些顶点通过一系列边结对(连接)。顶点用圆圈表示,边就是这些圆圈之间的连线。顶点之间通过边连接。

节点之间的关系是任意的,图中任意两个数据元素之间都有可能相关。

8、树(Tree)

树是一种非线性结构,由n(n>0)个有限节点组成有层次关系的集合。

术语:

  • 二叉树:每个节点最多含有两个子树;

  • 完全二叉树:除了最外层的节点,其他各层节点都达到最大数;

    • 补充:一棵深度为k的有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。
  • 满二叉树

    • 国内定义:除最后一层无任何子节点外,每一层上的所有节点都有两个子节点的二叉树。
    • 国外定义:如果一棵二叉树的节点要么是叶子节点,要么它有两个子节点,这样的树就是满二叉树。(容易理解)
  • 二叉查找树:

    • 任意节点的左子树若不为空,左子树所有节点的值均小于根节点的值。
    • 任意节点的右子树若不为空,右子树所有节点的值均大于根节点的值。
    • 任意节点的左右子树也是一棵二叉查找树。
  • **平衡二叉树:**也称AVL树,当且仅当任何节点的两棵子树的高度差不大于1的二叉树。Java中的HashMap的红黑树就是平衡二叉树!!!(补充:左右结点相差的高度最多为一

  • **红黑树:**红黑树是一种自平衡二叉查找树,它属于平衡树,但是却没有平衡二叉树那么“平衡”。

    红黑树的规则:

    • 规则1::每个节点不是黑色就是红色
    • 规则2:根节点为黑色
    • 规则3:红色节点的父节点和子节点不能为红色
    • 规则4:所有的叶子节点都是黑色(空节点视为叶子节点NIL)
    • 规则5:每个节点到叶子节点的每个路径黑色节点的个数都相等。

    红黑树大体来说是5+2,5是 5个规则 ,这5个规则可以通过 2个操作 来满足,一个操作是变色,另一个操作是旋转。旋转的操作和平衡二叉树的四个操作一样,只是旋转之后需要加入一个变色的操作。

红黑树自平衡基本操作:
变色:在不违反上述红黑树规则特点情况下,将红黑树某个node节点颜色由红变黑,或者由黑变红;
左旋:逆时针旋转两个节点,让一个节点被其右子节点取代,而该节点成为右子节点的左子节点
右旋:顺时针旋转两个节点,让一个节点被其左子节点取代,而该节点成为左子节点的右子节点

  • B树:一种对读写优化的自平衡二叉树,在数据库的索引中常见的BTree就是自平衡二叉树。

    B-tree是一种多路自平衡搜索树,它类似普通的二叉树,但是Btree允许每个节点有更多的子节点。

    以一个3阶的B-Tree举例

    每个节点占用一个盘块的磁盘空间,一个节点上有两个升序排序的关键字和三个指向子树根节点的指针,指针存储的是子节点所在磁盘块的地址。
    两个关键词划分成的三个范围域对应三个指针指向的子树的数据的范围域。
    以根节点为例,关键字为17和35,P1指针指向的子树的数据范围为小于17,P2指针指向的子树的数据范围为17~35,P3指针指向子树的数据范围为大于35。

    在这里插入图片描述

1,所有键值分布在整个树中
2,任何关键字出现且只出现在一个节点中
3,搜索有可能在非叶子节点结束
4,在关键字全集内做一次查找,性能逼近二分查找算法

B-Tree按照键值key(关键字)检索的算法非常简单:

从根节点进行二分法查找,如果找到,则返回对应节点的data,否则,对相应区间的节点再次二分法查找,一直找到叶子节点,如果找到了就返回对应的data,如果没有找到,则返回null。

  • B+Tree

    B+树:在B-树基础上,为叶子结点增加链表指针,所有关键字都在叶子结点中出现,非叶子结点作为叶子结点的索引;B+树总是到叶子结点才命中;

    在这里插入图片描述

    B+树:B+树是应文件系统所需而产生的B树的变形树。

    所有的非终端结点可以看成是索引部分,结点中仅含有其子树根结点中最大(或最小)关键字
    所有的叶子结点中包含了全部关键字的信息,及指向含有这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大的顺序链接。
    有m个子树的中间节点包含有m个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引。

    B+Tree优点

    1InnoDB存储引擎中页的大小为16KB(linux中),一般表的主键类型为INT(占用4个字节)或BIGINT(占用8个字节),指针类型也一般为48个字节(win中)
    2、也就是说一个页(B+Tree中的一个节点)中大概存储16KB/(8B+8B)=1K个键值(这里的K取值为〖10^3)。
    3、也就是说一个深度为3B+Tree索引可以维护10^3 * 10^3 * 10^3 = 10亿 条记录。
    说明:
      实际情况中每个节点可能不能填充满,因此在数据库中,B+Tree的高度一般都在2~4层。
      mysql的InnoDB存储引擎在设计时是将根节点常驻内存的,也就是说查找某一键值的行记录时最多只需要1~3次磁盘I/O操作。
    
    

    B-Tree与B+Tree的区别:

    1.B树和B+树的最大的区别在于非叶子节点是否存储数据
    2.B树是非叶子节点和叶子节点都会存储数据
    3.B+树只有叶子节点才会存储数据,而且存储的数据都是在一行上,并且这些数据都是有指针指向的,也就是有顺序的。

B-tree/B+tree区别(版本二):

​ 1)非叶子节点只存储键值信息。
​ 2)数据记录都存放在叶子节点中
​ 3)B+tree的所有关键字存储在叶子节点,非叶子节点不存储真正的data。
​ 4)B+tree为所有叶子节点增加了一个链指针。
​ 5)B+tree支持叶子节点的延展性(横向性)

1.B+树优点(选择B+树作为索引的原因)

1、单一结点存储更多的关键字,使得查询的IO次数减少;

2、所有查询都要查找到叶子节点,查询性能稳定;

3、所有叶子节点形成有序链表,便于区间查询以及全结点遍历更快。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值