From 6c64deabcc98d408cf81cc07e14bb65d044f4dbd Mon Sep 17 00:00:00 2001 From: xianyunyh Date: Tue, 17 Jul 2018 21:08:47 +0800 Subject: [PATCH 01/48] =?UTF-8?q?'=E5=A2=9E=E5=8A=A0=E8=B5=9E=E8=B5=8F'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 ++++++- mm_reward_qrcode.jpg | Bin 0 -> 43248 bytes 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 mm_reward_qrcode.jpg diff --git a/README.md b/README.md index abffd4a..fb5af24 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,6 @@ ##推荐阅读资料 - [PHP函数库](http://overapi.com/php) - - [PHP7内核剖析](https://github.com/pangudashu/php7-internal) - [php7-internal](https://github.com/laruence/php7-internal) - [PHP7-HashTable](http://nikic.github.io/2014/12/22/PHPs-new-hashtable-implementation.html) @@ -118,3 +117,9 @@ - [程序员的内功-算法和数据结构](http://www.cnblogs.com/jingmoxukong/p/4329079.html) - [数据结构和算法](http://www.cnblogs.com/skywang12345/p/3603935.html) - [剑指offer-PHP实现](https://blog.csdn.net/column/details/15795.html) + + + +如果这个系列的文章,对您有所帮助,您可以选择打赏一下作者。谢谢! + +![](mm_reward_qrcode.jpg) \ No newline at end of file diff --git a/mm_reward_qrcode.jpg b/mm_reward_qrcode.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6a848e4a359d36b1105ba43504dc925472f55cf5 GIT binary patch literal 43248 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 literal 0 HcmV?d00001 From de08b1232d24d4dbc8dd68a7a75ff8ed73cb64cf Mon Sep 17 00:00:00 2001 From: xianyunyh Date: Thu, 19 Jul 2018 21:57:43 +0800 Subject: [PATCH 02/48] =?UTF-8?q?'=E5=A2=9E=E5=8A=A02018-07-15=E9=9D=A2?= =?UTF-8?q?=E8=AF=95=E6=80=BB=E7=BB=93'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...42\350\257\225\346\200\273\347\273\223.md" | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 "\351\235\242\350\257\225/\351\235\242\350\257\225\346\200\273\347\273\223.md" diff --git "a/\351\235\242\350\257\225/\351\235\242\350\257\225\346\200\273\347\273\223.md" "b/\351\235\242\350\257\225/\351\235\242\350\257\225\346\200\273\347\273\223.md" new file mode 100644 index 0000000..306bcae --- /dev/null +++ "b/\351\235\242\350\257\225/\351\235\242\350\257\225\346\200\273\347\273\223.md" @@ -0,0 +1,45 @@ +参加了一次的面试,和面试官聊的还可以,最后让面试官对我简单评价下和给我一点建议,对方说我技术栈比较全面,但是可能缺少大型项目的锻炼,说的很对。大型项目可是自己的短板,理论的东西没有实战,只是理论。下面就记录下面试的问题。 + + + +1. 你们之前的项目的pv、uv是多少? + +这个我当时实话实说了,pv并不高,高并发不存在。架构简单,因为不想瞎扯,吹那么多 + +2. 之前项目有没有做过集群 + +这个确实做过,无论是采用的阿里云的负载均衡还是自己nginx搭建的反向代理和自己用lvs+keeplived做的实验,都说了 + +3. 做了集群,后端的机器如何拿到前面访问的真实IP + +这个通过添加header头的方式 + +4. 协成了解过吗?和线程的区别 + +用户态线程,由程序控制,开销小,线程CPU直接调度,CPU时钟切换,耗费资源 + +5. 分库分表做过没?采取什么样的方式 + +通过区间范围、hash + +6. mysql分区表了解过没 + +了解过,但是这种一般不推荐用 + +7. sso单点登陆有哪些方案 + +这个我当时想的是统一中心认证,使用jsonp拉取登陆信息。 + +8. 主流的框架,都看过源码没? + +看过thinkphp laravel的 + +9. swoole了解过没?使用过没? + +这个了解过,真实项目未使用。 + +10. golang的协程、python的协程,的区别 + +golang的协程goruntine + +11. 对加班怎么看? \ No newline at end of file From da33c45abd68ce272d7fde7a3f1b7fb107606516 Mon Sep 17 00:00:00 2001 From: xianyunyh Date: Mon, 23 Jul 2018 18:28:51 +0800 Subject: [PATCH 03/48] =?UTF-8?q?'=E5=A2=9E=E5=8A=A0=E7=88=AC=E8=99=AB'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../README.md" | 20 +++++ .../lagou.py" | 85 +++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 "\347\210\254\350\231\253\350\204\232\346\234\254/README.md" create mode 100644 "\347\210\254\350\231\253\350\204\232\346\234\254/lagou.py" diff --git "a/\347\210\254\350\231\253\350\204\232\346\234\254/README.md" "b/\347\210\254\350\231\253\350\204\232\346\234\254/README.md" new file mode 100644 index 0000000..89b10b1 --- /dev/null +++ "b/\347\210\254\350\231\253\350\204\232\346\234\254/README.md" @@ -0,0 +1,20 @@ +## 爬取招聘网数据 + +在我们找工作的时候,有些时候,需要到各个网站去找岗位,程序员当然是使用自己的方式来快速的寻找自己的岗位了。于是就想到使用python来抓取最新的符合自己薪资条件的岗位,以及对应的岗位需要的JD,然后如果匹配的话,那么自己可以一键投递。 + + + +- [x] 模拟登录 + +- [x] 抓取拉钩最新数据 +- [ ] 爬取51job网站数据 +- [ ] 爬取智联数据 +- [ ] 爬取boss数据 +- [ ] 一键投递 +- [ ] 岗位分析【分析出现最多的关键词】 +- [ ] web可视化 + + + + + diff --git "a/\347\210\254\350\231\253\350\204\232\346\234\254/lagou.py" "b/\347\210\254\350\231\253\350\204\232\346\234\254/lagou.py" new file mode 100644 index 0000000..52e3d5b --- /dev/null +++ "b/\347\210\254\350\231\253\350\204\232\346\234\254/lagou.py" @@ -0,0 +1,85 @@ +import requests +import json +import redis +from pyquery import PyQuery as pq + +""" +获取职位列表 +""" +def fetch(url,headers={}): + #用户登录后的cookie + try: + res = requests.get(url,headers=headers) + except Exception as e: + print(e) + return False + + if res.status_code != 200: + print("接口请求出错"+str(res.text)) + return False + + jsons = (res.json()) + try: + data = (jsons['content']['data']['page']['result']) + except Exception as e: + print(e) + return False + return data + +""" +插入数据到redis +""" +def insert(data): + pool= redis.ConnectionPool(host='localhost',port=6379,decode_responses=True) + r=redis.Redis(connection_pool=pool) + if data is not False: + for t in data: + #公司id + id = t['companyId'] + key = "companyId:"+str(id) + #职位id + positionId = t['positionId'] + #公司的id加入集合中去重 + resA = r.sadd("company",id) + + if resA == 1: + res = fetchDetail(positionId,headers=headers) + r.hmset("postion:"+str(positionId),res) + print(str(positionId)+"已经写入redis中") + r.hmset(key,t) + +# 获取职位详情 +def fetchDetail(id,headers={}): + detailUrl = 'http://m.lagou.com/jobs/'+str(id)+".html" + res = requests.get(detailUrl,headers=headers) + if res.status_code != 200: + print("请求出错"+str(res.text)) + return False + html = res.text + q = pq(html) + d = {} + d['title'] = q(".postitle h2").text() + d['salary'] = q(".salary").text() + d['workaddress'] = q(".workaddress").text() + d['workyear'] = q('.workyear').text() + d['education'] = q('.education').text() + d['company'] = q('.dleft h2').text() + d['positiondesc'] = q('.positiondesc').text() + return d + # print(q(".content").text()) + +if __name__ == '__main__': + + #职位列表的json接口 需要登陆 带cookie + page = 1 + pageSize = 100#最大支持100 + API_URL = 'http://m.lagou.com/listmore.json?pageNo='+str(page)+'&pageSize='+str(pageSize) + #cookie替换成自己登录后的cookie + cookie = 'Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1531361076,1532319384; LGUID=20180723131853-e4343a35-8e37-11e8-9ee6-5254005c3644; LGSID=20180723135216-8dffe0ce-8e3c-11e8-a327-525400f775ce; PRE_UTM=; PRE_HOST=; PRE_SITE=; PRE_LAND=https%3A%2F%2Fpassport.lagou.com%2Flogin%2Flogin.html; LG_LOGIN_USER_ID=564f3b59e53c65db601e411a55fa01278ce7cf79cb588be8; _putrc=51AF6FA824D5BE21; login=true; unick=%E7%94%B0%E9%9B%B7; gate_login_token=a47b874276333f9f31e46da6185e63a0935573d160846c4d; _gat=1; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1532325155; LGRID=20180723135240-9c59f5b7-8e3c-11e8-a327-525400f775ce' + headers = {'user-agent': 'my-app/0.0.1','cookie':cookie} + + data = fetch(API_URL,headers=headers) + insert(data) + + + From 8de3d30983f90b3225ff067b611f1de23a237e37 Mon Sep 17 00:00:00 2001 From: xianyunyh Date: Mon, 23 Jul 2018 23:33:24 +0800 Subject: [PATCH 04/48] =?UTF-8?q?'=E5=A2=9E=E5=8A=A0=E6=A8=A1=E6=8B=9F?= =?UTF-8?q?=E7=99=BB=E5=BD=95'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lagou.py" | 72 ++++++++++++++----- .../lagoutest.py" | 19 +++++ 2 files changed, 75 insertions(+), 16 deletions(-) create mode 100644 "\347\210\254\350\231\253\350\204\232\346\234\254/lagoutest.py" diff --git "a/\347\210\254\350\231\253\350\204\232\346\234\254/lagou.py" "b/\347\210\254\350\231\253\350\204\232\346\234\254/lagou.py" index 52e3d5b..a29dea9 100644 --- "a/\347\210\254\350\231\253\350\204\232\346\234\254/lagou.py" +++ "b/\347\210\254\350\231\253\350\204\232\346\234\254/lagou.py" @@ -2,14 +2,65 @@ import json import redis from pyquery import PyQuery as pq +import hashlib +import re + +#请求对象 +session = requests.session() + +#请求头信息 +HEADERS = { + 'Referer': 'https://passport.lagou.com/login/login.html', + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:51.0) Gecko/20100101 Firefox/51.0', +} +headers = {} +cookies = {} + +def get_password(passwd): + '''这里对密码进行了md5双重加密 veennike 这个值是在main.html_aio_f95e644.js文件找到的 ''' + passwd = hashlib.md5(passwd.encode('utf-8')).hexdigest() + passwd = 'veenike' + passwd + 'veenike' + passwd = hashlib.md5(passwd.encode('utf-8')).hexdigest() + return passwd + +def get_token(): + Forge_Token = "" + Forge_Code = "" + login_page = 'https://passport.lagou.com/login/login.html' + data = session.get(login_page, headers=HEADERS) + match_obj = re.match(r'.*X_Anti_Forge_Token = \'(.*?)\';.*X_Anti_Forge_Code = \'(\d+?)\'', data.text, re.DOTALL) + if match_obj: + Forge_Token = match_obj.group(1) + Forge_Code = match_obj.group(2) + return Forge_Token, Forge_Code + +def login(username, passwd): + X_Anti_Forge_Token, X_Anti_Forge_Code = get_token() + login_headers = HEADERS.copy() + login_headers.update({'X-Requested-With': 'XMLHttpRequest', 'X-Anit-Forge-Token': X_Anti_Forge_Token, 'X-Anit-Forge-Code': X_Anti_Forge_Code}) + postData = { + 'username': username, + 'password': get_password(passwd), + 'request_form_verifyCode': '', + 'submit': '', + } + response = session.post('https://passport.lagou.com/login/login.json', data=postData, headers=login_headers) + json_data = response.json() + if(json_data['state'] != 1): + print("登录失败,退出") + exit(-1) + +def get_cookies(): + session.get("https://passport.lagou.com/grantServiceTicket/grant.html") + return requests.utils.dict_from_cookiejar(session.cookies) """ 获取职位列表 """ -def fetch(url,headers={}): +def fetch(url,headers,cookies): #用户登录后的cookie try: - res = requests.get(url,headers=headers) + res = session.get(url,headers=headers,cookies=cookies) except Exception as e: print(e) return False @@ -43,15 +94,15 @@ def insert(data): resA = r.sadd("company",id) if resA == 1: - res = fetchDetail(positionId,headers=headers) + res = fetch_detail(positionId,headers,cookies) r.hmset("postion:"+str(positionId),res) print(str(positionId)+"已经写入redis中") r.hmset(key,t) # 获取职位详情 -def fetchDetail(id,headers={}): +def fetch_detail(id,headers,cookies): detailUrl = 'http://m.lagou.com/jobs/'+str(id)+".html" - res = requests.get(detailUrl,headers=headers) + res = session.get(detailUrl,headers=headers,cookies=cookies) if res.status_code != 200: print("请求出错"+str(res.text)) return False @@ -68,18 +119,7 @@ def fetchDetail(id,headers={}): return d # print(q(".content").text()) -if __name__ == '__main__': - - #职位列表的json接口 需要登陆 带cookie - page = 1 - pageSize = 100#最大支持100 - API_URL = 'http://m.lagou.com/listmore.json?pageNo='+str(page)+'&pageSize='+str(pageSize) - #cookie替换成自己登录后的cookie - cookie = 'Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1531361076,1532319384; LGUID=20180723131853-e4343a35-8e37-11e8-9ee6-5254005c3644; LGSID=20180723135216-8dffe0ce-8e3c-11e8-a327-525400f775ce; PRE_UTM=; PRE_HOST=; PRE_SITE=; PRE_LAND=https%3A%2F%2Fpassport.lagou.com%2Flogin%2Flogin.html; LG_LOGIN_USER_ID=564f3b59e53c65db601e411a55fa01278ce7cf79cb588be8; _putrc=51AF6FA824D5BE21; login=true; unick=%E7%94%B0%E9%9B%B7; gate_login_token=a47b874276333f9f31e46da6185e63a0935573d160846c4d; _gat=1; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1532325155; LGRID=20180723135240-9c59f5b7-8e3c-11e8-a327-525400f775ce' - headers = {'user-agent': 'my-app/0.0.1','cookie':cookie} - data = fetch(API_URL,headers=headers) - insert(data) diff --git "a/\347\210\254\350\231\253\350\204\232\346\234\254/lagoutest.py" "b/\347\210\254\350\231\253\350\204\232\346\234\254/lagoutest.py" new file mode 100644 index 0000000..794d4e5 --- /dev/null +++ "b/\347\210\254\350\231\253\350\204\232\346\234\254/lagoutest.py" @@ -0,0 +1,19 @@ +#!/usr/bin/env python +# -*- coding:utf-8 -*- +from lagou import login,get_cookies,fetch_detail,fetch + +if __name__ == "__main__": + username = '' + passwd = '' + login(username, passwd) + cookies = get_cookies() + print(cookies) + try: + # 同步session + url = 'https://m.lagou.com/listmore.json?pageNo=1&pageSize=10' + headers = {} + print("数据如下") + data = fetch(url,headers=headers,cookies=cookies) + print(data) + except Exception as e: + print(e) From 0b8ac60a573db615ab29f15dfe1d49607fc85962 Mon Sep 17 00:00:00 2001 From: xianyunyh Date: Tue, 24 Jul 2018 13:38:16 +0800 Subject: [PATCH 05/48] =?UTF-8?q?'=E5=A2=9E=E5=8A=A0gitattr'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 1 + .../__pycache__/lagou.cpython-36.pyc" | Bin 0 -> 3648 bytes .../lagoutest.py" | 4 ++-- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 .gitattributes create mode 100644 "\347\210\254\350\231\253\350\204\232\346\234\254/__pycache__/lagou.cpython-36.pyc" diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..13a5032 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.md linguist-language=html \ No newline at end of file diff --git "a/\347\210\254\350\231\253\350\204\232\346\234\254/__pycache__/lagou.cpython-36.pyc" "b/\347\210\254\350\231\253\350\204\232\346\234\254/__pycache__/lagou.cpython-36.pyc" new file mode 100644 index 0000000000000000000000000000000000000000..a44a28e3914045da3b1e552ef2d280e2fdf82265 GIT binary patch literal 3648 zcmb7HZEzGx8J_Q%-E2Y#IpNgO)ha!fGaEp-LO{LL1%xWdA#jo!qg%^%Cp-H!OHVIk zw65Y8(&ewFM`&iBK1GUjGo0f0u z>6qg?YRvUruGPF%&G(qeEN0&{{7j(vS==McVeTc(&oPf>P>-@K8$mtBa%>d!CN{=4 zp&n=BY%}W3Y=Uh;J;C%-T48bn-=obH^u#^U{bGlUZtvNulv4;>kA^gudCgccrCGC>6`M61EoaqSv0_Wi z##YT`_9~uIEe9>cCe{}X_}iUJwEqiU1j{NfGcKauOmWA2X{IHE(&11n@zUwA&RhA< z<`4Y z;ECNV%Stt|Bwv=kGyCG{nPbNidr5?ycER>XhL-oUsXYKlQ-iZ0bxPtG$W&shL(F zr<7x+RFHa`AL}D$i3~OX0(c$pyH##--+PEqf2&AeUs?=Bvvi(|V6m$l>_nZj%|QOo z2&zS4t6+#pEG4oi5<8M*aAgGT4*B-}jl2Edf4l$Vx7L4i>u>K}-MDzMf92hcf8Z)) zmGcE;TuZD<2pTz^HiF6(U&JW-eXAWtGO=ix#BK{HUt;m)Ko&gl0gMZZmOt^Yp!GLD z)~EJ1nu6y6*x?PldX_Nc2@Vl%MUVwrs6@be5>2*x_!C$z+J-^{c07H;Fmy*Zbk7)v zmBTGQg0TVBX(C}u;fWq2dXt1A?nVvdh7BSk^2S_m-+#ynOQPJ8r$~Y-{B%&Mb2+WL zlqMD&jz32J;*f=1GY4Q1P^J)8@hNMv`n#Wu4+BL}yl)6?3DGqloA z{_9E(9G;m2YzeUbGwA@D}vHB^As8Nm3sN znCUbKhlJDA_nAY>72cLmJn><4CL_d!P6S^vo|usof))@TLQ!xNvm+Xhz92F2!bIo3 zO%RMyMyZ%Q3XHwTA({vActnoZfWAqckT-5*Nzn`sSlpKO=wb(E3=%qN!9dx52qQ%z zL!x08LZ!ntVx8I7^cAFa=F~Id`^(F*HmiN5y<$S`;OZ5Nd1?5N@)01GA=k$S0+&Tl z4W)1+bwj*{@Hx_vE>f0N6-V6}LKqEKpwVdJo$!KtcUZgr2cUUtyj zpJc)RfTkT~#0ND+=~hoE0|xeYNZ0yr|N8#j>;20&`ro)EI18eC@BFfmO>EWn$6gpL zcLJ;V_DPx|K8Xi?D=IUVsA!+8bK+xwUPRE#Qk#;>GC@4iXa-S2^(ZmTT-{I7Z!=k;aA@g|$ zHQ2~`5A3Y6M+SCI*`ot{Oxc?T_PDY)59|qLZyDH=uw4-Qskz=ZQc@hQn?tAST6i{^ z?%Ane4l!SR99!??Pz+Q4a4%P+^bp7f&sTRRwrcgsLRX3_o$y*y=;-QPNht!^D~1c=CTG~lvqhj;Y)g>w79}14xtr4H*6JL1+GW3 zBPb~;7%6#4jP^OG(r)S;=$oHO;r9|Ghd|_8^q)ndpG$Q11faw;#+PtMc@%`EaY#R% zmmHwVQa1IaKQ+6sMSK)fm9PmqJ^OCEi!3C%g0i1@jtWW}Vw?&kn3VM&eP5dK>Aav4 zs7f?Sz!YZHB150~ND;k*&5(5({Bv~dj3|^IJ~B Date: Wed, 25 Jul 2018 00:10:23 +0800 Subject: [PATCH 06/48] =?UTF-8?q?'=E5=A2=9E=E5=8A=A0boss=E8=84=9A=E6=9C=AC?= =?UTF-8?q?'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../boss.py" | 57 +++++++++++++++++++ .../stop.txt" | 47 +++++++++++++++ .../word.py" | 44 ++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 "\347\210\254\350\231\253\350\204\232\346\234\254/boss.py" create mode 100644 "\347\210\254\350\231\253\350\204\232\346\234\254/stop.txt" create mode 100644 "\347\210\254\350\231\253\350\204\232\346\234\254/word.py" diff --git "a/\347\210\254\350\231\253\350\204\232\346\234\254/boss.py" "b/\347\210\254\350\231\253\350\204\232\346\234\254/boss.py" new file mode 100644 index 0000000..83d578b --- /dev/null +++ "b/\347\210\254\350\231\253\350\204\232\346\234\254/boss.py" @@ -0,0 +1,57 @@ +import requests +from pyquery import PyQuery as pq +headers = { + "x-requested-with":"XMLHttpRequest", + "user-agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1" +} + +session =requests.session() + +def fetch_list(url): + response = session.get(url,headers=headers) + if response.status_code != 200: + print("请求失败"+response.text) + exit(-1) + data = response.json() + html = (data['html']) + q = pq(html) + temp = {} + result = [] + for x in q(".item"): + temp['detail_url'] = 'https://www.zhipin.com/'+q(x).find('a').attr('href') + temp['title'] = q(x).find("h4").text() + temp['salary'] = q(x).find('.salary').text() + temp['company'] = q(x).find('.name').text() + temp['city'] = q(x).find('.msg em').eq(0).text() + temp['workyear'] = q(x).find('.msg em').eq(1).text() + temp['collect'] = q(x).find('.msg em').eq(2).text() + result.append(temp) + return result + + +def fetch_boss_detail(url): + response = requests.get(url,headers=headers) + if response.status_code != 200: + print(url+"抓取失败") + else: + result = {} + body = response.text + q = pq(body) + + result['salary'] = q(".salary").text() + all = q('.job-banner p').text().split(" ") + result['city'] = all[0] + result['workyear'] = all[1] + result['educational'] =all[2] + result['name'] = (q('.job-banner .name').text().split(" "))[0] + result['create_time'] = q('.job-tags .time').text() + result['body'] = q('.text').text() + return result + pass + + +#上海PHP +url = 'https://www.zhipin.com/mobile/jobs.json?page=3&city=101020100&query=PHP' +detail_url = 'https://www.zhipin.com/job_detail/3b31d8738e6d77421Xd_3tu4F1Q~.html' +data = fetch_boss_detail(detail_url) +print(data) diff --git "a/\347\210\254\350\231\253\350\204\232\346\234\254/stop.txt" "b/\347\210\254\350\231\253\350\204\232\346\234\254/stop.txt" new file mode 100644 index 0000000..912206e --- /dev/null +++ "b/\347\210\254\350\231\253\350\204\232\346\234\254/stop.txt" @@ -0,0 +1,47 @@ +岗位 +职责 +职位 +描述 +公司 +经验 +相关 +熟悉 +掌握 +熟练掌握 +岗位职责 +以上学历 +学历 +开发 +PHP +设计 +技术 +数据库 +优化 +优先 +系统 +工作 +负责 +精通 +能力 +框架 +代码 +团队 +编写 +编程 +文档 +维护 +良好 +熟练 +网站 +项目 +以上 +产品 +需求 +参与 +使用 +要求 +具备 +互联网 +了解 +任职 +分析 diff --git "a/\347\210\254\350\231\253\350\204\232\346\234\254/word.py" "b/\347\210\254\350\231\253\350\204\232\346\234\254/word.py" new file mode 100644 index 0000000..b4fdd6a --- /dev/null +++ "b/\347\210\254\350\231\253\350\204\232\346\234\254/word.py" @@ -0,0 +1,44 @@ + +import matplotlib.pyplot as plt #数学绘图库 +import jieba #分词库 +from wordcloud import WordCloud #词云库 +import jieba.analyse + +def stopwordslist(filepath): + stopwords = [line.strip() for line in open(filepath, 'r', encoding='utf-8').readlines()] + return stopwords + +# 对句子去除停用词 +def movestopwords(sentence): + stopwords = stopwordslist('stop.txt') # 这里加载停用词的路径 + outstr = '' + for word in sentence: + if word not in stopwords: + if word != '\t'and'\n': + outstr += word + # outstr += " " + return outstr + + +#1、读入txt文本数据 +text = open(r'lz.txt',"r").read() +text = movestopwords(text) +#2、结巴分词,默认精确模式。可以添加自定义词典userdict.txt,然后jieba.load_userdict(file_name) ,file_name为文件类对象或自定义词典的路径 +# 自定义词典格式和默认词库dict.txt一样,一个词占一行:每一行分三部分:词语、词频(可省略)、词性(可省略),用空格隔开,顺序不可颠倒 +stopWord = './stop.txt' +jieba.analyse.set_stop_words(stopWord) +cut_text= jieba.cut(text) +result= "/".join(cut_text)#必须给个符号分隔开分词结果来形成字符串,否则不能绘制词云 +#print(result) + +#3、生成词云图,这里需要注意的是WordCloud默认不支持中文,所以这里需已下载好的中文字库 +#无自定义背景图:需要指定生成词云图的像素大小,默认背景颜色为黑色,统一文字颜色:mode='RGBA'和colormap='pink' + + +jieba.analyse.set_stop_words(stopWord) +data = jieba.analyse.extract_tags(result.replace('/',''), topK=100, withWeight=False, allowPOS=()) +print(",".join(data)) +wc = WordCloud(font_path=r"simsun.ttc",background_color='white',width=800,height=600,max_font_size=50, + max_words=1000)#,min_font_size=10)#,mode='RGBA',colormap='pink') +wc.generate("/".join(data)) +wc.to_file(r"wordcloud.png") #按照设置的像素宽高度保存绘制好的词云图,比下面程序显示更清晰 From 5198f95de58e9dae7a7a9ac14f59824bb9d399a1 Mon Sep 17 00:00:00 2001 From: xianyunyh Date: Thu, 26 Jul 2018 09:44:51 +0800 Subject: [PATCH 07/48] =?UTF-8?q?'=E4=BF=AE=E6=AD=A3=E9=93=BE=E6=8E=A5?= =?UTF-8?q?=E9=94=99=E8=AF=AF'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "Linux/LinuxIO\346\250\241\345\236\213.md" | 2 +- Linux/README.md | 18 ++-- ...20\350\241\214\345\216\237\347\220\206.md" | 92 +++++++++++++------ .../boss.py" | 3 + 4 files changed, 77 insertions(+), 38 deletions(-) diff --git "a/Linux/LinuxIO\346\250\241\345\236\213.md" "b/Linux/LinuxIO\346\250\241\345\236\213.md" index 78ca37f..17b3c0d 100644 --- "a/Linux/LinuxIO\346\250\241\345\236\213.md" +++ "b/Linux/LinuxIO\346\250\241\345\236\213.md" @@ -109,7 +109,7 @@ aysnc_read("http://www.qq.com/",function($data){ 这个aysnc_read 是一个异步读的操作,当读的时候,底下的操作不会阻塞住,会先输出end。当数据到达的时候,再echo $data; -阻塞、非阻塞、发送在内核和用户空间之间。阻塞是指操作系统会挂起进程,直到数据准备好,非阻塞、操作系统不阻塞,当前进程可以继续执行。 +阻塞、非阻塞、发生在内核和用户空间之间。阻塞是指操作系统会挂起进程,直到数据准备好,非阻塞、操作系统不阻塞,当前进程可以继续执行。 举例说明 diff --git a/Linux/README.md b/Linux/README.md index 9352660..abb385f 100644 --- a/Linux/README.md +++ b/Linux/README.md @@ -1,14 +1,14 @@ ## 目录 -- [操作系统概述](https://github.com/xianyunyh/PHP-Interview/tree/master/Linux#%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E6%A6%82%E8%BF%B0) -- [Linux历史](https://github.com/xianyunyh/PHP-Interview/tree/master/Linux#gnu%E5%92%8Cgpl) -- [Linux基本命令](https://github.com/xianyunyh/PHP-Interview/blob/master/Linux/Linux%E5%91%BD%E4%BB%A4.md) -- [Linux(磁盘网络相关命令)](https://github.com/xianyunyh/PHP-Interview/blob/master/Linux/Linux%E5%91%BD%E4%BB%A42.md) -- [Crontab计划任务](https://github.com/xianyunyh/PHP-Interview/blob/master/Linux/crontab.md) -- [shell](https://github.com/xianyunyh/PHP-Interview/blob/master/Linux/shell.md) -- [进程和线程](https://github.com/xianyunyh/PHP-Interview/blob/master/Linux/shell.md) -- [AWK命令](https://github.com/xianyunyh/PHP-Interview/blob/master/Linux/AWK%E7%BB%83%E4%B9%A0.md) -- [SED命令](https://github.com/xianyunyh/PHP-Interview/blob/master/Linux/Sed%E7%BB%83%E4%B9%A0.md) +- [操作系统概述](Linux#%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E6%A6%82%E8%BF%B0) +- [Linux历史](#gnu%E5%92%8Cgpl) +- [Linux基本命令](Linux%E5%91%BD%E4%BB%A4.md) +- [Linux(磁盘网络相关命令)](Linux%E5%91%BD%E4%BB%A42.md) +- [Crontab计划任务](crontab.md) +- [shell](shell.md) +- [进程和线程](进程和线程.md) +- [AWK命令](AWK%E7%BB%83%E4%B9%A0.md) +- [SED命令](Sed%E7%BB%83%E4%B9%A0.md) diff --git "a/PHP/PHP\350\277\220\350\241\214\345\216\237\347\220\206.md" "b/PHP/PHP\350\277\220\350\241\214\345\216\237\347\220\206.md" index f895fd0..c1515fb 100644 --- "a/PHP/PHP\350\277\220\350\241\214\345\216\237\347\220\206.md" +++ "b/PHP/PHP\350\277\220\350\241\214\345\216\237\347\220\206.md" @@ -4,13 +4,16 @@ PHP是一种适用于web开发的动态语言。具体点说,就是一个用C 了解PHP底层实现的目的是什么?动态语言要像用好首先得了解它,内存管理、框架模型值得我们借鉴,通过扩展开发实现更多更强大的功能,优化我们程序的性能。 -1. PHP的设计理念及特点 +### **PHP的设计理念及特点** + 多进程模型:由于PHP是多进程模型,不同请求间互不干涉,这样保证了一个请求挂掉不会对全盘服务造成影响。当然,随着时代发展,PHP也早已支持多线程模型。 弱类型语言:和C/C++、Java、C#等语言不同,PHP是一门弱类型语言。一个变量的类型并不是一开始就确定不变,运行中才会确定并可能发生隐式或显式的类型转换,这种机制的灵活性在web开发中非常方便、高效,具体会在后面PHP变量中详述。 引擎(Zend)+组件(ext)的模式降低内部耦合。 中间层(sapi)隔绝web server和PHP。 语法简单灵活,没有太多规范。缺点导致风格混杂,但再差的程序员也不会写出太离谱危害全局的程序。 -2. PHP的四层体系 + +### PHP的四层体系 + PHP的核心架构如下图: php-core @@ -21,22 +24,40 @@ php-core 从图上可以看出,PHP从下到上是一个4层体系: -Zend引擎:Zend整体用纯C实现,是PHP的内核部分,它将PHP代码翻译(词法、语法解析等一系列编译过程)为可执行opcode处理,并实现相应的处理方法,实现了基本的数据结构(如hashtable、oo)、内存分配及管理、提供了相应的api方法供外部调用,是一切的核心,所有的外围功能均围绕Zend实现。 -Extensions:围绕着Zend引擎,extensions通过组件式的方式提供各种基础服务,我们常见的各种内置函数(如array系列)、标准库等都是通过extension来实现,用户也可以根据需要实现自己的extension以达到功能扩展、性能优化等目的(如贴吧正在使用的PHP中间层、富文本解析就是extension的典型应用)。 -Sapi:Sapi全称是Server Application Programming Interface,也就是服务端应用编程接口,Sapi通过一系列钩子函数,使得PHP可以和外围交互数据,这是PHP非常优雅和成功的一个设计,通过sapi成功的将PHP本身和上层应用解耦隔离,PHP可以不再考虑如何针对不同应用进行兼容,而应用本身也可以针对自己的特点实现不同的处理方式。 -Application:这就是我们平时编写的PHP程序,通过不同的sapi方式得到各种各样的应用模式,如通过webserver实现web应用、在命令行下以脚本方式运行等等。 +1. Zend引擎: + + Zend整体用纯C实现,是PHP的内核部分,它将PHP代码翻译(词法、语法解析等一系列编译过程)为可执行opcode处理,并实现相应的处理方法,实现了基本的数据结构(如hashtable、oo)、内存分配及管理、提供了相应的api方法供外部调用,是一切的核心,所有的外围功能均围绕Zend实现。 + +2. Extensions: + + 围绕着Zend引擎,extensions通过组件式的方式提供各种基础服务,我们常见的各种内置函数(如array系列)、标准库等都是通过extension来实现,用户也可以根据需要实现自己的extension以达到功能扩展、性能优化等目的(如贴吧正在使用的PHP中间层、富文本解析就是extension的典型应用)。 + +3. Sapi: + + Sapi全称是Server Application Programming Interface,也就是服务端应用编程接口,Sapi通过一系列钩子函数,使得PHP可以和外围交互数据,这是PHP非常优雅和成功的一个设计,通过sapi成功的将PHP本身和上层应用解耦隔离,PHP可以不再考虑如何针对不同应用进行兼容,而应用本身也可以针对自己的特点实现不同的处理方式。 + +4. Application: + + 这就是我们平时编写的PHP程序,通过不同的sapi方式得到各种各样的应用模式,如通过webserver实现web应用、在命令行下以脚本方式运行等等。 + 如果PHP是一辆车,那么车的框架就是PHP本身,Zend是车的引擎(发动机),Ext下面的各种组件就是车的轮子,Sapi可以看做是公路,车可以跑在不同类型的公路上,而一次PHP程序的执行就是汽车跑在公路上。因此,我们需要:性能优异的引擎+合适的车轮+正确的跑道。 -3. Sapi -如前所述,Sapi通过通过一系列的接口,使得外部应用可以和PHP交换数据,并可以根据不同应用特点实现特定的处理方法,我们常见的一些sapi有: +### SAPI + +如前所述,SAPI通过通过一系列的接口,使得外部应用可以和PHP交换数据,并可以根据不同应用特点实现特定的处理方法,我们常见的一些sapi有: + +**apache2handler**:这是以apache作为webserver,采用mod_PHP模式运行时候的处理方式。 +**cgi**:这是webserver和PHP直接的另一种交互方式,也就是大名鼎鼎的fastcgi协议,在最近今年fastcgi+PHP得到越来越多的应用,也是异步webserver所唯一支持的方式。 +**cli**:命令行调用的应用模式 + -apache2handler:这是以apache作为webserver,采用mod_PHP模式运行时候的处理方式。 -cgi:这是webserver和PHP直接的另一种交互方式,也就是大名鼎鼎的fastcgi协议,在最近今年fastcgi+PHP得到越来越多的应用,也是异步webserver所唯一支持的方式。 -cli:命令行调用的应用模式 -4. PHP的执行流程&opcode - 我们先来看看PHP代码的执行所经过的流程。 - ![img](https://www.awaimai.com/wp-content/uploads/2016/02/2011_09_20_02.jpg) +### PHP的执行流程&opcode + + +我们先来看看PHP代码的执行所经过的流程。 + +![img](https://www.awaimai.com/wp-content/uploads/2016/02/2011_09_20_02.jpg) 从图上可以看到,PHP实现了一个典型的动态语言执行过程:拿到一段代码后,经过词法解析、语法解析等阶段后,源程序会被翻译成一个个指令(opcodes),然后ZEND虚拟机顺次执行这些指令完成操作。PHP本身是用C实现的,因此最终调用的也都是C的函数,实际上,我们可以把PHP看做是一个C开发的软件。 @@ -59,7 +80,10 @@ ZEND_IS_EQUAL_SPEC_CV_CONST:判断相等 $a==1 ZEND_IS_IDENTICAL_SPEC_CV_CONST:判断相等 $a===1 -5. HashTable — 核心数据结构 + + +### **HashTable — 核心数据结构** + HashTable是Zend的核心数据结构,在PHP里面几乎并用来实现所有常见功能,我们知道的PHP数组即是其典型应用,此外,在zend内部,如函数符号表、全局变量等也都是基于hash table来实现。 PHP的hash table具有如下特点: @@ -78,18 +102,22 @@ Zend hash table实现了典型的hash表散列结构,同时通过附加一个 散列结构:Zend的散列结构是典型的hash表模型,通过链表的方式来解决冲突。需要注意的是zend的hash table是一个自增长的数据结构,当hash表数目满了之后,其本身会动态以2倍的方式扩容并重新元素位置。初始大小均为8。另外,在进行key->value快速查找时候,zend本身还做了一些优化,通过空间换时间的方式加快速度。比如在每个元素中都会用一个变量nKeyLength标识key的长度以作快速判定。 双向链表:Zend hash table通过一个链表结构,实现了元素的线性遍历。理论上,做遍历使用单向链表就够了,之所以使用双向链表,主要目的是为了快速删除,避免遍历。Zend hash table是一种复合型的结构,作为数组使用时,即支持常见的关联数组也能够作为顺序索引数字来使用,甚至允许2者的混合。 PHP关联数组:关联数组是典型的hash_table应用。一次查询过程经过如下几步(从代码可以看出,这是一个常见的hash查询过程,并增加一些快速判定加速查找。): +```c getKeyHashValue h; index = n & nTableMask; Bucket *p = arBucket[index]; while (p) { if ((p->h == h) & (p->nKeyLength == nKeyLength)) { - RETURN p->data; + return p->data; } p=p->next; } -RETURN FALTURE; +return FALTURE; +``` PHP索引数组:索引数组就是我们常见的数组,通过下标访问。例如 $arr[0],Zend HashTable内部进行了归一化处理,对于index类型key同样分配了hash值和nKeyLength(为0)。内部成员变量nNextFreeElement就是当前分配到的最大id,每次push后自动加一。正是这种归一化处理,PHP才能够实现关联和非关联的混合。由于push操作的特殊性,索引key在PHP数组中先后顺序并不是通过下标大小来决定,而是由push的先后决定。例如 $arr[1] = 2; $arr[2] = 3; 对于double类型的key,Zend HashTable会将他当做索引key处理 -6. PHP变量 + +### PHP变量 + PHP是一门弱类型语言,本身不严格区分变量的类型。PHP在变量申明的时候不需要指定类型。PHP在程序运行期间可能进行变量类型的隐示转换。和其他强类型语言一样,程序中也可以进行显示的类型转换。PHP变量可以分为简单类型(int、string、bool)、集合类型(array resource object)和常量(const)。以上所有的变量在底层都是同一种结构 zval。 Zval是zend中另一个非常重要的数据结构,用来标识并实现PHP变量,其数据结构如下: @@ -118,7 +146,8 @@ PHP变量通过引用计数实现变量共享数据,那如果改变其中一 对于引用型变量,其要求和非引用型相反,引用赋值的变量间必须是捆绑的,修改一个变量就修改了所有捆绑变量。 -整数和浮点数 +### 整数和浮点数 + 整数、浮点数是PHP中的基础类型之一,也是一个简单型变量。对于整数和浮点数,在zvalue中直接存储对应的值。其类型分别是long和double。 从zvalue结构中可以看出,对于整数类型,和c等强类型语言不同,PHP是不区分int、unsigned int、long、long long等类型的,对它来说,整数只有一种类型也就是long。由此,可以看出,在PHP里面,整数的取值范围是由编译器位数来决定而不是固定不变的。 @@ -127,7 +156,8 @@ PHP变量通过引用计数实现变量共享数据,那如果改变其中一 在PHP中,如果整数范围越界了怎么办?这种情况下会自动转换为double类型,这个一定要小心,很多trick都是由此产生。 -字符和字符串 +### **字符和字符串** + 和整数一样,字符变量也是PHP中的基础类型和简单型变量。通过zvalue结构可以看出,在PHP中,字符串是由由指向实际数据的指针和长度结构体组成,这点和c++中的string比较类似。由于通过一个实际变量表示长度,和c不同,它的字符串可以是2进制数据(包含\0),同时在PHP中,求字符串长度strlen是O(1)操作。 在新增、修改、追加字符串操作时,PHP都会重新分配内存生成新的字符串。最后,出于安全考虑,PHP在生成一个字符串时末尾仍然会添加\0。 @@ -136,20 +166,21 @@ PHP变量通过引用计数实现变量共享数据,那如果改变其中一 假设有如下4个变量: -```php $strA = '123'; - -``` - +```php +$strA = '123'; $strB = '456'; $intA = 123; $intB = 456; +``` 现在对如下的几种字符串拼接方式做一个比较和说明: // 下面两张情况,zend会重新malloc一块内存并进行相应处理,其速度一般 +```php $res = $strA . $strB $res = "$strA$strB" - +``` // 这种是速度最快的,zend会在当前strA基础上直接relloc,避免重复拷贝 +```php $strA = $strA . $strB // 这种速度较慢,因为需要做隐式的格式转换,实际编写程序中也应该注意尽量避免 @@ -159,12 +190,16 @@ $res = $intA . $intB // 本身对于格式识别和处理就需要耗费比较多时间,另外本身机制也是malloc。 // 不过sprintf的方式最具可读性,实际中可以根据具体情况灵活选择。 $strA = sprintf ("%s%s", $strA . $strB); -数组 +``` + +### **数组** + PHP的数组通过Zend HashTable来天然实现。 foreach操作如何实现?对一个数组的foreach就是通过遍历hashtable中的双向链表完成。对于索引数组,通过foreach遍历效率比for高很多,省去了key->value的查找。count操作直接调用HashTable->NumOfElements,O(1)操作。对于 '123' 这样的字符串,zend会转换为其整数形式。$arr['123']和$arr[123]是等价的。 -资源 +### **资源** + 资源类型变量是PHP中最复杂的一种变量,也是一种复合型结构。 PHP的zval可以表示广泛的数据类型,但是对于自定义的数据类型却很难充分描述。由于没有有效的方式描绘这些复合结构,因此也没有办法对它们使用传统的操作符。要解决这个问题,只需要通过一个本质上任意的标识符(label)引用指针,这种方式被称为资源。 @@ -178,7 +213,8 @@ PHP的zval可以表示广泛的数据类型,但是对于自定义的数据类 资源销毁:资源的数据类型是多种多样的。Zend本身没有办法销毁它。因此需要用户在注册资源的时候提供销毁函数。当unset资源时,zend调用相应的函数完成析构。同时从全局资源表中删除它。 资源可以长期驻留,不只是在所有引用它的变量超出作用域之后,甚至是在一个请求结束了并且新的请求产生之后。这些资源称为持久资源,因为它们贯通SAPI的整个生命周期持续存在,除非特意销毁。很多情况下,持久化资源可以在一定程度上提高性能。比如我们常见的mysql_pconnect ,持久化资源通过pemalloc分配内存,这样在请求结束的时候不会释放。 对zend来说,对两者本身并不区分。 -变量作用域 +### **变量作用域** + PHP中的局部变量和全局变量是如何实现的?对于一个请求,任意时刻PHP都可以看到两个符号表(symbol_table和active_symbol_table),其中前者用来维护全局变量。后者是一个指针,指向当前活动的变量符号表,当程序进入到某个函数中时,zend就会为它分配一个符号表x同时将active_symbol_table指向a。通过这样的方式实现全局、局部变量的区分。 获取变量值:PHP的符号表是通过hash_table实现的,对于每个变量都分配唯一标识,获取的时候根据标识从表中找到相应zval返回。 diff --git "a/\347\210\254\350\231\253\350\204\232\346\234\254/boss.py" "b/\347\210\254\350\231\253\350\204\232\346\234\254/boss.py" index 83d578b..374811a 100644 --- "a/\347\210\254\350\231\253\350\204\232\346\234\254/boss.py" +++ "b/\347\210\254\350\231\253\350\204\232\346\234\254/boss.py" @@ -46,6 +46,9 @@ def fetch_boss_detail(url): result['name'] = (q('.job-banner .name').text().split(" "))[0] result['create_time'] = q('.job-tags .time').text() result['body'] = q('.text').text() + result['location-address'] = q('.location-address').text() + if "工作职责" in result['body']: + print(1) return result pass From 073548de26706990072d89d4a26928d6fe59e1a1 Mon Sep 17 00:00:00 2001 From: xianyunyh Date: Fri, 27 Jul 2018 13:28:49 +0800 Subject: [PATCH 08/48] =?UTF-8?q?'=E5=A2=9E=E5=8A=A0mongodb=E4=B8=AD?= =?UTF-8?q?=E8=81=9A=E5=90=88=E5=B8=B8=E7=94=A8=E6=93=8D=E4=BD=9C'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MongoDb/MongoDB.md | 54 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/MongoDb/MongoDB.md b/MongoDb/MongoDB.md index 55bfa48..1526327 100644 --- a/MongoDb/MongoDB.md +++ b/MongoDb/MongoDB.md @@ -235,15 +235,15 @@ db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}]) # select by_user, count(*) from mycol group by by_user ``` -| $sum | 计算总和。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}]) | +| `$sum` | 计算总和。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}]) | | --------- | ---------------------------------------------- | ------------------------------------------------------------ | -| $avg | 计算平均值 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}]) | -| $min | 获取集合中所有文档对应值得最小值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}]) | +| `$avg` | 计算平均值 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}]) | +| `$min` | 获取集合中所有文档对应值得最小值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}]) | | $max | 获取集合中所有文档对应值得最大值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}]) | -| $push | 在结果文档中插入值到一个数组中。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}]) | +| `$push` | 在结果文档中插入值到一个数组中。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}]) | | $addToSet | 在结果文档中插入值到一个数组中,但不创建副本。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}]) | | $first | 根据资源文档的排序获取第一个文档数据。 | db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}]) | -| $last | 根据资源文档的排序获取最后一个文档数据 | db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}]) | +| `$last` | 根据资源文档的排序获取最后一个文档数据 | db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}]) | 聚合框架中常用的几个操作: @@ -264,6 +264,50 @@ db.articles.aggregate( [ #$match用于获取分数大于70小于或等于90记录,然后将符合条件的记录送到下一阶段$group管道操作符进行处理。 ``` +**聚合后排序操作** + +```bash +db.getCollection('position').aggregate({ + "$group": { + "_id": "$create_time", + "count": { + "$sum": 1 + } + } + +},{ + "$sort": { + "_id": -1 + } +}) +``` + +**起别名** + +```bash +db.getCollection('position').aggregate({ + "$group": { + "_id": "$create_time", + "count": { + "$sum": 1 + } + } + +},{ + "$sort": { + "_id": -1 + } + },{ + "$project": { + "date": "$_id", + "count": 1, + "_id": 0 + } + }) +``` + + + ### 原子性和事务处理 From e810e09b38ab1c5d12b53d345ef8a28e60e2e083 Mon Sep 17 00:00:00 2001 From: xianyunyh Date: Fri, 27 Jul 2018 15:34:52 +0800 Subject: [PATCH 09/48] =?UTF-8?q?'=E4=BF=AE=E6=AD=A3issue=E4=B8=AD?= =?UTF-8?q?=E6=8F=90=E5=87=BA=E7=9A=84=E9=97=AE=E9=A2=98'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../6.\351\235\242\345\220\221\345\257\271\350\261\241(OOP).md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/PHP/PHP\346\211\213\345\206\214\347\254\224\350\256\260/6.\351\235\242\345\220\221\345\257\271\350\261\241(OOP).md" "b/PHP/PHP\346\211\213\345\206\214\347\254\224\350\256\260/6.\351\235\242\345\220\221\345\257\271\350\261\241(OOP).md" index eabfe2e..2f595e4 100644 --- "a/PHP/PHP\346\211\213\345\206\214\347\254\224\350\256\260/6.\351\235\242\345\220\221\345\257\271\350\261\241(OOP).md" +++ "b/PHP/PHP\346\211\213\345\206\214\347\254\224\350\256\260/6.\351\235\242\345\220\221\345\257\271\350\261\241(OOP).md" @@ -157,7 +157,7 @@ class B extends A{ public static $s = 's'; const PI = 111; public function test(){ - echo parent::age;// 10 + echo $this->age;// 10 } From 30af03af282af2a3fa9d69093c214972f9fe8d3a Mon Sep 17 00:00:00 2001 From: xianyunyh Date: Thu, 2 Aug 2018 00:20:00 +0800 Subject: [PATCH 10/48] =?UTF-8?q?'=E4=BF=AE=E6=AD=A3'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...05\242\346\237\245\350\257\242\344\274\230\345\214\226.md" | 2 ++ "Mysql/\347\264\242\345\274\225.md" | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git "a/Mysql/MySQL\347\264\242\345\274\225\345\216\237\347\220\206\345\217\212\346\205\242\346\237\245\350\257\242\344\274\230\345\214\226.md" "b/Mysql/MySQL\347\264\242\345\274\225\345\216\237\347\220\206\345\217\212\346\205\242\346\237\245\350\257\242\344\274\230\345\214\226.md" index 9cb8a86..46caa30 100644 --- "a/Mysql/MySQL\347\264\242\345\274\225\345\216\237\347\220\206\345\217\212\346\205\242\346\237\245\350\257\242\344\274\230\345\214\226.md" +++ "b/Mysql/MySQL\347\264\242\345\274\225\345\216\237\347\220\206\345\217\212\346\205\242\346\237\245\350\257\242\344\274\230\345\214\226.md" @@ -42,6 +42,8 @@ various-system-software-hardware-latencies ### 详解b+树 +![b+树](https://tech.meituan.com/img/mysql_index/btree.jpg) + b+树 如上图,是一颗b+树,关于b+树的定义可以参见B+树,这里只说一些重点,浅蓝色的块我们称之为一个磁盘块,可以看到每个磁盘块包含几个数据项(深蓝色所示)和指针(黄色所示),如磁盘块1包含数据项17和35,包含指针P1、P2、P3,P1表示小于17的磁盘块,P2表示在17和35之间的磁盘块,P3表示大于35的磁盘块。真实的数据存在于叶子节点即3、5、9、10、13、15、28、29、36、60、75、79、90、99。非叶子节点只不存储真实的数据,只存储指引搜索方向的数据项,如17、35并不真实存在于数据表中。 diff --git "a/Mysql/\347\264\242\345\274\225.md" "b/Mysql/\347\264\242\345\274\225.md" index 4eaa96a..829abde 100644 --- "a/Mysql/\347\264\242\345\274\225.md" +++ "b/Mysql/\347\264\242\345\274\225.md" @@ -1,6 +1,6 @@ **Mysql索引概念:** -说说Mysql索引,看到一个很少比如:索引就好比一本书的目录,它会让你更快的找到内容,显然目录(索引)并不是越多越好,假如这本书1000页,有500也是目录,它当然效率低,目录是要占纸张的,而索引是要占磁盘空间的。 +说说Mysql索引,看到一个很少比如:索引就好比一本书的目录,它会让你更快的找到内容,显然目录(索引)并不是越多越好,假如这本书1000页,有500页是目录,它当然效率低,目录是要占纸张的,而索引是要占磁盘空间的。 **Mysql索引主要有两种结构:B+tree和hash.** @@ -33,7 +33,7 @@ FULLTEXT(全文索引) ALTER TABLE \`table_name\` ADD FULLTEXT ( \`column\` **B+Tree** -![](http://p.blog.csdn.net/images/p_blog_csdn_net/manesking/5.JPG) +![b+树](https://tech.meituan.com/img/mysql_index/btree.jpg) 1. 所有关键字都在叶子结点出现 From ad1113c9f96b0b31c3e7e279a8118fbddc96d34f Mon Sep 17 00:00:00 2001 From: xianyunyh Date: Thu, 2 Aug 2018 22:15:04 +0800 Subject: [PATCH 11/48] =?UTF-8?q?'=E4=BF=AE=E6=AD=A3=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E9=97=AE=E9=A2=98'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\347\254\224\350\257\225\351\242\2302.md" | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git "a/\351\235\242\350\257\225/\347\254\224\350\257\225\351\242\2302.md" "b/\351\235\242\350\257\225/\347\254\224\350\257\225\351\242\2302.md" index f4b37f3..629334b 100644 --- "a/\351\235\242\350\257\225/\347\254\224\350\257\225\351\242\2302.md" +++ "b/\351\235\242\350\257\225/\347\254\224\350\257\225\351\242\2302.md" @@ -4,7 +4,7 @@ 1. TCP报头格式 - ![图片加载中](http://img.blog.csdn.net/20170227111849763?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTWFyeTE5OTIwNDEw/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) + ![img](http://s1.51cto.com/images/20171216/1513399302449506.png) 端口号用来标识不同的应用程序。 @@ -41,13 +41,13 @@ - 5、首部长度:首部中32bit字的数目,可表示15*32bit=60字节的首部。一般首部长度为20字节。 - 6、数据 -1. TCP/UDP区别(不仅是宏观上的,最好能根据各自的机制讲解清楚) +3. TCP/UDP区别(不仅是宏观上的,最好能根据各自的机制讲解清楚) TCP存在三次握手。能进行流量控制,保证数据的完整。 UDP不存在握手。会导致丢包。传输比较快。 -2. HTTP状态码(最好结合使用场景,比如在缓存命中时使用哪个) +4. HTTP状态码(最好结合使用场景,比如在缓存命中时使用哪个) 2xx 标识正常 @@ -57,13 +57,13 @@ 5xx 服务器内部错误 -3. HTTP协议(一些报头字段的作用,如cace-control、keep-alive) +5. HTTP协议(一些报头字段的作用,如cace-control、keep-alive) -4. OSI协议、TCP/IP协议以及每层对应的协议。 +6. OSI协议、TCP/IP协议以及每层对应的协议。 -5. SESSION机制、cookie机制 +7. SESSION机制、cookie机制 -6. TCP三次握手、四次挥手(这个问题真的要回答吐了,不过真的是面试官最喜欢问的,建议每天手撸一遍,而且不只是每次请求的过程,各种FIN_WAIT、TIME_WAIT状态也要掌握)。 +8. TCP三次握手、四次挥手(这个问题真的要回答吐了,不过真的是面试官最喜欢问的,建议每天手撸一遍,而且不只是每次请求的过程,各种FIN_WAIT、TIME_WAIT状态也要掌握)。 [TCP详解](https://github.com/xianyunyh/tcp-ip-protocal) @@ -80,11 +80,15 @@ - 服务器再发送FIN,序号为N的数据包 进入LAST_ACK - 客户端收到后,进入TIME_WAIT,再发送ACK=1.ack=N+1的数据包 服务端进入 CLOSED -1. 打开网页到页面显示之间的过(涵盖了各个方面,DNS解析过程,Nginx请求转发、连接建立和保持过程、浏览器内容渲染过程,考虑的越详细越好)。 -2. http和https区别,https在请求时额外的过程,https是如何保证数据安全的 -3. IP地址子网划分 -4. POST和GET区别 -5. DNS解析过程 +9. 打开网页到页面显示之间的过(涵盖了各个方面,DNS解析过程,Nginx请求转发、连接建立和保持过程、浏览器内容渲染过程,考虑的越详细越好)。 + +10. http和https区别,https在请求时额外的过程,https是如何保证数据安全的 + +11. IP地址子网划分 + +12. POST和GET区别 + +13. DNS解析过程 **深入部分** From 46e8acd91febeedd6fceedb844e939f4f048a0ac Mon Sep 17 00:00:00 2001 From: xianyunyh Date: Sun, 12 Aug 2018 23:20:46 +0800 Subject: [PATCH 12/48] add gitcheat --- .../gitcheat.jpg" | Bin 0 -> 123237 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 "\347\211\210\346\234\254\346\216\247\345\210\266\345\231\250/gitcheat.jpg" diff --git "a/\347\211\210\346\234\254\346\216\247\345\210\266\345\231\250/gitcheat.jpg" "b/\347\211\210\346\234\254\346\216\247\345\210\266\345\231\250/gitcheat.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..5dd105aff87ab2bef4ba61d46c746a6a42cc5b42 GIT binary patch literal 123237 zcmdSAWk6e7w=NtCltK$F6t|WF#i6)EaR?Afa4#+HF2O25aShNSL4!L43szi;d$8gT z#fyL0`<4B^=X~efd+z;pSMq1gl_B$)V?J}tv1ab3?|uTF0OghB0T>t+^d z7tR)MU$Q|oYYm>v4usP)q`%1!8ijMA^bg>9StJXyFK0QdltV2vL6bVGV8CXj4)n&>p!WlIKI<&kB*XHTN1gcg+0WphE! z&IYo+JNR!oyAdUlgS0-5Ut#Nm)pg>B150;9^tD<{&Qyy;ISl!1QrOPimGRhd4z~hV zguegkDGbskq0<)5*bfI1eXdUU3TNA-;CK1br`@a5J5+6EZEhpTS3FtV8)g2@fq{`O zgST;YgM1x$t3CfJh+2PK>j zUAYfUD+NZteK@h@p>V@|xW}uu)#h0ahLUb#B4{)b2-|@F4qygBRxUl*4rd4#N~!BU zIJ{J?n~#80N=B-W2byIqlzlYEJPg(aj+xw`MZJREzH z6PSmjFu~gRs5h9y!an99w}PvRVqGJE!mV9CLE!*6%WD?k8$2-d-hY3iG|hM2q$I4K z!dx=YRJ!N{n zACRZIon#VE#_Cq&IIOt1j(ptWdLwdiLL_)m+I}#12LPq~XYFqPBEA2Iv>YhG?yoiz z|G%6Y^MOyTc8-AI2LIym*k6taHi-Y>+<(=#G030d8viCfwfN6|x-D$EUvRr=7HI#~ z=6?Jy>i^dF|B?EC_3jUG!-CP0bSe6P&(A2Hs4@I-rAO5olB18 zo+_91hG)TnHGWwCXv_NxWk=11>#z0y-nai~{69eB_ZP~le?uPl@5q1b`bSv&pCJFQ z>i-N2xqnly_Aj^>{E7P(8h7Wv$K1b0#Xp4Y#nX^C_|L==_G9kMY$k z^g@_I)Dys(JZ%!k*k5FIa2EZzzfYSQ9MiPe!M&<#TaRynmF*5|Ghk=f8uZ58Ujh>) zXM1`6_=ZA2p1OXgs3GoAVsbbM-XT!a5Zn?f9T4O_tMKI4S71VRC)Y2xr2>!BOyweh z-13RE7~insHzn$Jis^pdOi#IQll{F1x9VQ?&+Wqef z_pjkRgxn8sB1*8UfBI9DG5h8s#7YcibIVd#Y}94fy6stS#p~WcJzF87_Y%U)0%MGdPWOyk9?7PFoar6E9dU^4Je16;NMu2p+#M z@lC8=8p*33975Uff%bS_%7)(o-s}LoXzlz9R?P?qTqhBEJ!J?s91BlX#kI43iC^DT zY7zsfyc6F@M=1fEwT;Y=#P-6*GIAcmDxz82ErM6_YeR=fhfx^nK=la7?}9tPB`+BN zSbr7smL~eT3$7I?U~kpXlobsU*m7aQRVD%I@d&O3IOkolj0}sKTxbM@SMc|K|(>>_?|ikuYTXOHkz-o;-LOFjp z6*bGRxz^&)((>!+bQJqNXcI9XF-a1~8 z{GdI$-7E|lkvYd7aQI_Uy9*sii!oABl8tJ`2$|~UFSFd{HN^Yl_Nb;_F~TYGqO={* zJVyhUN_}=UXIe|I3!A@YO4tbXb5HBAzha&`me=(dguEVHRKjbe@#^$< zKf9XgAn5fmZnjo7`^NKgc5>7JqNn6;kRmLEfI6;uCuFX<+9HrxD|56YHyO&_gNhP` zn-`*I7d98KXUlk2tb_FA5FMFHzL{-J?ZV`W#e*nOvnmh98F<{OPnD=o#G!?Vt~E0w zE60XsUU!h&bt=-o++)MONvUF*w&KOY@|$fM<@b#YW`tFDfHdEf&t5hOq5|`a>n->Y z+8^dN(CjoeIJ|Cae3Eo1i6d+cB}%DirS!mkHhmyV-McB{JVkKDQH@%=Zr#NDdMtmmd%j%bzlW&v;pgI2Fg1EGx^=}I&K`WW`!LvB60UG+Q zt2g3xg*EqpL~#^x zvD;wW?~=b@e$q|!Gq>;ynX}NW-OI#BH+UVQsct>idCN)*P}qkhGmD~zsKukO-SpQs zDV^QA);pbu{2{Sin004kt9HP)PGF1%as-dz5#Cz+WZCBu=8*#OqB{V`td58!o^G=B zAgA%H?fc_#-O`7RtfL{0qAtqt&m=h{WnMxot=leaD3g}~v2=*KF2tTVN86Vt-pZt& zo>&bvHm4Tc4)_0I6ejQOGJFY@L@UBs;*%a zqz&OJsAjybIGNd_NaJ^}6eg20OxDzG_@peyuINNl_%nhudSYl}_%O#`y@k#?#wbA3 z!z$LjTJqA813#aP0w=XHz=(D*8^z{iJ1<^{RJ#!3&T|*E7-if(8>TSlCLQA_UslMb zW7~{T(EK<=pSc_~P5+E}p>uSiQXA^3z7^xV%9E2J)OuRI?uF)&Reu`W)^_oEkvhHn zJ`ui!I3vG}60L@sNUK^3+pI~Z;GB+>cXf$5l_x9}leqTd#2k1y9h7HzR(?%qo~S!O zugmacNix*-!R(tKx_ge^T(uu`qOmx{y${c{8}`Z&LNs~4x%M2kK5QNw{MLzI@!;AAJR9&)e%%i=9YZb93y@%6CK7=LyiHds=Pd3dL?^o+Keb z=3l%*gnFyT44-ZVSg#LfZH*V^_wvPquF?CIis=Kt5JUE1GsN_d3;TvX(xlljWZXuU z_;X*W)5*O(nj7*(iyD3tKEsr~5O_LcHNxRwirnr5!|~K3N<2YtG=C3!C_dT}v#Qo! z)kwlFd@-dGFJ&JYd+G$)An}}1JxeXYwgN#ReUbV^Q%R*RxKW^?Q9Hoxl$yD(1FKG9 zq63kwo}{E@<9YdFZ}QxGKO!-oqu3@7(3E-A%Jda)68yl06!mT}*5c^xgEy=gmNUsy z=}epx)e_&zS-(Se>ml2}uj5wKc>1V~+dn-0g!}UjFj#xge{F5to`d z^{so+Z4+YCNXfHGpI_ynQQrn#t&Ux^i!|s4=^02Qas(5Z%--AfG#9kDqT8`0C}|w} zSYdyGsWC-THBNjVN|es#>h`wrlS-baCJJuO}BjzpR2 z#c`@G8XQnqk(c(rOKNt0tHA>qplK@~hxoyykD(BG3FszB@>W{TE|T$~vBK~e#keOM zUx~g9Lkq(I&GcSaGc6ZC>Vm<0ZX5qGdPL>J&+h&eiS`)vo)N4i}9i{ z@~CT9!&sL=unbYM-s_woJ}%9HGH@;z$oaV>GcN9aBFY2j4~??+Y2kx4Z)9$~TVayd z)9Iz}uZFW7M59-c|E8QkqRap&P z)t3ZZm7v#Ck#|Kk-$HBWmizR9G5rO4xZAIVOMwD=g(fpMc%n1Y<%UR!1cwi+Wt?B0 z(;!y_)n4awCkJ^xCBBuP@-aL2Aa3hpg3{pqB5#UN z9&$ju1~-4Z4dT1`%()OjyKMt*pnNxg;d3vQngr^jU=9t>UNzjt+Z7A;>!fRx`}eVe zd8^!{r<$r_J^uY?&gIKSxat^I5@AhQ$hWdj;f!%t>L0Prql;|h??Wc}&076Jj^gUM z8%tsc^bhcOyQ!mf^mFR0JW?#ne@_;i6+yk7zxsoXIk80+oIcEKdK7hNtD+|IRMWNR z)Lhf}=Ix+cAXA+nL>t=0LLiVvfzo5`Ln#w_yeA{AP}OaGJcITY=ZK_N=e$YVq?;INPxREVX)`2BEJ~CqPDPG*h>q z&r81l9=A^lGrsq1f=sJh7T=Gi|B9Q?%0_=|-ay|fZdBWk2uj%d({iG8%yHJ25*eY-^m>t;R2t-lNi_EL&!IU5vT(WQk<)`7 zFakC_a{ZA4*0`TzSLX>z)3cnLMRqUkI={Ly;G{sn(-#HV3v|0njN-ppP_bRSQ3$DF zh|3hO`j40b6>&<+3R3n7#vq{E#=8fs&zb09YARmi?PM|w1FX)Q@w={b@3)1NLPl+n9gQ&!14 zL~#A=hH#%=&3d(Y%(wJTCs$c8jUF2Bd|XH=FG_#y84oRTKKF%6EpZIxYbiYpvDMZ5 zXOG@BZ;8uTj)uto{DBM_P}HyuSs#~U5hgd$VkcY*yydTbAF^wa;^`>c98kd_N+F(M zP%;^{$F4U**!#JUJZ_@Dk0`g6FfEgw;`?EtssX>>?LeV&Ed##<&4iCaTz;l=Obj;y z>n;2_!PC#tMw&b0-@DYavPI|JIqUGi2`EK$osMMjjcAT8u;MlCG=zd|I8-kOC`*1=_EQb4Po}lbbiWX>XiOzfgU?M@ex&6PG2e zT{G(3%8(kb&N>RJa(5yA7Q3=k-S7pfnbQ#TC?^jPAG=$0?@HD}W%ldClzU>WZE+_q zqT?JjZQc}s&qL9L6)$!k^n7#T{87)=VvS!bZlFbnAui9`Dv@Dr=G>(lM8)4rxIH{Z zS=U4{HEo`#OQgeLBR*|+BF@_@)WvJU9~37ZOA0N|o#T=tD4B!;4Mn5rC4Ojj+&DYd z_xt7PCqD1_FegZ@4us)J^_UpaLZVn7Y8so)W7p?%GzQakKQg~|Q12C9In1}HPP10E zd|vbtOG*T+$Autge!3u0Qb10zie{JBej%fAt6vwidvMqfn1`rcgbVx5JVYa_rriuQ zuk8E8>V8Nvi!LyNYEz#Jlzy>kR8SkN+^;DSvKMJs_K7D}wQk<&)sAZmBLx6Ioc=uN zF3oQcG+|OSFyooCO!eCUUUe;Un2I{x*BD|d`^gGkL#a0VCbS<35?VkwKtIVlTIHi#A?!GX->$4^h9r8f_$R*ro6-&0B<3bTp?j3@@<<--fLL@nwa6@Jf>MI3AOtE5X~?8Wa;40=h1ql)9liv zbJ-UfHaCv8qCV`vrc;4LG{qQI8$9}xVkYwUng5^|Ocxg%rpt+EItnU(Fw8MGRW(1i z^?peSe_Y=m4D&wqt?PiPXmLqJo^@T~`ZJpWo4C0=;= zy@5yx5F?O|nU1NR_Dz59X_|#fk)~%n#?N{eSi}7f@=IIia$FxtFpIIU0Gv{(A=_}{Tmqg*hCH9+diU0vGu1o5C@A&p$Lm`J zxX2P+9JpcF8oK3gxtIXK1FpE{Z+g~QfI6n8e|yzNvLksZawQiIzXBnxd&?LT4-R9< z*@UpqLRr+-6S$7=HGVVtWvN)BVqvH-7s;6Lg~}UFT!4r3{F4afYUk2Qc%}%^9l%8( zTYaQ}GIsgfmPz6rz*NxhG0MDOOEz%l(&1*>^igw|zvKU|!mZk$DmxEGB(M|N80eX8vMabf5Ih5v0x}$I$Mm zw70H$){4*&h$j%|J^y=(XXbZOV222a5yYsT&M(?S`WC*u0t0| zw`0)dA+)jFX~~=E#anaj6vSEMK5TEsFUue+HN3r+Sk~JxaS}l^L*H!^GT?YS=dYCp z^+3Wo@dBiJe6$ol;|ZM459cJ#tP}hUlQBCg9{`+(~uRSv46fM(Mfr{=MWv&?MQkDh(D{XU*r_1 z7u1H&PT+IM>%Yl~TPCZEU)p@OV!SV`l}MSDeLXq0;H^nbVzsg4rv|p6N_tEAOucXH z_!Lwe=~Uaay8kM?x(&+g{4wY~NxhFxvqymS@TA}=9JOO#Rkw|$P%>(4JyC>Yz-Fn$ zrE;C>YI!B9J~?tFvnPL1u+r^9?E@WSWN(lHV~FFDY)2x{KL_KQjtpc`O+%7Y-~`|sbzA<^TA7op+UCiV?spPak3{#!?`I6UWz>uUrYuYt&dO_ z($h%ml-zgLp#(|@8B;KgMkMsf(H%hZ^D(E{e?k!CVK2raatPbgm_T#rcqc3ySS_QKf1T(r82Z$|{bYroV; zER@&xTNKTKfa8#H<3@?PBZJn8KPl2?5Q$7qt59c0 zXDxx0GIqdUpl^{m~O{$$_*=t3w>zj={>)A7yu<{RMN_lt6UU|?TeXm28egpT|94a#} z)Eam842kz2D(k<-F~y>O&kt=$@^7r)RBldfRtSO^b=Fd7ozh?Qm~!#b>Nly86#ky6 zl?szw^}!q|>L>@s9pS!S-C|?H0UH+87#%%1sYWjpy>DMioAP9=gbsQnuqa^uB8hk< zlq!=-kCo^%e>j#`-q10UQ!ogID15pZ5Y2Q)%vPo8IF4%z#?tO!%h?I7m|A1ytjRvb)pn0b<@{MzxpM zt@F&NLJ!-H&gYxwbj?s!*$>N!uuH$}k6v}?vV)P<$)?v=6$MkS0UwE|?(%9_ExOQP zWaqZC%Wut*+9F|Ikx5hSKdeix^OMKc*Q09orfhX9bA?I6_D9w{V-RTMZ>4> zC8`+;WL9So2*42g_CPItxH3LyoAcH%nimI5v7udE;_k@HTSYr~Qr5d8W5B;&w@0LP zD;W>pF>mIpeM(|zPFHho-ahu}oe~G_Tv_N;?%gI{p#F14O zKgJlG@w15`1ahdi^s$BD*UJ}Fm8Y1!xFMtIiBE#!qkaW(S+h`d$-O>%hGKdv;`v%8 zywnXE4ui{ta{;Xrm{}Mu>FK^N?Uq447f|B^^(@9ltja8!E~k&#@`ngPAa%9yDb;5^ zXM^>jsMI|rx_P!@zR2c2X`ft9ZsMI@p$%3XoaD0WvDw;-bM%Xq-}OWLB@Z`}Rts+B z($Ll5{eU7hu@*+PBld$k0FLX8{>AUNJ8i72@nd&@tV>vR1@Y?sdNb3BAX8tVTxVIF z{l56+hGU({J#r$N+Q>)_qa$yiQV+?++Kl$ciTP|BQ=5?=ijZaX`p)tL4=Ts!BpiC= zAjL9Gt{Sem_)t^{4!6ws`?`P|dn?-j`@<`?y~^VvAAwJEY%)zdZ+`Yke3|4CzWH2hV!E#!2GWj8_&}22^L7vrU7Gfj;Y3keG;=P3rS6-Tuzolu6Uw?}hH00im#PPwnG%*-{xaj#;Ey$G^lh)RTDe|zN~lUq8Q(iXPi zzDp{nq?3xp3fa^Z&{&Y|kbhaLb-DH%>&cb;3cOmW8MZPE56zq|?ek{8*j~I&As9Jw z9cc=gcZBTkIX5oSbvc7GXD5yPo{WtHP)eLnAS6xzTCu5566${WC?Bmo(j~94U+c5> zj`vX&DDCY6gxXT>AuEbKPqEsDEb617y;Q<5F>(ojWdLrGnL)4e7m zn}VaFy&?It7N=S^#VxPIVy5PA&YFDuEE{UuBus@0#iwNkmOl@5?ZAmIC`yZyA&mP% zheBZ_`AXnKUuBLB>fH94;fZREC0P zA{1}Ta>QmqK^&Ab01l=IcJ|pUbccI*y0^wRk!;l*MBF?>2P?5Sl9_Y9i@H1PX(s3+q zpMh~8Tv|#dn`1S-7}oe($Guk0(4m69$E+Nx$odH0Ev>oys>L(tgXU(h*3??Rc zAaNg=(Hid(N8f4g*qEUxeP0QH-T?tG_*Z*U=*BJI&4GjcWT)65?+d}Qd8wwU)FnCl zZ&sotDYNa_vMY>HDO8ndByT533;G+L6hw+i6Rt^Rm(w$>2#fumG-|J6<1w{iQE46y z>40WYZGH{fqat<6gt>sln+wBthxEUXO!kJmXcYH*kKQxTsAHaqk|vE!h2gHcf_2iA zO}~bo39LoGY*=?a)~T1OC&#WfTayJmV4AGjE=wwCD%MOj=+8rrg5L;>!V z{s_2v?UDYLWEO7%X{#hw(By5~3SHz;hYhSC1wcFO9kmq%FGWi2_-a133ipV{X}-o= zDN(4%TCOU4XF&7ekte7fe<#JL4MMU#NT*%V2)j* z(+H)>6NTb1QR8(s8nZW8nn*Rx1}c?F>_n6K7BxL;K&%SA20#F*KJvb7VI&nq(5zV` zsNYz^+yPaQz$RxsX=ylf(TwB!z+dacyOWGH zy+mM+FxYO0jc*+?>q$&b9vkYzCq>2QH;$AcyWOu1P7{vi`lqzT8H0KPtA!revBhW$ zQP3_@)`P|qDJUVnq+EnVN8k4CZQi`W&k%r$>2zneyhVw_P$eGDMJKl~{~266MeFWW zf%>YejvV}=p4ThET|B-@*KE0IhKBi?Ro-QJ$aBVez3ER=`kXIg>juL(cNOFM>j+b< z-;aoWBKD%kqW(RxJu|}*88j!B-N(e3AKC`JQe9fBNno;COpSn%do6Dh#Ix{}dGKG_2^Bqv zB*ACtUMr?!W|P+XY5tWBXeE1j7LG#2vv8waxS+j0UbcjHeu;y}L(?6^&PB)1OMwi>SirHg;fm+n2a4kU-P1 z`dEh#LKavAQc_lZq`dopJJou}?$fnkFgWSKfdPG?CeHN^-XmNx7M5s|gyzdi87m4V zOr}e1akJSm8t^cq$jYO)YxYboU#OjbPcWcVv+J2iZ09QV_#W1lNZwoRgX!lO`8ycc z^Jr6n#@W2-Z#iLoT@9NCIm$sZPnP=9@D?s-40CuqE}7z-cQ7u_3|mGWVJCX!!w`g^B{r92e$S! zJA096c1NnM{TF+bEt><=Gq>)fTap5|r}MN2r6QMAT{e0p7|xE$LrtK_mroyM!pjY< z0vkz-oz$w55!_`bC-%=*U(Wifdd#kdDMy?K3L~AxmvkOT;3@)iK>1T128gmZ!Zcf5 z_N(PpBpp#(pCZgKVG2c238I6XF6z6xWn+oyp13s=eWdBt!uec@SMNcLc`qe`i4ZrM z3CsYs!;<**V-QnIlQ+b0Y(UOH!NzcLjSfS2c06*mEb3KqmX+`i{ZmA+S)L5x*VO*f z2JZ)ox(s&!44v67q-^%vCyx2`{j#AP4Mp+hHSHik8v4YE+b0|6$_|f_$d{uvIil-l zBqkZd)8pJ(Ena2@sS%+TN>b9$AU7Zwl7G@^);gNF8I=XE{Wo zBhiY?F+!_e7R`%GvyKfP6S0q|brXMc@YP#-1IJ@OQ31>i)6I3ul2g=nY+3C_99npl zfH7vEKXK1mftQXkf}#ot*SoD* zvESR^C6bIqD>A%=ef?D=Q9aTiF`wu7xK-9n$&|h~G4y*|Ro&yF#*K*I+V=ySYpuq> zd!>t+s8I*@waviHbA3lhDx)<9P^nMaB_K$3hsKul01h6g)fU>W5pUuejG0Z*Tw<|T zd>)jR^C&?FUvHU~wYRbMrX;UC(v`%AGjeRQh{53WNMrCdG>9)`$J9zsPw8YN$PCWZ zotf|FocVr>`HdOBaBu$Cm=(}{JOi-e5Z;hFOhF$udhWxSTAO&vF>LbyoNVPgMP6W@ zmgj=2U;ea~X@s_twW-Vp83CV98D}@@$OC@Hm7X=Ar@r^;6#zi+_(SO>Pw}B-vKkjs zVdTa8j+Gh7JAjgi>m4A{@z!1AKU7wm;SCcO~Rcjv6mH8wrjx1XGtV5Kd^xPDy_ovWRG6jZh#esih;cO7~Rav5MOAeF1y zO31s;v^|dw@RRtaAJ9kI;&pyL0ZLGvOj1kvx5plSBDJJGWmz@*JHj)IlC_e-mwBTp zaL#lAnJ`~v%P}^!3+br?+S^M%p6WXQlmm8na8Q`W(g5B%Hk%|6P1^>-b$y&EItX*_ij2rGh{0bHAH8=^MLMM_hHcG^eYS zNUl9JY4o|;&I3ABH~4nO+Wm_`wST&SMnMp0B=Jw(9Df-6ciknN>D*=pf59^L7gm~E ze*pBglH)IXTYot5=1(UI-Ew!7^M2_4*S&T__xk_BGc@Y|$DVEduRZ(!8IM2V`TKCb z>-;aG20Cx;b`k#K&*AtR5`V$-_u-iScgVW_9kPM{Ubr*X0o3AvN3B)Z?uby%mUQz`1`i4h@K{8y8xs&JP4~7LH0dNT+QMM zO^h9{;of>|RX7g`s2W67M_WQDdr7DK{PY*LXkL|42Ky>#hhw2j1Qk&q;xvohSXRX1 zmkf0a5zL(;&PWmFu^{=-ZYF z!#$zu*>J|%m>3JWP}{t~6=_(S?{7A^1GH`V(S{7Z#7=Aec&=4z8}&ZER_Nzr%Wuug zS7j|N^i>|2mqUWWGxuvPZYX=2m^@XNm5q*Hsqmi<3SLPG4T>Wox-Il8Rcxz+tJiva z&VpFTa5O072sK5%5WI>LM{FT{Gx+?fU*fmuD!RV0ksP)0^EkmlP8!^x=nXs>-hXfc zP@is{cpT4|ou<$aDb=1i=d~z3RI8w9r+?E+eO^i3H5^y!lpUX%t|d69<9>eL{=;Eh zQg59J$v@#-a#p{;HJjqJACCXsPhI;dqe6z=%IHvKW%v8bdHs*GL~d#GI*G{#b06r+ znq>m2H6lLll_^FikfusYd{ast=&z<=>g90KA{=oTBOIdozgMDX)lI9zIoz+mE-TH2YfU%Oa#CHq#mKIdw|X9so!DT_Ar)Gl zz4SjiAqx~2d~z!5(dWtju{%rnd7SeHOTW%@lK@}ekokQ7ssTF>r4ojD2Z1g(#7uus zJ;qFIJfXSssINBnW^`Bi^`ebw-qV1K;HBdiY5N*ZNA8}C-d)4RZ&MG$P9MYee~edT zzcbmGb>mS;G~Qol>#N(=V~U%h6Sk+=sf((k*7<&vJo1#NMA^ljOVZ*FfDh*r<(^Yf zeD3s(h^*FTYUN`pK`M-DpA8Mtk?bEJt#@C&m>em4WzV^#jPz6*NP5?<$^XUp^^I8` z1^uj%iibhb8daU8s^R=aMy%5;iJ9DUv-4DlWE$k{brxSqIp#y{dL}&^wW|OFag1F9 z-J1n^Ing?5%nxE}`F_V6GlrdMJQhD{&TP$ZBnS57-8K06GJ6enx`;lNVaI^HyQQf9 z9I>B*HqVNWF`LqCg4xSC_pPtOI6Sd~vy?T>gIAeT0iUB4)6Fel-KTBt56aV+ye>AY zO^zPZoA}M&PR?1X6P$#j0lUAqpgdw6_NQb7j#J8_l2(B|9#TJdNOq-b!P4i z&hCFKH;l3!t+d)aoSXNIfkpSZQaQtne6gI9v*3OxL9l*wT&;qXW?YlhwXAWz>M;$sueVVYRtjZ}KESC9- z3=EKQuk7x3Q+Or;8>`{${EsKSjTPP}Z!>nyW8Bbt*|>L*$VTMb5=a1gnL#}AY^x64 zh>qS`p$KbHWTpMrqxD#PbM?BREuj;yjpS2>E6^5|jqK)Sfrk5fruh7nCek6GzOw6z zJd)T!h?)sAK7lz3+vOQEL2nM*X1r%;&BD;zXqMzmlC{C{O0}HQQz?ls+{@V>Rwn9~ zMJ+3$Wi8EE`*i`6-YiDRHXYW#YbUJxlkJWssiK8CP29FaTXD5tDTz7j?VoX#>9z2h zxhgEgdU|JFIjJz7_u09>0r5uLL!iFJZpvHQWpx}+-5+uNy0ldaDb2-Cd#1%D(uCA5 z7Z&At-Ku8zoZF z#(I^Q7>5B&h`7fiRHnza_Hd>h50qGI(>r3X!*vKr*A>NG5!u|B=8K6O_#DUML<8z7ifFRVmiI9@*BTuT@L_FgFl1GhBSk#+|b$jtJZEEp?sstTaTDLv? z9eSiSw4&A4LEg4JQas)y7>&`r_bNYY&DdS-T(rBA)ku4x_I~(z&kINi7g`@na_oyGG#{Rm7yO|f?|G9%>W>bRRaCq@o zC2rgSTDg}y1b~8%!63jh-Qy2T{}Nl;l4g)elfksX1f&RuY_7AcTrBy=IBN7XJDpN) zO0qfQAiXL|w%H7K@3gj|hRf+XNKc%C|0GpNk8dXOWny-omV{ADRne=1cv~B`zJ&bM z8~dR$2cm_833Y6Rowtu@>DNrN`#_c7xRFuSLvecSg(1Icx7JCzA)p^Z<@c3dGyH=7 zG#f)ZB^lr^rq^S&25afGNweD}Yb@3I60h)De$|q} z>;sf3S5*>aP&pe1o$Hh&lecbWhlud$2pZ9#rRNki*E;VJ?fNDV&3(87#8~I&o$5)+8?w*<<+V$5@Gkw|(0p~Il%UN^ z#{^2=a=o!(dLdC1ba8x|(x+aJD~>C)GNRbcPj$=tM~Z@;d8aTSP4aeCo?%O*sLMrc z?L%OlH_uf}oCuR68{P%qMn^kfYo8`(FoEinXt?=+AGGAX@5&zQTLBJC`zrB zoSRuWW$!S{bMBV?#pB0FxFq_gOUr_Gl3w2Wf@YKpW+|y2eDL|Hl7P!2LPE2y70H~H zk(DXkqTPP&+IQg)?Uef55snT7t#w%WSdn@gIN?23d>1xk*f#^o6xWg!f>f#T@Wdoy zd@kqh>du~C?6Vel$+5ppETz5^I5l)uF#>wNeNme0krRGP1+sP~8UJ1>;P>P>Y!=~w z(aX~NOiSWr$}Mj_I!pPJp(;1tQyvx_3&>er^*KJ~GjYHTY`##9D#Gn@-YfPHWtjw< z&NCu%IZNdbC8{7lZf$i6>oq04E+T~*^naN~P^74*cD1&+@;mvG$_1zWHRo5qKHdQ) zvTCbbTzhaZSg4P(yGM?qc5@*Kc77L6+z4PNB@NagrAcL#IN~P>dniI=7O@Km*Z?s2 z6RM?kK|{$MG1$4eNFSfFVV+ylMBTX@;}b(oxsMF_=5)>C>{o0oG~qkl=#@r2hl>?i z+2c1YP1K)ncLI)&_~7ThEp=2n8kx6c7ha^pIc!Nt`jAuFXZ?ns{5PDD!uhp33s(M5 zr~7JjN1u0Rf|!(FPsA^yI3<@)1xj70*8OJMCxTn$*S~KnwF14=O3_gLGo+N&Ec6lD z6rL4%obp42ojlh|6h{5FN^Nmk5%(UG7Z=b(?}WtdIUA4a1n11(e_L5+`!J3hO{=Wv zX)r;*COMPVTIhBnlqQ+mHNczsUQYkbh zf-7?>;{>zmN2-$KN9q(=Y5mWgxK9)MLWt2+KJ-WGVtUoycX&lT#j{UF{%DJ>y^5pv z;nz00;zA+%=f&?we$paBe0V25s|os}*BACuAxha}62HDlt!f4~at0W;akV5fL0`I) z)fw0EUNUYfuwjtf#HbytC~!Yl zXy5*_U_2k@N}X1Z5(265{mrMizlGERI;6tKMP-tukHT}h#!tK~{-A1D;h$99@cvA> zgfVNo#tktsuCJ*ft`t)FB8Eri3vFntxa~yv1#lDjR+;q1_!yOe}syRQ#M<-Ad z%X}JjkoZ>20tT4G9iUpl>{!$7G7ngD=4p1rrk$A8P@o^BGs&rFJjd90TNtJ3tqr*M zx8eKwXGonoyoTY=6IsWE@9#EU6ZHE5OsDVSe2 z^~-f_r}4XL)yyrUlGx>R+}cK+atd@?pP!a)(Zudp1&=0G!{^~fAy0_vZ14ZUtmG$k z&kv1@p0W7%J76n)Td2rBnaVaDsaUR)aB+X8Et{}6jUg5o=iI9e!uD0`D^iwK91m+j zQ!M3?@7Ey@%v+h7(mWdU=!-+0Oz*5y7I-Z-nFFMqVw_0)8R zTjOt({hl^N0@ZeGStJq7d2`~jam-4+A8`kGY2w=AF^{bHBOlJYdVOZpXic7+xP+-F ze9L*`XQ(jY+|md^#H7}I@~?~%I?>pnR_IHwnwc#-Cr+ZMAlOm1vUpb)@*{RLS2k#G zT4&{BTDDMM!Jk=Y3j=!Syu8hC(MgFdyaBZz+gR&VmkE*$`;)IRSf!og0QBkhPSG<2 zHHoJaxo+^8DGuGEliU|WajQh4gW|LpVpD|)M=7JEbCOTBIgP8wEzLJ{L>&T<)m_y8 zAA9c|4rkZ(4HFST5Q0PvK`=t1cZn9GGrCbCO0>b~M2ir;4MU>0!RTf5F42QTH%c&i z4bh?`-$?H3danDupZj{=?|q){`2KnSI=ACE&AIp5YyH-5ueJBu$GnD|Gro#A=2Ebz z$7r(3uxMXu)p5(Rs-hPsA@Ah$l7vBh60rRaUrGy?y1;C&wzc1rhug4#-59qtc4StR zQt`g2NY(h3ZStaF)T2&)$Z~u@!liwQ6py(-EF<@`?J2qIb=$+>VK!OZ!xk;`!Xu2x z(FD>T{a(K5by2=lSVQvT6JyCdIX$f_A9@dDi*!GVtcZeOWOtP0ef0W-Wx#6XA zGmc;KMo-r#$p``JJ9{Z;?N`yax<+FR!}2a7cUpepbPxO@Q5;oMCKYj4)&-mSU5&&+ zqciJ-;gz9%>f^+^k6;omM(JBAh6*vZzO&r!kfO@rP$Dd@aw?r>{le9;_se&uG-dN8vLx0q5t4MMLlWk*=GUdXuVUkWg$v3B_ zI`8tiTlKjaRP<&N>>noD_cOP~-Om!1%2puaYc^>lj9g(h6Sq1nussht30m5wktq5N z2iOg)ZrDf<7jVnpNba3o=nz%mROI8EJpb z)j~VYH}N=qE#h8_@l%VfTZ)jq$wwAD`TCci1=BOLo5t20jGMScMC7oZPr^ zt1lXdAPH*?+Gnp7`F+ytKWQq!XAoXo{TWD$A{e}Yo#UxOuC}!9lRGrbzgJjz?(ct8 z_1bO?>9VU=`Cel7P#vu;G`wZGa|ca<1}xqS^_|M%-r^fP)|M3XUvNm#Hhx&-UCJL-~BMa%5jCDZ28 z<9v*x-Vwv2-m}v#?a<`A7bYxVVOI0c*u9RUFq>9$?6U7G^=&LO=j5Fds)CJ8jiZ{! zx=H{X>8K9|Dmu7W9^3(BY?xoQOzup9RL-xwZOEn?_)txFhy_+S*T$Pc$$P%=O|qlV zt>l+)+Ln5CcLpDr=EhiAu@uG^Si}GuPWJ*}W%vbDx8UZP-+zo7syEVhsH~LIE^o=B z&|~Ba4kPwlQBzZ=^103kCW`Dwap8_9gR8r{G184@SPNXPm~3g*`R*>AvwMH%jZc<_ z9NRI{QDp8i_*E=)_Hb-)Dt|UEZ^yQ}%`gT2NZ!=7FTNuXySU;S2Yi=x_qds_3a<7! zdOq9wVI#^KOM@Hceay=PU|@ngbwYJKcG0sRBMeFE0PT)VT6ISJ+i zFWudiIax8tzPdc@Vb7g6n;{o35|-TMOR{-JLoVTZR{It%@tbl>3O+n@#w7YZ<4AYG zQiSoU;nc8jh{GcddN|e1aU(PKEdB0mvYN{U46QE3wJfzv`EC?=;zVa=7R!X=Z0bT_ zZ*FSVTaZeUuQMv*;CPWGkXhEBGT+i1s$JW^+P}T7c~|GXCQ#C_M-8m7&8g4M%!y+$ ziWSr5?(WB5>tn8gyy8>wZ^xhelRh@~`92#mJRvk`Eqvy{9DH*)-vc=1;q`-|^8;S19kb4So{o zi@B@NXQu$ZViHl5np7f4&e^<402zW*ci%m`j*T|VGaxZEeF@$~*d1atGgye4W7ILP zByr^2EK*rlu8KB{W=HT+`y^o8>9IUG-Hu`KqnnE^P&jzKF`HX!JaO?OuP&Xh-27E8 z#yD0_J!~Nh^sP#pXy4o42Q6!>iuBfJ!e{i7_(6)NeOmp~Yner*`$S=@SL$Nm(NS*f z25P?brxj&i8~jzjbM@9v8cKyiJMG^`;Ni>Tq(6$4p!*9Gt|{%T-gwwk$)zwCykP(C z3R#@!7wYzQlglVrr(I?9vx|mR$xBqFdp;UgDW`J`9nC1FE`CP7U8YyGOp}@Uyx(D5 z>uS;JdbL!&``p)r4IlF^M>Fo#*!ZXd`hD+Kv}|Qj;73lLRx%lzkEJ6BmQL4tuh?|i zVZEq2z!IC%W?!=ownJFH`J1rhVyhmZhxw`V(}pLk(2Wm-ag{>L**GEtzA(nMv4`*4 zRYZAS?5nmr;j((T_yb!?>|i zH|u-xJ!%?@1^3yjBn_J%-#fjGhvn26y8C07=`z32I(5&$S)5^lmmO>-nOjDpQh&v) z97}>@aRxPbLOF_|InwZry z4I6Q1{N54@WtIaPL4U)%gMXJ-U?8}ds9Hlp#H2KSRU(ogX7 z+~#;-b4h~(Xo|CG`*JKS9PeC)!`|yzHI&f0OMW+WUP*Zn9Kjx7>DTM_5G7P4(&LNVSifFoke4t_!QD+bRu5TSis9Tb*#dqlV6NfBM zAkbXwt!^%v{6mS$_|-MFkMmCHUL?QcKi^5lLpCL9j-R8CB#$KFvvTSFfjKRe>+BU4r=_?oE z{q12G&D}0t%&xm$vH5gK{OrhW-36l=Wernp`Ji4MKV^3;{($5+M%=C$|Ih+IN!(XU{OpZzbS5^VV> z=u%@)8)Va%T%wVx#b*`TzmseTtq15ny56%`d3P%W-040#jaJ(kNzw}C&=w3<#5~Ty z(qSz1R6kQaGKT`ZJ-oXTN4(V1K5J&zU7gSxR>>FI>ixxrMJ1KKYuV^4-X7gxH4>L? z{)zL(duNH@JVs6a@tMeWf`bV`D2-t~w!XzBSYb7O4@=UUB&zOKl(_M1ON|d=Lt@Z? zfTg;gHiXsM z1L*I`1!JBkolYu>tck9a(7R&|aq%*}AR&nVJ5Eu$B`2j<1=B5>XT7 zQy(XQ$BdrG@o`%e8ms9oyDtn85f6wPll>MWjE?bm*$VmII~E@(kxH_h=t8kvi(MnH z!!_;8DuRFc3PD_1%g#?6M~BO}u);-wYhkQg>O^wg=6!6M&gMdLsWk6P{yPbeLUE_X zHX1gj^Z@gCQ=jv-P<$aehqA+Wu)ShAUFw| zW5}5$gOzW_rr#9!AUi)yHDoR+* zL<%Y`N)$zX$Mn5ZyH$_!q$q~A9cE-~b4{IpE$ZwHgd}?$80ty$GT6Lu_EZVuflTUP z0@Oq|ytt34W_^F+WWd-jbDe^Zr-V=u(3&SNm5o!%eNp9Jr&?KG6Ek$F&ybQfvT za?WHE;Jga-V)gX>_GQXG_~NGRuGqxXNAhK@gtvo*3&^EI=FXtg>+GeA{3EZ1g@1{u z?K0K5ynN(^oF3ULD=atCvVzT9hINU(Rx3`uiqLNt{YsU(YC$_&bnx=t0b*7-jN~>t z(5$QlY<}1QO?_!MY`Xn8=ZjKx(2pI+4}ue8-ds(Z4{cQ}nZ9EXboHy=>G*jGAU2Rl zD>hX#>oB%YpVlpOhlVy#W3>ggGK*AG7}M+>68v_Ne}JYtHNQVUHiV)vUEp?tlVDS{ zyy`SS&Wn3(O9`*z14Nd7t5SCsT{AX*UoRQ68N6}ZUUAsN&BX9Ut254ObC2=6xSE3b#JI02N_prYZYiFaDblCF zj@&Ebv`sQ^MV9W!r5+9fRwVNBfr`qoo4W3GnO;O1?NTGglZJ+}_&j2$b0`*{*eV zSaK@=AJ07NLzc_lm=fPZf?DNEu{-F2$5t7CG~VTmW+-69-}yZFf8E)F13&)yr1*dL zv)-4zU9ivr=&eo}W7imWn?Ih(k_tI{ zX&;;3{g2M%e<7T|69CBfZ|3rsg6#i)CDnKrRbxY$#73W>EEd+|7vYgeRVe~VLn>uRV=W0^vR{EIyZ8hzey|D_Fo zr@LP(|NY#wQ2(D=%m1)8Y4zmw0efm~{3ZrX^4E*)sXF*bqK0yednW2>e9 zYDhQOkOWW;J^qKm{3;yG<>meit(ki-A@>U60gS*DI3889K9zJa81fSbd%FJ{?ed48 zILxR1r#|s$SnHbq*ljz>Y|GPC+Ap}lz$9j~n&~G?@nE5!IFnw{w6<51&~OHZnRcj| zeb$7GQbHafa4rs85_Cw`uwxv1wA^U1v8lFV6jly>6$jqH7Nnx7`EC(^U!X?5eVtjc zfp7oIu0~#pG6W%)#l*$#&efY@JO0=XEoe7fgs<>J)r+pG(Y0BXVzR#SdF3`TB5;m` zz@3VZ-o)FCh5atv7**RlH(h}G;AJWyziR7H_6^d4+A1du=La7YGhsJ9Wel(G(ep_dk}=yTX^F?$q$AL9kB*pw>b3H6NzH zo`qMY)CEdIN!Y7Bq^K-V>Q{BW7F@h;|1nC&Uf! z=?8~tIPTY8^a)!whXE&!^9=as8|iw-&q}%y@dl#u9i*?4spQ`6Dx84e0eYRD(}x`$ zn>qu-^DvL+IICX}ICbObe%f-lKx}<`hR&KnC?xJ1#qqsxrbtS-<6`$LzC%Ni

