树的应用

数据结构与算法

day04

归并排序:

分治法的一个非常典型的应用 归并排序的思想就是先递归分解数组,再合并数组。

关键在于合并操作的时候让其有序,而咱们分开操作并未有序排列。归并排序得到的是一个新的列表,而不是像之前的排序算法一样,实在原有的基础上进行的操作

  • 最优时间复杂度:O(nlogn)
  • 最坏时间复杂度:O(nlogn)
  • 稳定性:稳定
二分法查找:

两种实现方式:递归方式与非递归的方式

递归的方式我们要清楚什么时候结束递归

非递归的方式我们在整体的列表上进行查找,如何进行划分中间值

  • 最优时间复杂度:O(1)
  • 最坏时间复杂度:O(logn)

树:

容易混淆的几个关于树的术语:

  • 节点的度:一个节点含有的子树的个数称为该节点的度;
  • 树的度:一棵树中,最大的节点的度称为树的度;
  • 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
  • 树的高度深度:树中节点的最大层次;
  • 堂兄弟节点:父节点在同一层的节点互为堂兄弟;

常见的树的应用场景:

  • MySQL数据库的索引结构(增加索引使查找效率提高了,但是使咱们的删除,添加,修改效率降低了,因为可能要修改整个的树的结构)
  • 文件系统的目录结构(Linux,Mac)
  • 很多经典的AI算法其实都是树搜索,此外机器学习中的decision tree也是树结构

二叉树:

二叉树的性质:

性质1: 在二叉树的第i层上至多有2^(i-1)个结点(i>0)
性质2: 深度为k的二叉树至多有2^k - 1个结点(k>0)
性质3: 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;
**性质4:**具有n个结点的完全二叉树的深度必为 log2(n+1)
**性质5:**对完全二叉树,若从上至下、从左至右编号,则编号为i 的结点,其左孩子编号必为2i,其右孩子编号必为2i+1;其双亲的编号必为i/2(i=1 时为根,除外) —> 当然,如果我们的根节点从0开始计数,则不相同

二叉树是每个节点最多有两个子树的树结构,分别为左子树和右子树

代码

咱们在二叉树中插入元素的时候,采用到了队列的数据结构(在我们实现很多高级的数据结构的时候,难免需要考虑并且使用到一些我们以前使用的数据结构)

二叉树的遍历

广度优先遍历:

深度优先遍历:先序遍历,中序遍历,后序遍历

注意

知道前和中、或者中和后两对遍历序列都可以唯一确定这颗二叉树,但是根据前和后这对遍历序列则不能确定这颗二叉树

复杂度的总结:

算法稳定性的总结:

考研复习痛苦,心情不稳定,快些选一堆好友来聊天吧

—> 快速排序,希尔排序,简单选择排序,堆排序 不稳定

时间复杂度:

平均时间复杂度: 快些以 nlogn 的速度归队 —> 快速排序,希尔排序,归并排序,堆排序,其他的平均时间复杂度均为
O ( n l o g n ) \mathrm{O}\left(\mathrm{n}{logn}\right) O(nlogn)
最坏时间复杂度:除了快速排序的时间复杂度为
O ( n 2 ) \mathrm{O}\left(\mathrm{n}^{2}\right) O(n2)
其他的最坏的时间复杂度均和平均时间复杂度一致

两个最优时间复杂度:直接插容易插变成O(n),起泡起的好变成O(n),即序列均为有序状态的情况

细节:

  • 经过一趟排序,能够保证一个元素到达最终位置,这样的排序是交换类的排序(起泡,快速)和选择类的排序(简单选择,堆)
  • 排序方法的排序趟数和原始序列有关 — 交换类的排序(这里咱们不考虑插入排序)

堆和栈的区别:

堆(Heap)与栈(Stack)是开发人员必须面对的两个概念,在理解这两个概念时,需要放到具体的场景下,因为不同场景下,堆与栈代表不同的含义。一般情况下,有两层含义:
(1)程序内存分配场景下,堆与栈表示两种内存管理方式
(2)数据结构场景下,堆与栈表示两种常用的数据结构 (不做过多的解释)

栈由操作系统自动分配释放 ,用于存放函数的参数值局部变量等,其操作方式类似于数据结构中的栈;其中函数中定义的局部变量按照先后定义的顺序依次压入栈中,也就是说相邻变量的地址之间不会存在其它变量。栈的内存地址生长方向与堆相反,由高到底,所以后定义的变量地址低于先定义的变量

堆由开发人员分配和释放, 若开发人员不释放,程序结束时由 OS 回收,分配方式类似于链表.

(1)管理方式不同。栈由操作系统自动分配释放,无需我们手动控制;堆的申请和释放工作由程序员控制,容易产生内存泄漏;

(2)空间大小不同。每个进程拥有的栈的大小要远远小于堆的大小

(3)生长方向不同。堆的生长方向向上,内存地址由低到高;栈的生长方向向下,内存地址由高到低,向着内存地址减小的方向增长(不做过多研究,了解就好,涉及底层的知识)

(4)分配方式不同。堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配

(5)分配效率不同。栈由操作系统自动分配,会在硬件层级对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是由C/C++提供的库函数或运算符来完成申请与管理,实现机制较为复杂,频繁的内存申请容易产生内存碎片

(6)存放内容不同。栈存放的内容,函数返回地址、相关参数、局部变量和寄存器内容等;堆,一般情况堆顶使用一个字节的空间来存放堆的大小,而堆中具体存放内容是由程序员来填充的

可以把栈看做自动挡,而堆看做手动挡,当然,手动挡灵活,因此,分配大量的内存空间,主要还是用堆

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值