数据结构(面试)

  • 时间复杂度
  1. 评判规则:量化算法执行的操作/执行步骤的数量;
  2. 最重要的项:时间复杂度表达式中最有意义的项
  3. 大O记法:O(最重要的一项)
  4. O(1)表示一个特殊复杂度,含义为某个任务通过有限可数的资源即可完成,于输入数据量n无关;
  5. 一个顺序结构的代码,时间负责度是O(1);
  6. 二分查找法,分而治之的二分策略,时间复杂度为O(logn);
  7. 一个简单的for循环或并列两个for循环,时间复杂度是O(n);
  8. 两个嵌套的for循环,时间复杂度是O(n^2);
  • Hash算法
  • 散列表 (散列表就是对数组的一种扩展,是由数组演化而来
  • hashtable 散列表(特性是:数组支持按照下标随机访问数据)
    • 线程安全,sycn非常影响插入性能的
  • ConcurrentHashMap
    • 分段锁 不会影响整个table的,只会影响Hash值一样的(jdk1.7)
  • HashMap
  1. 散列函数:先用H(key)=key MOD7有冲突后解决方法
  2. Hash冲突
    • 链表法
    1. 将产生冲突的值以链表的形式连接起来,将相同hash值的对象以链表的形式进行存储,当链表过长时转换成红黑树;
    • 开放寻址
    1. 冲突处理:线性探测法 (向下顺延1个)
    2. 二次探测法:di=1^2,-1^2,2^2,-2^2     Hi=(H0+di+m)%m
    3. 双散列法:ReHash(key)=keyMOD11+1 Hi=(H0+i*ReHash(key))%m
  3. 动态扩容
    1. HashMap的初始容量是16;
    2. 扩容阈值是0.75;
    3. 何时扩容:
      1. HashMap中存储的数据个数超过数组长度*0.75,就要扩容;
      2. 如果单个链表的长度超过8,但是数组的长度没有超过64,就扩容;
    4. 何时树化:
      1. 单链长度超过8,数组长度超过64(包含)才进行树化;
      2. 哪个链超过了阈值就哪个链树化;
      3. 如果树化后的节点数小于6,就退树化,变成链表;
  4. 位图
  • 二叉查找树
  1. 平衡二叉树 :它的左子树和右子树的深度之差(平衡因子)的绝对值不超过1,且它的左子树和右子树都是一颗平衡二叉树。
  2. 二叉查找树 :左节点都比根节点小,右节点都比根节点大;
  3. 完全二叉树:完全二叉树第i层至多有2(i-1)个节点,共i层的完全二叉树最多有2i-1个节点;
  4. 满二叉树:满二叉树一定是完全二叉树,但反过来不一定成立;
  5. 非叶子节点数总是比叶子节点数多1,即如果叶子节点数为N,非叶子节点数则为N+1;
  • 多路查找树
  1. B树 (B-树):每个节点高度都相等。最下面是叶子节点,叶子节点实际上是一个空指针,实际的值被称为终端节点,可以查找到实际的关键字;
    1. 对于m叉树,树中每个节点至多有m棵子树,即至多有m-1个关键字;
    2. 一组数插入后会分裂int(m/2)

    3. 若根节点不是终端节点,则至多有两棵子树;
    4. 除根节点外的所有非叶子节点至少有m/2棵子树,即至少含有m/2-1个关键字;
    5. 所有的叶子节点都出现在同一层次上,并且不带信息;
    6. 非叶子节点由k关键字和p指针组成,怕、Pi-1所值子树中所有结点的关键字均小于Ki,Pi所值子树中所有结点的关键字均大于Ki;
  2. B+树 
    1. 组合索引符合最左匹配原则;

    2. 每个节点最多有m个子节点;
    3. 除了根节点外,每个节点至少有m/2个子节点,如果除不尽,就像上取整,比如5/2=3;
    4. 根节点要么是空的,要么是独根,否则至少有2个子节点;
    5. 有k个子节点必有k个关键码;
    6. 叶节点的高度一致;
    7. B树和B+树的区别:B+树非叶子节点上是不存储数据的,仅存储键值,而B树节点中不仅存储键值,也会存储数据;B+树增加了系统的稳定性以及遍历查找效率;
  3. 红黑树(存中的意义防止二叉树退化成链表)
    1. 根节点一定是黑色;
    2. 两个红色节点不能靠着;
    3. 在HashMap: jdk1.7用链表;jdk1.8版本中引入了红黑树,在链表大于8的时候;
    4. 数据库的索引不能用红黑树,因为红黑树会频繁操作磁盘IO的资源;
  4. HashMap为什么不用B+树而用红黑树?
    1. B+tree是放在磁盘的(大数据量)会牵扯到分裂,红黑树在内存里面的(少量数据);
  1. 大根堆
  2. 小根堆
  3. 优先级队列
  4. 斐波那契堆
  5. 二顶堆
  1. 权重
    1. 有权图
    2. 无权图
  2. 方向
    1. 有向图
    2. 无向图
  • 线性表
  1. 连续存储--数组
  2. 离散存储--链表
    1. 单向链表
    2. 双向链表
    3. 循环链表
    4. 非循环链表
    5. 跳表
    • 基础知识
    1. 出栈(pop)和入栈(push);
    2. 栈是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表。允许插入和删除一端,为变化的一端,称为栈顶,另一端为固定的一端,称为栈底;
    • 栈的使用场景
    1. 子程序的调用:在跳往子程序前,会先将下个指令的地址存到堆栈中,直到子程序执行完后再将地址取出,以回到原来的程序中;
    2. 处理递归调用:和子程序的调用类似,只是除了存储下一个指令的地址外,也将参数、区域变量等数据存入堆栈中;
    3. 表达式的转换与求值(中缀表达式转后缀表达式)(实际解决);
    4. 二叉树的遍历;
    5. 图形的深度优先(depth-first)搜索法;
    • 栈的思路分析
    1. 使用一个数组来模拟栈;
    2. 定义一个top来表示栈顶,初始化为-1;
    3. 入栈的操作,当有数据加入到栈时,top++;stack[top]=data;
    4. 出栈的操作,int value=stack[top];top--,return valuel;
    • 栈的类型
    1. 顺序栈
    2. 链式栈
  3. 队列
    1. 普通队列
    2. 双端队列
    3. 阻塞队列
    4. 并发队列
    5. 阻塞并发队列
  • 排序算法
  • 比较类排序
  1. 交换排序
    1. 冒泡排序
    2. 快速排序
  2. 插入排序
    1. 简单插入排序
    2. 希尔排序
  3. 选择排序
    1. 简单选择排序
    2. 堆排序
  4. 归并排序
    1. 二路归并排序
    2. 多路归并排序
  • 非比较类排序
  1. 计数排序
  2. 桶排序
  3. 基数排序 
  •  基本算法
    • 枚举算法
    • 递归算法
    • 分治算法
    • 回溯算法
    • 贪心算法
    • 动态规划
posted @ 2024-01-21 19:40  卡皮巴拉  阅读(6)  评论(0编辑  收藏  举报