IRIS's BLOG

王圆圆的每日报告


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 搜索

自我介绍

发表于 2019-01-05 | 分类于 面试 | | 阅读次数:
字数统计: 242 | 阅读时长 ≈ 1

自我介绍

一、基本信息:

中南研二,本科中南保研本校,现研究方向为数据可视分析。

二、项目:

  • 可视分析的项目:高维数据降维
  • iOS项目:天气和
  • 以及上一个部门的,四面的面试官推荐的技术栈React-redux-antD等,来重写了iOS的小项目。

三、合适的原因:

  • 专业比较对口,可视分析不只是展示的工具,而是将人类的感知和知识加入到交互中,对数据进行深层次的模式分析和探索。上一面面试官介绍需要做一些数据分析的数据产品。
  • 喜欢技术。自己有申请苹果开发者账号,APP正在审核中。之前和别人做的外包Doable也有上线。
  • 有毅力,为了拿下校运会跨栏金牌,坚持晨跑。且身体健康,可以接受高强度的工作。

具体项目介绍

Java开发 - 老虎机

发表于 2019-01-05 | 分类于 Java开发 | | 阅读次数:
字数统计: 678 | 阅读时长 ≈ 3

老虎机

image-20190307224935020

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
package test.iris;

import java.awt.Color;

import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;

public class UI extends JFrame
{
private static UI ui = null;
static String[] paths =
{ "1.png", "2.png", "3.png" };

private MyLabel labelLeft = new MyLabel(paths[0], 0);// 左图
private MyLabel labelCenter = new MyLabel(paths[1], 1);// 中图
private MyLabel labelRight = new MyLabel(paths[2], 2);// 右图

private JButton button = new JButton("开始");// 开始按钮

private JLabel labelMessage = new JLabel("");// 结果标签

private UI()
{
setTitle("老虎机");
setBounds(200, 200, 500, 500);
JPanel panel = new JPanel();
setContentPane(panel);
panel.setLayout(new GridLayout(3, 1));
panel.setBorder(new EmptyBorder(50, 50, 50, 50));

// 上中下三块面板
JPanel panelTop = new JPanel();
JPanel panelCenter = new JPanel();
JPanel panelBottom = new JPanel();

panel.add(panelTop);
panel.add(panelCenter);
panel.add(panelBottom);

// 三张图片显示区域
panelTop.setLayout(new FlowLayout());
panelTop.add(labelLeft);
panelTop.add(labelCenter);
panelTop.add(labelRight);

// 开始按钮面板
panelCenter.setLayout(new GridLayout(1, 1));
panelCenter.setBorder(new EmptyBorder(30, 100, 30, 100));
button.addActionListener(new MyListener());
panelCenter.add(button);

// 抽奖结果面板
panelBottom.setLayout(new GridLayout(1, 1));
labelMessage.setBorder(BorderFactory.createLineBorder(Color.BLACK));
labelMessage.setFont(new Font("微软雅黑",0 , 40));
labelMessage.setForeground(Color.red);
labelMessage.setHorizontalAlignment(SwingConstants.CENTER);

panelBottom.add(labelMessage);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}

public static UI getInstance()
{
return UI.ui;
}

public static String[] getPaths()
{
return paths;
}

public MyLabel getLabelLeft()
{
return labelLeft;
}

public MyLabel getLabelCenter()
{
return labelCenter;
}

public MyLabel getLabelRight()
{
return labelRight;
}

public JButton getButton()
{
return button;
}

public JLabel getLabelMessage()
{
return labelMessage;
}

public static void main(String[] args)
{
UI.ui = new UI();
}
}

class MyListener implements ActionListener
{
private boolean buttonFlag = false;// 按钮点击状态,默认未点击
public static boolean threadFlag = true;//线程中断标志

@Override
public void actionPerformed(ActionEvent e)
{

UI ui = UI.getInstance();
JButton button = ui.getButton();
JLabel labelMessage = ui.getLabelMessage();

MyLabel labelLeft = ui.getLabelLeft();
MyLabel labelCenter = ui.getLabelCenter();
MyLabel labelRight = ui.getLabelRight();
if (buttonFlag)
{
threadFlag = false;
buttonFlag = false;
button.setText("开始");

synchronized (labelLeft) //等待三个线程释放锁
{
synchronized (labelCenter)
{
synchronized (labelRight)
{
int leftId = labelLeft.getId();
int centerId = labelCenter.getId();
int rightId = labelRight.getId();
String result = getResult(leftId, centerId, rightId);
labelMessage.setText(result);
}
}
}
} else
{
threadFlag = true;
buttonFlag = true;
new MyThread(220, labelLeft).start();
new MyThread(150, labelCenter).start();
new MyThread(60, labelRight).start();
labelMessage.setText("");
button.setText("暂停");
}
}

public static String getResult(int leftId, int centerId, int rightId)
{
String result = null;
if (leftId == centerId & leftId == rightId)
result = "一等奖";
else if (leftId == centerId || leftId == rightId || centerId == rightId)
result = "二等奖";
else
result = "未中奖";
return result;
}
}