_5 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 z 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 Date: Mon, 13 Aug 2018 22:44:41 +0800 Subject: [PATCH 13/48] Update .gitattributes --- .gitattributes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 13a5032..9ff5125 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1 @@ -*.md linguist-language=html \ No newline at end of file +*.md linguist-language=php From 21d8f23b165104a8937874ebf93edf56d315cab5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=97=B2=E4=BA=91=E9=87=8E=E9=B9=A4?= Date: Mon, 3 Sep 2018 23:28:57 +0800 Subject: [PATCH 14/48] Set theme jekyll-theme-minimal --- _config.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 _config.yml diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000..2f7efbe --- /dev/null +++ b/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-minimal \ No newline at end of file From ee4c036a45506e60f885ee20b3e442908fd5cee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=97=B2=E4=BA=91=E9=87=8E=E9=B9=A4?= Date: Mon, 3 Sep 2018 23:30:23 +0800 Subject: [PATCH 15/48] Set theme jekyll-theme-tactile --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 2f7efbe..259a24e 100644 --- a/_config.yml +++ b/_config.yml @@ -1 +1 @@ -theme: jekyll-theme-minimal \ No newline at end of file +theme: jekyll-theme-tactile \ No newline at end of file From 8bdec3b63886cd5159a6c03bbf665a53bd5f5dee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=97=B2=E4=BA=91=E9=87=8E=E9=B9=A4?= Date: Mon, 3 Sep 2018 23:30:45 +0800 Subject: [PATCH 16/48] Set theme jekyll-theme-architect --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 259a24e..3397c9a 100644 --- a/_config.yml +++ b/_config.yml @@ -1 +1 @@ -theme: jekyll-theme-tactile \ No newline at end of file +theme: jekyll-theme-architect \ No newline at end of file From 6ffa9e7ef84368fd1b0ee5e2bd9962ad6e1f3598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=97=B2=E4=BA=91=E9=87=8E=E9=B9=A4?= Date: Mon, 3 Sep 2018 23:34:18 +0800 Subject: [PATCH 17/48] Set theme jekyll-theme-tactile --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 3397c9a..259a24e 100644 --- a/_config.yml +++ b/_config.yml @@ -1 +1 @@ -theme: jekyll-theme-architect \ No newline at end of file +theme: jekyll-theme-tactile \ No newline at end of file From f365c2e508a55b2e59186c153d8cd60179b94d74 Mon Sep 17 00:00:00 2001 From: xianyunyh Date: Mon, 1 Oct 2018 13:33:20 +0800 Subject: [PATCH 18/48] edit readme --- README.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fb5af24..d6b62fa 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,10 @@ 这个项目是自己准备面试整理的资料。可能包括PHP、MySQL等资料。方便自己以后查阅,会不定期更新,如果错误,请指出,谢谢。欢迎大家提交PR,谢谢大家的star -有童鞋提议整理成gitbook的版本的。于是我又开了一个gitbook的分支。来完善这个。目前还没整理完成。 - 可以通过[https://xianyunyh.gitbooks.io/php-interview/](https://xianyunyh.gitbooks.io/php-interview/)预览。欢迎有精力的朋友完善一下。谢谢。 -[GITbooK分支](https://github.com/xianyunyh/PHP-Interview/tree/gitbook) + +### 目录 - [Linux](Linux/REAMDE.md) @@ -101,8 +100,18 @@ - [面试](面试/README.md) - + + +## 生成自己的Gitbook + +```bash +$ npm install gitbook-cli -g +$ git clone https://github.com/xianyunyh/PHP-Interview +$ cd PHP-Interview +$ gitbook serve # 本地预览 +$ gitbook build # 生成静态的html +``` ##推荐阅读资料 - [PHP函数库](http://overapi.com/php) @@ -122,4 +131,4 @@ 如果这个系列的文章,对您有所帮助,您可以选择打赏一下作者。谢谢! -![](mm_reward_qrcode.jpg) \ No newline at end of file +![qrcode](mm_reward_qrcode.jpg) \ No newline at end of file From d3c1a57001094dbeca362aa70104145c95a80b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=97=B2=E4=BA=91=E9=87=8E=E9=B9=A4?= Date: Sun, 18 Nov 2018 19:07:34 +0800 Subject: [PATCH 19/48] =?UTF-8?q?Update=20=E7=AC=94=E8=AF=95=E9=A2=984.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\347\254\224\350\257\225\351\242\2304.md" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/\351\235\242\350\257\225/\347\254\224\350\257\225\351\242\2304.md" "b/\351\235\242\350\257\225/\347\254\224\350\257\225\351\242\2304.md" index c945417..b2237af 100644 --- "a/\351\235\242\350\257\225/\347\254\224\350\257\225\351\242\2304.md" +++ "b/\351\235\242\350\257\225/\347\254\224\350\257\225\351\242\2304.md" @@ -10,7 +10,7 @@ 3. `$a = 3; echo "$a",'$a',"\\\$a","$a"."$a","$a"+"$a"` - 33$a\$a336 + 3$a\$a336 4. require include区别 @@ -65,4 +65,4 @@ 19. 项目中遇到了什么问题, 20. 之前的项目有没有其他的优化方案? 21. 平时怎么学习的? -22. 未来的职业的职业方向? \ No newline at end of file +22. 未来的职业的职业方向? From 4e3d3124c5e1611347cb706942a1a3987fcfaf1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=97=B2=E4=BA=91=E9=87=8E=E9=B9=A4?= Date: Sun, 18 Nov 2018 19:09:14 +0800 Subject: [PATCH 20/48] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dcrontale=E4=B8=AD?= =?UTF-8?q?=E7=9A=84=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Linux/crontab.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Linux/crontab.md b/Linux/crontab.md index b79a303..e0f7273 100644 --- a/Linux/crontab.md +++ b/Linux/crontab.md @@ -19,7 +19,7 @@ ```shell * * * * * echo "hello" #每1分钟执行hello -3,15 * * * * myCommand #每小时第三分钟和第五分钟执行 +3,15 * * * * myCommand #每小时第三分钟和第十五分钟执行 3,15 8-11 * * * myCommand# 在上午8点到11点的第3和第15分钟执行 3,15 8-11 */2 * * myCommand #每隔两天的上午8点到11点的第3和第15分钟执行 30 21 * * * /etc/init.d/smb restart #每晚的21:30重启smb @@ -34,4 +34,4 @@ ``` $service cron restart -``` \ No newline at end of file +``` From 04dc8b10ab165a67810783cad7fa607cbeb16beb Mon Sep 17 00:00:00 2001 From: Kael Li Date: Sat, 29 Dec 2018 14:40:15 +0800 Subject: [PATCH 21/48] =?UTF-8?q?=E5=86=85=E5=AE=B9=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E5=8A=A0=E6=A0=BC=E5=BC=8F=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kael Li --- "Linux/LinuxIO\346\250\241\345\236\213.md" | 32 +-- "Linux/Linux\345\221\275\344\273\244.md" | 6 +- "Mysql/MySQL\344\274\230\345\214\226.md" | 3 +- ...45\350\257\242\344\274\230\345\214\226.md" | 200 ++++++++++-------- 4 files changed, 127 insertions(+), 114 deletions(-) diff --git "a/Linux/LinuxIO\346\250\241\345\236\213.md" "b/Linux/LinuxIO\346\250\241\345\236\213.md" index 17b3c0d..c1d34d8 100644 --- "a/Linux/LinuxIO\346\250\241\345\236\213.md" +++ "b/Linux/LinuxIO\346\250\241\345\236\213.md" @@ -6,7 +6,7 @@ ### 2. 进程切换 -为了控制进程的执行,内核必须有能力挂起正在CPU上运行的进程,并恢复以前挂起的某个进程的执行。这种行为被称为进程切换。因此可以说,任何进程都是在操作系统内核的支持下运行的,是与内核紧密相关的 +为了控制进程的执行,内核必须有能力挂起正在CPU上运行的进程,并恢复以前挂起的某个进程的执行。这种行为被称为进程切换。因此可以说,任何进程都是在操作系统内核的支持下运行的,是与内核紧密相关的 从一个进程的运行转到另一个进程上运行,这个过程中经过下面这些变化: @@ -17,23 +17,23 @@ > 5. 更新内存管理的数据结构。 > 6. 恢复处理机上下文。 - + ### 3. 进程的阻塞 -> 正在执行的进程,由于期待的某些事件未发生,如请求系统资源失败、等待某种操作的完成、新数据尚未到达或无新工作做等,则由系统自动执行阻塞原语(Block),使自己由运行状态变为阻塞状态。可见,进程的阻塞是进程自身的一种主动行为,也因此只有处于运行态的进程(获得CPU),才可能将其转为阻塞状态。`当进程进入阻塞状态,是不占用CPU资源的`。 +> 正在执行的进程,由于期待的某些事件未发生,如请求系统资源失败、等待某种操作的完成、新数据尚未到达或无新工作做等,则由系统自动执行阻塞原语(Block),使自己由运行状态变为阻塞状态。可见,进程的阻塞是进程自身的一种主动行为,也因此只有处于运行态的进程(获得CPU),才可能将其转为阻塞状态。`当进程进入阻塞状态,是不占用CPU资源的`。 ### 4. 进程缓存区、内核缓冲区 缓冲区的出现是为了减少频繁的系统调用,由于系统调用需要保存之前的进程数据和状态等信息,而结束调用之后回来还需要回复之前的信息,为了减少这种耗时耗性能的调用于是出现了缓冲区。在linux系统中,每个进程有自己独立的缓冲区,叫做**进程缓冲区**,而系统内核也有个缓冲区叫做**内核缓冲区**。 - **操作系统使用read函数把数据从内核缓冲区复制到进程缓冲区,write把数据从进程缓冲区 复制到内核缓冲区中** + **操作系统使用read函数把数据从内核缓冲区复制到进程缓冲区,write把数据从进程缓冲区复制到内核缓冲区中** ### 5. 文件描述符fd 文件描述符(File descriptor)是计算机科学中的一个术语,`是一个用于表述指向文件的引用的抽象化概念`。 文件描述符在形式上是一个非负整数。实际上,`它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表`。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开 -## Linx/Unix 5种IO模型 +## Linx/Unix 5种IO模型 当一个io发生时候的,涉及到的步骤和对象 @@ -46,12 +46,12 @@ 经历的步骤 -- 等待数据准备,比如accept(), recv()等待数据 -- 将数据从内核拷贝到进程中, 比如 accept()接受到请求,recv()接收连接发送的数据后需要复制到内核,再从内核复制到进程**用户空间** +- 等待数据准备,比如accept(), recv()等待数据 +- 将数据从内核拷贝到进程中, 比如 accept()接受到请求,recv()接收连接发送的数据后需要复制到内核,再从内核复制到进程**用户空间** ### 阻塞IO -![img](https://upload-images.jianshu.io/upload_images/1446087-9522cafa9e14abd0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/552) +![img](https://upload-images.jianshu.io/upload_images/1446087-9522cafa9e14abd0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/552) > 当用户进程调用了recvfrom这个系统调用,kernel就开始了IO的第一个阶段:准备数据(对于网络IO来说,很多时候数据在一开始还没有到达。比如,还没有收到一个完整的UDP包。这个时候kernel就要等待足够的数据到来)。这个过程需要等待,也就是说数据被拷贝到**操作系统内核的缓冲区**中是需要一个过程的。而在用户进程这边,整个进程会被阻塞(当然,是进程自己选择的阻塞)。当kernel一直等到数据准备好了,它就会**将数据从kernel中拷贝到用户内存**,然后kernel返回结果,用户进程才解除block的状态,重新运行起来。 @@ -59,7 +59,7 @@ ### 非阻塞IO -![img](https://upload-images.jianshu.io/upload_images/1446087-0c604ff4a2d8dc5d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/603) +![img](https://upload-images.jianshu.io/upload_images/1446087-0c604ff4a2d8dc5d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/603) 当用户进程发出read操作时,如果kernel中的数据还没有准备好,**那么它并不会block用户进程,而是立刻返回一个error**。从用户进程角度讲 ,它发起一个read操作后,并不需要等待,而是马上就得到了一个结果。用户进程判断结果是一个error时,它就知道数据还没有准备好,于是它可以再次发送read操作。一旦kernel中的数据准备好了,并且又再次收到了用户进程的system call,那么它马上就将数据拷贝到了用户内存,然后返回 @@ -67,27 +67,27 @@ IO multiplexing就是我们说的select,poll,epoll,有些地方也称这种IO方式为event driven IO。select/epoll的好处就在于单个process就可以同时处理多个网络连接的IO。它的基本原理就是select,poll,epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。 -![img](https://upload-images.jianshu.io/upload_images/1446087-3b0399b077daf0a8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/609) +![img](https://upload-images.jianshu.io/upload_images/1446087-3b0399b077daf0a8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/609) -在一个调用中阻塞`select`,等待数据报套接字可读。当`select` 返回套接字可读时,我们然后调用`recvfrom` 将数据报复制到我们的应用程序缓冲区中 .使用`select`需要两次系统调用而不是一次 +在一个调用中阻塞`select`,等待数据报套接字可读。当`select` 返回套接字可读时,我们然后调用`recvfrom` 将数据报复制到我们的应用程序缓冲区中 .使用`select`需要两次系统调用而不是一次 在IO multiplexing Model中,实际中,**对于每一个socket,一般都设置成为non-blocking,因为只有设置成non-blocking 才能使单个线程/进程不被阻塞(或者说锁住),可以继续处理其他socket。如上图所示,整个用户的process其实是一直被block的。只不过process是被select这个函数block,而不是被socket IO给block。** ### 异步 I/O -![img](https://upload-images.jianshu.io/upload_images/1446087-e707464b299104e1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/572) +![img](https://upload-images.jianshu.io/upload_images/1446087-e707464b299104e1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/572) 用户进程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从kernel的角度,当它受到一个asynchronous read之后,首先它会立刻返回,所以不会对用户进程产生任何block。然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发送一个signal,告诉它read操作完成了 ### 异步、同步、阻塞、非阻塞 -同步就是一个任务的完成需要依赖另外一个任务时,只有等待被依赖的任务完成后,依赖的任务才能算完成,这是一种可靠的任务序列 +同步就是一个任务的完成需要依赖另外一个任务时,只有等待被依赖的任务完成后,依赖的任务才能算完成,这是一种可靠的任务序列 -异步是不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了 +异步是不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了 -阻塞调用是指调用结果返回之前,当前线程会被挂起,一直处于等待消息通知,不能够执行其他业务 +阻塞调用是指调用结果返回之前,当前线程会被挂起,一直处于等待消息通知,不能够执行其他业务 -非阻塞调用指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回 +非阻塞调用指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回 异步、同步是发生在用户空间内,当用户发起一个IO的调用的时候,同步的时候,如果这个操作比较耗时间,会阻塞后面的流程 diff --git "a/Linux/Linux\345\221\275\344\273\244.md" "b/Linux/Linux\345\221\275\344\273\244.md" index e26973b..c59a44a 100644 --- "a/Linux/Linux\345\221\275\344\273\244.md" +++ "b/Linux/Linux\345\221\275\344\273\244.md" @@ -134,7 +134,7 @@ sed '/^$/d' file #删除空白行 详细教程可以查看 http://awk.readthedocs.io/en/latest/chapter-one.html ```shell -awk ' BEGIN{ statements } statements2 END{ statements } ' +awk ' BEGIN{ statements } statements2 END{ statements } ' ``` 工作流程 @@ -161,11 +161,11 @@ $2:第二个字段的文本内容; awk '{print $2, $3}' file # 日志格式:'$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"' #统计日志中访问最多的10个IP -awk '{a[$1]++}END{for(i in a)print a[i],i|"sort -k1 -nr|head -n10"}' access.log +awk '{a[$1]++}END{for(i in a)print a[i],i|"sort -k1 -nr|head -n10"}' access.log ``` -### 排序 port +### 排序 sort - -n 按数字进行排序 VS -d 按字典序进行排序 - -r 逆序排序 diff --git "a/Mysql/MySQL\344\274\230\345\214\226.md" "b/Mysql/MySQL\344\274\230\345\214\226.md" index bcc8aa4..4531e19 100644 --- "a/Mysql/MySQL\344\274\230\345\214\226.md" +++ "b/Mysql/MySQL\344\274\230\345\214\226.md" @@ -34,9 +34,8 @@ select * from user where name like '%a' - 应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描 -- 很多时候用 exists 代替 in 是一个好的选择: +- 很多时候用 exists 代替 in 是一个好的选择 -- ## btree索引 diff --git "a/Mysql/MySQL\347\264\242\345\274\225\345\216\237\347\220\206\345\217\212\346\205\242\346\237\245\350\257\242\344\274\230\345\214\226.md" "b/Mysql/MySQL\347\264\242\345\274\225\345\216\237\347\220\206\345\217\212\346\205\242\346\237\245\350\257\242\344\274\230\345\214\226.md" index 46caa30..2fcb85e 100644 --- "a/Mysql/MySQL\347\264\242\345\274\225\345\216\237\347\220\206\345\217\212\346\205\242\346\237\245\350\257\242\344\274\230\345\214\226.md" +++ "b/Mysql/MySQL\347\264\242\345\274\225\345\216\237\347\220\206\345\217\212\346\205\242\346\237\245\350\257\242\344\274\230\345\214\226.md" @@ -4,14 +4,14 @@ MySQL凭借着出色的性能、低廉的成本、丰富的资源,已经成为 ```sql select - count(*) + count(*) from - task + task where - status=2 - and operator_id=20839 - and operate_time>1371169729 - and operate_time<1371174603 + status=2 + and operator_id=20839 + and operate_time>1371169729 + and operate_time<1371174603 and type=2; ``` @@ -42,10 +42,10 @@ various-system-software-hardware-latencies ### 详解b+树 -![b+树](https://tech.meituan.com/img/mysql_index/btree.jpg) +![b+树](https://tech.meituan.com/img/mysql_index/btree.jpg) b+树 -如上图,是一颗b+树,关于b+树的定义可以参见B+树,这里只说一些重点,浅蓝色的块我们称之为一个磁盘块,可以看到每个磁盘块包含几个数据项(深蓝色所示)和指针(黄色所示),如磁盘块1包含数据项17和35,包含指针P1、P2、P3,P1表示小于17的磁盘块,P2表示在17和35之间的磁盘块,P3表示大于35的磁盘块。真实的数据存在于叶子节点即3、5、9、10、13、15、28、29、36、60、75、79、90、99。非叶子节点只不存储真实的数据,只存储指引搜索方向的数据项,如17、35并不真实存在于数据表中。 +如上图,是一颗b+树,关于b+树的定义可以参见B+树,这里只说一些重点,浅蓝色的块我们称之为一个磁盘块,可以看到每个磁盘块包含几个数据项(深蓝色所示)和指针(黄色所示),如磁盘块1包含数据项17和35,包含指针P1、P2、P3,P1表示小于17的磁盘块,P2表示在17和35之间的磁盘块,P3表示大于35的磁盘块。真实的数据存在于叶子节点即3、5、9、10、13、15、28、29、36、60、75、79、90、99。非叶子节点不存储真实的数据,只存储指引搜索方向的数据项,如17、35并不真实存在于数据表中。 ### b+树的查找过程 @@ -82,12 +82,12 @@ select count(*) from task where status = 0 ; ### 慢查询优化基本步骤 0. 先运行看看是否真的很慢,注意设置SQL_NO_CACHE -1.where条件单表查,锁定最小返回记录表。这句话的意思是把查询语句的 where都应用到表中返回的记录数最小的表开始查起,单表每个字段分别查询,看哪个字段的区分度最高 -1. explain查看执行计划,是否与1预期一致(从锁定记录较少的表开始查询) -2. order by limit 形式的sql语句让排序的表优先查 -3. 了解业务方使用场景 -4. 加索引时参照建索引的几大原则 -5. 观察结果,不符合预期继续从0分析 +1. where条件单表查,锁定最小返回记录表。这句话的意思是把查询语句的 where都应用到表中返回的记录数最小的表开始查起,单表每个字段分别查询,看哪个字段的区分度最高 +2. explain查看执行计划,是否与1预期一致(从锁定记录较少的表开始查询) +3. order by limit 形式的sql语句让排序的表优先查 +4. 了解业务方使用场景 +5. 加索引时参照建索引的几大原则 +6. 观察结果,不符合预期继续从0分析 几个慢查询案例 下面几个例子详细解释了如何分析和优化慢查询 @@ -97,32 +97,32 @@ select count(*) from task where status = 0 ; ```sql select - distinct cert.emp_id + distinct cert.emp_id from - cm_log cl + cm_log cl inner join ( select emp.id as emp_id, - emp_cert.id as cert_id + emp_cert.id as cert_id from - employee emp + employee emp left join - emp_certificate emp_cert - on emp.id = emp_cert.emp_id + emp_certificate emp_cert + on emp.id = emp_cert.emp_id where emp.is_deleted=0 - ) cert + ) cert on ( - cl.ref_table='Employee' + cl.ref_table='Employee' and cl.ref_oid= cert.emp_id - ) + ) or ( - cl.ref_table='EmpCertificate' + cl.ref_table='EmpCertificate' and cl.ref_oid= cert.cert_id - ) + ) where - cl.last_upd_date >='2013-11-07 15:03:00' + cl.last_upd_date >='2013-11-07 15:03:00' and cl.last_upd_date<='2013-11-08 16:00:00'; ``` @@ -131,8 +131,9 @@ where 先运行一下,53条记录 1.87秒,又没有用聚合语句,比较慢 53 rows in set (1.87 sec) -1.explain +1.explain +```sql +----+-------------+------------+-------+---------------------------------+-----------------------+---------+-------------------+-------+--------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+-------+---------------------------------+-----------------------+---------+-------------------+-------+--------------------------------+ @@ -141,42 +142,43 @@ where | 2 | DERIVED | emp | ALL | NULL | NULL | NULL | NULL | 13317 | Using where | | 2 | DERIVED | emp_cert | ref | emp_certificate_empid | emp_certificate_empid | 4 | meituanorg.emp.id | 1 | Using index | +----+-------------+------------+-------+---------------------------------+-----------------------+---------+-------------------+-------+--------------------------------+ +``` 简述一下执行计划,首先mysql根据idx_last_upd_date索引扫描cm_log表获得379条记录;然后查表扫描了63727条记录,分为两部分,derived表示构造表,也就是不存在的表,可以简单理解成是一个语句形成的结果集,后面的数字表示语句的ID。derived2表示的是ID = 2的查询构造了虚拟表,并且返回了63727条记录。我们再来看看ID = 2的语句究竟做了写什么返回了这么大量的数据,首先全表扫描employee表13317条记录,然后根据索引emp_certificate_empid关联emp_certificate表,rows = 1表示,每个关联都只锁定了一条记录,效率比较高。获得后,再和cm_log的379条记录根据规则关联。从执行过程上可以看出返回了太多的数据,返回的数据绝大部分cm_log都用不到,因为cm_log只锁定了379条记录。 如何优化呢?可以看到我们在运行完后还是要和cm_log做join,那么我们能不能之前和cm_log做join呢?仔细分析语句不难发现,其基本思想是如果cm_log的ref_table是EmpCertificate就关联emp_certificate表,如果ref_table是Employee就关联employee表,我们完全可以拆成两部分,并用union连接起来,注意这里用union,而不用union all是因为原语句有“distinct”来得到唯一的记录,而union恰好具备了这种功能。如果原语句中没有distinct不需要去重,我们就可以直接使用union all了,因为使用union需要去重的动作,会影响SQL性能。 优化过的语句如下 ```sql select - emp.id + emp.id from - cm_log cl + cm_log cl inner join - employee emp - on cl.ref_table = 'Employee' - and cl.ref_oid = emp.id + employee emp + on cl.ref_table = 'Employee' + and cl.ref_oid = emp.id where - cl.last_upd_date >='2013-11-07 15:03:00' - and cl.last_upd_date<='2013-11-08 16:00:00' - and emp.is_deleted = 0 + cl.last_upd_date >='2013-11-07 15:03:00' + and cl.last_upd_date<='2013-11-08 16:00:00' + and emp.is_deleted = 0 union select - emp.id + emp.id from - cm_log cl + cm_log cl inner join - emp_certificate ec - on cl.ref_table = 'EmpCertificate' - and cl.ref_oid = ec.id + emp_certificate ec + on cl.ref_table = 'EmpCertificate' + and cl.ref_oid = ec.id inner join - employee emp - on emp.id = ec.emp_id + employee emp + on emp.id = ec.emp_id where - cl.last_upd_date >='2013-11-07 15:03:00' - and cl.last_upd_date<='2013-11-08 16:00:00' + cl.last_upd_date >='2013-11-07 15:03:00' + and cl.last_upd_date<='2013-11-08 16:00:00' and emp.is_deleted = 0  ``` -不需要了解业务场景,只需要改造的语句和改造之前的语句保持结果一致 +4.不需要了解业务场景,只需要改造的语句和改造之前的语句保持结果一致 5.现有索引可以满足,不需要建索引 @@ -188,12 +190,12 @@ where ```sql select from -stage_poi sp +stage_poi sp where -sp.accurate_result=1 +sp.accurate_result=1 and ( - sp.sync_status=0 - or sp.sync_status=2 + sp.sync_status=0 + or sp.sync_status=2 or sp.sync_status=4 ); @@ -202,6 +204,7 @@ and ( 0.先看看运行多长时间,951条数据6.22秒,真的很慢 951 rows in set (6.22 sec) + 1.先explain,rows达到了361万,type = ALL表明是全表扫描 2.所有字段都应用查询返回记录数,因为是单表查询 0已经做过了951条 @@ -210,6 +213,7 @@ and ( 看一下accurate_result = 1的记录数 +```sql select count(*),accurate_result from stage_poi group by accurate_result; +----------+-----------------+ | count(*) | accurate_result | @@ -218,12 +222,14 @@ select count(*),accurate_result from stage_poi group by accurate_result; | 2114655 | 0 | | 972815 | 1 | +----------+-----------------+ +``` 我们看到accurate_result这个字段的区分度非常低,整个表只有-1,0,1三个值,加上索引也无法锁定特别少量的数据 再看一下sync_status字段的情况 +```sql select count(*),sync_status from stage_poi group by sync_status; +----------+-------------+ | count(*) | sync_status | @@ -231,6 +237,7 @@ select count(*),sync_status from stage_poi group by sync_status; | 3080 | 0 | | 3085413 | 3 | +----------+-------------+ +``` 同样的区分度也很低,根据理论,也不适合建立索引 @@ -241,15 +248,17 @@ select count(*),sync_status from stage_poi group by sync_status; 5.根据建立索引规则,使用如下语句建立索引 -alter table stage_poi add index idx_acc_status(accurate_result,sync_status); +```alter table stage_poi add index idx_acc_status(accurate_result,sync_status);``` 6.观察预期结果,发现只需要200ms,快了30多倍。 952 rows in set (0.20 sec) + 我们再来回顾一下分析问题的过程,单表查询相对来说比较好优化,大部分时候只需要把where条件里面的字段依照规则加上索引就好,如果只是这种“无脑”优化的话,显然一些区分度非常低的列,不应该加索引的列也会被加上索引,这样会对插入、更新性能造成严重的影响,同时也有可能影响其它的查询语句。所以我们第4步调差SQL的使用场景非常关键,我们只有知道这个业务场景,才能更好地辅助我们更好的分析和优化查询语句。 无法优化的语句 +```sql select c.id, c.name, @@ -266,37 +275,37 @@ select c.data_source, from_unixtime(c.created_time) as created_time, from_unixtime(c.last_modified) as last_modified, - c.last_modified_user_id + c.last_modified_user_id from - contact c + contact c inner join - contact_branch cb - on c.id = cb.contact_id + contact_branch cb + on c.id = cb.contact_id inner join - branch_user bu - on cb.branch_id = bu.branch_id + branch_user bu + on cb.branch_id = bu.branch_id and bu.status in ( 1, - 2) + 2) inner join - org_emp_info oei - on oei.data_id = bu.user_id - and oei.node_left >= 2875 - and oei.node_right <= 10802 - and oei.org_category = - 1 + org_emp_info oei + on oei.data_id = bu.user_id + and oei.node_left >= 2875 + and oei.node_right <= 10802 + and oei.org_category = - 1 order by c.created_time desc limit 0 , 10; - +``` 还是几个步骤 0.先看语句运行多长时间,10条记录用了13秒,已经不可忍受 10 rows in set (13.06 sec) + 1.explain ```sql - +----+-------------+-------+--------+-------------------------------------+-------------------------+---------+--------------------------+------+----------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+-------------------------------------+-------------------------+---------+--------------------------+------+----------------------------------------------+ @@ -314,22 +323,22 @@ rows返回的都非常少,看不到有什么异常情况。我们在看一下 select count(*) from - contact c + contact c inner join - contact_branch cb - on c.id = cb.contact_id + contact_branch cb + on c.id = cb.contact_id inner join - branch_user bu - on cb.branch_id = bu.branch_id + branch_user bu + on cb.branch_id = bu.branch_id and bu.status in ( 1, - 2) + 2) inner join - org_emp_info oei - on oei.data_id = bu.user_id - and oei.node_left >= 2875 - and oei.node_right <= 10802 - and oei.org_category = - 1 + org_emp_info oei + on oei.data_id = bu.user_id + and oei.node_left >= 2875 + and oei.node_right <= 10802 + and oei.org_category = - 1 +----------+ | count(*) | +----------+ @@ -390,6 +399,7 @@ c.created_time desc limit 0 , ``` 10 rows in set (0.00 sec) + 本以为至此大工告成,但我们在前面的分析中漏了一个细节,先排序再join和先join再排序理论上开销是一样的,为何提升这么多是因为有一个limit!大致执行过程是:mysql先按索引排序得到前10条记录,然后再去join过滤,当发现不够10条的时候,再次去10条,再次join,这显然在内层join过滤的数据非常多的时候,将是灾难的,极端情况,内层一条数据都找不到,mysql还傻乎乎的每次取10条,几乎遍历了这个数据表! 用不同参数的SQL试验下 @@ -410,45 +420,49 @@ select c.data_source, from_unixtime(c.created_time) as created_time, from_unixtime(c.last_modified) as last_modified, - c.last_modified_user_id + c.last_modified_user_id from - contact c + contact c where exists ( select - 1 + 1 from - contact_branch cb + contact_branch cb inner join - branch_user bu - on cb.branch_id = bu.branch_id + branch_user bu + on cb.branch_id = bu.branch_id and bu.status in ( 1, - 2) + 2) inner join - org_emp_info oei - on oei.data_id = bu.user_id - and oei.node_left >= 2875 - and oei.node_right <= 2875 - and oei.org_category = - 1 + org_emp_info oei + on oei.data_id = bu.user_id + and oei.node_left >= 2875 + and oei.node_right <= 2875 + and oei.org_category = - 1 where - c.id = cb.contact_id - ) + c.id = cb.contact_id + ) order by c.created_time desc limit 0 , 10; Empty set (2 min 18.99 sec) ``` -2 min 18.99 sec!比之前的情况还糟糕很多。由于mysql的nested loop机制,遇到这种情况,基本是无法优化的。这条语句最终也只能交给应用系统去优化自己的逻辑了。 +2 min 18.99 sec! + +比之前的情况还糟糕很多。由于mysql的nested loop机制,遇到这种情况,基本是无法优化的。这条语句最终也只能交给应用系统去优化自己的逻辑了。 通过这个例子我们可以看到,并不是所有语句都能优化,而往往我们优化时,由于SQL用例回归时落掉一些极端情况,会造成比原来还严重的后果。所以,第一:不要指望所有语句都能通过SQL优化,第二:不要过于自信,只针对具体case来优化,而忽略了更复杂的情况。 慢查询的案例就分析到这儿,以上只是一些比较典型的案例。我们在优化过程中遇到过超过1000行,涉及到16个表join的“垃圾SQL”,也遇到过线上线下数据库差异导致应用直接被慢查询拖死,也遇到过varchar等值比较没有写单引号,还遇到过笛卡尔积查询直接把从库搞死。再多的案例其实也只是一些经验的积累,如果我们熟悉查询优化器、索引的内部原理,那么分析这些案例就变得特别简单了。 -写在后面的话 +##写在后面的话 + 本文以一个慢查询案例引入了MySQL索引原理、优化慢查询的一些方法论;并针对遇到的典型案例做了详细的分析。其实做了这么长时间的语句优化后才发现,任何数据库层面的优化都抵不上应用系统的优化,同样是MySQL,可以用来支撑Google/FaceBook/Taobao应用,但可能连你的个人网站都撑不住。套用最近比较流行的话:“查询容易,优化不易,且写且珍惜!” -参考 -参考文献如下: +##参考文献如下 + 1.《高性能MySQL》 + 2.《数据结构与算法分析》 From c8c6d95df332636872980a94bdbdd7032face6d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E7=B2=BD=E5=AD=90?= <862275679@qq.com> Date: Thu, 24 Jan 2019 15:12:21 +0800 Subject: [PATCH 22/48] isset(false)=true --- .../\347\254\224\350\257\225\351\242\230.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/\351\235\242\350\257\225/\347\254\224\350\257\225\351\242\230.md" "b/\351\235\242\350\257\225/\347\254\224\350\257\225\351\242\230.md" index a2a792a..91caf33 100644 --- "a/\351\235\242\350\257\225/\347\254\224\350\257\225\351\242\230.md" +++ "b/\351\235\242\350\257\225/\347\254\224\350\257\225\351\242\230.md" @@ -217,7 +217,7 @@ function getPoint(Node $a,Node $b) { 17、**isset(null) isset(false) empty(null) empty(false)输出** -​ false,false,true,true +​ false,true,true,true,[参考](http://php.net/manual/zh/types.comparisons.php) 18、**优化MYSQL的方法** From 642dc13c3896ad0031082017e4e0bc34731df0c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E7=B2=BD=E5=AD=90?= <862275679@qq.com> Date: Thu, 24 Jan 2019 16:33:12 +0800 Subject: [PATCH 23/48] =?UTF-8?q?=E8=A1=A5=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\347\254\224\350\257\225\351\242\230.md" | 69 +++++++++++++++++-- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git "a/\351\235\242\350\257\225/\347\254\224\350\257\225\351\242\230.md" "b/\351\235\242\350\257\225/\347\254\224\350\257\225\351\242\230.md" index 91caf33..ac44e8a 100644 --- "a/\351\235\242\350\257\225/\347\254\224\350\257\225\351\242\230.md" +++ "b/\351\235\242\350\257\225/\347\254\224\350\257\225\351\242\230.md" @@ -391,15 +391,76 @@ type 记录变量的类型。然后根据不同的类型,找到不同的value ![img](01.png) -38、有两个文件文件,大小都超过了1G,一行一条数据,每行数据不超过500字节,两文件中有一部分内容是完全相同的,请写代码找到相同的行,并写到新文件中。PHP最大允许内内为255M。 +38、有两个文本文件,大小都超过了1G,一行一条数据,每行数据不超过500字节,两文件中有一部分内容是完全相同的,请写代码找到相同的行,并写到新文件中。PHP最大允许内内为255M。 + +```php +// 思路:使用协程yield +function readFieldFile($fileName) +{ + $fp = fopen($fileName, "rb"); + while (!feof($fp)) { + yield fgets($fp); + } + fclose($fp); +} + +$file1 = readFieldFile('big1.txt'); +$file2 = readFieldFile('big2.txt'); + +$file1->rewind(); +$file2->rewind(); +while ($file1->valid() && $file2->valid()) { + if ($file1->current() == $file2->current()) { + file_put_contents('big.txt', $file1->current(), FILE_APPEND); + } + $file1->next(); + $file2->next(); +} +``` 39、请写出自少两个支持回调处理的PHP函数,并自己实现一个支持回调的PHP函数 -preg_matacth_callback. call_user_func +preg_match_callback. call_user_func + +```php +function myCallBack(Closure $closure, $a, $b) +{ + return $closure($a, $b); +} + +myCallBack(function ($a, $b) { + return $a + $b; +}, 1, 2); + +``` -40、请写出自少两个获取指定文件夹下所有文件的方法(代码或思路)。 +40、请写出至少两个获取指定文件夹下所有文件的方法(代码或思路)。 + +```php +// 递归获取,排除.和..,除了文件夹就是文件 +function myScanDir($dir) +{ + $files = array(); + if (is_dir($dir)) { + if ($handle = opendir($dir)) { + while (($file = readdir($handle)) !== false) { + if ($file != "." && $file != "..") { + if (is_dir($dir . "/" . $file)) { + $files[$file] = myScanDir($dir . "/" . $file); + } else { + $files[] = $dir . "/" . $file; + } + } + } + closedir($handle); + return $files; + } + } +} + +``` -41、请写出自少三种截取文件名后缀的方法或函数(PHP原生函数和自己实现函数均可) +41、请写出至少三种截取文件名后缀的方法或函数(PHP原生函数和自己实现函数均可) basename expload() strpos From 6f966ba0d01959a115720720cb7b3f3c54705e38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=97=B2=E4=BA=91=E9=87=8E=E9=B9=A4?= Date: Fri, 25 Jan 2019 14:57:43 +0800 Subject: [PATCH 24/48] Create Git_removeCommits.md --- .../Git_removeCommits.md" | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 "\347\211\210\346\234\254\346\216\247\345\210\266\345\231\250/Git_removeCommits.md" diff --git "a/\347\211\210\346\234\254\346\216\247\345\210\266\345\231\250/Git_removeCommits.md" "b/\347\211\210\346\234\254\346\216\247\345\210\266\345\231\250/Git_removeCommits.md" new file mode 100644 index 0000000..a4abb5e --- /dev/null +++ "b/\347\211\210\346\234\254\346\216\247\345\210\266\345\231\250/Git_removeCommits.md" @@ -0,0 +1,100 @@ +在 Git 开发中通常会控制主干分支的质量,但有时还是会把错误的代码合入到远程主干。 虽然可以 直接回滚远程分支](https://harttle.land/2018/03/12/reset-origin-without-force-push.html), 但有时新的代码也已经合入,直接回滚后最近的提交都要重新操作。 那么有没有只移除某些 Commit 的方式呢?可以一次 [revert](https://git-scm.com/docs/git-revert) 操作来完成。 + +# 一个例子 + +考虑这个例子,我们提交了 6 个版本,其中 3-4 包含了错误的代码需要被回滚掉。 同时希望不影响到后续的 5-6。 + +``` +* 982d4f6 (HEAD -> master) version 6 +* 54cc9dc version 5 +* 551c408 version 4, harttle screwed it up again +* 7e345c9 version 3, harttle screwed it up +* f7742cd version 2 +* 6c4db3f version 1 +``` + +这种情况在团队协作的开发中会很常见:可能是流程或认为原因不小心合入了错误的代码, 也可能是合入一段时间后才发现存在问题。 总之已经存在后续提交,使得直接回滚不太现实。 + +下面的部分就开始介绍具体操作了,同时我们假设远程分支是受保护的(不允许 Force Push)。 思路是从产生一个新的 Commit 撤销之前的错误提交。 + +# git revert + +使用 `git revert ` 可以撤销指定的提交, 要撤销一串提交可以用 `..` 语法。 注意这是一个前开后闭区间,即不包括 commit1,但包括 commit2。 + +``` +git revert --no-commit f7742cd..551c408 +git commit -a -m 'This reverts commit 7e345c9 and 551c408' +``` + +其中 `f7742cd` 是 version 2,`551c408` 是 version 4,这样被移除的是 version 3 和 version 4。 注意 revert 命令会对每个撤销的 commit 进行一次提交,`--no-commit` 后可以最后一起手动提交。 + +此时 Git 记录是这样的: + +``` +* 8fef80a (HEAD -> master) This reverts commit 7e345c9 and 551c408 +* 982d4f6 version 6 +* 54cc9dc version 5 +* 551c408 version 4, harttle screwed it up again +* 7e345c9 version 3, harttle screwed it up +* f7742cd version 2 +* 6c4db3f version 1 +``` + +现在的 HEAD(`8fef80a`)就是我们想要的版本,把它 Push 到远程即可。 + +# 确认 diff + +如果你像不确定是否符合预期,毕竟批量干掉了别人一堆 Commit,可以做一下 diff 来确认。 首先产生 version 4(`551c408`)与 version 6(`982d4f6`)的 diff,这些是我们想要保留的: + +``` +git diff 551c408..982d4f6 +``` + +然后再产生 version 2(`f7742cd`)与当前状态(HEAD)的 diff: + +``` +git diff f7742cd..HEAD +``` + +如果 version 3, version 4 都被 version 6 撤销的话,上述两个 diff 为空。 可以人工确认一下,或者 grep 掉 description 之后做一次 diff。 下面介绍的另一种方法可以容易地确认 diff。 + +# 另外一种方式 + +类似 [安全回滚远程分支](https://harttle.land/2018/03/12/reset-origin-without-force-push.html), 我们先回到 version 2,让它合并 version 4 同时代码不变, 再合并 version 5, version 6。 + +``` +# 从 version 2 切分支出来 +git checkout -b fixing f7742cd +# 合并 version 4,保持代码不变 +git merge -s ours 551c408 +# 合并 version 5, version 6 +git merge master +``` + +上述分支操作可以从 [分支管理](https://harttle.land/2016/09/02/git-workflow-branch.html) 一文了解。 至此,`fixing` 分支已经移除了 version 3 和 version 4 的代码,图示如下: + +``` +* 3cb9f8a (HEAD -> v2) Merge branch 'master' into v2 +|\ +| * 982d4f6 (master) version 6 +| * 54cc9dc version 5 +* | c669557 Merge commit '551c408' into v2 +|\ \ +| |/ +| * 551c408 version 4, harttle screwed it up again +| * 7e345c9 version 3, harttle screwed it up +|/ +* f7742cd version 2 +* 6c4db3f version 1 +``` + +可以简单 diff 一下来确认效果: + +``` +# 第一次 merge 结果与 version 2 的 diff,应为空 +git diff f7742cd..c669557 +# 第二次 merge 的内容,应包含 version 5 和 version 6 的改动 +git diff c669557..3cb9f8a +``` + +现在的 `HEAD`(即 `fixing` 分支)就是我们想要的版本,可以把它 Push 到远程了。 注意由于现在处于 `fixing` 分支, 需要 [Push 时指定远程分支](https://harttle.land/2016/09/05/git-workflow-remote.html) 为 `master`。 From fffb9f4e87f6fc801c687725d7097a21f32a5133 Mon Sep 17 00:00:00 2001 From: fymmx Date: Mon, 28 Jan 2019 18:10:09 +0800 Subject: [PATCH 25/48] Update php7.md --- PHP/php7.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/PHP/php7.md b/PHP/php7.md index 0eebc9c..12941c8 100644 --- a/PHP/php7.md +++ b/PHP/php7.md @@ -35,7 +35,7 @@ if(isset($_GET['a'])) { $a = isset($_GET['a']) ? $_GET['a'] : 'none'; #PHP 7 -$a = isset($_GET['a']) ?? 'none'; +$a = $_GET['a'] ?? 'none'; ``` @@ -50,7 +50,7 @@ function sumOfInts(int ...$ints) { return array_sum($ints); } -ar_dump(sumOfInts(2, '3', 4.1)); // int(9) +var_dump(sumOfInts(2, '3', 4.1)); // int(9) # 严格模式 declare(strict_types=1); @@ -352,10 +352,8 @@ function handler(Throwable $e) { ... } list 会按照原来的顺序进行赋值。不再是逆序了 ```php -list($a,$b,$c) = [1,2,3]; -var_dump($a);//1 -var_dump($b);//2 -var_dump($c);//3 +list($array[], $array[], $array[]) = [1, 2, 3]; +var_dump($array); // [1, 2, 3] ``` list不再支持解开字符串、 From afd48f544e43e20be09b796ba414729231b6910b Mon Sep 17 00:00:00 2001 From: xianyunyh Date: Mon, 18 Feb 2019 22:51:27 +0800 Subject: [PATCH 26/48] =?UTF-8?q?=E5=A2=9E=E5=8A=A0php7.3=E6=96=B0?= =?UTF-8?q?=E7=89=B9=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PHP/php7.md | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/PHP/php7.md b/PHP/php7.md index 12941c8..756cbd4 100644 --- a/PHP/php7.md +++ b/PHP/php7.md @@ -662,3 +662,111 @@ var_dump( ); ``` +## PHP 7.3 + +#### 1. 灵活的heredoc 和nowdoc + +在php 7.3 之前我们定义一大段的字符串。需要用到heredoc + +```php +'1','b'=>'2']; +#php 7.3之前 +$firstKey = key(reset($array)); +# php 7.3 +$firstKey = array_key_first($array);//a +$lastKey = array_key_last($array);//b +``` + +### 6.废除并移除大小写不敏感的常量 + +你可以同时使用大小写敏感和大小写不敏感的常量。但大小写不敏感的常量会在使用中造成一点麻烦。所以,为了解决这个问题,PHP 7.3 废弃了大小写不敏感的常量。 + +原先的情况是: + +- 类常量始终为「大小写敏感」。 +- 使用 `const` 关键字定义的全局常量始终为「大小写敏感」。注意此处仅仅是常量自身的名称,不包含命名空间名的部分,PHP 的命名空间始终为「大小写不敏感」。 +- 使用 `define()` 函数定义的常量默认为「大小写敏感」。 +- 使用 `define()` 函数并将第三个参数设为 `true` 定义的常量为「大小写不敏感」。 + +如今 PHP 7.3 提议废弃并移除以下用法: + +- In PHP 7.3: 废弃使用 `true` 作为 `define()` 的第三个参数。 +- In PHP 7.3: 废弃使用与定义时的大小写不一致的名称,访问大小写不敏感的常量。`true`、`false` 以及 `null` 除外。 \ No newline at end of file From de1c31c1a9d41cfd3f1853410bca3ab46bb3cab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=97=B2=E4=BA=91=E9=87=8E=E9=B9=A4?= Date: Mon, 4 Mar 2019 21:01:42 +0800 Subject: [PATCH 27/48] Update README.md --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d6b62fa..456b7dd 100644 --- a/README.md +++ b/README.md @@ -101,8 +101,6 @@ - [面试](面试/README.md) - - ## 生成自己的Gitbook ```bash @@ -112,8 +110,8 @@ $ cd PHP-Interview $ gitbook serve # 本地预览 $ gitbook build # 生成静态的html ``` -##推荐阅读资料 +## 推荐阅读资料 - [PHP函数库](http://overapi.com/php) - [PHP7内核剖析](https://github.com/pangudashu/php7-internal) - [php7-internal](https://github.com/laruence/php7-internal) @@ -127,8 +125,13 @@ $ gitbook build # 生成静态的html - [数据结构和算法](http://www.cnblogs.com/skywang12345/p/3603935.html) - [剑指offer-PHP实现](https://blog.csdn.net/column/details/15795.html) +## 致谢 + +- [OMGZui](https://github.com/OMGZui) +- [fymmx](https://github.com/fymmx) + 如果这个系列的文章,对您有所帮助,您可以选择打赏一下作者。谢谢! -![qrcode](mm_reward_qrcode.jpg) \ No newline at end of file +![qrcode](mm_reward_qrcode.jpg) From 710a603353829c2f732398406449c504e90b0b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=97=B2=E4=BA=91=E9=87=8E=E9=B9=A4?= Date: Wed, 6 Mar 2019 22:54:07 +0800 Subject: [PATCH 28/48] =?UTF-8?q?Create=2005=E8=B0=88=E8=96=AA=E8=B5=84.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...05\350\260\210\350\226\252\350\265\204.md" | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 "\351\235\242\350\257\225/05\350\260\210\350\226\252\350\265\204.md" diff --git "a/\351\235\242\350\257\225/05\350\260\210\350\226\252\350\265\204.md" "b/\351\235\242\350\257\225/05\350\260\210\350\226\252\350\265\204.md" new file mode 100644 index 0000000..e6964a4 --- /dev/null +++ "b/\351\235\242\350\257\225/05\350\260\210\350\226\252\350\265\204.md" @@ -0,0 +1,27 @@ +谈薪资的时候,基本上是我们到了面试的最后的步骤了,这个时候,你的报价决定你以后的工作的工资的多少。也是很关键的一步,我之前面试的就是由于缺乏经验,导致自己报价低了。然后入职之后再往上加,就很难了。 + + + +在我们面试的时候,我们**尽量不要先出牌**,比如我们在填表格的时候,期望薪资, 可以写上面谈,或者写一个范围区间。不要写一个具体的数字,因为很多hr人员都会压低你的工资。比如你写的是20k,可能hr会给你18k。 + +- 你期望的薪资是多少? + +**了解该公司所在地区、所属行业、公司规模等信息**,你的薪水要求应该在该公司所在地 区、行业、公司规模相应的薪水范围之内。**尽可能提供一个你期望的薪水范围,而不是具体的薪金数。** 了解具体的福利情况。好的福利可以让你的薪资加上不少。比如有的公司是15薪,然后公司稍低点,有的工资高,但是福利少。你可以权衡一下。 + + + +- 你的上一份的薪资是多少? + + 问你这个问题的时候,是想知道和你当前薪资对比,比如你上一份是10k ,这次你报价20k,别人应该只会给你15k。所以上一份的薪资,应该和本次的报价,不是特别差别大。但是也不能一样。不然你跳槽就没不涨薪,上一份的薪资,你就应该把你的福利也加上。比如你有绩效奖金,薪资调整都加上,得到一个范围值,不要告诉具体的数值。比如你薪资15k,你加上乱七八糟的,你可以说15-18k之间。 + +- 你认为每年的加薪幅度是多少? + + 提示:通常, 比较可靠的回答是: 你希望收入的增长和生活水平的提高保持一致。你还应该提到, + + 你的业绩将是加薪的主要因素 + + **求职者** : 总体来说,取决于我个人的业绩和公司的业绩(盈利状况)。但一般而言,至少和生活水平的提高保持一致。 + + + +在面试过程中,我们做的准备与实际遇到的问题总会有一些出入。记得大致的原则,巧妙的随机应变。懂得自己在市场中的定位,将对薪资的确定更为有利。 From 43afcca4662001eb4e3170401304b9c06bd30f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=97=B2=E4=BA=91=E9=87=8E=E9=B9=A4?= Date: Sun, 7 Apr 2019 23:13:44 +0800 Subject: [PATCH 29/48] mq question --- MQ/question.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 MQ/question.md diff --git a/MQ/question.md b/MQ/question.md new file mode 100644 index 0000000..f9ed9ec --- /dev/null +++ b/MQ/question.md @@ -0,0 +1,25 @@ +1. 消息队列的作用 +- 流量消峰 + 并发量大的时间,所有的请求直接怼到数据库,造成数据库连接异常,将请求写进消息队列,后面的系统再从消息队列依次来取出。 +- 异步 + 一些非必要的业务逻辑以同步的方式运行,太耗费时间。改成异步,可以提高系统的响应时间。 +- 解耦 + 将消息写入消息队列,需要消息的系统自己从消息队列中订阅。从而使该系统不需要改代码。 +2. 如何保证消息队列高可用 +集群 +3. 如何保证消息不被重复消费 +那造成重复消费的原因?,就是因为网络传输等等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将消息分发给其他的消费者。 +消费前做检测,比如写库成功的时候,写入到redis中,再次消费的时候如果redis已存在,则不进行消费 +4. 如何保证消费的可靠性传输? +其实这个可靠性传输,每种MQ都要从三个角度来分析: + + - 生产者弄丢数据 + + 从生产者弄丢数据这个角度来看,RabbitMQ提供transaction和confirm模式来确保生产者不丢消息 + - 消息队列弄丢数据 + + 处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。这个持久化配置可以和confirm机制配合使用 + - 消费者弄丢数据 + + 消费者丢数据一般是因为采用了自动确认消息模式。这种模式下,消费者会自动确认收到信息。这时rabbitMQ会立即将消息删除,这种情况下,如果消费者出现异常而未能处理消息,就会丢失该消息。 + 手动确认消息 From bdf07abc6b848c7c9d8b414f3e536b224f7a55db Mon Sep 17 00:00:00 2001 From: haolong Date: Thu, 11 Apr 2019 11:02:22 +0800 Subject: [PATCH 30/48] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E4=B8=B2=E7=AE=97=E6=B3=95=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\345\255\227\347\254\246\344\270\262.md" | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 "\346\225\260\346\215\256\347\273\223\346\236\204/\345\255\227\347\254\246\344\270\262.md" diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204/\345\255\227\347\254\246\344\270\262.md" "b/\346\225\260\346\215\256\347\273\223\346\236\204/\345\255\227\347\254\246\344\270\262.md" new file mode 100644 index 0000000..3c54298 --- /dev/null +++ "b/\346\225\260\346\215\256\347\273\223\346\236\204/\345\255\227\347\254\246\344\270\262.md" @@ -0,0 +1,30 @@ +##旋转字符串 +给定一个字符串,要求把字符串前面的若干个字符移动到字符串的尾部,如把字符串“abcdef”前面的2个字符'a'和'b'移动到字符串的尾部,使得原字符串变成字符串“cdefab”。请写一个函数完成此功能,要求对长度为n的字符串操作的时间复杂度为 O(n),空间复杂度为 O(1)。 +###解法一:暴力移位法 +```php +function move(&$str , $n){ + for ($i = 0; $i<$n; $i++){ + LeftShiftOne($str); + } +} + +function LeftShiftOne(&$str){ + $len = strlen($str); + $last = $str[$len - 1]; + for ($i = 0; $i<$len-1; $i++){ + $str[$i - 1] =$str[$i]; + } + $str[$len-2] = $last; +} +$str = "abcd"; +move($str, 4); + +``` +时间复杂度为O(m n),空间复杂度为O(1),空间复杂度符合题目要求,但时间复杂度不符合,所以,我们得需要寻找其他更好的办法来降低时间复杂度。 +###解法二:三步反转法 +对于这个问题,换一个角度思考一下。 +将一个字符串分成X和Y两个部分,在每部分字符串上定义反转操作,如X^T,即把X的所有字符反转(如,X="abc",那么X^T="cba"),那么就得到下面的结论:(X^TY^T)^T=YX,显然就解决了字符串的反转问题。 +例如,字符串 abcdef ,若要让def翻转到abc的前头,只要按照下述3个步骤操作即可: +首先将原字符串分为两个部分,即X:abc,Y:def; +将X反转,X->X^T,即得:abc->cba;将Y反转,Y->Y^T,即得:def->fed。 +反转上述步骤得到的结果字符串X^TY^T,即反转字符串cbafed的两部分(cba和fed)给予反转,cbafed得到defabc,形式化表示为(X^TY^T)^T=YX,这就实现了整个反转。 \ No newline at end of file From a395ad84740f018cf400a5392283d00a5247c9cd Mon Sep 17 00:00:00 2001 From: haolong Date: Thu, 11 Apr 2019 11:47:01 +0800 Subject: [PATCH 31/48] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E4=B8=B2=E7=AE=97=E6=B3=95=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\345\255\227\347\254\246\344\270\262.md" | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204/\345\255\227\347\254\246\344\270\262.md" "b/\346\225\260\346\215\256\347\273\223\346\236\204/\345\255\227\347\254\246\344\270\262.md" index 3c54298..6040c2d 100644 --- "a/\346\225\260\346\215\256\347\273\223\346\236\204/\345\255\227\347\254\246\344\270\262.md" +++ "b/\346\225\260\346\215\256\347\273\223\346\236\204/\345\255\227\347\254\246\344\270\262.md" @@ -25,6 +25,41 @@ move($str, 4); 对于这个问题,换一个角度思考一下。 将一个字符串分成X和Y两个部分,在每部分字符串上定义反转操作,如X^T,即把X的所有字符反转(如,X="abc",那么X^T="cba"),那么就得到下面的结论:(X^TY^T)^T=YX,显然就解决了字符串的反转问题。 例如,字符串 abcdef ,若要让def翻转到abc的前头,只要按照下述3个步骤操作即可: -首先将原字符串分为两个部分,即X:abc,Y:def; -将X反转,X->X^T,即得:abc->cba;将Y反转,Y->Y^T,即得:def->fed。 -反转上述步骤得到的结果字符串X^TY^T,即反转字符串cbafed的两部分(cba和fed)给予反转,cbafed得到defabc,形式化表示为(X^TY^T)^T=YX,这就实现了整个反转。 \ No newline at end of file +- 首先将原字符串分为两个部分,即X:abc,Y:def; +- 将X反转,X->X^T,即得:abc->cba;将Y反转,Y->Y^T,即得:def->fed。 +- 反转上述步骤得到的结果字符串X^TY^T,即反转字符串cbafed的两部分(cba和fed)给予反转,cbafed得到defabc,形式化表示为(X^TY^T)^T=YX,这就实现了整个反转。 +```php + +/** + * 旋转字符串 + * @param $str + * @param $start + * @param $end + */ +function ReverseString(&$str, $start, $end){ + while($start < $end){ + $t = $str[$start]; + $str[$start++] = $str[$end]; + $str[$end--] = $t; + } +} + + +/** + * @param $str + * @param $n 字符串长度 + * @param $m 移动位数 + */ +function LeftRotateString(&$str, $n, $m){ + $m %= $n; + ReverseString($str, 0, $m-1); + ReverseString($str, $m, $n-1); + ReverseString($str, 0, $n-1); + +} + +$str = "abcd"; +LeftRotateString($str, strlen($str), 1); +``` + +这就是把字符串分为两个部分,先各自反转再整体反转的方法,时间复杂度为O(n),空间复杂度为O(1),达到了题目的要求。 \ No newline at end of file From 32320e55125d215688fad11f6b1006c4c28a1766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E4=BA=B2=E5=BC=BA?= Date: Fri, 5 Jul 2019 17:41:32 +0800 Subject: [PATCH 32/48] leetcode-php --- ...30\347\233\256\351\233\206\345\220\210.md" | 620 ++++++++++++++++++ ...72\346\234\254\346\223\215\344\275\234.md" | 223 +++++++ .../\345\240\206\346\240\210.md" | 115 ++++ .../\346\225\243\345\210\227\350\241\250.md" | 111 ++++ ...14\345\210\206\346\237\245\346\211\276.md" | 156 +++++ ...50\346\200\201\350\247\204\345\210\222.md" | 259 ++++++++ 6 files changed, 1484 insertions(+) create mode 100644 "\346\225\260\346\215\256\347\273\223\346\236\204/Leetcode\347\273\217\345\205\270\344\272\214\345\217\211\346\240\221\351\242\230\347\233\256\351\233\206\345\220\210.md" create mode 100644 "\346\225\260\346\215\256\347\273\223\346\236\204/\344\272\214\345\217\211\346\240\221\345\237\272\346\234\254\346\223\215\344\275\234.md" create mode 100644 "\346\225\260\346\215\256\347\273\223\346\236\204/\345\240\206\346\240\210.md" create mode 100644 "\346\225\260\346\215\256\347\273\223\346\236\204/\346\225\243\345\210\227\350\241\250.md" create mode 100644 "\347\256\227\346\263\225/\344\272\214\345\210\206\346\237\245\346\211\276.md" create mode 100644 "\347\256\227\346\263\225/\345\212\250\346\200\201\350\247\204\345\210\222.md" diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204/Leetcode\347\273\217\345\205\270\344\272\214\345\217\211\346\240\221\351\242\230\347\233\256\351\233\206\345\220\210.md" "b/\346\225\260\346\215\256\347\273\223\346\236\204/Leetcode\347\273\217\345\205\270\344\272\214\345\217\211\346\240\221\351\242\230\347\233\256\351\233\206\345\220\210.md" new file mode 100644 index 0000000..1cb0b19 --- /dev/null +++ "b/\346\225\260\346\215\256\347\273\223\346\236\204/Leetcode\347\273\217\345\205\270\344\272\214\345\217\211\346\240\221\351\242\230\347\233\256\351\233\206\345\220\210.md" @@ -0,0 +1,620 @@ +## :pencil2:Leetcode经典二叉树题目集合 + +####php-leetcode之路 [Leetcode-php](https://github.com/wuqinqiang/leetcode-php) +**** +### :pencil2:1.二叉树的前序遍历(leetcode144) + + +​ + + +**前序遍历,先访问根结点,然后在访问左子树,最后访问右子树。可以利用栈的特点,这里我结合了队列和栈的特点来实现。先压入树,取出根节点。先把根节点值push到队列中,然后把右子树压入栈中,最后压入左子树。返回队列。当然你可以调整成你想要的实现方式。(只要前中后序顺序理解正确即可)** + +```php + +/** + * Definition for a binary tree node. + * class TreeNode { + * public $val = null; + * public $left = null; + * public $right = null; + * function __construct($value) { $this->val = $value; } + * } + */ + +class Solution { + + /** + * @param TreeNode $root + * @return Integer[] + */ + function preorderTraversal($root) { + $res=[]; + $list=[]; + array_unshift($res,$root); + while(!empty($res)){ + $current=array_shift($res); + if($current==null) continue; + array_push($list,$current->val); + array_unshift($res,$current->right); + array_unshift($res,$current->left); + } + return $list; + } +} + +``` + +**** + +### :pencil2:2.二叉树的中序遍历(leetcode94) + + +​ + + +```php + /** + * @param TreeNode $root + * @return Integer[] + */ + function inorderTraversal($root) { + $res=[]; + $this->helper($root,$res); + return $res; + } + function helper($root,&$res){ + if($root !=null){ + if($root->left !=null) $this->helper($root->left,$res); + array_push($res,$root->val); + if($root->right !=null) $this->helper($root->right,$res); + } + + } +``` + +**或者不用递归** + +```php + /** + * @param TreeNode $root + * @return Integer[] + */ + function inorderTraversal($root) { + $res=[]; + $list=[]; + while(!empty($list) || $root !=null){ + while($root != null){ + array_unshift($list,$root); + $root=$root->left; + } + $root=array_shift($list); + array_push($res,$root->val); + $root=$root->right; + } + return $res; + } +``` +**** + + +### :pencil2:3.二叉树的后序遍历(leetcode145) + + +​ + + +```php + /** + * @param TreeNode $root + * @return Integer[] + */ + function postorderTraversal($root) { + $list=[]; + $res=[]; + array_push($list,$root); + while(!empty($list)){ + $node=array_shift($list); + if(!$node) continue; + array_unshift($res,$node->val); + array_unshift($list,$node->left); + array_unshift($list,$node->right); + } + return $res; + } + } +``` +**** + +### :pencil2:4.二叉树的层次遍历(leetcode102) + + +​ + + +**DFS和BFS都可以解,竟然已经要我们按照层打印了,那么先使用BFS,思路就是先判断树是否是空,不是空加入一个队列的结构中,如果队列不为空,取出头元素,那么当前元素表示的就是当前这一层了,所以只需要遍历这一层里的所有的元素即可,然后下一层....** + +```php + class Solution { + + /** + * @param TreeNode $root + * @return Integer[][] + */ + function levelOrder($root) { + if(empty($root)) return []; + $result = []; + $queue = []; + array_push($queue,$root); + while(!empty($queue)){ + $count = count($queue); + $leveQueue = []; + for($i = 0;$i<$count;$i++){ + $node = array_shift($queue); + array_push($leveQueue,$node->val); + if($node->left) array_push($queue,$node->left); + if($node->right) array_push($queue,$node->right); + } + array_push($result,$leveQueue); + } + return $result; + } + } +``` + +**如果使用DFS的话,就是一条路走到黑,然后再重新一路路的退回来再找下一路,所以这样的话,每一次我们需要记录一下当前他所在的这个点属于哪一层即可,代码用递归实现。** +```php + +class Solution { + + /** + * @param TreeNode $root + * @return Integer[][] + */ + function levelOrder($root) { + if(empty($root)) return []; + $result=[]; + $this->helper($result,$root,0); + return $result; + } + + function helper(&$result,$node,$level){ + if(empty($node)) return ; + if(count($result)<$level+1){ + array_push($result,[]); //说明当前行没有结果 + } + array_push($result[$level],$node->val); + $this->helper($result,$node->left,$level+1); + $this->helper($result,$node->right,$level+1); + } +} + +``` +**** + +### :pencil2:5.二叉树的最大深度(leetcode104) + + +​ + + +**DFS和BFS都可以解,竟然已经要我们按照层打印了,那么先使用BFS,思路就是先判断树是否是空,不是空加入一个队列的结构中,如果队列不为空,取出头元素,那么当前元素表示的就是当前这一层了,所以只需要遍历这一层里的所有的元素即可,然后下一层....** + +```php + + /** + * @param TreeNode $root + * @return Integer + */ + function maxDepth($root) { + if(empty($root)) return 0; + $left = $this->maxDepth($root->left); + $right = $this->maxDepth($root->right); + return $left<$right? $right+1:$left+1; + return max($left,$right)+1; + } +``` +**** + +### :pencil2:6.二叉树的最小深度(leetcode111) + + +​ + + +**DFS和BFS都可以求解** + +```php + + //BFS + /** + * @param TreeNode $root + * @return Integer + */ + function minDepth($root) { + if(empty($root)) return 0; + if(!$root->right) return $this->minDepth($root->left)+1; + if(!$root->left) return $this->minDepth($root->right)+1; + $left=$this->minDepth($root->left); + $right=$this->minDepth($root->right); + return min($left,$right)+1; + + } +``` + +```php + +//DFS + /** + * @param TreeNode $root + * @return Integer + */ + function minDepth($root) { + if(empty($root)) return 0; + $left=$this->minDepth($root->left); + $right=$this->minDepth($root->right); + if($left==0 || $right==0) return $left+$right+1; + return min($left,$right)+1; + } +``` +**** + + +### :pencil2:7.判断是否是平衡二叉树(leetcode110) + + +​ + + +**每一节点的两个子树的深度相差不能超过1。如果是空树,直接true。** + +```php + + +class Solution { + + /** + * @param TreeNode $root + * @return Boolean + */ + private $result=true; + function isBalanced($root) { + if(empty($root)) return true; + $this->helper($root); + return $this->result; + } + function helper($root) +{ + if(!$root) return ; + $left=$this->helper($root->left); + $right=$this->helper($root->right); + if(abs($left-$right)>1) $this->result=false; + return max($left,$right)+1; + } +} +``` +**** + + +### :pencil2:8.判断是否是对称二叉树(leetcode101) + + +​ + + +**1.两个子节点都是空,那说明他们是对称的返回true** + +**2.一个子节点为空,另一个子节点不为空,false** + +**3.两个子节点都不为空,但是他们不相等,false** + +**4.两个子节点不为空且相等,继续判断他们的左子树和右子树,把左子树的左子节点和右子树的右子节点进行比较,把左子树的右子节点和右子树的左子节点进行比较** + +```php + /** + * @param TreeNode $root + * @return Boolean + */ + function isSymmetric($root) { + if(empty($root)) return true; + return $this->helper($root->left,$root->right); + } + function helper($l,$r){ + if(!$l && !$r) return true; + if(!$l || !$r || $l->val != $r->val) return false; + return $this->helper($l->left ,$r->right) && $this->helper($l->right,$r->left); + } +``` +**** + +### :pencil2:9.反转二叉树(leetcode226) + + +​ + + +```php + + /** + * @param TreeNode $root + * @return TreeNode + */ + function invertTree($root) { + if(!$root) return null; + $list=[]; + array_push($list,$root); + while(!empty($list)){ + $node=array_shift($list); + $temp=$node->left; + $node->left=$node->right; + $node->right=$temp; + if($node->left) array_push($list,$node->left); + if($node->right) array_push($list,$node->right); + } + return $root; + } +``` +**递归解** +```php + /** + * @param TreeNode $root + * @return TreeNode + */ + function invertTree($root) { + if(empty($root)){ + return null; + } + $right=$this->invertTree($root->right); + $left=$this->invertTree($root->left); + $root->left=$right; + $root->right=$left; + return $root; + } +``` +**** + + +### :pencil2:10.给定单链表(值有序)转化成平衡二叉查找树(leetcode109) + + +​ + + +**先将链表数据转换成有序数组,然后利用二分查找的特性,构建左右子树。** + +```php + +/** + * Definition for a singly-linked list. + * class ListNode { + * public $val = 0; + * public $next = null; + * function __construct($val) { $this->val = $val; } + * } + */ +/** + * Definition for a binary tree node. + * class TreeNode { + * public $val = null; + * public $left = null; + * public $right = null; + * function __construct($value) { $this->val = $value; } + * } + */ +class Solution { + + /** + * @param ListNode $head + * @return TreeNode + */ + function sortedListToBST($head) { + $data=[]; + while($head){ + array_push($data,$head->val); + $head=$head->next; + } + return $this->helper($data); + } + + function helper($data) +{ + if(!$data) return ; + $middle=floor(count($data)/2); + $node=new TreeNode($data[$middle]); + $node->left=$this->helper(array_slice($data,0,$middle)); + $node->right=$this->helper(array_slice($data,$middle+1)); + return $node; + } +} +``` +**** + + +### :pencil2:11.强盗打劫版本3(leetcode337) + + +​ + + +**最后的目的算出最多能抢金额数而不触发报警器。除了根节点,每一个结点只有一个父节点,能直接相连的两个节点不能同时抢,比如图1,抢了根节点,直接相连的左右子结点就不能抢。所以要么抢根节点的左右子结点,要么根结点+根结点->left->right+根结点->right->right。** + + +```php + +//递归 +/** + * @param TreeNode $root + * @return Integer + */ + function rob($root) { + if($root==null){ + return 0; + } + $res1=$root->val; + if($root->left !=null) { + $res1 +=$this->rob($root->left->left)+$this->rob($root->left->right); + } + if($root->right !=null){ + $res1 +=$this->rob($root->right->left)+$this->rob($root->right->right); + } + + $res2=$this->rob($root->left)+$this->rob($root->right); + return max($res1,$res2); + + } +``` + +**上面那种大量的重复计算,改进一下。** + + **如果结点不存在直接返回0,对左右结点分别递归,设置了4个变量,ll和lr分别表示左子结点的左右子结点的最大金额数,rl和rr分别表示右子结点的左右子结点的最大金额数。所以我们最后比较的还是两种情况,第一种就是当前结点+左右子结点的左右子结点的值(即这里定义的ll,lr,rl,rr).第二种是当前结点的左右子结点的值(也就是说我只抢当前结点的子结点,不抢当前结点和孙子结点),再通俗的说就是如果树的层数是3层,要么抢中间一层,要么抢上下两层,谁钱多抢谁。** + + ```php +/** + * @param TreeNode $root + * @return Integer + */ + function rob($root) { + $l=0;$r=0; + return $this->countMax($root,$l,$r); + } + function countMax($root,&$l,&$r){ + if($root==null) return 0; + $ll=0;$lr=0;$rl=0;$rr=0; + $l=$this->countMax($root->left,$ll,$lr); + $r=$this->countMax($root->right,$rl,$rr); + return max($root->val+$ll+$lr+$rl+$rr,$l+$r); + } +``` +**** + +### :pencil2:12.判断二叉树路径和是否存在(leetcode112) + + +​ + + +**只要使用深度优先算法思想遍历每一条完整的路径,如果是个空树直接false,如果结点没有左右子树(说明此时已然是叶子结点,判断值是否是给定值,这个条件正好是递归终止的条件),相等直接返回true,根据这个推导出递归公式。** + +```php +/** + * @param TreeNode $root + * @param Integer $sum + * @return Boolean + */ + function hasPathSum($root, $sum) { + if($root==null){ + return false; + } + if($root->left ==null && $root->right==null && $root->val==$sum) return true; + return $this->hasPathSum($root->left,$sum-$root->val) || $this->hasPathSum($root->right,$sum-$root->val); + } +``` + +**改成迭代** + +```php + +/** + * @param TreeNode $root + * @param Integer $sum + * @return Boolean + */ + function hasPathSum($root, $sum) { + if($root==null){ + return false; + } + $res=[]; + array_push($res,$root); + while(!empty($res)){ + $node=array_shift($res); + if(!$node->left && !$node->right ){ + if($node->val==$sum) return true; + } + if($node->left){ + $node->left->val +=$node->val; + array_push($res,$node->left); + } + if($node->right){ + $node->right->val +=$node->val; + array_push($res,$node->right); + } + } + return false; + } +``` +**** + + +### :pencil2:13.判断是否是二叉查找树(leetcode98) + + +​ + + +**思路有两种,二叉查找树的特点就是左子树上的结点都小于根结点,右子树上的结点都大于根节点。所以有两个方向,可以分别递归的判断左子树,右子树。或者拿左子树上的最大值,右子树上的最小值分别对应根结点进行判断。** + +```php + +/** + * Definition for a binary tree node. + * class TreeNode { + * public $val = null; + * public $left = null; + * public $right = null; + * function __construct($value) { $this->val = $value; } + * } + */ +class Solution { + + /** + * @param TreeNode $root + * @return Boolean + */ + function isValidBST($root) { + return $this->helper($root,null,null); + } + function helper($root,$lower,$upper){ + if($root==null) return true; + $res=$root->val; + if($lower !==null && $res<=$lower) return false; + if($upper !==null && $res>=$upper) return false; + if(!$this->helper($root->left,$lower,$res)) return false; + if(!$this->helper($root->right,$res,$upper)) return false; + return true; + } +} +``` +**** + + +### :pencil2:14.找出二叉树最后一层最左边的值(leetcode513) + + +​ + + +**思路有两种,二叉查找树的特点就是左子树上的结点都小于根结点,右子树上的结点都大于根节点。所以有两个方向,可以分别递归的判断左子树,右子树。或者拿左子树上的最大值,右子树上的最小值分别对应根结点进行判断。** + +```php + /** + * @param TreeNode $root + * @return Integer + */ + function findBottomLeftValue($root) { + $data=[]; + array_push($data,$root); + while(!empty($data)){ + $node = array_shift($data); + if($node->right) array_push($data,$node->right); + if($node->left) array_push($data,$node->left); + } + return $node->val; + } +``` +**** + + + + + + diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204/\344\272\214\345\217\211\346\240\221\345\237\272\346\234\254\346\223\215\344\275\234.md" "b/\346\225\260\346\215\256\347\273\223\346\236\204/\344\272\214\345\217\211\346\240\221\345\237\272\346\234\254\346\223\215\344\275\234.md" new file mode 100644 index 0000000..0a052e5 --- /dev/null +++ "b/\346\225\260\346\215\256\347\273\223\346\236\204/\344\272\214\345\217\211\346\240\221\345\237\272\346\234\254\346\223\215\344\275\234.md" @@ -0,0 +1,223 @@ +## :数据结构线性表之二叉树1 +####php-leetcode之路 [Leetcode-php](https://github.com/wuqinqiang/leetcode-php) + + +​ + + +### :pencil2:一.二叉树的定义 +**既然都叫二叉树了,那么二叉树的特点是每个至多只有两棵子树。换句话来说,每个结点的度不超过两个,并且二叉树的子树还存在左右之分,它的次序不能任意颠倒。** +### :pencil2:二叉树的表现形态 + + +​ + + +**1.满二叉树:棵深度为k有且有2^k-1结点的树称之为满二叉树,比如图中的a(深度为4,拥有15个结点)。这里我们就可以得到二叉树的一个特性:在二叉树的第i层中至多有2^i-1个结点(i>=1)。当然了他不止这一个特性。。。** + +**2.完全二叉树:深度为k,有n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树中编号从1至n一一对应时,才是完全二叉树。这里图c不是完全二叉树,假设根节点A是1,那么图c在n等于12这个点上就没有对应。所以不是完全二叉树。所以完全二叉树的特点:(1)叶子结点只可能在层次最大的两层上出现。(2)对任意一个结点,若其右子树的最大层次是l,那么其左子树的最大层数必须是l或者l+1。** + +**三·二叉树的存储树这种结构的存储不像线性结构那样简单,并不能直接用前后关系来描述。一个树有有很多的子树,一个结点不止一个后继。下面用图来说明用数组存储和链表存储。** + +### :pencil2:三.二叉树的存储 + + +​ + + +**按照顺序存储的结构。用一组连续的存储单元至上而下,至左到右存储,图中的0表示不存在该结点,每一个不存在的点我们都需要浪费一个空间。所以在最坏的情况下,一个深度为k且只有k个结点的单支树(树中不存在度为2的结点)却需要长度为2^k-1的一维数组。所以这种顺序存储适合完全二叉树。** + + +​ + + +**链式存储的结构是由一个数据元素和分别指向其左右子树的两个分支构成。包含了三个域:数据域,左右指针域。链表的头指向树的根节点。** + +### :pencil2:四·二叉树的前中后序遍历 +```php + +//二叉树 +class Tree{ + public $res=''; + public $left=null; + public $right=null; + public function __construct($res) +{ + $this->res=$res; + } + +} +//前序遍历 + function front($tree){ + if($tree==null){ + return ; + } + echo $tree->res.'
'; + front($tree->left); + front($tree->right); +} + +//中序遍历 + function middle($tree) +{ + if($tree==null){ + return ; + } + middle($tree->left); + echo $tree->res.'
'; + middle($tree->right); + } + +//后序遍历 + function backend($tree) +{ + if($tree==null){ + return ; + } + backend($tree->right); + backend($tree->left); + echo $tree->res.'
'; +} + +$treeA=new Tree('a'); +$treeB=new Tree('b'); +$treeC=new Tree('c'); +$treeA->left=$treeB; +$treeA->right=$treeC; +// +//front($treeA); +//echo "-------------------".'
'; +//middle($treeA); +//echo "-------------------".'
'; +//backend($treeA); +``` + +### :pencil2:五.二叉排序树的插入,查找,删除. +**我主要说明一下删除操作,删除操作主要分三种情况:(1)如果待删除结点中,只有一个左子结点,那么只要把待删除结点的父结点的left指向待删除结点的左子结点。(2)如果待删除结点只有一个右子结点,那么只要把带删除结点的父结点的right指向带删除结点的右子结点。(3)如果待删除结点有左右结点,那么需要找到这个结点右子树中最小的结点,把他替换到待删除的结点上面。** + + + ​ + + +```php + +class Tree{ + public $res=''; + public $left=null; + public $right=null; + public function __construct($res) +{ + $this->res=$res; + } + +} + +class BinarySortTree +{ + public $tree; + + public function getTree() +{ + return $this->tree; + } + + //插入 + public function insertTree($data) + { + if(!$this->tree){ + $this->tree=new Tree($data); + return ; + } + $p=$this->tree; + while($p){ + if($data<$p->res){ //如果插入结点当前结点 + if(!$p->left){ //并且不存在左子结点 + $p->left=new Tree($data); + return ; + } + $p=$p->left; + }elseif ($data>$p->res){ + if(!$p->right){ + $p->right=new Tree($data); + return ; + } + $p=$p->right; + }else{ + return ; + } + } + } + + + + //删除 + public function deleteTree($data) +{ + if (!$this->tree) { + return; + } + $p = $this->tree; + $fatherP = null; + while ($p && $p->res !== $data) { + $fatherP=$p; //结点的父结点 + if ($data > $p->res) { + $p = $p->right; + }else{ + $p=$p->left; + } + } + + //如果二叉树不存在 + if($p==null){ + var_dump('当前树中没有此结点');return; + } + + //待删除待有两个子结点 + if($p->left && $p->right){ + $minR=$p->right; + $minRR=$p;// 最小结点的父结点 + //查找右子树的最小结点 + while($minR->left){ + $minRR=$minR; + $minR=$minR->left; + } + $p->res=$minR->res;//把右子树上最小结点的值赋值给待删除结点 + $p=$minR; + $fatherP=$minRR; + + } + $child=null; + if($p->left){ + $child=$p->left; + }elseif($p->right){ + $child=$p->right; + }else{ + $child=null; + } + + if(!$fatherP){ //待删除结点是根结点 + $this->tree=$child; + }elseif ($fatherP->left==$p){ //待删除结点只有一个左结点,把待删除结点的父结点的left指向待删除结点的子节点 + $fatherP->left=$child; + }else{ //待删除结点只有一个右结点,把待删除结点的父结点的right指向待删除结点的子节点 + $fatherP->right=$child; + } + + } +} + +$sortTree=new BinarySortTree(); +$sortTree->insertTree(9); +$sortTree->insertTree(8); +$sortTree->insertTree(10); +$sortTree->insertTree(5); +$sortTree->insertTree(6); +$sortTree->insertTree(4); +//$sortTree->search(1); +//$sortTree->deleteTree(8); +//var_dump($sortTree->getTree()); +``` + + + + diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204/\345\240\206\346\240\210.md" "b/\346\225\260\346\215\256\347\273\223\346\236\204/\345\240\206\346\240\210.md" new file mode 100644 index 0000000..a298935 --- /dev/null +++ "b/\346\225\260\346\215\256\347\273\223\346\236\204/\345\240\206\346\240\210.md" @@ -0,0 +1,115 @@ +## :数据结构线性表之堆栈 + +####php-leetcode之路 [Leetcode-php](https://github.com/wuqinqiang/leetcode-php) + + +​ + + +### :pencil2:一.栈的特点 +**栈是仅限在栈顶进行插入和删除的线性表.对栈来说,表尾端称之为栈顶,表头端称之为栈底.假设栈S=(a1,a2,a3,a4,a5....an),那么a1为栈的栈底,an为栈顶元素.对栈的操作是按照后进先出的原则,因此栈又称之为(LIFO)数据结构.** + +### :pencil2:二.栈的表示和实现 +**和线性表类似,栈也有两种存储的方式.顺序栈,即栈的存储是利用一组连续的存储单元依次存放自栈底到栈顶的元素.同时还要定义指针top指向栈顶元素在顺序栈中的位置.通常的做法是top=0表示空栈.一般在使用栈的过程中难以预料所需要的空间大小.所以预先分配大小的容量,当栈的使用空间不够时,再进行动态的扩容.top作为栈顶的指针,初始的时候指向栈底,当有元素入栈时,top自增,当从栈中删除一个元素时,top--,然后删除元素,所以top始终指向栈顶的下一个空位置.** + ```php +LOC(ai+1)=LOC(ai)+L //申明 这里的i,i+1是下标 +``` +**线性结构的顺序表示以元素在计算机中的物理位置相邻来表示逻辑位置相邻,相邻两个元素之间的位置以物理位置的角度分析就是相差一位,只要确定了存储线性表的起始位,那么我们就能任意存储线性表中元素,下图具体表示** + + +​ + + +### :pencil2:三.栈的使用场景 +**栈的使用场景很多,例如idea的撤销回退功能,浏览器前进和后退功能.数制的转换,表达式求值,八皇后.......** +### :pencil2:四.用栈实现代码 +```php + +/** + * 使用栈实现十进制转8精制,其他转换类似 + */ +function tenChageEight($num) +{ + $data=[]; + while($num) { + $val = $num % 8; + $num = intval(floor($num / 8)); + array_unshift($data, $val); + } + $data2=[]; + while(!empty($data)){ + array_push($data2,array_shift($data)); + } + return implode($data2); +} +var_dump(tenChageEight(1348)); +``` +**** +```php + +class Stack +{ + private $stack=[]; + private $size=0; + public function __construct($size) +{ + $this->size=$size; + } + + /** + *推入栈顶 + */ + public function push($value) +{ + if(count($this->stack)>=$this->size){ + return false; + } + array_unshift($this->stack,$value); + + } + /** + *出栈 + */ + public function pop() +{ + if($this->size==0){ + return false; + } + array_shift($this->stack); + } + /** + *获取栈顶元素 + */ + public function top() +{ + if($this->size==0){ + return false; + } + return current($this->stack); + } + + public function data() +{ + return $this->stack; + } + +} + +$stack=new Stack(10); +$stack->push(2); +$stack->push(10); +$stack->push(8); +$stack->pop(); +var_dump($stack->top()); +var_dump($stack->data()); +``` +### 联系 + + +​ + + + + + + diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204/\346\225\243\345\210\227\350\241\250.md" "b/\346\225\260\346\215\256\347\273\223\346\236\204/\346\225\243\345\210\227\350\241\250.md" new file mode 100644 index 0000000..a5c2117 --- /dev/null +++ "b/\346\225\260\346\215\256\347\273\223\346\236\204/\346\225\243\345\210\227\350\241\250.md" @@ -0,0 +1,111 @@ +## 数据结构之散列表 +####php-leetcode之路 [Leetcode-php](https://github.com/wuqinqiang/leetcode-php) + +​ + + +### :pencil2:一.散列表的介绍 +**散列表也叫哈希表,在前面的各种数据结构中(数组,链表,树等),记录在结构中的相对位置是随机的,和记录的关键字不存在确定的关系。在顺序结构中,顺序查找,比较的结果是'='或者'!=',在二分查找,二叉排序树比较的关系是'>','=‘,’<‘,查找的效率依赖于查找过程中比较的次数。** +**什么样的方法能使得理想情况下不需要进行任何比较,通过一次存储就能得到所查的记录。答案就是记录存储位置和关键字之间的对应关系。** + + +​ + + +**我们记录了存储位置和关键字的对应关系h,因此在查找的过程中,只要根据对应关系h找到给定值k的像h(k),如果结构中存在关建字和k相等的记录,那么肯定是存储在h(k)的位置上,就像上图k1..k5的一样,我们称这个对应关系h为散列函数或者是哈希函数。** +**** +**从上面的例子可以看出:** + +**1.散列函数是一个映像,因此设定散列函数可以非常灵活。** + +**2.从图中可以看出,k2 != k5 ,但是h(k2)===h(k5),这就是散列冲突。** + +### :pencil2:二.散列冲突 + + +​ + + +**我们看当前例子,关键字 John Smith !=Sandra Dee,但是通过散列函数之后h(John Smith)===h(Sandra Dee),他们的位置都在散列表01这个位置,但是这个位置只能存储一个记录,那多出来的记录存放在哪里?** + +**正因为散列函数是一个映像,我们在构造散列函数的时候,只能去分析关键字的特性,选择一个恰当的散列函数来避免冲突的发生。一般情况下,冲突只能尽可能的减少,而不能完全避免。** + +### :pencil2:三.散列函数的构造 +**先来看看什么是好的散列函数。如果对于关键字集合中任意一个,经过散列函数映射到地址集合中任何一个位置的概率都是相等的,就可以称为均匀散列函数。** + +**1.直接定址法** + +**取关键字或者关键字的某个线性函数值为哈希地址。** + +**h(key)=key或者h(key)=a*key+b a,b为常量。比如说做一个地区年龄段的人数统计,我们就可以把年龄1-100作为关键字,现在你要查38岁的人口数时只需要h(38)=???。** +**** + +**2.数字分析法** + +**要通过具体的数字分析,找出关键字集合的特点和关系,通过这组关系构造一个散列函数。** +**** +**3.平方取中法** + +**取关键字平方后的中间几位为哈希地址,因为一般情况下,选定哈希函数时并不一定知道关键字的全部情况,取哪几位也不一定合适,而一个平方后的中间几位数和数的每一位都有关,由此使随机分布的关键字得到的哈希地址也是随机的。** +**** +**4.折叠法** + +**将关键字分割成位数相同的几部分,然后取这几部分的叠加和,也就是舍去它的进位,作为他的哈希地址。** +**** +**5.除留余数法** +**取关键字被某个不大于散列表表长m的数(暂且称之为p)除后所得余数为哈希地址。** +```php +h(key)=key MOD p, p<=m +``` +**以上都偏于理论,具体的使用需要视情况而定,通常,考虑的因素有以下几点** + +**1.计算散列函数所需的时间** + +**2.关键字的长度** + +**3.哈希表的大小** + +**4.关键字的分布情况** + + **5.记录查找的频率** + + ### :pencil2:四.处理冲突 + **之前说过,散列函数可以减少冲突,但是不能避免,这时候我们就需要处理冲突。** + + **1.开放寻址法** + + **简单的来说,下图中当前哈希表的长度是8,现在已填入关键字1,9,3,4,5的记录,假如当前我们需要再填入关键字10这条记录。通过散列函数得出h(3)===h(10),但是此时哈希地址2已被3占领。现在我们咋么处理?** + + **线性探测再散列得到下一个地址3,发现3也被占领,再求下一个地址4,还被占领,直到5这个位置时,处理冲突过程结束,把当前h(10)记录在地址为5的位置即可。也可以使用二次探测再散列或者伪随机再散列都是属于开放寻址法。** + + + ​ + + +**** + +**2.再散列法** + +**即在同义词产生地址冲突时计算另一个散列函数的地址,直到冲突不再发生,这种方法毋庸置疑,增加了计算的时间。** +**** +**3.链地址法** + +**将所有关键字为同义词的记录存储在同一个线性链表中。初始状态是一个空指针。凡是通过关键字计算出地址一样的记录都插入到当前位置的链表中,在链表中插入的位置可以是表头,表尾,或者表中,以保持同义词在同一个线性表中按关键字有序。** + + + ​ + + + **** + + **4.建立一个公共溢出区** + + **假设散列函数的值域为[0,m-1],则设置向量HashTable[0,m-1]为基本表,每一个分量存储一个记录,另外设置向量OverTable[0,v]为溢出表。所有关键字和基本表中关键字为同义词的记录,不管它们由哈希函数得到的哈希地址是什么,一旦发生冲突,都填入溢出表中。** +**** + +### 联系 + + + + + diff --git "a/\347\256\227\346\263\225/\344\272\214\345\210\206\346\237\245\346\211\276.md" "b/\347\256\227\346\263\225/\344\272\214\345\210\206\346\237\245\346\211\276.md" new file mode 100644 index 0000000..697f3c1 --- /dev/null +++ "b/\347\256\227\346\263\225/\344\272\214\345\210\206\346\237\245\346\211\276.md" @@ -0,0 +1,156 @@ +## :算法之排序二分查找 +####php-leetcode之路 [Leetcode-php](https://github.com/wuqinqiang/leetcode-php) + +### :pencil2:二分查找 + + +​ + + + +**二分查找是一种常见的查找方式。在生活中有一个猜大小的例子。比如给定一个0-100的范围,让你猜出事先我所设置的数字,每次把数字的范围缩小到一半。第一次猜50,大了还是小了,继续缩小数字的范围。但是有一个前提,我们得保证我们查找的是一个有序的范围。** + +**** + +### :pencil2:查找思想 + +**二分查找针对的是一个有序的集合。它的查找算法有点类型分治的思想,就像上面所说的。每次我通过中间的数和指定的数进行比较,判断大小,缩小猜测的区间,最多到区间等于0的时候,结果也就是最终指定的答案。二分查找是一种高效的查找算法,它的时间复杂度是O(logn).** + +**** + +### :pencil2:php实现二分查找 + +**1.我们先实现一个最基础的,在一个有序数组中(数组没有重复的值)查找给定值。(迭代)** + +```php +function binarySerach($data,$res) +{ + $l=0; + $r=count($data)-1; + while($l<=$r){ + // $middle=floor(($l+$r)/2); + // $middle=$l+floor(($r-$l)/2); + $middle=$l+(($r-$l)>>1); //使用位运算查找更高效 + if($data[$middle]==$res) return $middle; + elseif ($data[$middle]>$res) $r=$middle-1; + else $l=$middle+1; + } + return -1; +} +$data=[2,5,6,7,12,34]; +$res=12; +var_dump(binarySerach($data,$res)); +``` +**** + +**使用递归实现刚才的操作。** + +```php +function binarySerach($data,$res){ + return recursion($data,0,count($data)-1,$res); +} + +function recursion($data,$l,$r,$res) +{ + if($l>$r){ + return -1; + } + $middle=$l+(($r-$l)>>1); + if($data[$middle]==$res) return $middle; + elseif ($data[$middle]>$res) return recursion($data,$l,$middle-1,$res); + else return recursion($data,$middle+1,$r,$res); +} +$data=[2,5,6,7,12,34]; +$res=12; +var_dump(binarySerach($data,$res)); +``` +**** + + +### :pencil2:二分查找的变形问题 + +**上面的那个注释是在数字没有重复的情况下,现在我们来实现数组中有重复值的情况下,如何查找出第一个等于给定值的元素。其实就是在做等于判断的时候如果索引是0那么是第一个等于给定值的数,或者当前等于给定值的上一个索引值不等于给定值。** + +```php + +function binarySerach($data,$res){ + $l=0; + $r=count($data); + while($l<=$r){ + $middle=$l+(($r-$l)>>1); + if($data[$middle]>$res) $r=$middle-1; + elseif($data[$middle]<$res) $l=$middle+1; + else{ + if($middle==0 || $data[$middle-1] !==$res) return $middle; + else $r=$middle-1; + } + } +} +$data=[2,5,6,7,8,8,10]; +$res=8; +var_dump(binarySerach($data,$res)); +``` +**** +**查找第一个大于等于给定值的元素。** +```php + +//查找第一个大于等于给定值的数 +function binarySerach($data,$res) +{ + $l=0; + $r=count($data)-1; + while($l<=$r){ + $middle=$l+(($r-$l)>>1); + if($data[$middle]<$res) $l=$middle+1; + else{ + if($middle==0 || $data[$middle-1]<$res ) return $middle; + else $r=$middle-1; + } + } + +} +$data=[2,5,6,7,8,8,10]; +$res=9; +var_dump(binarySerach($data,$res)); +``` +**** + +**针对数组是一个循环有序的数组Leetcode35题** +```php + +function binarySerach($data,$res) +{ + $l=0; + $r=count($data)-1; + while($l<=$r){ + $middle=$l+(($r-$l)>>1); + if($data[$middle]==$res) return $middle; + elseif ($data[$middle]>$data[$r]){ + if($data[$l]<=$res && $data[$middle]>$res) $r=$middle-1; + else $l=$middle+1; + }else{ + if($data[$middle]<=$res && $data[$r] >$res) $r=$middle-1; + else $l=$middle+1; + } + } +} +$data=[5,6,7,8,1,2,3,4]; +$res=7; +var_dump(binarySerach($data,$res)); +``` + +**当然二分查找还有很多的应用场景,我就总结到这了。** + + + + +### 联系 + + +​ + + + + + + diff --git "a/\347\256\227\346\263\225/\345\212\250\346\200\201\350\247\204\345\210\222.md" "b/\347\256\227\346\263\225/\345\212\250\346\200\201\350\247\204\345\210\222.md" new file mode 100644 index 0000000..30c3dd4 --- /dev/null +++ "b/\347\256\227\346\263\225/\345\212\250\346\200\201\350\247\204\345\210\222.md" @@ -0,0 +1,259 @@ +## :算法算法之动态规划 + +####php-leetcode之路 [Leetcode-php](https://github.com/wuqinqiang/leetcode-php) + +***动态规划需要花很长时间去练习巩固的。其实在理解动态规划之前正确的顺序应该是先写递归,因为很多动态规划的转移方程都是通过递归加记忆法从而推导出公式,但是我随性,所以就不按套路出牌了。接下来就是简单介绍一下动态规划以及应用场景,最后把之前刷过的动态规划的题目全放出来,方便一次性查看。*** +**** + +### :pencil2:动态规划的介绍 + +***动态规划背后的思想简单概括就是,若要解一个指定的问题,我们需要解它的不同部分问题(子问题),再合并子问题求出最终想要的解。*** + +***在现实生活中,有一类活动的过程,由于它的特殊性,可将过程分成若干个互相联系的阶段,在它的每一阶段都需要作出决策,从而使整个过程达到最好的活动效果。因此各个阶段决策的选取不能任意确定,它依赖于当前面临的状态,又影响以后的发展。当各个阶段决策确定后,就组成一个决策序列,因而也就确定了整个过程的一条活动路线。这种把一个问题看做是一个前后关联具有链状结构的多阶段过程就称为多阶段决策过程,这种问题称为多阶段决策最优化问题。每个阶段中,都求出本阶段的各个初始状态到过程终点的最短路径和最短距离,当逆序倒推到过程起点时,便得到了全过程的最短路径及最短距离,同时附带得到了一组最优结果。*** + + +**** + +### :pencil2:动态规划的步骤 + + ***1.递归+记忆化 ->反向推出递推公式*** + + ***2.状态的定义 opt[n],dp[n].*** + + ***3.状态转移的方程dp[n]=dp[n-1]+dp[n-2]*** + + ***4.最优子结构*** +****** +**最经典的爬楼梯问题,给定一个数字代表着楼梯的层数,每次你可以走一步或者两步,求最终你可以有几种方式到达顶峰。递归是自上而下,一层层调用,到了递归的出口,又一层层的回来。而动态规划是从下而上的去思考,比如还是这个爬楼梯问题,如果是动态规划的思想就是** +```php + +f[n]=f[n-1]+f[n+2]; +//一个斐波那契数列 +``` + +***动态规划需要大量的实战练习,一般你只要记住两步,定义好状态,有些时候单单定义一个一维数组的状态是不够的,二通过状态的定义推出递推公式。具体看场景使用。(下面是leetcode70,72,120,121,122,123,152,300动态规划的题目)*** + + +​ + + +```php + /** + * @param Integer $n + * @return Integer + */ + function climbStairs($n) { + if($n<=1){ + return 1; + } + $res[0]=1; + $res[1]=1; + for($i=2;$i<=$n;$i++){ + $res[$i]=$res[$i-1]+$res[$i-2]; + } + return $res[$n]; + + } +``` +****** + + + +​ + + +```php + /** + * @param String $word1 + * @param String $word2 + * @return Integer + */ + function minDistance($word1, $word2) { + + for($i=0;$i<=strlen($word1);$i++) $dp[$i][0]=$i; + for($i=0;$i<=strlen($word2);$i++) $dp[0][$i]=$i; + + for($i=1;$i<=strlen($word1);$i++){ + for($j=1;$j<=strlen($word2);$j++){ + if(substr($word1,$i-1,1)==substr($word2,$j-1,1)){ + $dp[$i][$j]=$dp[$i-1][$j-1]; + }else{ + $dp[$i][$j]=min($dp[$i-1][$j],$dp[$i][$j-1],$dp[$i-1][$j-1])+1; + } + } + } + return $dp[strlen($word1)][strlen($word2)]; + } +``` +****** + + + +​ + + +```php + /** + * @param Integer[][] $triangle + * @return Integer + */ + function minimumTotal($triangle) { + if(empty(count($triangle))){ + return 0; + } + for($i=count($triangle)-1;$i>=0;$i--){ + for($j=0;$j +​ + + +```php + /** + * @param Integer[] $prices + * @return Integer + */ + function maxProfit($prices) { + + //二维数组的0,1,2表示的状态分别是没买股票,买了股票, 卖了股票 + $res=0; + $pro[0][0]=$pro[0][2]=0; + $pro[0][1]=-$prices[0]; + for($i=1;$i +​ + + +```php + /** + * @param Integer[] $prices + * @return Integer + */ + function maxProfit($prices) { + $dp[0][0]=0; + $dp[0][1]= -$prices[0]; + $res=0; + for($i=1;$i +​ + + +```php + /** + * @param Integer[] $prices + * @return Integer + */ + function maxProfit($prices) { + $res=0; + $dp[0][0][0]=0; + $dp[0][0][1]= -$prices[0]; + $dp[0][1][0]= -$prices[0]; + $dp[0][1][1]= -$prices[0]; + $dp[0][2][0]=0; + + for($i=1;$i +​ + + +```php + /** + * @param Integer[] $nums + * @return Integer + */ + function maxProduct($nums) { + $max=$min=$res=$nums[0]; + for($i=1;$i +​ + + +```php + +/** + * @param Integer[] $nums + * @return Integer + */ + function lengthOfLIS($nums) { + if(empty($nums)){ + return 0; + } + $res=1; + for($i=0;$i Date: Fri, 5 Jul 2019 17:44:34 +0800 Subject: [PATCH 33/48] Leetcode-php --- ...221\351\242\230\347\233\256\351\233\206\345\220\210.md" | 7 ++++++- ...221\345\237\272\346\234\254\346\223\215\344\275\234.md" | 7 ++++++- .../\345\240\206\346\240\210.md" | 2 +- .../\346\225\243\345\210\227\350\241\250.md" | 7 +++++-- .../\344\272\214\345\210\206\346\237\245\346\211\276.md" | 2 +- .../\345\212\250\346\200\201\350\247\204\345\210\222.md" | 6 +++++- 6 files changed, 24 insertions(+), 7 deletions(-) diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204/Leetcode\347\273\217\345\205\270\344\272\214\345\217\211\346\240\221\351\242\230\347\233\256\351\233\206\345\220\210.md" "b/\346\225\260\346\215\256\347\273\223\346\236\204/Leetcode\347\273\217\345\205\270\344\272\214\345\217\211\346\240\221\351\242\230\347\233\256\351\233\206\345\220\210.md" index 1cb0b19..e31bb76 100644 --- "a/\346\225\260\346\215\256\347\273\223\346\236\204/Leetcode\347\273\217\345\205\270\344\272\214\345\217\211\346\240\221\351\242\230\347\233\256\351\233\206\345\220\210.md" +++ "b/\346\225\260\346\215\256\347\273\223\346\236\204/Leetcode\347\273\217\345\205\270\344\272\214\345\217\211\346\240\221\351\242\230\347\233\256\351\233\206\345\220\210.md" @@ -1,6 +1,6 @@ ## :pencil2:Leetcode经典二叉树题目集合 -####php-leetcode之路 [Leetcode-php](https://github.com/wuqinqiang/leetcode-php) +#### php-leetcode之路 [Leetcode-php](https://github.com/wuqinqiang/leetcode-php) **** ### :pencil2:1.二叉树的前序遍历(leetcode144) @@ -613,6 +613,11 @@ class Solution { ``` **** +### 联系 + + +​ + diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204/\344\272\214\345\217\211\346\240\221\345\237\272\346\234\254\346\223\215\344\275\234.md" "b/\346\225\260\346\215\256\347\273\223\346\236\204/\344\272\214\345\217\211\346\240\221\345\237\272\346\234\254\346\223\215\344\275\234.md" index 0a052e5..766ea8e 100644 --- "a/\346\225\260\346\215\256\347\273\223\346\236\204/\344\272\214\345\217\211\346\240\221\345\237\272\346\234\254\346\223\215\344\275\234.md" +++ "b/\346\225\260\346\215\256\347\273\223\346\236\204/\344\272\214\345\217\211\346\240\221\345\237\272\346\234\254\346\223\215\344\275\234.md" @@ -1,5 +1,5 @@ ## :数据结构线性表之二叉树1 -####php-leetcode之路 [Leetcode-php](https://github.com/wuqinqiang/leetcode-php) +#### php-leetcode之路 [Leetcode-php](https://github.com/wuqinqiang/leetcode-php) @@ -218,6 +218,11 @@ $sortTree->insertTree(4); //var_dump($sortTree->getTree()); ``` +### 联系 + + +​ + diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204/\345\240\206\346\240\210.md" "b/\346\225\260\346\215\256\347\273\223\346\236\204/\345\240\206\346\240\210.md" index a298935..42ed110 100644 --- "a/\346\225\260\346\215\256\347\273\223\346\236\204/\345\240\206\346\240\210.md" +++ "b/\346\225\260\346\215\256\347\273\223\346\236\204/\345\240\206\346\240\210.md" @@ -1,6 +1,6 @@ ## :数据结构线性表之堆栈 -####php-leetcode之路 [Leetcode-php](https://github.com/wuqinqiang/leetcode-php) +#### php-leetcode之路 [Leetcode-php](https://github.com/wuqinqiang/leetcode-php) diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204/\346\225\243\345\210\227\350\241\250.md" "b/\346\225\260\346\215\256\347\273\223\346\236\204/\346\225\243\345\210\227\350\241\250.md" index a5c2117..5174d2b 100644 --- "a/\346\225\260\346\215\256\347\273\223\346\236\204/\346\225\243\345\210\227\350\241\250.md" +++ "b/\346\225\260\346\215\256\347\273\223\346\236\204/\346\225\243\345\210\227\350\241\250.md" @@ -1,5 +1,5 @@ ## 数据结构之散列表 -####php-leetcode之路 [Leetcode-php](https://github.com/wuqinqiang/leetcode-php) +#### php-leetcode之路 [Leetcode-php](https://github.com/wuqinqiang/leetcode-php) @@ -102,8 +102,11 @@ h(key)=key MOD p, p<=m **假设散列函数的值域为[0,m-1],则设置向量HashTable[0,m-1]为基本表,每一个分量存储一个记录,另外设置向量OverTable[0,v]为溢出表。所有关键字和基本表中关键字为同义词的记录,不管它们由哈希函数得到的哈希地址是什么,一旦发生冲突,都填入溢出表中。** **** + ### 联系 -### 联系 + + ​ + diff --git "a/\347\256\227\346\263\225/\344\272\214\345\210\206\346\237\245\346\211\276.md" "b/\347\256\227\346\263\225/\344\272\214\345\210\206\346\237\245\346\211\276.md" index 697f3c1..6c5aa57 100644 --- "a/\347\256\227\346\263\225/\344\272\214\345\210\206\346\237\245\346\211\276.md" +++ "b/\347\256\227\346\263\225/\344\272\214\345\210\206\346\237\245\346\211\276.md" @@ -1,5 +1,5 @@ ## :算法之排序二分查找 -####php-leetcode之路 [Leetcode-php](https://github.com/wuqinqiang/leetcode-php) +### php-leetcode之路 [Leetcode-php](https://github.com/wuqinqiang/leetcode-php) ### :pencil2:二分查找 diff --git "a/\347\256\227\346\263\225/\345\212\250\346\200\201\350\247\204\345\210\222.md" "b/\347\256\227\346\263\225/\345\212\250\346\200\201\350\247\204\345\210\222.md" index 30c3dd4..4443d82 100644 --- "a/\347\256\227\346\263\225/\345\212\250\346\200\201\350\247\204\345\210\222.md" +++ "b/\347\256\227\346\263\225/\345\212\250\346\200\201\350\247\204\345\210\222.md" @@ -1,6 +1,6 @@ ## :算法算法之动态规划 -####php-leetcode之路 [Leetcode-php](https://github.com/wuqinqiang/leetcode-php) +#### php-leetcode之路 [Leetcode-php](https://github.com/wuqinqiang/leetcode-php) ***动态规划需要花很长时间去练习巩固的。其实在理解动态规划之前正确的顺序应该是先写递归,因为很多动态规划的转移方程都是通过递归加记忆法从而推导出公式,但是我随性,所以就不按套路出牌了。接下来就是简单介绍一下动态规划以及应用场景,最后把之前刷过的动态规划的题目全放出来,方便一次性查看。*** **** @@ -251,7 +251,11 @@ f[n]=f[n-1]+f[n+2]; } ``` ****** +### 联系 + +​ + From eee17a2f122f161deccb6a98ccbb7455670d2492 Mon Sep 17 00:00:00 2001 From: xianyunyh Date: Sun, 22 Sep 2019 17:22:46 +0800 Subject: [PATCH 34/48] edit redis --- Cache/Redis.md | 7 ++ .../Readme.md" | 73 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 "\346\223\215\344\275\234\347\263\273\347\273\237/Readme.md" diff --git a/Cache/Redis.md b/Cache/Redis.md index b43dba6..54cfc97 100644 --- a/Cache/Redis.md +++ b/Cache/Redis.md @@ -39,3 +39,10 @@ redis是一个开源的支持多种数据类型的key=>value的存储数据库 > hset、hget、hmget、hmset、hkeys、hlen、hsetnx、hvals +### redis 各种类型的场景使用 + +- string 就是存储简单的key=>value的字符串 +- list 使用场景。做先进先出的消费队列 +- set 进行集合过滤重复元素 +- zset 有序集合,排行榜 TOP N +- hash 适合存储一组数据,比如用户的信息 以用户id为键,里面记录用户的昵称等信息。 \ No newline at end of file diff --git "a/\346\223\215\344\275\234\347\263\273\347\273\237/Readme.md" "b/\346\223\215\344\275\234\347\263\273\347\273\237/Readme.md" new file mode 100644 index 0000000..60290d5 --- /dev/null +++ "b/\346\223\215\344\275\234\347\263\273\347\273\237/Readme.md" @@ -0,0 +1,73 @@ + +# 操作系统概论 + +操作系统是一种计算机软件。在硬件之上,应用程序之下。主要功能就是管理底下的计算机硬件,并为上层的应用程序提供统一的接口。 + +![img](https://camo.githubusercontent.com/9f8cbe895e7729fc61e18424f2edb7b23ef9d6f3/687474703a2f2f6974666973682e6e65742f486f6d652f4d6f64756c65732f496d616765732f6974666973685f34343836395f302e6a7067) + +**系统调用**:应用程序直接调用操作系统提供的接口 如write 函数 + +**库函数调用**:应用程序通过一些库函数直接调用 如 fwrite + +## 内核态和用户态 + +操作系统为了管理内存。将内存分为**内核空间**(内核态)和**用户空间**。内存空间和用户空间之间有隔离。 + +**用户空间即上层应用程序的活动空间**,应用程序的执行必须依托于内核提供的资源,包括CPU资源、存储资源、I/O资源等。为了使上层应用能够访问到这些资源,内核必须为上层应用提供访问的接口:即系统调用 + + + + + +![img](https://images2015.cnblogs.com/blog/431521/201605/431521-20160523163606881-813374140.png) + +内核从本质上看是一种软件——控制计算机的硬件资源,并提供上层应用程序运行的环境。 + +shell就是外壳。类似一种胶水的功能。可以通过shell访问内核。 + +内核态与用户态是指CPU的运行状态(即特权级别),每个进程的每种CPU状态都有其运行上下文,运行上下文就包括了当前状态所使用的空间,CPU访问的逻辑地址(即空间)通过地址映射表映射到相应的物理地址(即物理内存)。在Linux系统中,进程的用户空间是独立的,而内核空间是公用的,进程切换时,用户空间切换,内核空间不变。 + +对于多数CPU而言,处于内核态时,可以访问所有地址空间,而处于用户态时,就只能访问用户空间了。 + + + +## 用户态和内核态切换 + +操作系统的资源是有限的,如果访问资源的操作过多,必然会消耗过多的资源,而且如果不对这些操作加以区分,很可能造成资源访问的冲突。 + +为了减少有限资源的访问和使用冲突,Unix/Linux的设计哲学之一就是:对不同的操作赋予不同的执行等级,就是所谓特权的概念 + +Linux操作系统中主要采用了0和3两个特权级,分别对应的就是内核态和用户态。运行于用户态的进程可以执行的操作和访问的资源都会受到极大的限制,而运行在内核态的进程则可以执行任何操作并且在资源的使用上没有限制。很多程序开始时运行于用户态,但在执行的过程中,一些操作需要在内核权限下才能执行,这就涉及到一个从用户态切换到内核态的过程 + +![img](https://images2015.cnblogs.com/blog/431521/201605/431521-20160523210140147-1668637440.gif) + + + +## 库函数调用和系统调用的区别 + +![这里写图片描述](http://img.blog.csdn.net/20170117211419709?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTEZfMjAxNg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) + +系统调用(英语:system call),指运行在用户空间的应用程序向操作系统内核请求某些服务的调用过程。 系统调用提供了用户程序与操作系统之间的接口。一般来说,系统调用都在内核态执行。由于系统调用不考虑平台差异性,由内核直接提供,因而移植性较差(几乎无移植性)。 + +库函数(library function),是由用户或组织自己开发的,具有一定功能的函数集合,一般具有较好平台移植性,通过库文件(静态库或动态库)向程序员提供功能性调用。程序员无需关心平台差异,由库来屏蔽平台差异性。 + +| 函数库调用 | 系统调用 | +| ----------------------------- | ----------------------- | +| 平台移植性好 | 依赖于内核,不保证移植性 | +| 调用函数库中的一段程序(或函数) | 调用系统内核的服务 | +| 一个普通功能函数的调用 | 是操作系统的一个入口点 | +| 在**用户空间**执行 | 在**内核空间**执行 | +| 它的运行时间属于“用户时间” | 它的运行时间属于“系统”时间 | +| 属于过程调用,调用开销较小 | 在用户空间和内核上下文环境间切换,开销较大 | +| 库函数数量较多 | UNIX中大约有90个系统调用,较少 | +| 典型的C函数库调用:printf scanf malloc | 典型的系统调用:fork open write | + +![clip_image002](http://blog.chinaunix.net/attachment/201207/11/27105712_13419741441gpp.gif) + +读写IO通常是大量的数据(这种大量是相对于底层驱动的系统调用所实现的数据操作单位而言),使用库函数调用可以大大减少系统调用的次数。这是因为缓冲区技术。在用户空间和内核空间,对文件操作都使用了缓冲区,当内核缓冲区写满之后或写结束之后才将内核缓冲区内容写到文件对应的硬件媒介中。 + +**不带缓冲指的是每个read和write这些文件I/O操作都调用的是系统调用,属于内核态的操作** + +诸如fread和fwrite这些标准I/O操作属于用户态操作,具体是库函数的实现,需要借助用户缓冲区来实现 + +更多内容可以参考 [操作系统](https://github.com/xianyunyh/studynotes/tree/master/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F) \ No newline at end of file From 350d6aebe0037bd117923133c94eeb0c7ec19a12 Mon Sep 17 00:00:00 2001 From: xianyunyh Date: Thu, 3 Oct 2019 20:45:08 +0800 Subject: [PATCH 35/48] =?UTF-8?q?=E4=BF=AE=E6=94=B9websocket?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../README.md" | 20 --- .../__pycache__/lagou.cpython-36.pyc" | Bin 3648 -> 0 bytes .../boss.py" | 60 --------- .../lagou.py" | 125 ------------------ .../lagoutest.py" | 19 --- .../stop.txt" | 47 ------- .../word.py" | 44 ------ ...14\345\210\206\346\237\245\346\211\276.md" | 2 +- .../Webscokt.md" | 95 ++++++++++++- 9 files changed, 90 insertions(+), 322 deletions(-) delete mode 100644 "\347\210\254\350\231\253\350\204\232\346\234\254/README.md" delete mode 100644 "\347\210\254\350\231\253\350\204\232\346\234\254/__pycache__/lagou.cpython-36.pyc" delete mode 100644 "\347\210\254\350\231\253\350\204\232\346\234\254/boss.py" delete mode 100644 "\347\210\254\350\231\253\350\204\232\346\234\254/lagou.py" delete mode 100644 "\347\210\254\350\231\253\350\204\232\346\234\254/lagoutest.py" delete mode 100644 "\347\210\254\350\231\253\350\204\232\346\234\254/stop.txt" delete mode 100644 "\347\210\254\350\231\253\350\204\232\346\234\254/word.py" diff --git "a/\347\210\254\350\231\253\350\204\232\346\234\254/README.md" "b/\347\210\254\350\231\253\350\204\232\346\234\254/README.md" deleted file mode 100644 index 89b10b1..0000000 --- "a/\347\210\254\350\231\253\350\204\232\346\234\254/README.md" +++ /dev/null @@ -1,20 +0,0 @@ -## 爬取招聘网数据 - -在我们找工作的时候,有些时候,需要到各个网站去找岗位,程序员当然是使用自己的方式来快速的寻找自己的岗位了。于是就想到使用python来抓取最新的符合自己薪资条件的岗位,以及对应的岗位需要的JD,然后如果匹配的话,那么自己可以一键投递。 - - - -- [x] 模拟登录 - -- [x] 抓取拉钩最新数据 -- [ ] 爬取51job网站数据 -- [ ] 爬取智联数据 -- [ ] 爬取boss数据 -- [ ] 一键投递 -- [ ] 岗位分析【分析出现最多的关键词】 -- [ ] web可视化 - - - - - diff --git "a/\347\210\254\350\231\253\350\204\232\346\234\254/__pycache__/lagou.cpython-36.pyc" "b/\347\210\254\350\231\253\350\204\232\346\234\254/__pycache__/lagou.cpython-36.pyc" deleted file mode 100644 index a44a28e3914045da3b1e552ef2d280e2fdf82265..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3648 zcmb7HZEzGx8J_Q%-E2Y#IpNgO)ha!fGaEp-LO{LL1%xWdA#jo!qg%^%Cp-H!OHVIk zw65Y8(&ewFM`&iBK1GUjGo0f0u z>6qg?YRvUruGPF%&G(qeEN0&{{7j(vS==McVeTc(&oPf>P>-@K8$mtBa%>d!CN{=4 zp&n=BY%}W3Y=Uh;J;C%-T48bn-=obH^u#^U{bGlUZtvNulv4;>kA^gudCgccrCGC>6`M61EoaqSv0_Wi z##YT`_9~uIEe9>cCe{}X_}iUJwEqiU1j{NfGcKauOmWA2X{IHE(&11n@zUwA&RhA< z<`4Y z;ECNV%Stt|Bwv=kGyCG{nPbNidr5?ycER>XhL-oUsXYKlQ-iZ0bxPtG$W&shL(F zr<7x+RFHa`AL}D$i3~OX0(c$pyH##--+PEqf2&AeUs?=Bvvi(|V6m$l>_nZj%|QOo z2&zS4t6+#pEG4oi5<8M*aAgGT4*B-}jl2Edf4l$Vx7L4i>u>K}-MDzMf92hcf8Z)) zmGcE;TuZD<2pTz^HiF6(U&JW-eXAWtGO=ix#BK{HUt;m)Ko&gl0gMZZmOt^Yp!GLD z)~EJ1nu6y6*x?PldX_Nc2@Vl%MUVwrs6@be5>2*x_!C$z+J-^{c07H;Fmy*Zbk7)v zmBTGQg0TVBX(C}u;fWq2dXt1A?nVvdh7BSk^2S_m-+#ynOQPJ8r$~Y-{B%&Mb2+WL zlqMD&jz32J;*f=1GY4Q1P^J)8@hNMv`n#Wu4+BL}yl)6?3DGqloA z{_9E(9G;m2YzeUbGwA@D}vHB^As8Nm3sN znCUbKhlJDA_nAY>72cLmJn><4CL_d!P6S^vo|usof))@TLQ!xNvm+Xhz92F2!bIo3 zO%RMyMyZ%Q3XHwTA({vActnoZfWAqckT-5*Nzn`sSlpKO=wb(E3=%qN!9dx52qQ%z zL!x08LZ!ntVx8I7^cAFa=F~Id`^(F*HmiN5y<$S`;OZ5Nd1?5N@)01GA=k$S0+&Tl z4W)1+bwj*{@Hx_vE>f0N6-V6}LKqEKpwVdJo$!KtcUZgr2cUUtyj zpJc)RfTkT~#0ND+=~hoE0|xeYNZ0yr|N8#j>;20&`ro)EI18eC@BFfmO>EWn$6gpL zcLJ;V_DPx|K8Xi?D=IUVsA!+8bK+xwUPRE#Qk#;>GC@4iXa-S2^(ZmTT-{I7Z!=k;aA@g|$ zHQ2~`5A3Y6M+SCI*`ot{Oxc?T_PDY)59|qLZyDH=uw4-Qskz=ZQc@hQn?tAST6i{^ z?%Ane4l!SR99!??Pz+Q4a4%P+^bp7f&sTRRwrcgsLRX3_o$y*y=;-QPNht!^D~1c=CTG~lvqhj;Y)g>w79}14xtr4H*6JL1+GW3 zBPb~;7%6#4jP^OG(r)S;=$oHO;r9|Ghd|_8^q)ndpG$Q11faw;#+PtMc@%`EaY#R% zmmHwVQa1IaKQ+6sMSK)fm9PmqJ^OCEi!3C%g0i1@jtWW}Vw?&kn3VM&eP5dK>Aav4 zs7f?Sz!YZHB150~ND;k*&5(5({Bv~dj3|^IJ~B -​ +​ diff --git "a/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234/Webscokt.md" "b/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234/Webscokt.md" index 08b8f20..37e0ab4 100644 --- "a/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234/Webscokt.md" +++ "b/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234/Webscokt.md" @@ -2,7 +2,7 @@ > Websocket是html5提出的一个协议规范,参考rfc6455。 > -> websocket约定了一个通信的规范,通过一个握手的机制,客户端(浏览器)和服务器(webserver)之间能建立一个类似tcp的连接,从而方便c-s之间的通信。在websocket出现之前,web交互一般是基于http协议的短连接或者长连接。 +> websocket约定了一个通信的规范,通过一个握手的机制,客户端(浏览器)和服务器(webserver)之间能建立一个类似tcp的连接,从而方便C-S之间的通信。在websocket出现之前,web交互一般是基于http协议的短连接或者长连接。 > > WebSocket是为解决客户端与服务端实时通信而产生的技术。websocket协议本质上是一个基于tcp的协议,是先通过HTTP/HTTPS协议发起一条特殊的http请求进行握手后创建一个用于交换数据的TCP连接,此后服务端与客户端通过此TCP连接进行实时通信。 @@ -10,7 +10,7 @@ ### Websocket和HTTP协议的关系 -同样作为应用层的协议,WebSocket在现代的软件开发中被越来越多的实践,和HTTP有很多相似的地方,这里将它们简单的做一个纯个人、非权威的比较: +同样作为应用层的协议,WebSocket在现代的软件开发中被越来越多的实践,和HTTP有很多相似的地方,这里将它们简单比较: #### 相同点 @@ -58,12 +58,10 @@ Sec-WebSocket-Version: 13 ```http HTTP/1.1 101 Switching Protocols -Content-Length: 0 Upgrade: websocket Sec-Websocket-Accept: ZEs+c+VBk8Aj01+wJGN7Y15796g= -Server: TornadoServer/4.5.1 Connection: Upgrade -Date: Wed, 21 Jun 2017 03:29:14 GMT +Sec-WebSocket-Protocol: chat, superchat ``` Sec-Websocket-Accept 是一个校验。用客户端发来的sec_key 服务器通过sha1计算拼接商GUID【258EAFA5-E914-47DA-95CA-C5AB0DC85B11 】 。然后再base64encode @@ -96,10 +94,95 @@ Sec-Websocket-Accept 是一个校验。用客户端发来的sec_key 服务器通 - Payload data:任意长度数据。包含有扩展定义数据和应用数据,如果没有定义扩展则没有此项,仅含有应用数据。 +### 服务端简单实现 +```php +// 封装ws 协议的数据包 +function build($msg) { + $frame = []; + $frame[0] = '81'; // 81 就是 10000001 第一位1表示最后一个数据段,最后一位1表示这是文本数据 + $len = strlen($msg); + if ($len < 126) { + //7位长度 第一个是掩码 默认是0 + //小于126的时候 也是 01111110 数据包第二个字节表示长度 + $frame[1] = $len < 16 ? '0' . dechex($len) : dechex($len); + } else if ($len < 65025) { + //7位 + 16位 01111110 00000000 00000000 + $s = dechex($len); + $frame[1] = '7e' . str_repeat('0', 4 - strlen($s)) . $s; + } else { + //7位 + 64位 01111111 00000000 00000000 + $s = dechex($len); + $frame[1] = '7f' . str_repeat('0', 16 - strlen($s)) . $s; + } + $data = ''; + $l = strlen($msg); + for ($i = 0; $i < $l; $i++) { + $data .= dechex(ord($msg{$i})); + } + //最后是数据内容 + $frame[2] = $data; + $data = implode('', $frame); + return pack("H*", $data); +} +//拆包 +function parse($buffer) { + $decoded = ''; + $len = ord($buffer[1]) & 127; + if ($len === 126) { + $masks = substr($buffer, 4, 4); + $data = substr($buffer, 8); + } else if ($len === 127) { + $masks = substr($buffer, 10, 4); + $data = substr($buffer, 14); + } else { + $masks = substr($buffer, 2, 4); + $data = substr($buffer, 6); + } + for ($index = 0; $index < strlen($data); $index++) { + $decoded .= $data[$index] ^ $masks[$index % 4]; + } + return $decoded; + } +$socket = stream_socket_server("tcp://0.0.0.0:8888", $errno, $errstr); +if (!$socket) { + echo "$errstr ($errno)
\n"; + die; +} +while (1) { + $conn = stream_socket_accept($socket); + $data = stream_get_contents($conn,500); + $data = explode("\r\n",$data); + $secKey = ""; + foreach ($data as $key=>$val) { + if (strpos($val,"WebSocket-Key:") >= 1 ) { + $key = explode(":",$val ); + $secKey = $key[1]; + } + } + //固定key 算法 base64(sha1(key+258EAFA5-E914-47DA-95CA-C5AB0DC85B11)) + $hashkey = base64_encode(sha1(trim($secKey)."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true)); + $ws = "HTTP/1.1 101 Switching Protocols\r\n"; + $ws .= "Upgrade: websocket\r\n"; + $ws .= "Connection: Upgrade\r\n"; + $ws .= "Sec-WebSocket-Version:13\r\n"; + $ws .= "Sec-WebSocket-Accept: $hashkey\r\n"; + $ws .= "Sec-WebSocket-Protocol: chat\r\n"; + $ws .= "\r\n"; + if (!$conn) { + continue; + } + fwrite($conn, $ws); + fwrite($conn,build("hello")); + fclose($conn); + break; +} +fclose($socket); +``` + ### 客户端 ```js -var websocket = new WebSocket("ws://127.0.0.1") +var websocket = new WebSocket("ws://127.0.0.1:8888","chat") websocket.onopen = function(){ } From 304cb61982acf488aa0d45581d58e44632b9f9e2 Mon Sep 17 00:00:00 2001 From: xianyunyh Date: Thu, 3 Oct 2019 21:29:45 +0800 Subject: [PATCH 36/48] https --- .../HTTP2.md" | 22 ++++++++++++++++-- .../images/http2.png" | Bin 0 -> 46892 bytes .../images/https.png" | Bin 0 -> 100501 bytes 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 "\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234/images/http2.png" create mode 100644 "\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234/images/https.png" diff --git "a/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234/HTTP2.md" "b/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234/HTTP2.md" index e8ae82a..2f329c8 100644 --- "a/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234/HTTP2.md" +++ "b/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234/HTTP2.md" @@ -39,7 +39,7 @@ HTTP1.0最早在网页中使用是在1996年,那个时候只是使用一些较 3. HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。 4. HTTPS可以有效的防止运营商劫持,解决了防劫持的一个大问题。 -![img](http://tenny.qiniudn.com/HTTPQUBIE2.png) +![img](images/https.png) ## 使用SPDY加快你的网站速度 @@ -64,5 +64,23 @@ SPDY位于HTTP之下,TCP和SSL之上,这样可以轻松兼容老版本的HTT - **header压缩,**如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。 - **服务端推送**(server push),同SPDY一样,HTTP2.0也具有server push功能。目前,有大多数网站已经启用HTTP2.0,例如[YouTuBe](https://www.youtube.com/),[淘宝网](http://www.taobao.com/)等网站,利用chrome控制台可以查看是否启用H2 -![img](http://tenny.qiniudn.com/diff332.png) +![img](images/http2.png) +```conf +server { + listen 443 ssl http2; + server_name example.com; + root /var/www/example.com/public; + + # SSL + ssl_certificate /etc/live/example.com/fullchain.pem; + ssl_certificate_key /etc/live/example.com/privkey.pem; + ssl_trusted_certificate /etc/live/example.com/chain.pem; + + # index.html fallback + location / { + try_files $uri $uri/ /index.html; + } +} + +``` \ No newline at end of file diff --git "a/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234/images/http2.png" "b/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234/images/http2.png" new file mode 100644 index 0000000000000000000000000000000000000000..9cf1a93689e88adfdb3b24b38baa8d0754fbb909 GIT binary patch literal 46892 zcmeFZWmuK#);25%h#-Oj1|cX70wUd^lF}uO(%m2pA|gt6hjdGKn1IquIwd9zD&6mx ztiASLKHvBK`u;q}@$PjTi{+Y5?)$pOJ+2Ywd5$YkK~4e>hXm)`xpR0@k`I;6ojV@_ z|6*Zd!6%JGqqonUqdX_|P*mkP+Umr`Bh~(s(_h4$>F-{OD@R7W(IUycbn$jPNmQPN zwXM{nwlFOJunvd&F+UvEb2tB-lT>PKR-Q(uIAGc?v4G&SI?mLKQYslZ8)8Kkmm7dRriJukZwvckz8c+M5mK zRbj-w6~a1B7H}ZZPaGGm_aX@jm_@ z#h^?(QaFMS8|F2=NaM9|+9hIy#i@iuW6YNDZRdxS3~1=BnZte6{X1)8o%q5>1dcwE zqMAM8W(V)h2lB<{_g6}q@7!9;N%guf6U!1@BSgyNygGb^XSG}SRD00_ovC~a34aWF zZdinSyh~s=d#8|I@!dW1mzutgTf3jzslvtwYZK%v;t~zZcO=>LiU@?uyO$$(sUu(|(;7>5}vlI4z8K z;KpQvgm0pA&-og>duAExgO8acEkgVu?Dm7lsY0F|!Q7Lk(lK}Af0cW#6jgW7rFvZD zDSn}G^{==Th;5j!J67jZaFgG;&~>eHsAIg=p)*C$eTLDv(QUh9e<9UoW$bu&O1Rjw ztg&~a`PBNB`zjl|^*GPwm`(E+)ucDXObM6C`Qm)fUr4~hBl%p3PdZ@sc&do`FL za>Li&RJv_1YYWPLBMvwxPc|#^EOHO?mfPa(a;vebJs0ee-^nhMY^)7G#d`YQvNjDn zt`4)AYTTjt7R_{h*kfz4msYdCr{&d^$=v1zWqCp3ik)|FS?({SxLfy>JrtrIt^OIr z-gQsVedqBUf$>nWj(Bum46~MH`Atr5of_M8jWWYPo$D;+;4kAGR-*{|umX77HL^-g zmLFbVRy}6uj=OY4{sk8w3}KX2tHN(9|_I_Y(2wRx~o zl9&;~$N1duu6JJz@xjEe370A2JZiVAhkY`vBU40#baE92OhgP1oV(t@TUQ%Cc2~fg zQ;y1Ho$YB+^b{CKq9T^^+a;pOYZfz|9)ADyQ&co-N*TH9TsQ-N$~wj}t~T-q)}o>^ z(MZ8Xi+92pGrX}qR*t(ds2nyI0bYAh@+x+@Qls2BUM`t$L?|fz{+Bnz>_uADRolob z5@b*FRSS%5vR90YHWLKhtKfUGi^a~3Soz8>!IAPpwLJ%xcYBmoCTj52CuhFA9os}i ze*T0nJl=$ZgVRxF^nF!kf&b~pmty#YTc3Y@CY0xJQwU>Ph{w|^xfR*cTc93dPZfra zwk=q*S_a>B;dkF%xANMbk4;P3Ci*FSx*xjs=}N_&FBFbs!NW3VjwC{<;p;ePL831& zKgBUEYub0t0Vj$GBY+llHFs^_ArXg@x3S>wbP{Q!p+J(MT#~{T0G~B7VAx9 zr|6d+$ts$UqLQlwl=py!sQ^xamJ00P2f0(JL>cy4I#R-UrzjC>xzX;7v#VHyvi)f4a<0;eAv}j@_1= z_d61;ogW<|WU^K*ipVzzJ6HazRrQ40;*+}Xao;le!$?xJI^DNY{;H5f_%PmRmgF^i z*N9lR_@E*43yK+)!c)Bt%rd6AIF_VzOqBEx?Eyu-p% zXvuv;Uvc`dtW{t5uV=q=ktj>IKR0JNc0n#-y2<P1rB1+Qn#?q2$friEswPiy9u(4|slAshM?5DUxr{3CD2dVA2QBJd zHmYP5AAGm%7TmqD>!_E$Lb&g-oR>qgZE;D~O)Pe43w8$)-(0R@296-Z-3rAdTrB)s zmPC&A{T3yS$dk51vTKyK9Y5Ya=p|^&_Q@8#C>x03u`*Or{poGMWbLKS$nL-DM?*2n zc(=9htj%{3_r>?A`BLo*H*vWswzih~4c21%wiC=BItbMFLu@9mqR4hnd^ovcT$Yei z7m0;~BUtP%xZxn-)57Lbj7cL(nS+t9lBbj_@W`xKlb-$BU*%btsITF2Wu9`*HOBPp z(!L6!yvJ6f6%0|y*`M1C-R7g!amd#po-$Sx=Hh;w-(M~$xyGrr)9rI^lgId6`~%AA zN4^jkt}*UFKEYvrTal((pyn@b^tPg?T-$~GaBFGSqocjK`Q)HrADL+L;#+nvQjUME zBF*U0F~K^|H|0%p{~clG<GCcb5NhiR)}I_o#8ry1m(pS&QP@uZ{FeyZp|p?~iqm zUCE?T0qgb_zs=6Ft;h^|JHjHJ%4=CXJ;5fM&&(Wuz}Nd^-$Y?>tjg-U#i%I*<|T>*xh=-AZs1lE*fcxEXZQZ9u9 zNpy}~#fjE+?RPcGsA&YMC*2Az;*o^%Ez@uIJiyPQ_P#F)>GroGIDu@2SDkYFeWRck zttvSX^5U7bsxXWS!qxD3rhU?kmJZVRB)FL;@*t?MhcbAUq;YUCYgW)ZUP*O$47O=y z!Tusjsg7}tRaZNg9wHHI#a)W)i`JW-yA#(Pm(7(Ne|@=5s(SKB3KBk3RJHiJ@@c4T zXW<+ByE~6iYmh>%q4S}|KtAzvGxIl&)Pf^->FKe*xt$*Ga({Vil5IDg#Ov@PqzFHO zi%ExJT;!4P$(}*oWr-#R*lCZiP>)bf)Aak(=DB16gTc@I&|?a zVAz>%3F7spSoTR)kmRv$wfZG|7%b5f9}L&_rNMZ&7&S#ziuR%{m1}j55YFxn+Kr^-GL?2ZR1z z?H8=V0w_}4mKg{Sh<4WNH@NgXw^fx$pl-TPLe!efQacwBg@3r-mAVU?P(%oO&aLs9 zHOnU`Mom`xEQjBx_muW|ekwEWOb~6Qw!Jjd){c)6!t1I*PlP@~sNfKr-$8wDUVcJh{*w6}sYn+2Bpx=?>#Cz}qmpNNP*Rt2XoYj&`VaKh z5ORK6@4k!cd30s#nN3M*+)2k-06zK{6M3-3nAYPkz_unj=Y?dgk-V# zJw?vDhilbSw^XFJGnS^By?e?`DG(3y^qRdy6LW>Bj!FC^_fYLF_1$TIH`yXtv6TrZ z|KgCHiF6)K?dt>wpB1TI=kWW7WH#B)f4dV(7`A?Y!TltD$u4o@+am#QPWSqQ<$||y zGWPY|iQKHUh3wZW?$lwvxM9^EUqy%vyke|OK+6aMRx z{vh|aw8@2iu?t(%=&I|iO?&T9wuS9h!(FQf({VJj!>vvr~S!+D0!j(3sKdAsO4Vmx`NI zE_%Hy#r0iDwjVEwD!UvVPMxxFY=4boGk6ST#Btk4-rEG!&>?>Q5Ws;mr_`8zO{nha zUOQbX5#KBn4kKzzImynN=}t?!?_D>MVw)ETd9t-8688yt+@|Zu-B(LBNFz=gHoK^7 zw_2LR-w`QBt3n$WR9uO?gfLCXoWq0;%Z&DMoPGkAm3fu*ggJX(vi7#d(a%r#Ym^TX zPJclchRydnMN-%93$f_;Js%%EXakPij2vbg?2B}jQ+G{LT)&Rne!>$M)ihPI zqstv?%hp;(hLjBy>x@mVE{&9%P#!}6H9}ixl4SSFs*B{w)1Y2Qx+QC`RiRrO(3GH+ z;6BgNP2_hewrXd0-&uV>m(O|vHY5@B?^f%h$=Zx+fGA&IC^__<>8`NfKgB?A)o$X8!b8Il zVC~72B4pQZ@ex~4thF~9dzsgR^H)jrTuy)Hb6~cp9~KfC*Na*^uUd7xdZlw%G;1KX+4@Qnd|KUrCwr%18ef^7=rB9=k z7M*~Z;4qt@p}Kz`7Yw2!(}(tgqL+4~enFj3$t(}K$cQ7swm2K2WPw_dw7cR(vVOUw z-{;|qNl|AF?CC|*%MzS2II$d*pP^X$So93a5y)>LxE|1=Ij>JZ%UrA=HL$9*d9ZwV z`Vp7)ZiUd$wU(9vvFO{ z+#Wcn9}9=C0fB^^7nH{B-^J1iL|RtR-(F|s8q#)77kABiK3^%VolrebiABzvjUELfY>Tj#(Q`hs6qm z%lOjYtWd39lTZ}&5CZf)5Cu0OM`J~6M~VyqM8eX4q*G}=fK#ZhtjY=Hx0$m3O`EeW z)Luq^@8=KWwy@ix{)}2xg^J|^0k_=ROmS#Svf-WIbWz7iZiN(>Qq_;DuW{y!)Oa(; zQN6|5%7Y~^paFVG(}8)q85hS)io5O0ddR{aN zAJBR`H<}dGzG(I)>=hm<)>=YW3kt}<<5R1(p9egUjIbgIzn1Q2vmSG;I+rvmPdt|v zAwPcL*9;AJ-(=ur!SKN%t;9r|CSKFhbxq;@xkyy#gzr&?>G;+tW!v_aornuPnp|t3^>AeHS~! zob$fxZ^H~yKQC#zWJjf*rCic4{qn-(6?cg#Cf!z;QF$<}5O&@5t$6%e25^tWA%CUY zK0d7&2fG_KD3nXZ9M6r=>Z1u}49PucvG4mHSJ_NipYMUTfbMUvAGuPqRyBq*(Lu^> zom7&-!B+-}fFpp+{`F?>i6?Z6IGC=Yq||$&9~J>Gqo{~o{wTxR$YFYu;y>NYIW+u> zi|b2%_(C^So=pf2km;5xL7lov-MhYq>`v9oy;%TF9x4@J^s%Pp1gB42;CLOR8N0`p zm$%q_dc2XQtkvYCZ&d90!O&2~hc7uzDw=vgsRs=9OhsX*!EYacTw>2#nA8^e}bVg=byk!b~yUgdV%@v z_EW&*cDgp9Uh(5n?N8}J3W<`w^ymoOxc-d?DIiEPPIw0 zQ_MbC8gA44O`8*sk)ERPoG;ZW0d(~n7(~OhOpnl#Tqa$S09(tn%?xVUFmrSdsH*E2 zbqO7=zWm+$HNOzB6T1vremPA5fl*NM{ec1J)_}{px;NZHri9Bg(gtkWXZ&Nvlu|8iAy53qYcN z_7}-9`AxGzg`$|X26rqjS(W9xm7tn(>o{?Kr-7%?6yC!Tco1nFqgJHJ>ByGq@Wh8M zgxAB4o&-R|Y@Y+SMJatzQPDJ?Ea~X`tj$OEJ=l4^(H9#Or@lfpA7}JE26LxwK1S;? zG`|@kJtV_%e+BtR*Lt-5%ypOKLIr-mcHJ2bvc(CzmOirTL(p$HJJ;Y2vD@{|o1oY;FNlMx6LPpT^FgGVV^X0&I%BvI3%B;7ty- ze3fnZ-CLjY~;9FaPTnV2nE}PuC!_Vo7Ou^ z?Pi2&dFG?0?Ke>17|IRLe*6qL=bIs1Ol9JWiuz}v|7_dJ0uo_WVF*_H$ESM_d|G-b zhQiDL^ZRGHp_40AnC!zDf1(d!g=nLO^M|)#@~N_a93GYgJr? zswg-n=qzmh`>(vQ33v`>`RuR#V`)%YjACGu^^41V{o_*~Vfggej+__wpHD49X$1+& zEQ7}2k55}D;M0?ukR;51J~d?+7ewBQ-iSY$=4pI1bO~>5i7xcNZFy!D$wVLw{_it$ ziy+3mzqJ7WHTgf>=f9r)kNx<+J%GH)VO}6I7I55KBtnX-oh`hU@!lem)V|WxjN$sW zmgbXoBG~S2ylBD*8v(nHT5mNX>_7H@8#Ag*tGgA2_2_P7Xf_{^ z{^)U-VF$+v3q{}hh1;}@u=#My0|hxYFiy7~1k;7+9uG;@{t*d%FF|}X#!mS3pTLd! zlP)m?)8*)l@qbtz;^QlbgzOldPyZc9&thK*w6bp7-xRI?h=i06AQIkufxP#}C4AID zMbqduPtW}i2Zt5khG)AZ>Tu(aOSBZgC3G9@qe%ZWL>R=!S82SL{!j|=zko*Cls9C(~+&wmQnb4D-vM#W>@HWIzdkJ>6&XvIJ27HV|>8E^iFp_GU;V{+ewaV+PQ`oKYp0 zpjFrM1?om&uSH698#@|YHyx z?B&6ucZ&mAWh$Ij)YzZ@)Zc8Q3cVp{<)~Ep?91aK&C197zvnyqvSd0_y-&<`R!0n) z4wjkv-#x<3c;f&{gY0Kt-gL1X1uKilI|7((QD6C3Ia;k)`(~R9v}bwWVm!{=SsUFv zJY(Z0Ae?nEzq!WHaj&yf6lKW?{Q7Kp-G7!U%nr6}P~^e_T1m|e&gM6!lHo{ob`{L< zoD{cwtAyoZqSL)u{7vA|6BIMVZ#IIQrnS>$%F_e|=w#4^hxZwT3K|3JV{@`y;vEn8 zKX0EgZ|xEApB!%X>hB(2%*c89FDjg%EvW@ai?v`Y@=_21Apr;L9RI+375&!L*GDqr z59mY{9kfI~q!M!6g4-CM9PJxVxA<1^=JT5(G{~M$`&Kcmz;krmG)a0YZ#h_~Q8i*- zQSLGAd!d85di)v4a~e$(=jZr1sZ>V-F5QfXoX2HG{0N}1)~vR+(!+6<`YRed*U$&T ztm>AU&Jh3>Zu=_q{OD#7DIYVj#slR%v9&ffB$ms&tYy<^6e94uE$$u;y`I|=4QNcr z>x-H?)C-?naS-N${=jKS$HcfR$xN><`|n4D((e=(s?t*ulkH0j9q|Sy2P>>vSeV`* zD+;L>z>(%4cpHJ<1O4WgMpn|Z&iG#;N@N*4RM|vI?kPso-pt#UzACFRtjX5HY@i2y zWt#y8YH^?ZPdI}(j>Nb@M&~f->Po#$YTE~mZmS|OXT{dFb1ZpYM@Uw{E zz@TY~#b6;DG@_gV201IH`0y4ei;MVBOPCSYugp&`--fs^Y@$94KVC z%kerHX(^Yvt(YlhT46g-0O&=%RdnW+(E`*D^y_HA3+KMr`C?L=hTf2xd;ygahDN~6jCNP_ zYEjx6zc}dB;{ZhMQv0l#M_Wyzs@7>O5kh8Gtxl7%wL9gV*e}Q5*)-%$)L^ckt}O#< zAP$l*YC<3t!O;?^H8YO}^ar8+{D;4DBJ7EwOB6x^rb731l($_4cZLnte5CSC38mms zYsr0g0op0qcGyv6UoZ&a{feSbj6oGrRoKOMhC^T<$xj1{!46bw?mi%CYmQI45&%GH zL!oU+PJ z?7YongKOGLKw(U#W%%CT3*io@EmmhA?vV<2l2B%)b6V{A;7YpX0@5sJgc{v6LK>6J z?PDH)2F_2FJb}}r&7G_(@;3ErRcQj_6hzdXKqoqfPcq#=R8S_!uxa-ZN}9NvG`=v{ zEj!p=;V-aXF7Z(9>bYV!;g1NtFrhIhpq~G5pjkCKKaztrCu#eEm_zhZ7NxG}ZnV1Y zlI6ASk}6e&jg;$-u!G9?m%D1cFqXEv_&0_rm~oJQMTAqjv<*2tU2YI0QeO2GUTKei zaUWC1ZHfOBrPDzvAx8&~MJJ>xk_lff8Kc0jPLQLm8rPZShu5e|UGTpzVFHVp~>C( z1@CAkFmBz`7ol7n43-hJL)c&+WA&^6mvs*utGZE?gqd~lcGwE~mR-j-)7-D$s(DIZ zx(0IlDwF^nIcDj&(5I2z+%@rVm(8*IH>gFcqXV0!IbCKz znyKHs$mx>Fc=1@3G9!;J3b>@p?k@ew@|nBlLK*hCWeVl$6IKmJzrS}rz!x+WwrGx& z<6}_h@;*JB;$jl~;1DZ#J(WwGZ$a`q5Rv9xg1g$J9E`U8lC|b)nb`^lcImWjC_Jgx zsi*lZN~W>cDqfNK?TJg&_DgkPj}ZQKo=spX;vgd3;0#vl$)&jNGT{{KSyzzL4mlVP z=Uc{nHy_kuEgR_Y&JrP1%2Jvlb}KYjbG;C|<>>b?wGQM4BiSoidUtc1OlGBUvH|V0 ztk1J1DG*ZeOxrLSKr^RND$y0J_X5aqhgQGPLsdO@9dRN(QRh_dn}e<$t?^y8tDvN5 zbn-~`ZS3KCJ?pcobv|`wzog8Z`1QIcoqC^WFavNN9|Cr~g`p}>JD=kw$(_o1wc&*o z=l6jPbisB+r|DJnlxy@qMe0n3bJ2IdpMRA7n#I>2_xd%JTm?}p?$rVaJDB}B@~p#+ z?$s6r?;3$HEbgoaTAz*Gy!V~|M3r`}JthZLc=7s>he`DaZ6K4?C?45~~zx4y-#YrUzVG9Vw?XKPlV_^`U5U z$vi9(s=^U|N4L>zC%2EWftmb~<;I<50VKeZdukG|)tHCmdAUm0x#!luFO67#lV36k z7hIcWEv?$!bQ64JIZ;=M62Dr#BU;jSlGp{_rmBF`UnbKx%rSO+so-5sP1&IGgyhm< zMrf6%+?I{JtR?8|mLwC)$e@63!$sRJJw-9pwIMgzX?ui)``W=ky<9W{Zk)$ME{+wM z8=g+23bFo@@+%e1P4xq;O7a|)p@(^TrYFnG(_7>!-cs8cp)n{Hpj)w1v41;C-bl?` zu2a6qxF$TJu4NoVy3UoFBW?aK|L)BM)T}uJ6@|Gl-z?9jWg64S3;cR%^(~jSh=lsl zhZabL)`udQvqVtElC*J6Ufy445JjxAsVQwrVP=`viQRV&dpYyPz$M2St2aFU#k#GO z?5hC`$zu&eGI=F-W4x#|4#&lwG&GW#kyI;GrP+*4zo+CaK*K5MR44tJPuOXrN8dnN zj)2IDVq4gyF6`l$oRRH8s>H$M=~7Or<wx;{oc`c9+a;GgmpsQ2Z6_3PI0nMe8u0+!>XNCLO4Hsu>&ktVLy;ylc<%@j zIIb2aU@;`SE$5{dWOxmF7|LZeIxh9)j+LS2U49n$VC5+*u`5nA$Wqtl$S6gAmz47R zz$1T!%4$}3ox=ogx3Of+QCUN3`%`+rt>sBhq&r?pO!1X(p&$%p&}32YSI3phH+T;aX`W^y)T7T7 zEg3$Wg895LocX4Aq_{naZOuutOs6vPjwaRjlNhR&2a6IV?aq%ezIN)~AbX27;MWslZ-J`T$$l3AAkR3m|$%bK+uJq?S)VfGB z+8;}9j3eIe2qt{n@Vt4Q(^g>h{ii*oQi4yMU@1PysU+Wh#m@Y=?68~y8eqU~ zJVVVj^B^ga;)O(7j)JBua)LAcSOwpL4>x+`A|>Ismbg2ZZGpGmu3hIa zvEnjv9+skZX%Nn$y9%?_$cBe#+bj1fqi8H$&W>4j4IeR9iJG$?_Bfq4x_E zE7cZNmLn04(~Ilf$So&qhnl#z92aI`48f>+WwNn8nS>fCcSU?J$V9kGs>r8b{*m8x zv-g?Lk=Qa;7u!HbLh!Q+Y)+DwD9)0SjFr^iVqBViE>Oi8y;bu5T?tA%wCq{Q@gTt& zA_e7ZoJ=YSLY{6PWrdPIEw*Pxj(_sy|2}hEfaaWp07b!qRYx;)2d*7f!<5J9U4#PulKT1$NV={X< z{P3`Pg^V+r@FH|(R1h&qBXkf09A5o{+;9UST&Y z&Tct;uU-Zqj%Qs{*R3c?O~jtbR$j4s$m6oVRk0aJmtxB*J$7hnBtIr97-a{=z+;&7 zu?ln|oB>5caKV=S0RAnSZ4<$bhRvDL(BQMobJ3LL^IMj>wv-s8Oh`40N~&Z|K`Thk zESC{^k!&QKs%xW_1%i`IB@NG@M!Ggss_MN$MktH;68NUnQwX3_WdA_d$68&eL$hIm zWv5Lh<}MrX>FJ6TmCqx@MH*+`Fs(Mc89jl#&lN6i&jgc6oxfp1CnTr z;5~JDDb9PLCwyj5<8+Nh9Xowvxz1R)SeP)?f3ssTLWZSOHZ5c0Y0wECpM3Cz%Vef> z??Wo_S5Qc9GtQ-30>eU1=ZA$?W~3%K0&u13bvH}Ysqd;7Kqne9%gqZ&fX5QK))0cX`%kvWL~jcp|g1ys6?$LK*PS| zmW-mtlZqRDODh*^*NT}GPMbk-Yz%V&zV+!O;oBgp1z@OLMA`bTbc-2z_rsCl$(UH(O}`tGasI=5g-q z!f;fJv)d-XKO-V`>*KY~wMZoZ1D$%f;`h?-7c`(|q8j5pK3=4YD>Y~(5j-x0x;qU! zKWBhs9>nonBvJD6O!baSSGRZloYjugU2i%$JeeiQm12brg#%#DHLj;pZ!ouBN=8q@ zw1_o7;&f-s28kMuDGJ)kTJK2CrE{;_%Bi)l=uugG4dp9B0 z4ggAIoI%LNadOqHG;j$qO3k5UYEFXU1SnaB_t>rIAIJg zx#;mN&n-o*rb>&UY|AiW%nCkka%JM`^$13hh);zYHbZ?Xok_j8qTXx*k9%DI>dhxzo((Du>Tj<&@q*Yf zr!jAZL$3&$hN2Z!-3bvj7b2SEDO72RXi$~neoI9&@FD*#XZ8!P>xDj%|5 z6zy*=jK%(ToC-vksA7QJr;3mQfZTp(YkEOUCpy9S71-(%;=~aVNOu7k_OeuXm*XPm zAhqk&-ZVt-!ad;_x%Ryl0ISWfq&CBah@40wT@kc*jL$iBJOKx`a>$(j9!uIdE_H0{ z7;prlTSr!;APUsoMPKH7=R1R-c_=?ZWXr5w)6+E0LznXW-5OmnY3Ya@D7l&xlk=|0 zbhWrHV`aofs&q3cIM>lGwr522*R_tYY?UahFJ^BBPlM9u8tJ6XslGhlS zZ}vDuaOcS(2M103ArB#58Vt^H9BwHNDRSd(ZAgeVd+9%PS6VZ;)}5r; zD(Q3xTGZq(Pfr<302FE+q|2A#z>NEiyViHr+2q$~|#HBb_GLxX8oib6uz@l`}%VO%ZLI8*u|m znuO`L64N`|FX}zH)@;%w4}9RAJOZ)G-2@8v|ELi%r9_U8ITP|Dkdcl^=MX0z%pjC7 zC^7Hwg2Ud|s|JGTrI;r}*aACMmj94Uh8ANqMSQ_N;Pv)Ig-o*kdR+XQ|B`vZM}NU9+x67w+FC{uwS3c$H=~Qe4mq z;SnkGt3501Z!JK~-BMOTt8pj^WdV>}J!<{+xbX+oH91U}qyz3UDB=8>+~>?1nPMUi zdt4TS9ZgE%6t1v7OEj$3K&#LHL+7E3dd1uG3v+*Rp~LVnrNP60sxjIupbBqjI!Y4w z_cNl*MxX^OOw|>wf8y%r&|R6KiW-Vdjgyf)G|xq zeg>qa|3jHF1P|@%xzFqR4-yk}SEz>5lB()om;BdFe`~@+m#_-c{evHa#eIhR1^xdt zvhR$pz+w6)3HQ?BsGDcE16N1b{O#&tkI+(hjIX3V`16r;QKFxZs_%mSG~qRP((>2c z>3_UlG*)aPCVG1MpJJj6RDZln9}#Da=QDBSE+KEucEsO5o{IzV%O3mY#Xs4WbLb;i zz`P;+5@$-he;Y^u3h2dnnMb03+|+j!lt#v_$r*oMA_Xq7)sgis?ay^PL&s4*+okx& zCD6Lz5^hK(MTI}#5Neup#BL$?k4yNNz$FA7^62URc)~DpaN^Y(2bDiA(ZUXwNU2pJ zLJ1Q7{U8KwA@J^<$9Wn5xWx2L*t6Z*j5vSV$PhJi$iGfT{KqAJ20@Ev!a|Jsr;W-` zO~(I=nbT^nOY=GInX(c^-aj)Gk)nQ2CpQt>1)DXwV`S0FBQr3GuOa4MswLZQODxByN|1>!MN+?lsVv+e@5d>_A|B4{~5$XT$)tY=^cO<*)ClZdy(zN$% z6BxlnQ1iy2Mv57lfw3J!&21oitE{xx?dRI=%rC?yyKgTW0e5dACw%Pau#oI>Fkiug z58(!6*puF;o}gctj!N0BT}ZJ2{y3^np#2i)l~A!X*&=$EMzv=Tb#@6%lo5|S11^$_ z)kp=7FS)a@5PJ#6TP<~%z zcn^juIboixl&UHF&IT|rt)>JR(Hi@zCAt&H)Ce(B1JnTy(Cu5EpcqB7o-|(uojS+- zGH&4HOI?TZRll#on_~DL8*~;B?bSt`-Y$=U)O&>Q(e^W_$~$!3iH~ao>YD@skF;!z ztG^m`$#b| zSMJRZ1O!Vcmw2QgU=x8pwF+v5AqgYSW)8UT##t~|&hlW8?gvXbiJ*^|8dM(56Z6N(ep33(7$6rUj0kg}dTkiq zSBAOhcs5eXFbUWuu8yU=19KRF(Fl?rd4O%JKK3iu#j~3v2%jGHTTV8Nz&QQq+;{zi zlAISCcSbGNl!Z7;17lzS&^PzRUBN7On8piEnPxCm>VJH!)9}1>X`;RwuMOd`o#fCJ zxId@Z3S+_Vnf=yRQOf*r=P@gB7Y)>O0!*+O!q|OoDC!{ z5)Ry{*iK(&!3@f8Wog_}O7uq;6ueC)=;l~)ca3kL2sJZWdKz%J(x~Sg* zM$2}Lv#fEvp%cpnD~jy#_O>YKrJyF-FGj~9fIoX;rI^xKkG0I zaj#a9^EuMPiAW}&ttw}LEWw-OciURb9fOgYa$hSrPC)fN(95sKY=9L_1A5u{@V?PE zA`}>fyO(``2n4+_x%|8X6fz_0{0r@2Ni&l;8)A6x7_GJKZCrV(#9TN_Huq`Ru z*w!hjd$KJD0zj)|)OkI`qg{=tLC&3OpPl{{p!e-dShkwr1vv8$)IWH2i2;asmvpNn zOh7c~c_5Um?LZ`OxVCxS_a)}h-f`D7kE>H+3k6*Pon0VT^hLo3jJl{GchVzL$ z`s^0QAkGvn8UKOUf`h4qjaJv1cbbnGiOe8VApM> zJ`sU#p~FJ*VR2a>>*izU{$iba$;7dF^A{@Fk8h5JipzTcC0!Z0uAt|&ZIB8_16e8F zH|SA+7`8~Wu0PQWb>2lmzq<#^6!)-awq%y+ij(oEfI{8QchvZ z+oni-n6EZM0A7uSEhrB{G`JIoKrv*8lG=89NLm{F;+NBF9YJj87o z_pb%nMCTdSr@aYMn^Mtu_r}SBrI3h(5&GwE={TW%$1-0wxyq2Y6r9k-$a^05;pm`7 zaf|ck*H^0ShkQ7CBhbH~R8!XPka@i?#9f5Ujq@E&K&xU!ag~$sO_U1O_L8F)!Nbvz z`Lo;|PmDUG$Z|T@ng}JSS}P+c!pM(wELUexV^_7x_~7ykGq~%QW|gH`y(s-O0#9L} z7RUNQyy8y(Kta@UF=Q4lpwtt16nHO_EydQrEV7w0KA8tot?8 zn1)eEobgq}v`J}%W)gi~vp&>B&#bIxT;D8pJ>(V~xUTE_0~D1@x<*qg;spnf7#Yr8 zB9F`Ixm=7%!lo^i;VM!8bY;}P8hcL{2Ev+}KcDc6cFryYHN~usm__wIkv~X!BZekl zf#m%0EscRQD(T9TiLu<-M)5nc)C@kV%JMX-VLu{bEU1-fFrCcT<0X~eUt`L3cq}Kh zZ>Xg~7t#EfBUg-v&_#&EQ1bi?iV{b|u$K{;;6gZwp`~jga>pby^&e9`^M<6fgE3Rf zmX}z(91$+r7pyb!aM0$3EtM_5Q_Sz6!9JRCwh4JwRU3vqn%iL;=pdNi^+rqbeu9Q+ zE=QBOpK(<-!Ck>@dwD>r`$E>0Sp<<}Mn^In&{h?1USYrZr0eL3(=sBk%52!Fbf*`) ztgC175nJz(c5ei-o%$@r!5CaZ0i)T=bvTfP>Dg`0vZ{!KQwyOVPo$22M@oTKq_W<> zKE05(Qo8PD-u_!cDV&I8&u0T#fpg!hu%Byy`E;Ayq6DqbAy$|B%`BdCgEI0I=p{RMxvoL>uD__1>g zQ5O9z=R^Qv)fF8ufxYI!*91(C}Pf5oT)1!kLl!~;(%6Ao1ZO%BWsQ} zive|uGsm*f6((}G#q?6Hi}kv`8OYd6*LnE1W31isr=Go&;(i>BO-2}P;NA>^{e$gq z_PUR*+NN+Z5~_wglFGOJh#7*D#!)whnvTU*dJvis7&xG!=C_zjCP(qLXKial$BgmZ zW7@p-P~4n&fc^TrvDNr5k!{9Rx-YsrW zM~fsA$+N2_zdRVFi%hb)w^ky zXjviCh; z)buMcNB;egnDI`JBro#bDtw)s>|zokdL{b{A$eSZj*nx`!pdBB3yP$|&E^dq5T24s zI8@kVX8JPrSapncjQMlzkDDyEjxl*&{c-2P1oR1j5%nGokF}!9`DgfAT$R=H_~oy- zN#4k@7tGJQpSScF*cntD8`9}FmGT?QmCx*hn0?)<|NRQWgG*D1axLiILehhZwFg7c zEcCktQ3wmoMBPb0{CNidQF3E;@yuT0PfL(q;E)|~H}Pr(by+-|9{5G)d9Y7{>CfD> zZBXo%w%UrbyHNDxwGwmijnxiGxR;I=cK8kF+8@eri2pOJf(739-fU7UEpRA0|CEWwl(*1K?6DroyV$UE~U~ z`&VrG5ZAjz_0S6^3UKZo*5^!rCog%g~Y#BHc?=^qd#9`Ez_ z+r3P9IpOPnmMeK#r#qH%g<)bC|0<>6U7}I?QhO9Mrh*j`YkQe+Q6|CXB_*#q#E}YVk>+SJa>S|SQm!v;sBG@ zHwEM0#&C>RD~IP_#pP~}PRM1_# zhkpJ3&N@b^ys&~%*;OibYR;jOqxT&}&tqM>K~SlexdX>(*8QLM-aMM>_Wd8tj*>ED zXh3KnL!``vEm3BhjmT7F9y4!qgCdk7^E}To&uLUjW-?dGJXCB#bgo;&^Z0zv`RA;& z&ibwO{XG9Xt(~^L-|zc<-`91$riuQF!e&L4NayWQhzG>>-kYS$sgc#URx%89<{bQP zsd`bO21h?iD!JTj)oi@4D*oyX*c(mSS$$0@V2SaOop^A;F0gV9*<2=yb0?ve(nMHS zYd_viqS;J{j|6a(bx>i1`R*V;v%6LEY^K5l5;Kh9@i#Jpp2v3vUk0Yc=%@Q?!l3y* z0klRztG5$&8Iv}J4H~I$ENfs54rWQ4R;KL;5t3^}>UAFDH7yM%w&rX5xF!^mGQO#| z-&a&&F9!1F>DVc|`~b~4s9|xM8f003W%HIAjAOJ~DbynZs9EhgTjbW17wFsLQNuEp zjf{S5q}3u6)J!ZhCbd5zEb_fA$(UJ6f~fe`O!huyEll<9Y^*b!nHg}rl^3RMyXSPY z**DMZAqe|BuTf0L5&G)#=MB{kXzk4r3f=Y!7oWAlCunb5XjTr@_(NiaRBlAbRby~w z_>l$%`3#vvLQ){vly%(dA0V|hIL0tUo>Bp@gMzQskCcCN#Vg_MC z(B6X7`fgyZb_av0fYgmu=yz4X`k@)D?QF;FI|)J;yIx0kD9XghXRkt`xM2=;r>)-G zQ!`bblBv|dca7*8JCE;!PUg5?+3%1oGV@QY!uq@iaKl3Ebi|~B&u`Q zUnq*3Q--FlAE6*Us+M45#29y0O*7(=&#CdyA}5jaYTRY{bgeJMw{7q#NNWM#cCv~e z2~N`k;{s1Qp|H$yq|>FrGC^ysIdxa z=w_ImnDLx5-?HUs%RP3bK8{2}(3rCLbl%RjTt(#$^Q^hF6@4$jn-@P1sZMpVs(Uj; zR6xDF5BbIfV^r(tuLmeqKh5DtslJx$afo;Z@1}zcBO69z62Ac`UCJa2rzb7A=M+-fD;EQ{h$#3K$x zZ8k5EX!MVY#yqRaQfPJ+n#=Zm}gbol#?nf4t?8&7P%8 zpEDKJ3*GNy@O2+mDCoN)PZ}t!2?4YA%&KC~iI;mfY7-GM`uCDBLnwCu+L02cMX;-U z4r^Brt`MKet(Eg`eJ%TKAS>8BpHty9kdi4@D^Xm@gG!;=255YOe zT?2}#`;j51|Ker6dt0{%DNaf~CQs{q#1g*6-x)a&X-3xmg-jADvVPXe@78HA-S;6Q z>DxrMlOFk}bg&7Y|5ohO{s(ZuUcxX&sce01!6w?Ql}BRR*@(N=bVR_-jM&Kx-a+5f&Pdi|~tz;JnOPR5(w z0zL-#vR0~wZ?=|yiAt>QaWVc)Z}FZIU^sjIql*7905%47$Zf%Tf%!kI83F)?6Dgoe zhjI45eq}LoTM!~pZMJ4`N7f8XJ%JjVp-Nq3#=$7LeX~;bA7j^la6?r4BSbzVVe8*j zw{cB}5K8;Y7v}%PWez?WpZzZ6+&zyW7CM z-IpNxt#H%Vh9v>AUlTlw_U3O0_w}3o|M*Gl!>jOL)`kDHb7w0g1FZPJ7(ZH-*#G~D z6!drM6c#J?iF-LO?v&ZFF<5BlL;Cu5pJ09QEyN3a29!-mRhy>PKuu&)WA0d*yB4?k zNj8EzzVh+p71}>f{KhkjU4dt|!(8d@rdR!rZ=l8aK5Eo+n;| zl+^PVs+XrL@I@T#;#9!3-eflRH4{Qm!1e0sp0DYVh9_Za_v-UU4PkU_L3aV{uL?_O zV8eMo8oBgdj*JF z-A6ukU@uitHUCy(Lko#48$oZvS z-t$FlA6@hQRSkfjIkNO19r~SJ~7`? z!GFpOz{OCJ+qe3G8Qg6_Ukk8Q?}rW$HioJ99x{7F@vDZRrFjQo7`hKH-N4o1(-j#~ zSF*q;ddDXkAI*?$1%z3E7ex@=6^OI$O&PD+J2^lKSmBXtSYTKuKCU<{&|3Z37)dqQ>Zp>e&X;*a zu~Fs_cewNJ!6OU@BRaw~_;3n%XPq2P`eco;aO)eiH{w3gR_|7wxN>hc^yf(3Tl;3; zH*R1a_Hb-9zIR^lPGj7hm-$@XqG8LLq-~G}I%p4WS?_L<|rSV9GG)|ryotklqx8=`*eZb7(Ik8tYIR?$M%55(r* z2&jPVqcSuf%?d~3P1jd?9`y~wnzjI7+M51*RXbR8ub!#~_-62|qc8XE6(sXrxKV_; zV33>80wdYt7B|U4R*0~WoD99NoAnS4QZUgB>&HCMC6P4kE-1wOMKIJIqVl92-Ha@D{0D{j$L|!G0(0yq)zqe?cyrKq54GrbR&IbE}iO zG=m=zW^+;|f*Yu~Lf?Frd0IlCp0sYu8E>u}n^8RqC8M}W-6a^%M8hC$BRmDf5bc6i zoiDv$e^3bXU7Zn$Wj7$nd(c%4Jc1C6fP8Ytplz4VB?RC?ufj~FTsE@At%KgH2$?FNHE(J z&P8WgMffUMi*Hd6vA}_RGlKH_A&KW6h{z-_|6%;LMo3=OhXAJO5{)V{FxoY{-{k^+ zxV2wjFpU-U^+J= zl>nTR=jQZl6%iTAbGcNd&ga#rE~iDuwL%zK3zIX6J7=v4cT$>%NZkxboQzdxAgV%u z%}iVD&RU(qOqNkbiW)c$G5x91=6E3dVl_v<81M5inVGTNpd%m@r3&@~3{ zHxaRp8i)C?ZHrOL8u5n*xS>w(EuO7BvpVS{nW~keQ)q`c4TT0XdvjL4={OzKj8^@q z%f+<&(-_Aa$WZILCMg2NAb$zeQbFc_CVcDFcAU&HQ$p5m#)UQ5~Jofd}40Z%OW zl6n|J8C6q2T_uu2vn9V|ZCjA(5x{Z8V9d)Oex;e7r7g zG0#OCiNdG3K9rBNTJnNyI5%39<%3Dbse}~eci5w`>u`vxf~|hQH}~yU;dh!q4rehY z`=bBokU2%DkjfF=wgpOt<}m!BDpNV5BgfAdHPll{F0`7~lpOF^-@%U;!dKjXk#;!A zPf12CC1rbHK+|}-{iR`m7zFHxPQ~iW&;Ja!F>6m#2ov*fBaX{_YJ#cthoO~~>}3Xo zJR*U^D^kHU?RimsM_D|v2GfWS3V3SeK~=bXKS!-6uZmsKIcb?wk@0R;<;5Jr-Ezwg zjy5~5jiTc2MSoxj_U}G95ywGLO&J~`%B9|`N!Jj}>yq>&dfnC$d}KIvAlJg`T#lTP zkCjxqPFrUPP@MXGzGibV>UB50#>zSfJ$rB!Iy0!xMhr5WJ;}%YBb#KgbuN0IicUw7 zmG3YQPaJ`zY*y2`jg-JZ=2fu7Pw*^WigALh!BcwUl~8|#$%YeE)^CT;gsi!>UfE(l*z0 z{vfcY;(WHKEPdhDqi!dQ@Oe-dl&>@;$H7AgwH6P6%cA$P)Uv~-&=Roz>6NBeq2>~p zw_++nQ~6C@6%K$B;X%`lFr9)MB6Rh6miM4k}GZ;o(ycUNf*Z zN!R@GcC1yTh?^pqj-4N=&P^?81F|!mL_`t5NPfqUKp_-=`mi?aYNwolCf1uK#weBZ z`DCeKiu~LW9;6~QjdaGGRiVySPd=R%>TWL>Y2Sz_KjeNWfb^TV z=61$8cPUx6L|E1H6LuZl4P@a4Dwfq+3&yx@?c*O=2tZ5>Tz|LZ85t+PeLS{j{NrSI zQHOIAY;m(w{FIR{^XjzhuNK*=HXVv?TxWY}4jz+=N?y3SQQ5Pb6xJduyDziC$7S=vfbCaI{7{mg zx@72N{!~|PH)T^lX!-(&b3@Xx_YdLY$DWDIwIHNu#q z>mz}|CGG)PAfMg3NilI>>YYFzR*3~6!i8zi$aiN+itdrfMFPdJZ#{?o%mOxjV;uP@ z(og=G^Xxz`M@YvH#b%?<$RHS$UnW8+Q6jcwU~httODEm9qPTx*cS-Pp{E^A|m2Bbh zotmFdw(@I}1vbr2jw)NlH-UdnEObJBxs2rpX~dzXYaP^J#J|HR>W?T+%eGPW<6A4? zd9H|^OXQQQBCMs1N#tNeejsk|w65!^lbTpU;{ms6+b-riSXI=cb(!lUc=gVPCc~jif0mB5aDX9{;P2PwX77} zesAH0H`la?4tC)F{6UNuCk%(LiG(PA^G%kYGs`KQqT}hUt}z(Hff}aeUD|e zn30!$dQU_0=;}sqVp`$1-aj{bDB~pA>6U}}Byo8b6I7QkX|>IF&h0HyY`Skll~T~p zo)9bQc&S(^(8dT{xV;N6%X5-{x({8d)Szu2W0YTekTe7my0$;!?vkAWj_R!okFMrG z)z@o_XdcKGW?*gLX461Mu&o_=@ThwDG2M3Cp^?n)d&dlGE7z2Jhk=V*-MIM9h<=*u zdq- z08PueepO`2{G3F8DhGjI7J*sg1DG(ylp#(FXCjYdtWFg;v(1d6LklU{3~TyO+h6kf z_IM;5eMbiq573aKuN5`RVXL5om2`+v+BcUT{(!Ito7j_`*ufOb#VsVFY_b?F%>)~IgOLNC=w zytA_|CazrhhJqDA-5$6znQI@R09Cm@A95183F}qM-@a1SLd`!juhhSg*IjaM{xDI_ z+8K8;4jCmudRgOmZ$YBndCLW#wz->>OnZ9IjMaW4>$Kau9C{` zkw}gCIhFJB=7V;5Qd;uy$Emv7)L4%vk?Cu^x$idzF){H++aJ-X*cY`HX8z1n|rqciY7lN zNaz_VYKkoA6FvqWJr;9Sra96cK2X}tHcM`kB`9-M;7||FP|Pwf0jj%e!cUX}dNX$N zbsNZ3t7UEW;0^BAb7~<@zUhSpCgM4(W_ig*hFYlFBvgCfMBub~3O;0`DUu|ylWebMm;bLuWDX7;N`BI+;5!u?Fs#t4-mCKW*D*6FS&R~{vF`3ERvjP^* zP*35EGuSkTt#XdG*tZch38LKY_`8*!OLnn&4eZC%B`3M2fd?IbJo|{qEXnK=vz@ee zNnRC~_|1S;R~Wt7emuG{;7_3Vu{P&hQRjei4MET?sK`8auThMa*luZXmPl$fK_z*1 zVOLxAEecVh1`T7Og)h5l$KDjewrm}BqaTx1j0W_jldm;HhH$v!SwT#^Ccc5otX zI3%QV<0`fqv%EgM!){SV_QqSIVaCfE(se)f@EW8?4yU9!#PDQC>fp*9Bi$Qw8&6bIQQo$NNr1PU?_02e=MQKI zdxQZ7xdL{$FK7J12mJcQyX^|^ekmtOOl-bYf%>^WLAKdZIi2%ye9*~6o_%R-ehou# zIL^kio;?gC@R+SB%C6ioEvJ7u*s|Tn#Jv4b?8oz6lVyvv+>WtuIej^j%zFdsG+5&~ z((|Dvb3a5G{cCr(wjZADAA+$RV{!IqbADzr!bHM$a4yHjCJw{=<>ks_!@X(g`K8Ve zip#B3Q|^7;cn3K7mWJ*!(vasjfYYhXJwF%)HzR*S12{I(E1%BAhUhCeHa+0A7F?0j)!Z0dD0l(q+%=HO z;68z?%&@qA9Ih3XAD*|zq8d9f$@I4j8PDt#cAIE_zKcEw^8`_@+1)tmT7+l zrzI5HGkrxfrg7heQo)-9<}zO}-nb+(FM%PSzOluB#PGc%C+6bb@5nNUQCG3B;Km)U zjrSm@kMQf(V20QbgZnt^gVy;kVT{{AtK%`JhJzFn<~MMHBXmiP zC!%Tk|23nB6YA7nxIgpKTVgiLu#doOO_}4F>#w!30gb}aX(0=m0d0j_0#mEkroVx> z85plfI=tK9$o;cijCc7T_9feNJGWpG;8{pG^{dMKXU5Ow@aaE+^9Bg#Y`cFmsz(0eKjdhPUiER5p8!pM;o>s2y69o7o+wk2Ekh(hMrc{PLFW$6SosdcWVz zFBdU#uI?ruVRj`jUt8`^+Oz4>u$96sPOd8x1pVc|E)Y3r;7{y3Yqj||pXLGIfxZh$ zPyh9kurQ6`T3mBX`|lh7_fq_`i2hGm6-n;=UFtjk>>77{F`$C2>4k85-3q&SM9^*q zyY*(H^>2HfI&o*C!G0`uE0rkQPjw4OZMhD7x)b3Q5%Rw|cUTTGVbBQL)qa&1@Lq8S zU1dRKW*=Z$D9f@L^3IGIMeLZ}SfzF)HUQ>rjmGm#i@I>KmX;)7rT)A;eiPW~ju*fZ(mKWzgrx8MY31ETi{i`22n-$wL~zQ_%t?Oe0}p>X5w7 z!X3}GYwIn(>m>-BdV^{s6bu;ysdz2xhkt@bPw=pOFh3}KU2c96NW(z%vb+71zcc$cz{9*XHSN%!UtEJlx?U)AYy^aMX~~#E z9X8Y2315}J{RiaEH3c(?yv@>4m}B*vK2c)T#a-g?;dE-k%QKh3&=u^@>Q5l`G?>F% z!MmR_MKTQKeLpO}&-<>=v#wr#2G`CE)P@&b=Z0(-*k6Dvj|D>Z1ui}zMIyGl*{yLl z2s|p6ctZSBduUT|es_{F0axue5WA}a*7qL`r@$r5=4P>>Q?t-0IQ@&jN6P`OyW4b8 z7h=lKo>=(;mSh4*Mg8-8qckXDxNq2Bn{@+p&P!+-q`(y(h*Dc`>JF6MW&lX-#a*W@ z3?YIVIp`a?6wzTO$d9Zy@x=FSOjtK|e)8l7HR&}|{f5jBSk zC8OV${-qKLyVx>#^4j(@{Lsof-&S!A(+q8U{~Cke+gOp7rH9kEu!sC%8uiYw5rD0p z*%Xg5NRCr1l}J2XgbZFhRnGl6(P>=$0sTD_lV$TD`@y5N8T&95AZE|~o&(IVF4?hzx$w#elA`!G)rM;)%nX!)%v9}BF z94mTCRWkoMJYS$IWs$2R6QiCl;SQ4ZzU#a&f{c^AQ=k%P9DYDhw~cVis;2uf9>>uJ zu3t~Kor@XE^h_b{Vj!KYX5g>-@T|b@a#mOCr7{Ko+`il%G|0B<&a+JLS+T6JR{hzz zmlQC+3S0Giaq#~!XV1#-)AaCFCFXYO-1uFX=pJdUbR2ovg;dL{$#~2pGfuHbf{#v#z3>OjdU-}4)6#6-Dbuu@Z%B^x{c>yVQ>7ACfa?TP? z@;ado#+YW{hBpdR_Y-YOA=8fPoyVINJV0U}1q=z{Zxe~@3r97RPm^7kL#%aAp$M^V z-owdQ5u7f_s}07AK+7)dWC2o{CGu*9>$C43KAr9>d+h~ae}?bRb>Wh%0@-d>uP^>W zfm9k@BiTbH#5cAmNfe+iKHn5$;hxuAnQ@oy3uhlFcJenZsJK1V!UCmg$(W%7`|rB) zZaQZ2gZN}t>U3AO`5eeK9zH#Ctx`Xqm}PjVu2Uc*g{{>)Bhk=*5;oF9GSG78j1{RR zN|k5wF0KgTwdOy)1~&CJKQROT-15f7hrS0$UePPL-dYhFm(NN0c|u>Q}7@ z5V)wwLg`7b?txovft%dWi9=5^8h9=6pYOSr zwIv%i^m=CGeCo;Qa^QH~!aZEe#oCnQ1d3U~Mh(eZlL{zP74EgHRN38HL&#H(X?wCj z@rIrg1$TN*Px;^+vKmxKbR)R6Z0sX<`VC3}J4=9q6LA}EJ_Zl(9zF|S0H}KtG%Jj1 z6B#pd#X?}XTq5h9I%dpWGL8fs*M@MfA^uf38O5-X5qi^lV|TjggWwv-6-hq zKF3g~(??Yu%%o^QZV6itSA_IUj6!RO(?jV5~p=M7c;ESNAcF++d(pD!>@w%)h@m8mEUzR z6wyZ$y^2vqVc>31XTZ%kger>-FoV)EACfE%1Z1-)=I2MgN-;b`hGoQ5gV2iORK&?R zEAq@H$aS}Z(Ok%t!q=*RODoGFYGxqi0q38L|8bs>EG zjF96!r_@TL-@_x~`0-g~-IYn1PQ9zZyUV1!w1zMEET$i*YB(Zwdp-L@q))(1j%o!y z=wz1FKC5EdK?%kH<6MZsDSxG>2jjR_%p1plU%2C>^jJ`|H7}-5C%|<5R&Dq(`8qEG z*XvBf82ilRL_MiPFH=ZGUIo#vWLZcmNRwzed&k_#O1UnKj@Bazcl$G8ggBc&m#FxC zB#59=7xcF9eVbYv|E0m5%@-Fm2Z~H)a-WG+8FsoxoO$ZxROhYl+Xfxzo_uNZ-%Lj`tNJeATMW z4EUBLNV!V!hR4NL;K8Im-1EuZZU9hk0iaY>xJ{aJ$>PP4xKcX z6c`zh5N_jD^#0S7W5fLdvT`DEQxub|i+ZwO;epv<`qBzQkq$=-rm9voUZ6bDwGzUu z_$gJVnjQB(>ywz?kn9di+RG2LzOk@B54%Pnjc{*N!!c>{D(?G~d4!2$Dl^ok7kMf2 z>oLm7=~{4+lk(nO`AK)J9`k1t1Mq||X*wPWwmblMuvIF1Yq+{NvsB#`lNx!yv)-sR@Lnh%**JLE5r)9$tEJ%6>7E;;DtKPcv}&hN<2^&9#ErQVQ*vb zBcZ+l>dXCN?=IgC@oHcq#h^*mmN4!=4`nTe(Mk*kfBjf8UvNZJ)C^wK=eF*vMjN?$~hgvbY^*_catkaBfzi7 z{fl(D#h;(TqW&Wi|HWqHMNDi9MSQU@UhB(aVM{l@j@~*PTI3H>T&As(gCNbdzxg3Y zBY$2LxGF|Oh)23pzi4vQ7lVvaqdm(iXxWw(qCORxEuMalqJY+YcMkoP_>hqzm-R+b$_@R(AasP4fGBoiIIeK z+ksqDX>PqaoMed4ZQ3#Qt8|qU8L`vD=~fWk?diavNr%B2gA-5I=vOi`?`yTtB*;&Oh>%WLgWrU(+O;w&l1mYH}g# z+WoN2NS>*S;GCpjii@Cnn=pgQ#|)q*5k{*07mzkiT7yYw_=GN^k0F+*vh!+b z`1a?I{Aig~;>Ejsc00fY?b|AZ{|>E->3*u8!PC(JTb!6Xup=~oI)LLOYftqh?e$pI zrs&^7_4XEq#D$5-NtX*4kR&ujazudKrf;_<%ii6lcQY{PLH>6zXF@SxAtxWK7~J8< zdAB9z_B@1LQn(~{l!Low5<;x(I%65V*Q)KvIKb>!$uy91#trG~Gl;NxS9Fjze6OfXf)~H}TjmnbXJhgsGBMsn zhpBXLWKqxbrY1h(v9@n4>|{=?U+MgVL49F%JwoyK6phUW!Y`># z8fF^kd41PUBg%D~sis8l8e^L#wT4<{L>H}(){L#`bl4!JA&L@b^5)Mtu>c+c6Y4DeqPJ*aMhdG4A^9rp`|+Jd>k$M5wip_h02!rX=N zo`xMAdt2|mMs6!qWt|R6WS)A7>Pl{SFdM6zVgtWERe9w zJL!#rR)z9>@64zzY8K zk_;dT{YoYM%@bVp>#$?|_pSe#wEu6uApRe#9K!xAkYzS_YR0`RIBYkD@h@c%bM;Gx zJHBO#cs@ZVXVU z|Jxsa@cjk0T~5YcA`cG0=H^ec^SUFIgkU!Spl)^ID$|Y283F z7HxYK!x3~M>Wj|Z8F(gpeQs7t{oW497kzS;8BtPxDu`us%MqXi61z^?1|1AN8mwwm`#0KG2Ui-7XV6m8{JOTvm_VvM}iB&xxk1~ml z>@^NGxpH{%FKS+Vdc$j^k;OC51HmrPF?$!SIfj2#crE>tCror$O5k zVX=2O@eVY?hL5_7@v)_gBZw84qn&Ss)GuTH$jsHv+pZDmJ4@|{hZa9sQB5E#Vx)Yk z@yQrK(Ov>hqsk?oOLlIz<`P>@%?G0?)bvU$#dnwHMrNmAgG5bYD690)4+xAU8n8+n zQV&PfYIe)tC~|*#QhHM)+hR#(8&mUL(Huw}1A|k~GWw!?!@9n0NBeXdr-387xQ{FW zP{g8agPQU-TGp?M2-5^ARx^Mqw6k<`qTU&w&meal&pZNI2d{+NtRTufszS-1Fxx%s z-<|mL$Jn{!se~O7F4{5=i{GwrN&onAjdBwC0}7bD*p-UCkPhKOuFcAII>vmjLF5vR zJdp&{??`15+-qE>%#b3e#G)4Wx5c~!RcMKMz47d`-yL?8#4Z1oo1HaHV_kDyCsnp0~L0=bGqgG2Tv`bUYKQrK7hMu5cDHxfRH{u(u z2491tcVEI;;=P=#9-OSy=M;}bB=02o2BxkDL}*-l9A5KQM0w1Q_8PGg#t$;lC%S(O zbUjzte^%B*=*Xgh=$+U-3S_|YMC$^5o3&B#bSkKs6|X5I(1UiX z8PjMfmA128P`^tJH)jj@`*Z==LK5V(76;voK>tlXLhz`2n>;i;o?u$&-5Y?#q5dRY zYV5b!3plE`GE0)VeKn-;p+9D6Hy}0^XA-W0e;jktE2jq+t;!Jfj0b><1_hbhN>}OZ zAC0#N9_fJjI{#qNJIJSHKRMibfNoW@E)_Xtv%*%o9OiP=WNCiI;FXoW!xHRNgF0JA zCp*fjg^?z9cI2fR+33l3CCLh(+qnW^VHk~```NCU_h`;N4d|LWC&Ly?w&-&)#>VbI z&)*vMQ;{EG6-`-?4m$SDbF$-sF`q^cbM&#y&BK&R@|$A{`_aaGF!_aCI-WKO5p- zsi#r>={MNO{PCk~8R|1EH96+WJFMuxTfEv%CPQIYdgQFQTwOv_ZO*Pd3M$~_YbP;w z%@FuCXSjk3-jIdDNcJ|8ab4!tYAf4-^DU#tjd>H3FN-a-YjB*@Xvk)l(BJ}i;Tww{ zEQ@E^G~wxuzL#$J=MyB6la|^vg1`PnyE>wF3HZ%b>LfiAkCFB0v&`%z zvI!kMu8ZSOdv+?uBwL8FOv=uT8CW(|gAZnFAHf9t?4))} z^6OH@<<@Z3DSkNj=qI1Pf#D-_4V{;%wGJ*} zVm+vCiZ&PdmcT!wA%9~sR5>t>S6)6Q_@=~rbrFTFJtRrFN=Ie_ZM5?Bgb137b3$iafbk(;=RXk+wFSqO^R-8WDE5_cq{bG$ z1Hwq^bTRUfRf^*L(#a$K`0nBox819IX9926hIR?(f8JQq;5M~9>tOq*0P#~JA(NT> z>?D)gZI1UtzRih3M}}2Mk^}s?vo!DSJ0QwuR6jsP#PfOzC~Gycx^&{q0I8B!ux#hz z+o#=+@G@SVy!r%%Ou{~V_)6B4Ej}sd z@|neqAD@r=KD^08uH;gXOy#U(#tcRP@=jC+xOU{a@y@7gCy&4*8IzMoMOZaSYF{@@ zzMUE~ua+rJtnS_ZKbCINEi&+YuY1YBxtcwk@=Pq7p7&w$<&)u;@lUn2=m%85MXdhO zc*^bRnETnC`(eXl))F+*RIt|Inw;?j0?+iphtY~Okc-V&U0IIUSTqP zP8QmCR>4(+cQ!^-GIVV>=P@X4pWGWg_2=>fqd8ngOU`Lt@MfDmuDc6#tUgeex3heF zFcfvdMBY>?WhzWL{p~yNh)Q!9^H;D^vr3(EEg73*44NDjeX-~zepss&`PCY=A{Ti-nWiq!JT(2#!y?ob)*m(rRTCnm#yc5Wg3^OQghGVb~#^yF| z2L#N5<44Zdx;vuii0@(pJyPN~PbP3zHKR5xoJ4C%lN%e%H)-Gvj&jHigFc!%+jtuI zb)iGe^*U@51SM2D)2%@gMt*}2MTU!Ab66aBj~e8p0#fKIef%(4I@Aew>dczcPmKf% zyg@9$dT@G_e4Bhkax$WG!jc8t;^uJUyh!NIxy{J$1Yav|RyHDzy zuM(!xm1_Lwqlz=hTP78_|ucs0KQv=}p0(GS;ON`WJ4MzaRva>GbS zx4H8?e?&Y=R8*;4f_g+5giRq+3Y}$Lkik)|^wd-uyzkGAYVrCf6Ze4SLUfT7aUUqT zUvN6$aeg^NdijpaaE|vL%)8P~qZI+CQ#26%n#{5fh+RorQ+|Dq(@(4LGSKv<&D(ya zRv)i?fAwXpnr+9G1B_C+o~goBo@pbQ%F&l1#lBk8dh-pLXJYsLTvfee;<}#isP*>& zZNlg^7*4TTxu+9)P{({TOf`!CF^3VZHOCJptH^K*EGOESCGtJ88Z1!?LZ#`^o>nAc zJ?pyjN|aTahKY@R;#Jvvh3sQl6a<$UigLlTnolL6@ia54$f-rryt&gU>%GS1w{c>N`fWY?*XqG4NZ!AU;6Lb~ z%eyyQK@fndp~Xe3H6^ledeUM8KbA(DN3!}G#1^at*^}=f&KCCCRKm)2jws&+ z1ZSmnCW@k|$$1o3ov-&?5VX-E=>u(}#n%06%G%&dWFL+rzQ0B-tmlM#Y|e4}s(jhm znf7~o;a8VAZH1HPY9szOM)b0B*B4FVGb>8PuI!5iAk5}ck03Hlbr$vc?SfS=i?v*35gJBYpCH*bUQo_lINqE_9gt573d1NFTd0$LH{T zf`XGx969=&YC`cY17Jimq5a&E{JJVqJ(*`&jjtz z3Yr|mAr1IE$Q!6hgT`c-ED!zJJN+6A$t{{6L+{?pnBcvrTk|5>X9CWtojr3mcy1oL zs|0UZ<572FPP za0A|yH4yigWe>K6M85W?QL#&*x$pgdSu+0pmK)>T z>oDx63F`b;h$Osx{XC5CpNT|f{5{Gy-b)5h*Z;op|7VvX$^BNpe8;a<`I5{3!{M`I zoy02-H{O5wF!qkg`hd0G=A^tdba3rq+P?X|zz@HVl3t2=uo;%L+(8dM;Y+inp`Y0P ztW+c{fd{b`5nhkm350BhZQ4N;q&ysY_)ls3=Z69Hyxp(-A1^P!g6gOkIk)Mp*^Wc| zF#l1w<3C>ZhMHhuM)W`2Nq54lwUy0+n_oU>1gpi-2LbAw_4 literal 0 HcmV?d00001 diff --git "a/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234/images/https.png" "b/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234/images/https.png" new file mode 100644 index 0000000000000000000000000000000000000000..c998d8534939b0b25da12df321e15df3eb049eb2 GIT binary patch literal 100501 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