1.数据结构分类
- 集合关系:简单的集中在一起
- 线性结构:一对一的关系
- 树形结构:一对多的层级关系
- 图形结构:多对多的关系
2.什么是链表数据结构?
一个元素,他会存一个指针指向相邻元素的地址。
分双向和单向 链表
双向链表:存了下一个元素的地址还有上一位的地址。
比如:mysql的叶子节点就用的链表结构,叶子节点存的是数据。
3.跳表的算法复杂度是多少?为什么?
跳跃表是一种随机化的数据结构,在查找,插入和删除这些字典操作上,其效率可比拟于平衡二叉树(如红黑树),大多数操作只需要O(logn)平均时间
基于有序单链表,在链表的基础上,每个节点不只包含一个指针,还可能包含多个指向后继节点的指针,这样就可以跳过一些不必要的节点,从而加快查找,删除等操作。传统的单链表是一个线性结构,向有序的链表插入,查找一个结点需要O(n)的时间,如果使用跳跃表,就可以减少查找所需的时间。
4.跳表用在哪里?
redis的有序集合用到了跳表。(有点像范围,像树的结构)
5.链表用在哪里?
mysql limit 2,4 其实2需要扫描,但是4不需要扫描,因为他是个链表
索引需要寻址,全表扫描2
如果有索引就查找的快了
6.算法具有的五个基本特性是什么?
算法具有五个基本特性:输入,输出,有穷性,确定性和可行性
7.堆的理解?
堆就是数组实现的二叉树,所以没有使用父指针或者子指针,堆根据"堆属性"来排序,堆属性 决定了树种节点的位置。
堆的常用方法
- 构建优先队列
- 支持堆排序
- 快速找到一个集合中的最小值(或最大值)
最大堆:
8.什么是二叉搜索树?
一个节点分两个叉,右节点数值大于左节点
9.数据库索引为什么用B+树而不用红黑树呢?
2-3树对二叉树的优化
2-3树优化后就是红黑树,
现代磁盘的结构设计,这里讲了b b+ 树
B-树
1.B-树 中间节点也存数据
mongodb底层是B-树 (ps:之前都不知道)
如果limit 就很麻烦了,
B+树 log(n)
1.中间节点不保存数据,保存的是索引, 叶子节点保存的所有数据
2.叶子节点是一个链表结构
有个概念是叶子节点 (mysql的数据存在叶子节点上了,用链表连接方便范围查询,非叶子节点是索引)
10.mysql磁盘IO的主要过程?
需要先从磁盘读到内存,那就产生一次io,优化什么,优化的是io
树有多少层就有多少io。层级越小,io越小
二叉树,层级太高。
11.B树的优势是什么?
IO次数足够少,
B+树对B树又进行了一次优化。
12.为什么经常修改,修改次数大于查询次数的mysql表不适合索引?
因为索引要重建。因为是平衡二叉树,树结构要重建(叫索引重建)
但是不一定每次修改都重建索引,因为mysql有一个缓冲区。有个日志分批次的。
13.php的sql数据结构的理解?
php.net/manual/zh/book.spl.php
mysql 架构:连接器->查询缓存->分析器->优化器->执行器
B+树数据全部存放在叶子节点,B+树中查询任意数据的次数,都是n次,n表示的是B+树的高度
php7 不用下载包 ,拓展库就有,直接new 就能实现9种数据结构
这些会随着进程销毁而销毁
//堆 分为最大堆和最小堆
//队列和栈都是线性结构 底层是 指针
//队列先进先出 (排队取票)
$q = new SplStack();//栈 先进后出 (便签)
$q[]=1;
$q[]=2;
$q[]=3;
$q->push(4);
var_dump($q);
$q->rewind();//翻
var_dump($q);
while($q->valid())
{
echo $q->current().'<br>';
$q->next();
}
括号序列
$str = "[{[]]}}";
function se($str)
{
$len = strlen($str);
if($len<2) return false;
if($len%2 ==1) return false;
$tmp = array(
'['=>']',
'('=>')',
'{'=>'}'
);
$mid = array();
for($i=0;$i<$len;$i++)
{
if(isset($tmp[$str[$i]]))
{
$mid[] = $str[$i];
}
elseif($str[$i] == $tmp[$mid[count($mid)-1]])
{
array_pop($mid);
}
else
{
return false;
}
}
if($mid) return false;
return true;
}
var_dump(se($str));
冒泡排序: 大家都见鱼吐泡泡吧,其实冒泡排序就是两个数换位置,每次都把大的数放后面(从小到大)
一次遍历只能解决的是数组当前最大的数会移动到数组尾部,
两次遍历就能将所有位置都按照从小到大的顺序排列了
$arr = [1,3,5,4,8];
function select($arr)
{
$num = count($arr);
for($i=0;$i<$num;$i++) //0,1,2,3,4
{
for($j=$num-1;$j>$i;$j--) // 4,3,2,1 3,2
{
if($arr[$j-1]>$arr[$j])
{
$tmp = $arr[$j];
$arr[$j] = $arr[$j-1];
$arr[$j-1] =$tmp;
}
}
}
return $arr;
}
总结: 外从小到大 内从大到小, 内key要大于外key
快排 啥是快排思想就是以一个为基准,小于的放左边,大于它的放右边。(ps:好像军训站队)
function quick($arr)
{
$num = count($arr);
if($num<2)
{
return $arr;
}
$mid = $arr[0];
$left = array();
$right = array();
for($i=1;$i<$num;$i++)
{
if($arr[$i]<$mid)
{
$left[] = $arr[$i];
}
else
{
$right[] = $arr[$i];
}
}
$left = quick($left);
$right = quick($right);
return array_merge($left,array($mid),$right);
}
二分法
function two($num,$target)
{
$n = count($num);
$left = 0;
$right = $n-1;
while($left<=$right)
{
$mid = $left + floor(($right-$left)/2);
if($num[$mid]==$target)
{
return $mid;
}
elseif($num[$mid]>$target)
{
$right = $mid-1;
}
else
{
$left = $mid+1;
}
}
return false;
}
var_dump(two($num,$target));