class MyLabel extends JLabel
{
private int id;// 标签id

public MyLabel(String path, int id)
{
ImageIcon icon = new ImageIcon(path);
setIcon(icon);
this.id = id;
}

public int getId()
{
return id;
}

public void setId(int id)
{
this.id = id;
}

}

class MyThread extends Thread
{
private long time;
private MyLabel label;
private Random random = new Random();
public MyThread(long time, MyLabel label)
{
this.time = time;
this.label = label;
}
@Override
public void run()
{
synchronized (label) //锁住lable对象
{
while (MyListener.threadFlag)
{
try
{
Thread.sleep(time);
int id = random.nextInt(3);
label.setId(id);
ImageIcon icon = new ImageIcon(UI.paths[id]);
label.setIcon(icon);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}

Objective-C学习

发表于 2018-09-05 | 分类于 iOS课程 | | 阅读次数:
字数统计: 9 | 阅读时长 ≈ 1

APP启动

冷启动:

热启动:

image-20190318215907380

笔试题 - iOS

发表于 2018-09-05 | 分类于 iOS | | 阅读次数:
字数统计: 423 | 阅读时长 ≈ 1

1、(iOS开发选做)实现多线程都有哪几种方法?

A、使用@synchronized(self)

B、使用GCD

C、使用NSOperationQueue

D、使用@thread

正确答案:B C

2、表视图的相关类有哪些?

UITableView

UITableViewController

UITableViewDelegate

UITableViewDataSource

正确答案: A B

错误答案解析:C.UITableViewDelegate是代理协议D.UITableViewDataSource是数据源协议

3、iOS中导航设计模式有几种?

平铺导航、 标签导航、 树形导航、 模态视图导航

正确答案: A B C, 平铺导航( UITabbarController ) 标签导航( UINavigationController ) 树形导航(UIPageViewController)

4、为什么说Object-C是runtime language?

将数据类型的确定由编译时,推迟到了运行时
运行时机制使我们直到运行时才去决定一个对象的类别,以及调用该类别对象指定方法。
假使A继承了B类,那么在编译时就已经生成了A的实例
多态是指不同对象以自己的方式响应相同的消息的能力

ABD

简答题

一、用Object-C定义并实现一个基于数组的循环队列类,当队列放满需支持动态的扩展队列长度。

定义一个结构体,以及int变量front,rear用于跟踪数据填充情况。

1.当队列rear+1对数组长度取余等于front时,说明数组已填充满,那么需要扩展,即重新new 数组,长度为原来2倍,然后将原来数据copy新数组中,同时回收旧的数组

2.当rear==front时为空

注:使用rear+1前提是front指定的空间不存放值,这样就可知front==rear时时队列为空,而避免混淆队列是空还是满。

笔试题 - 前端

发表于 2018-09-05 | 分类于 iOS | | 阅读次数:
字数统计: 562 | 阅读时长 ≈ 2

1、正则表达式 /a+(bab)?(caac)*/ ,下列选项中是该正则表达式的子集是? :C

第一步:理解题目。

题目中的 a+ 代表 字符“a” 出现1次或者若干次,(bab)? 代表 字符 “bab” 出现一次或者0次,(caac)* 表示重复了“0或者若干次”的字符“caac”,即 字符“caac”出现0次或者若干次 。

若改题目为/李+太?白*/,可匹配:李、李太、李白、李太白、李李、李李太、李李白白、李李太白白等。

第二步:理解选项,选出子集。

A /(bab)(caca)/ :匹配含有 “babcaca” 的字符串,不是题目中的 “babcaac”, 就好比是在找 “太星” 而不是”太白”,而且没有a,所以该正则匹配的结果不可能出现在题目匹配的结果中,错误。

B /a(bab){2}(caac)*/ :其中(bab){2} 表示 字符串“bab”必须出现2次,与题干正则显然不同,错误。

C /a{2}/ :其中(a){2} 表示 字符“a”必须出现2次,就好比 “李李” ,属于题目匹配结果的子集,正确。

D /a+(bab){0,1}(ca)+(ca)/ :前半部分正确,后半部分(ca)+(ca)明显错误。

E /a(^bab)+(caac){1,}/:正则本身有误,(^bab)匹配以”bab”开头的字符串,但前面还有a,也就是匹配以a开头的字符串,两者矛盾。

F /a+(babc){2,}(acc){1,}/:分组和区间值都不正确。

2、目前 HTTP2 协议已经逐渐普及到日常服务器中,以下对于 HTTP2 协议描述正确的是:ABCD

http2的新特性:多路复用 二进制分帧 首部压缩(Header Compression) 服务端推送(Server Push)

  • 所有http请求都建立在一个TCP请求上,实现多路复用
  • 可以给请求添加优先级
  • 服务器主动推送 server push
  • HTTP2的头部会减小,从而减少流量传输

3、请问下面哪种方式可以在不改变原来数组的情况下,拷贝出数组 b ,且满足 b!=a 。例如数组 a 为 [1,2,3] 。 :BD

  • let b=a;
  • let b=a.slice();
  • let b=a.splice(0,0);
  • let b=a.concat();

A选项 b=[1,2,3] b==a

B选项 b=[1,2,3] b!=a

C选项 b=[] b!=a

D选项 b=[1,2,3] b!=a

数据结构 - 2 散列表

发表于 2018-03-12 | 分类于 数据结构 | | 阅读次数:
字数统计: 1k | 阅读时长 ≈ 3

来源

来源于数组支持按下表访问的特性,是数组的拓展。

构造:首先根据数据确定哈希函数,接着选择冲突解决方法,最后构造散列表,再写上需要的增加、查找、删除的方法。

插入:根据key键值,经过哈希函数,得到哈希值,插入表中。

查找:根据key值查找。

三个问题:如何设计散列函数,如何根据装载因子动态扩容,以及如何选择散列冲突解决方法。

设计散列函数

定义

key值通过哈希函数之后,数据散列到列表中。

4个要求

  1. 哈希之后,值为大于0的整数,对应到数组的下标

  2. 同一个key的哈希结果相同

  3. 哈希之后的值均匀分布

  4. 哈希方法不能太复杂

根据装载因子动态扩容 rehash

原因

装载因子——给定一个能存放n个元素的、具有m个槽位的散列表T:

定义T的装载因子:α = n / m

对于动态的数据集,一开始无法知道其大小,其频繁的插入和删除,可能导致装载因子过大或者过小。此时我们需要动态扩容。

方式

  • 一次扩容

插入数据的时间复杂度O(1),但是某次达到装载因子阈值的插入时需要重新对原来数据进行hash操作,再放入新元素。非常耗时,需要优化放入分批扩容。

  • 分批扩容

对于插入:获取一个新的2倍大小的哈希表,将新元素哈希之后插入,同时选择原哈希表中的一个数据插入新表,直至原哈希表为空。

对于查找:现在新表中查询,再查找旧表。

选择冲突解决的办法

定义

不同的key值散列之后,有可能获得同样的值,发生散列冲突

2个方法

  • 空间寻值法:

    1 种类:
    • 线性寻址:index + i
    • 平方寻址:index + i^2
    • 二次哈希:经过两次哈希函数得到的值
    2 对应方法
    • 增加:冲突后,往后找寻空位置放置元素

    • 查找:哈希之后的值不是要找寻的元素时,往后面继续寻找。找到返回true;若找到空,则说明不存在该元素。

    • 删除:注意。删除后标记delete,而不知直接删除。否则查找方式受影响。

    3 缺点
    • 装载因子不能过大,因此要求的空位要足够,需要较大的内存
    • 会发生一次集群、二次集群,经过哈希之后的值都分布在某一段,插入和查找的时间成本变多
  • 链接法

    • 方法:将冲突元素装在以h(k)开头的链表
    • 查找时间:为Θ(1 + α),查找操作最坏情况下,需要常数时间。
    • 优点:装载因子可以较大,要求的内存少
    • 优化:如果链表中元素较多的时候,我们可以使用改造为其他高效的动态数据结构(树等),及时最极端情况下也只是退化为一棵树,查找时间还是0(log n)。

例子

工业散列表:Java 中的 HashMap

1 初始大小:默认16,预先知道数据大小可以设计出适合大小避免rehash

2 装载因子和动态扩容:0.75,自动扩容为2倍

3 散列冲突:链接法。jdk1.8版本中,优化链表,如果链表>8,则转化为红黑树,查找更快;<8时,变为链表,因为树结构平衡维护。

word的拼写检查

1 数据存储的数据结构:50w个英文单词不超多10M,存储于哈希表中。

2 单词比对:对于每次输入的单词,作为key值,hash之后,查找哈希表,若查找不到,则标注拼写错误。

总结

当数据量比较小、装载因子小的时候,适合采用开放寻寻址法。

数据量大,空间不足,使用链表法。

数据结构 - 2 散列表

发表于 2018-03-12 | 分类于 数据结构 | | 阅读次数:
字数统计: 1.5k | 阅读时长 ≈ 5

二叉树

为什么需要二叉树?

线性表查询快

链表(双向)插入删除快

哈希表结合两者优点,但是构建需要考虑的多

二叉树结合三者优点,且更符合人类认知+可以映射现实的结构

树

存储:

一种是基于指针或者引用的二叉链式存储法,一种是基于数组的顺序存储法

链式存储法:每个节点有三个字段,其中一个存储数据,另外两个是指向左右子节点

顺序存储法:完全二叉树适合,不浪费空间,堆其实就是一种完全二叉树。

高度、深度、层数:

“高度”这个概念,其实就是从下往上度量,3-0

“深度”这个概念在生活中是从上往下度量的,0-3

“层数”跟深度的计算类似,不过,计数起点是 1,也就是说根节点从1开始。

image-20190312155307376

二叉树

遍历

image-20190312154334354

前序遍历:打印顺序为本节点、左节点、右节点

中序遍历:打印顺序为左节点、本节点、右节点

后序遍历:打印顺序为左节点、右节点、本节点

时间复杂度是 O(n)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
前序遍历的递推公式:
preOrder(r) = print r->preOrder(r->left)->preOrder(r->right)

中序遍历的递推公式:
inOrder(r) = inOrder(r->left)->print r->inOrder(r->right)

后序遍历的递推公式:
postOrder(r) = postOrder(r->left)->postOrder(r->right)->print r

// 真实代码
void preOrder(Node* root) {
if (root == null) return;
print root // 此处为伪代码,表示打印 root 节点
preOrder(root->left);
preOrder(root->right);
}

void inOrder(Node* root) {
if (root == null) return;
inOrder(root->left);
print root // 此处为伪代码,表示打印 root 节点
inOrder(root->right);
}

void postOrder(Node* root) {
if (root == null) return;
postOrder(root->left);
postOrder(root->right);
print root // 此处为伪代码,表示打印 root 节点
}

按层遍历:使用队列。

根节点入队列,此时队列不为空。取出队列第一个元素打印出来,若其左节点存在就存入队列,否组什么也不做,右节点同理。

直至队列为空,表示数的层次遍历结束,层次遍历也是一个广度优先遍历算法。

翻转二叉树

1
2
3
4
5
6
7
8
def inverttree(self, treenode):      #真正的翻转只有这8行代码
if treenode == None:
return None
temp = treenode.lchild
treenode.lchild = treenode.rchild
treenode.rchild = temp
self.inverttree(treenode.lchild)
self.inverttree(treenode.rchild)

二叉查找树

支持:快速插入、删除、查找一个数据

要求:树中的任意一个节点,其左子树中的每个节点值都小于该节点,有字数节点值大于该节点。

查找、插入和删除

首先取根节点,两者相等则返回,数小于该节点则在其左子树中递归;大于则在右边递归查找。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// 节点类
class static class Node{
private int data;
private Node left;
private Node right;
// 初始化方法
public Node(int data){
this.data = data;
}
}
// 二叉树类
public class binarySeachTree{
// 声明一棵树,根节点为 tree
private Node tree;

// 1.查找函数
public Node find(int data){
//复制
Node p = tree;
// 不为空则继续查找
while(data != null){
// 是否相等
if(data < p.data) p = p.left
else if(data > p.data) p = p.right
else return p;
}
// 为空返回空,表示没找到
return null;
}

// 2.插入函数
public void insert(int data){
// 若根节点为空,根节点为该数据,实例化
if (tree == null){
tree = new Node(data)
return;
}
Node p = tree;
// 若不为空
while(p != null){
// 小于,查看节点左边是否有节点,没有就实例化,有就继续判断下一个
if(data < p.data) {
if(p.left = null){
p.left = new Node(data)
}
p = p.left;
}else if(data > p.data){
if(p.right == null){
p.right = new Node(data)
}
p = p.right;
}
}
}

public class Question_39 {
//----递归求二叉树深度----
public static int treeDepth(BinaryTreeNode root){
if(root == null){
return 0;
}
int left = treeDepth(root.left);
int right = treeDepth(root.right);

return (left>right)?(left+1):(right+1);
}

}

其他操作:最大最小、前驱后继节点

中序遍历(左中右)二叉查找树,可以输出有序的数据序列,时间复杂度是 O(n),非常高效率。

因此,二叉查找树也叫作二叉排序树。

支持重复数据的二叉查找树

方式一:一个节点不仅存储数据,通过链表和支持动态扩容的数组等数据结构,把值相同的数据存储于一个节点上。

方式二:更优雅。相等的时候看做大于该值。

二叉查找树的时间复杂度分析

最差情况:二叉查找树,根节点的左右子树极度不平衡,已经退化成链表。O(n)。

时间复杂度其实都跟树的高度成正比,也就是 O(height)。

两个极端情况的时间复杂度分别是 O(n) 和 O(logn)。

而对于完全二叉树:

问题就转变成另外一个了,也就是,如何求一棵包含 n 个节点的完全二叉树的高度?

完全二叉树的层数小于等于 log n +1,也就是说,完全二叉树的高度小于等于 (log n)。

平衡二叉树是 O(logn)。

散列表和二叉查找树比较

排序:散列表无序排序,输出有序数据前需要排序;二叉查找树有序,中序遍历可以在时间复杂度O(n)中,输出有序序列。

稳定性:散列表扩容耗时多、散列冲突的时候性能不稳定;平衡二叉查找树较稳定,时间稳定在 O(logn)。

构造复杂:散列表更加复杂,需要考虑散列函数、负载因子动态扩容、冲突解决。平衡二叉树只需要考虑平衡性。

空间:对于散列表的开放寻址法,装载因子不能太大,需要更多的空间。

数据结构 - 2 散列表

发表于 2018-03-12 | 分类于 数据结构 | | 阅读次数:
字数统计: 1.5k | 阅读时长 ≈ 5

其他二叉树

平衡二叉树-AVL 树(没有很严格)

平衡二叉树(balanced binary tree),又称 AVL 树。它或者是一棵空树,或者是具有如下性质的二叉树:

  1. 它的左子树和右子树都是平衡二叉树,
  2. 左子树和右子树的深度之差的绝对值不超过1。

平衡二叉树是对二叉搜索树(又称为二叉排序树)的一种改进。二叉搜索树有一个缺点就是,树的结构是无法预料的,随意性很大,它只与节点的值和插入的顺序有关系,往往得到的是一个不平衡的二叉树。在最坏的情况下,可能得到的是一个单支二叉树,其高度和节点数相同,相当于一个单链表,对其正常的时间复杂度有O(log(n))变成了O(n),从而丧失了二叉排序树的一些应该有的优点。

###

红黑树

红黑树的五个基本原则:

  1. 首先它一颗平衡树,每个节点是红色或黑色的。
  2. 根节点是黑色的。
  3. 每个叶节点(null)是黑色的。
  4. 如果一个节点是红色的,则它的两个子节点是黑色的。
  5. 对每个节点,从该节点到其所有后代叶节点上的简单路径,包含相同数目的黑色节点。

比较重要的是第4点和第5点,因为它可以保证我们树的最长路径不超过最短路径的两倍。也就是说一个n个节点的红黑树,它的高度至多为2lg(n+1),虽然不是严格平衡,但至少查找的效率还是可以接受的。

红黑树在高度方面不像AVL有个左右子树高度差不超过1的限制,同时红黑树的维护效率比AVL高很多。红黑树需要旋转的次数较少。

Java中的map就是通过红黑树来实现的。

Question:动态数据结构支持动态地数据插入、删除、查找操作,除了红黑树,还有哪些?比较优劣和场景。

动态数据结构是支持动态的更新操作,里面存储的数据是时刻在变化的,通俗一点讲,它不仅仅支持查询,还支持删除、插入数据。

而且,这些操作都非常高效动态数据结构有链表,栈,队列,哈希表等等。

链表适合遍历的场景,插入和删除操作方便;

栈和队列可以算一种特殊的链表,分别适用先进后出和先进先出的场景。

哈希表适合插入和删除比较少(尽量少的扩容和缩容),查找比较多的时候。

红黑树对数据要求有序,对数据增删查都有一定要求的时候。

B树(平衡多路查找树)

B树和平衡二叉树稍有不同的是B树属于多叉树又名平衡多路查找树(查找路径不只两个),数据库索引技术里大量使用者B树和B+树的数据结构;

(1)排序方式:所有节点关键字是按递增次序排列,并遵循左小右大原则;

image-20190326152824931

B树相对于平衡二叉树的不同是,每个节点包含的关键字增多了,特别是在B树应用到数据库中的时候,数据库充分利用了磁盘块的原理,把节点大小限制和充分使用在磁盘快大小范围;把树的节点关键字增多后树的层级比原来的二叉树少了,减少数据查找的次数和复杂度;

目的:使树的层级减少达到快速查找数据的目的。

适合:外部存储。磁盘。

##B+树

B+树是B树的一个升级版,相对于B树来说B+树更充分的利用了节点的空间,让查询速度更加稳定,其速度完全接近于二分法查找。

image-20190326153116561

  • 特点

1、B+树的层级更少:相较于B树B+每个非叶子节点存储的关键字数更多,树的层级更少所以查询数据更快;

2、B+树查询速度更稳定:B+所有关键字数据地址都存在叶子节点上,所以每次查找的次数都相同所以查询速度要比B树更稳定;

3、B+树天然具备排序功能:B+树所有的叶子节点数据构成了一个有序链表,在查询大小区间的数据时候更方便,数据紧密性很高,缓存的命中率也会比B树高。

4、B+树全节点遍历更快:B+树遍历整棵树只需要遍历所有的叶子节点即可,而不需要像B树一样需要对每一层进行遍历,这有利于数据库做全表扫描。

B树相对于B+树的优点是,如果经常访问的数据离根节点很近,而B树的非叶子节点本身存有关键字其数据的地址,所以这种数据检索的时候会要比B+树快。

哈弗曼树

  • 定义:给定n个权值作为n的叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman tree)。

  • 构造:

    假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为:

    1. 将w1、w2、…,wn看成是有 n 棵树的森林(每棵树仅有一个结点);
    2. 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;
    3. 从森林中删除选取的两棵树,并将新树加入森林;
    4. 重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。

IOS12+Swift4+Xcode10开发 - 5 任务清单APP

发表于 2018-03-08 | 分类于 APP | | 阅读次数:
字数统计: 201 | 阅读时长 ≈ 1

学习建议

源码和资源链接:http://a.ixuea.com/zl 密码: JnPM

这是学习建议:
推荐对着视频敲一遍代码(如果没有足够的时间可以先看一遍视频,不敲代码,这样对课程讲的内容有一个大概了解,后面工作中遇到了问题才知道去哪一节找),后面遇到问题了可以直接先看电子书看是否能理解,如果不能理解再找到相应的视频学习,工作中可以直接打开电子书对应的章节复用相应的代码。

http://www.ixuea.com/books/16

需求分析

TableViewController

增加任务

删除任务

修改任务

需求

遇到的困难

知识点

阅读全文 »

数据结构 - 数组

发表于 2018-01-05 | 分类于 数据结构 | | 阅读次数:
字数统计: 225 | 阅读时长 ≈ 1

08 | 栈:如何实现浏览器的前进和后退功能?

image-20190324214941336

abc顺序浏览页面,回退返回a页面,前进返回b页面。

若此时在进入新的页面d,则无法再回到页面c,需要清空第二个栈。

ps.内存中的堆栈和数据结构堆栈不是一个概念,可以说内存中的堆栈是真实存在的物理区,数据结构中的堆栈是抽象的数据存储结构。

09 | 队列:队列在线程池等有限资源池中的应用

线程池没有空闲线程时,新的任务请求线程资源时,线程池该如何处理?

第一种是非阻塞的处理方式,直接拒绝任务请求;另一种是阻塞的处理方式,将请求排队,等到有空闲线程时,取出排队的请求继续处理。

1…4567
IRIS

IRIS

64 日志
19 分类
22 标签
GitHub E-Mail
0%
© 2019 IRIS | Site words total count: 72.2k