-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
304 lines (159 loc) · 393 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Borderland</title>
<subtitle>小亮的个人博客</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://jaxchan.top/"/>
<updated>2020-04-08T02:58:49.947Z</updated>
<id>http://jaxchan.top/</id>
<author>
<name>JaxChan</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>我的项目经历:后端业务框架记录</title>
<link href="http://jaxchan.top/2020/%E6%88%91%E7%9A%84%E9%A1%B9%E7%9B%AE%E7%BB%8F%E5%8E%86-%E5%90%8E%E7%AB%AF%E4%B8%9A%E5%8A%A1%E6%A1%86%E6%9E%B6%E8%AE%B0%E5%BD%95.html/"/>
<id>http://jaxchan.top/2020/%E6%88%91%E7%9A%84%E9%A1%B9%E7%9B%AE%E7%BB%8F%E5%8E%86-%E5%90%8E%E7%AB%AF%E4%B8%9A%E5%8A%A1%E6%A1%86%E6%9E%B6%E8%AE%B0%E5%BD%95.html/</id>
<published>2020-04-08T02:57:34.000Z</published>
<updated>2020-04-08T02:58:49.947Z</updated>
<content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>其实当初做完自己的博客之后就想着写一篇关于自己项目经历的文章。</p><p>毕竟这是一个经历,是我大学美好青春、热血挥洒的地方。哪怕它没那么好、没那么美妙。</p><p>明天下午是字节的面试。也就尽我所能把我项目里的事情讲清楚,写的东西虽然不一定有用。也当时一个记录吧。</p><h1 id="Borderland-个人博客"><a href="#Borderland-个人博客" class="headerlink" title="Borderland 个人博客"></a>Borderland 个人博客</h1><h2 id="项目名称"><a href="#项目名称" class="headerlink" title="项目名称"></a>项目名称</h2><p>项目名字叫做Borderland,叫做无主之地。当时玩无助之地2,就记住了这个名字。也就用了这个名字。</p><p><a href="https://github.com/JaxChan25/borderland" target="_blank" rel="noopener">点我查看项目代码</a></p><p>下面我的语言想必没有多专业。但尽量说清楚。</p><h2 id="后端是如何运行起来的?"><a href="#后端是如何运行起来的?" class="headerlink" title="后端是如何运行起来的?"></a>后端是如何运行起来的?</h2><h3 id="项目初始化"><a href="#项目初始化" class="headerlink" title="项目初始化"></a>项目初始化</h3><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Init 初始化配置项</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Init</span><span class="params">()</span></span> {</span><br><span class="line"><span class="comment">// 从本地读取环境变量</span></span><br><span class="line">godotenv.Load()</span><br><span class="line"></span><br><span class="line"><span class="comment">// 设置日志级别</span></span><br><span class="line">util.BuildLogger(os.Getenv(<span class="string">"LOG_LEVEL"</span>))</span><br><span class="line"></span><br><span class="line"><span class="comment">// 读取翻译文件</span></span><br><span class="line"><span class="keyword">if</span> err := LoadLocales(<span class="string">"conf/locales/zh-cn.yaml"</span>); err != <span class="literal">nil</span> {</span><br><span class="line">util.Log().Panic(<span class="string">"翻译文件加载失败"</span>, err)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 连接数据库</span></span><br><span class="line">model.Database(os.Getenv(<span class="string">"MYSQL_DSN"</span>))</span><br><span class="line">cache.Redis()</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li><p>godotenv是为了后面使用 os.Getenv(“SOME_ENV_VAR”) 读取环境变量。读取的文件为.env</p></li><li><p>连接Mysql数据库. 单例模式</p><ul><li>使用的是GORM连接数据库的方法。ORM是一种Object-Relationl Mapping,它的作用是在关系型数据库和对象之间作一个映射。</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">持久化的设计则实现了数据处理层内部的 业务逻辑 和数据逻辑分离的解耦合,数据存取逻辑完全分离。 </span><br><span class="line">而 ORM 作为持久化设计中的最重要也最复杂的技术,也是目前业界热点技术。</span><br><span class="line"></span><br><span class="line">数据库的表(table) --> 类(class)</span><br><span class="line">记录(record,行数据)--> 对象(object)</span><br><span class="line">字段(field)--> 对象的属性(attribute)</span><br></pre></td></tr></table></figure></li></ul><ul><li><p>打开的连接 = 正在使用的连接(inuse) + 处于空闲状态的连接(idle)</p></li><li><p>开启了<strong>migration</strong> 模式,自动创表</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">migration</span><span class="params">()</span></span> {</span><br><span class="line"><span class="comment">// 自动迁移模式</span></span><br><span class="line">DB.AutoMigrate(&User{})</span><br><span class="line">DB.AutoMigrate(&Article{})</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// User 用户模型</span></span><br><span class="line"><span class="keyword">type</span> User <span class="keyword">struct</span> {</span><br><span class="line">gorm.Model</span><br><span class="line">UserName <span class="keyword">string</span></span><br><span class="line">PasswordDigest <span class="keyword">string</span></span><br><span class="line">Nickname <span class="keyword">string</span></span><br><span class="line">Status <span class="keyword">string</span></span><br><span class="line">Avatar <span class="keyword">string</span> <span class="string">`gorm:"size:1000"`</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>其中gorm.Model包含以下字段</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Model <span class="keyword">struct</span> {</span><br><span class="line">ID <span class="keyword">uint</span> <span class="string">`gorm:"primary_key"`</span></span><br><span class="line">CreatedAt time.Time</span><br><span class="line">UpdatedAt time.Time</span><br><span class="line">DeletedAt *time.Time <span class="string">`sql:"index"`</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><ul><li>连接redis Nosql数据库. 单例模式</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Redis 在中间件中初始化redis链接</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Redis</span><span class="params">()</span></span> {</span><br><span class="line">db, _ := strconv.ParseUint(os.Getenv(<span class="string">"REDIS_DB"</span>), <span class="number">10</span>, <span class="number">64</span>)</span><br><span class="line">client := redis.NewClient(&redis.Options{</span><br><span class="line">Addr: os.Getenv(<span class="string">"REDIS_ADDR"</span>),</span><br><span class="line">Password: os.Getenv(<span class="string">"REDIS_PW"</span>),</span><br><span class="line">DB: <span class="keyword">int</span>(db),</span><br><span class="line">})</span><br><span class="line"></span><br><span class="line">_, err := client.Ping().Result()</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line">util.Log().Panic(<span class="string">"连接Redis不成功"</span>, err)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">RedisClient = client</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="装载路由器"><a href="#装载路由器" class="headerlink" title="装载路由器"></a>装载路由器</h3><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// NewRouter 路由配置</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewRouter</span><span class="params">()</span> *<span class="title">gin</span>.<span class="title">Engine</span></span> {</span><br><span class="line">r := gin.Default()</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 中间件, 顺序不能改</span></span><br><span class="line">r.Use(middleware.Session(os.Getenv(<span class="string">"SESSION_SECRET"</span>)))</span><br><span class="line">r.Use(middleware.Cors())</span><br><span class="line">r.Use(middleware.CurrentUser())</span><br><span class="line"> </span><br><span class="line"> v1 := r.Group(<span class="string">"/api/v1"</span>){</span><br><span class="line"> v1.POST(<span class="string">"ping"</span>, api.Ping)</span><br><span class="line"> auth := v1.Group(<span class="string">""</span>)</span><br><span class="line">auth.Use(middleware.AuthRequired())</span><br><span class="line">{</span><br><span class="line"> auth.DELETE(<span class="string">"user/logout"</span>, api.UserLogout)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"><span class="keyword">return</span> r</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li><p>使用的就是gin的路由。</p></li><li><p>用了四个中间件。</p><ul><li><p><strong>Session</strong></p><ul><li>session必须依赖于cookie才能使用,生成一个sessionId放到cookie里面传递给client</li><li><strong>用户验证</strong>这种场合一般会用 Session。因此,维持一个会话的核心就是客户端的唯一标识,即Session ID。</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Session 初始化session</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Session</span><span class="params">(secret <span class="keyword">string</span>)</span> <span class="title">gin</span>.<span class="title">HandlerFunc</span></span> {</span><br><span class="line">store := cookie.NewStore([]<span class="keyword">byte</span>(secret))</span><br><span class="line"><span class="comment">//Also set Secure: true if using SSL, you should though</span></span><br><span class="line">store.Options(sessions.Options{HttpOnly: <span class="literal">true</span>, MaxAge: <span class="number">7</span> * <span class="number">86400</span>, Path: <span class="string">"/"</span>})</span><br><span class="line"><span class="keyword">return</span> sessions.Sessions(<span class="string">"gin-session"</span>, store)</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul></li></ul><ul><li><p><strong>CurrentUser</strong> 用于获取session的user。用上下文c里包含的gin-session生成一个session数据结构,获取本数据结构的user_id。然后查看这个user_id是否能在数据库查到。如果可以,说明已经顺利登录。</p><ul><li><p>```GO<br>// CurrentUser 获取登录用户<br>func CurrentUser() gin.HandlerFunc {</p><pre><code>return func(c *gin.Context) { session := sessions.Default(c) uid := session.Get("user_id") if uid != nil { user, err := model.GetUser(uid) if err == nil { c.Set("user", &user) } } c.Next()}</code></pre><p>}</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">- **AuthRequired** 是用来鉴权的</span><br><span class="line"></span><br><span class="line"> - 当我们登录的时候,除了验证账号密码以外,还会设置session。因此返回的response也会有gin-session。</span><br><span class="line"></span><br><span class="line"> ```GO</span><br><span class="line"> // Login 用户登录函数</span><br><span class="line"> func (service *UserLoginService) Login(c *gin.Context) serializer.Response {</span><br><span class="line"> var user model.User</span><br><span class="line"> </span><br><span class="line"> //此处验证登录的账号密码</span><br><span class="line"> </span><br><span class="line"> // 设置session</span><br><span class="line"> service.setSession(c, user)</span><br><span class="line"> </span><br><span class="line"> return serializer.BuildUserResponse(user)</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// setSession 设置session</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(service *UserLoginService)</span> <span class="title">setSession</span><span class="params">(c *gin.Context, user model.User)</span></span> {</span><br><span class="line">s := sessions.Default(c)</span><br><span class="line">s.Clear()</span><br><span class="line">s.Set(<span class="string">"user_id"</span>, user.ID)</span><br><span class="line">s.Save()</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul></li></ul><pre><code>![image-20200407233754153](E:\project\markdown-code\note\项目经历\main.assets\image-20200407233754153.png)- 等我们需要使用**AuthRequired** 中间件保护的接口的时候,浏览器会携带该cookies进行api访问。<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// AuthRequired 需要登录</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">AuthRequired</span><span class="params">()</span> <span class="title">gin</span>.<span class="title">HandlerFunc</span></span> {</span><br><span class="line"><span class="keyword">return</span> <span class="function"><span class="keyword">func</span><span class="params">(c *gin.Context)</span></span> {</span><br><span class="line"><span class="keyword">if</span> user, _ := c.Get(<span class="string">"user"</span>); user != <span class="literal">nil</span> {</span><br><span class="line"><span class="keyword">if</span> _, ok := user.(*model.User); ok {</span><br><span class="line">c.Next()</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">c.JSON(<span class="number">200</span>, serializer.CheckLogin())</span><br><span class="line">c.Abort()</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure>- 当我们logout的时候,也会清理掉这个session<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// UserLogout 用户登出</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">UserLogout</span><span class="params">(c *gin.Context)</span></span> {</span><br><span class="line">s := sessions.Default(c)</span><br><span class="line">s.Clear()</span><br><span class="line">s.Save()</span><br><span class="line">c.JSON(<span class="number">200</span>, serializer.Response{</span><br><span class="line">Code: <span class="number">0</span>,</span><br><span class="line">Msg: <span class="string">"登出成功"</span>,</span><br><span class="line">})</span><br><span class="line">}</span><br></pre></td></tr></table></figure></code></pre><ul><li><p><strong>所以总结来说,如何进行鉴权?</strong></p><ul><li>后端对每个请求,都会通过它的cookies里面包含的session获取user_id</li><li>通过user_id查询数据库是否存在该用户,如果查询成功,就将当前gin.Context的user设置为查询到的user。否则就为空。</li><li>当访问需要登录的接口的时候,就会查询gin.Context里面的user是否存在,如果存在就可以访问;否则就不能访问。</li><li>用户的登录会产生一个session信息在reponse的cookies,登出会消除掉这个session信息。</li></ul></li></ul><ul><li><p><strong>Cors</strong> 是解决跨域问题的</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的。</span><br><span class="line">其实我们通常所说的跨域是狭义的,是由浏览器同源策略限制的一类请求场景。</span><br><span class="line">同源策略/SOP(Same origin policy)是一种约定,由Netscape公司<span class="number">1995</span>年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指<span class="string">"协议+域名+端口"</span>三者相同,即便两个不同的域名指向同一个ip地址,也非同源。</span><br></pre></td></tr></table></figure></li></ul><p>再跑在3000端口就可以了。后端就运行起来了。</p><hr><p>下面我就分一下几种接口的类型,主要讲一下如何进行接口的开发。</p><h2 id="开发接口的流程是怎么样的?"><a href="#开发接口的流程是怎么样的?" class="headerlink" title="开发接口的流程是怎么样的?"></a>开发接口的流程是怎么样的?</h2><ol><li>在router中绑定url以及响应函数</li></ol><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">v1.POST(<span class="string">"user/register"</span>, api.UserRegister)</span><br></pre></td></tr></table></figure><ol><li>在api文件夹新建user.go,创建响应函数</li></ol><p>每个响应函数都有不同的处理。有的需要传参,有的不需要。</p><ul><li>如果传参,就需要用到 gin里面的<strong>ShouldBind</strong> 进行参数解析。</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// ArticlePost 提交markdown格式的article</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">ArticlePost</span><span class="params">(c *gin.Context)</span></span> {</span><br><span class="line"></span><br><span class="line">service := service.ArticlePostService{}</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> err := c.ShouldBind(&service); err == <span class="literal">nil</span> {</span><br><span class="line">res := service.Post()</span><br><span class="line">c.JSON(<span class="number">200</span>, res)</span><br><span class="line">} <span class="keyword">else</span> {</span><br><span class="line">c.JSON(<span class="number">200</span>, ErrorResponse(err))</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>如果不传参,就不需要用(也别用,否则会报错)。</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// ShowArticle 取得单个article文件</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">ShowArticle</span><span class="params">(c *gin.Context)</span></span> {</span><br><span class="line">service := service.ShowArticleService{}</span><br><span class="line">res := service.Show(c.Param(<span class="string">"id"</span>))</span><br><span class="line">c.JSON(<span class="number">200</span>, res)</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol><li>可以看到在第二步的时候,有进行服务的初始化。所以为了完成第二步,事实上也需要code所需要的服务。</li></ol><p>以上传文章为例,我们在service文件夹创建article_post_service.go</p><ul><li>在<strong>ShouldBind</strong> 的时候,会对sevice进行数据绑定。为了正确绑定,我们要定义Service的结构</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// ArticlePostService 管理文章上传的服务</span></span><br><span class="line"><span class="keyword">type</span> ArticlePostService <span class="keyword">struct</span> {</span><br><span class="line">Title <span class="keyword">string</span> <span class="string">`form:"title" json:"title" binding:"required,min=2,max=30"`</span></span><br><span class="line">Catalog <span class="keyword">string</span> <span class="string">`form:"catalog" json:"catalog"`</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>结构说明<ul><li>Title必须大写,才可以被外面访问。</li><li>tag内容有说明想要绑定的数据是以什么格式从前端传来后端的,binding对字段进行校验。<ul><li>form:title。其中form表示表单,title表示传来的字段名字。</li><li>binding后就是对输入属性的具体要求。required表示必选,也说明了最小值和最大值。</li></ul></li></ul></li></ul><ul><li><p>然后需要定义<strong>针对结构体的方法函数</strong> 可能用于进一步验证,也可能用于真正的业务处理。下面两个函数,分别说明。</p><ul><li>表单验证</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// valid 验证表单</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(service *ArticlePostService)</span> <span class="title">valid</span><span class="params">()</span> *<span class="title">serializer</span>.<span class="title">Response</span></span> {</span><br><span class="line"></span><br><span class="line">count := <span class="number">0</span></span><br><span class="line">model.DB.Model(&model.Article{}).Where(<span class="string">"title = ?"</span>, service.Title).Count(&count)</span><br><span class="line"><span class="keyword">if</span> count > <span class="number">0</span> {</span><br><span class="line"><span class="keyword">return</span> &serializer.Response{</span><br><span class="line">Code: <span class="number">40001</span>,</span><br><span class="line">Msg: <span class="string">"该文章已经上传"</span>,</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>特别注意!</strong></p><p>这里的model.DB就是mysql的单例对象。这里的 <strong>Article结构体</strong> 和 上面定义的 <strong>ArticlePostService结构体</strong></p><p>是两个不同的结构体。前者用于GORM,后者用于业务流程。上面在讲项目初始化的时候,有讲到过。</p></li></ul><ul><li><p>业务逻辑函数</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">// Post 用于文章上传</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(service *ArticlePostService)</span> <span class="title">Post</span><span class="params">()</span> <span class="title">serializer</span>.<span class="title">Response</span></span> {</span><br><span class="line"> </span><br><span class="line"> <span class="comment">//校验</span></span><br><span class="line"><span class="keyword">if</span> err := service.valid(); err != <span class="literal">nil</span> {</span><br><span class="line"><span class="keyword">return</span> *err</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"> <span class="comment">//对service里面的数据进行处理,已略代码</span></span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"> <span class="comment">//由service -> model</span></span><br><span class="line">article := model.Article{</span><br><span class="line">Title: service.Title,</span><br><span class="line">Catalog: service.Catalog,</span><br><span class="line">Introduction: intro,</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 将文章写入数据库</span></span><br><span class="line"><span class="keyword">if</span> err := model.DB.Create(&article).Error; err != <span class="literal">nil</span> {</span><br><span class="line"><span class="keyword">return</span> serializer.ParamErr(<span class="string">"写入文章失败"</span>, err)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"> <span class="comment">//返回序列化好的输出</span></span><br><span class="line"><span class="keyword">return</span> serializer.Response{</span><br><span class="line">Data: serializer.BuildArticleResponse(article, <span class="string">""</span>),</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><ol><li><p>可以留意到第四步里面的业务函数,返回的是一个<strong>serializer.Response{}</strong> 。这是为了让我们后端处理后的结果,等有序、pretty返回到前端。</p><p>下面就介绍serializer模块。</p></li></ol><ul><li><p>为了返回统一的response.(json),我们首先定义了一个<strong>通用的序列化器Response</strong></p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Response 基础序列化器</span></span><br><span class="line"><span class="keyword">type</span> Response <span class="keyword">struct</span> {</span><br><span class="line">Code <span class="keyword">int</span> <span class="string">`json:"code"`</span></span><br><span class="line">Data <span class="keyword">interface</span>{} <span class="string">`json:"data,omitempty"`</span></span><br><span class="line">Msg <span class="keyword">string</span> <span class="string">`json:"msg"`</span></span><br><span class="line">Error <span class="keyword">string</span> <span class="string">`json:"error,omitempty"`</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Code通常是说明后端的状态处理码。这里的码和HTTP的状态码有不同的地方。我们通常都是直接返回HTTP的statuscode = 200,但是在response里面在说明一个自定义的码,来说明后端的处理情况。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 三位数错误编码为复用http原本含义</span></span><br><span class="line"><span class="comment">// 五位数错误编码为应用自定义错误</span></span><br><span class="line"><span class="comment">// 五开头的五位数错误编码为服务器端错误,比如数据库操作失败</span></span><br><span class="line"><span class="comment">// 四开头的五位数错误编码为客户端错误,有时候是客户端代码写错了,有时候是用户操作错误</span></span><br><span class="line"><span class="keyword">const</span> (</span><br><span class="line"><span class="comment">// CodeCheckLogin 未登录</span></span><br><span class="line">CodeCheckLogin = <span class="number">401</span></span><br><span class="line"><span class="comment">// CodeNoRightErr 未授权访问</span></span><br><span class="line">CodeNoRightErr = <span class="number">403</span></span><br><span class="line"><span class="comment">// CodeDBError 数据库操作失败</span></span><br><span class="line">CodeDBError = <span class="number">50001</span></span><br><span class="line"><span class="comment">// CodeEncryptError 加密失败</span></span><br><span class="line">CodeEncryptError = <span class="number">50002</span></span><br><span class="line"><span class="comment">//CodeParamErr 各种奇奇怪怪的参数错误</span></span><br><span class="line">CodeParamErr = <span class="number">40001</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//环境错误</span></span><br><span class="line">CodeEnv = <span class="number">101</span></span><br><span class="line">)</span><br></pre></td></tr></table></figure></li></ul><ul><li>通常Error信息由gin/go自带的err来添加。</li><li>我们要真正返回信息,就放在<strong>Data</strong>这一块。譬如我们有很多文章model,但是我们需要序列化成一个输出的struct。这个struct会在返回时自动转为json。</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Article 文章序列化器</span></span><br><span class="line"><span class="keyword">type</span> Article <span class="keyword">struct</span> {</span><br><span class="line">ID <span class="keyword">uint</span> <span class="string">`json:"id"`</span></span><br><span class="line">Title <span class="keyword">string</span> <span class="string">`json:"title"`</span></span><br><span class="line">Introduction <span class="keyword">string</span> <span class="string">`json:"introduction"`</span></span><br><span class="line">Content <span class="keyword">string</span> <span class="string">`json:"content"`</span></span><br><span class="line">Catalog <span class="keyword">string</span> <span class="string">`json:"catalog"`</span></span><br><span class="line">View <span class="keyword">uint64</span> <span class="string">`json:"view"`</span></span><br><span class="line">Like <span class="keyword">uint64</span> <span class="string">`json:"like"`</span></span><br><span class="line">CreatedAt <span class="keyword">string</span> <span class="string">`json:"created_at"`</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>也要定义序列化函数,将数据从 model转为序列化的struct。</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// BuildArticle 序列化文章</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">BuildArticle</span><span class="params">(article model.Article, content <span class="keyword">string</span>)</span> <span class="title">Article</span></span> {</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> Article{</span><br><span class="line">ID: article.ID,</span><br><span class="line">Title: article.Title,</span><br><span class="line">Introduction: article.Introduction,</span><br><span class="line">Content: content,</span><br><span class="line">Catalog: article.Catalog,</span><br><span class="line">View: article.ViewNumber(),</span><br><span class="line">Like: article.LikeNumber(),</span><br><span class="line">CreatedAt: article.CreatedAt.Format(<span class="string">"2006-01-02 15:04"</span>),</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>如果只序列化一个文章,只要用上面的这个函数就好。但是如果要序列化多篇文章,就得再写一个能处理多条信息的序列化器。</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">// BuildArticleResponse 序列化单篇文章响应</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">BuildArticleResponse</span><span class="params">(article model.Article, content <span class="keyword">string</span>)</span> <span class="title">Article</span></span> {</span><br><span class="line"><span class="keyword">return</span> BuildArticle(article, content)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// BuildArticlesResponse 序列化多篇文章响应</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">BuildArticlesResponse</span><span class="params">(items []model.Article)</span> <span class="params">(articles []Article)</span></span> {</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> _, item := <span class="keyword">range</span> items {</span><br><span class="line">articles = <span class="built_in">append</span>(articles, BuildArticle(item, <span class="string">""</span>))</span><br><span class="line">}</span><br><span class="line"><span class="keyword">return</span> articles</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>同时,data里面要再嵌套一个<strong>基础列表结构</strong> ,同时构造好它的通用函数</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">//DataList 基础列表结构</span></span><br><span class="line"><span class="keyword">type</span> DataList <span class="keyword">struct</span> {</span><br><span class="line">Items <span class="keyword">interface</span>{} <span class="string">`json:"items"`</span></span><br><span class="line">Total <span class="keyword">uint</span> <span class="string">`json:"total"`</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//BuildListResponse 列表构建器</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">BuildListResponse</span><span class="params">(items <span class="keyword">interface</span>{}, total <span class="keyword">uint</span>)</span> <span class="title">Response</span></span> {</span><br><span class="line"><span class="keyword">return</span> Response{</span><br><span class="line">Data: DataList{</span><br><span class="line">Items: items,</span><br><span class="line">Total: total,</span><br><span class="line">},</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol><li>序列化好后,直接返回。gin会将数据从struct转为json。</li></ol><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"code"</span>: <span class="number">0</span>,</span><br><span class="line"> <span class="attr">"data"</span>: {</span><br><span class="line"> <span class="attr">"items"</span>: [</span><br><span class="line"> {</span><br><span class="line"> <span class="attr">"id"</span>: <span class="number">1</span>,</span><br><span class="line"> <span class="attr">"title"</span>: <span class="string">"自序"</span>,</span><br><span class="line"> <span class="attr">"introduction"</span>: <span class="string">"为什么要搭博客有很多原因,..."</span>,</span><br><span class="line"> <span class="attr">"content"</span>: <span class="string">""</span>,</span><br><span class="line"> <span class="attr">"catalog"</span>: <span class="string">"建站日记"</span>,</span><br><span class="line"> <span class="attr">"view"</span>: <span class="number">201</span>,</span><br><span class="line"> <span class="attr">"like"</span>: <span class="number">9</span>,</span><br><span class="line"> <span class="attr">"created_at"</span>: <span class="string">"2020-02-16 15:15"</span></span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="attr">"id"</span>: <span class="number">2</span>,</span><br><span class="line"> <span class="attr">"title"</span>: <span class="string">"test1"</span>,</span><br><span class="line"> <span class="attr">"introduction"</span>: <span class="string">"我是简介啊啊啊..."</span>,</span><br><span class="line"> <span class="attr">"content"</span>: <span class="string">""</span>,</span><br><span class="line"> <span class="attr">"catalog"</span>: <span class="string">"建站日记"</span>,</span><br><span class="line"> <span class="attr">"view"</span>: <span class="number">26</span>,</span><br><span class="line"> <span class="attr">"like"</span>: <span class="number">1</span>,</span><br><span class="line"> <span class="attr">"created_at"</span>: <span class="string">"2020-02-16 15:41"</span></span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="attr">"id"</span>: <span class="number">3</span>,</span><br><span class="line"> <span class="attr">"title"</span>: <span class="string">"test2"</span>,</span><br><span class="line"> <span class="attr">"introduction"</span>: <span class="string">"我是简介啊啊啊我是简介啊啊啊..."</span>,</span><br><span class="line"> <span class="attr">"content"</span>: <span class="string">""</span>,</span><br><span class="line"> <span class="attr">"catalog"</span>: <span class="string">"建站日记"</span>,</span><br><span class="line"> <span class="attr">"view"</span>: <span class="number">6</span>,</span><br><span class="line"> <span class="attr">"like"</span>: <span class="number">1</span>,</span><br><span class="line"> <span class="attr">"created_at"</span>: <span class="string">"2020-02-16 15:41"</span></span><br><span class="line"> },</span><br><span class="line"></span><br><span class="line"> ],</span><br><span class="line"> <span class="attr">"total"</span>: <span class="number">3</span></span><br><span class="line"> },</span><br><span class="line"> <span class="attr">"msg"</span>: <span class="string">""</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>上面讲完了一个接口的开发流程。</p><p>下面针对某些特定技术讲解。</p><h2 id="如何使用redis"><a href="#如何使用redis" class="headerlink" title="如何使用redis?"></a>如何使用redis?</h2><h3 id="理论学习"><a href="#理论学习" class="headerlink" title="理论学习"></a>理论学习</h3><p>Redis 可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API的非关系型数据库。访问很快。</p><p><strong>什么是Redis持久化? </strong></p><p>持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。</p><p>其他就都不展开了。</p><h3 id="redis如何实现点赞数量的功能?"><a href="#redis如何实现点赞数量的功能?" class="headerlink" title="redis如何实现点赞数量的功能?"></a>redis如何实现点赞数量的功能?</h3><p>和上面开发接口一样,也要定义api,定义service。只在service里面的业务函数中,直接调用了model里面定义好的点赞函数。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//文章点赞数加一</span></span><br><span class="line">article.AddLike()</span><br></pre></td></tr></table></figure><p>让我们来看看这个函数。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//AddLike 文章喜欢+1</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(article *Article)</span> <span class="title">AddLike</span><span class="params">()</span></span> {</span><br><span class="line"></span><br><span class="line"><span class="comment">//增加文章喜欢点击数</span></span><br><span class="line">cache.RedisClient.Incr(cache.ArticleLikeKey(article.ID))</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>其中生成key的函数</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//ArticleLikeKey 生成Article喜欢的Key</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">ArticleLikeKey</span><span class="params">(id <span class="keyword">uint</span>)</span> <span class="title">string</span></span> {</span><br><span class="line"><span class="keyword">return</span> fmt.Sprintf(<span class="string">"like:article:%s"</span>, strconv.Itoa(<span class="keyword">int</span>(id)))</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>那怎样才可以返回累计的数目呢?简单的查询。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//LikeNumber 文章喜欢的累计数</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(article *Article)</span> <span class="title">LikeNumber</span><span class="params">()</span> <span class="title">uint64</span></span> {</span><br><span class="line"></span><br><span class="line">countStr, _ := cache.RedisClient.Get(cache.ArticleLikeKey(article.ID)).Result()</span><br><span class="line">count, _ := strconv.ParseUint(countStr, <span class="number">10</span>, <span class="number">64</span>)</span><br><span class="line"><span class="keyword">return</span> count</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="redis如何实现每日点击排行榜?"><a href="#redis如何实现每日点击排行榜?" class="headerlink" title="redis如何实现每日点击排行榜?"></a>redis如何实现每日点击排行榜?</h3><p>在我们增加点击量的时候,也增加有序集合里面的点击率。后者设置任务让它每天清零。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//Addview 文章游览+1</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(article *Article)</span> <span class="title">Addview</span><span class="params">()</span></span> {</span><br><span class="line"></span><br><span class="line"><span class="comment">//增加视频点击数</span></span><br><span class="line">cache.RedisClient.Incr(cache.ArticleViewKey(article.ID))</span><br><span class="line"></span><br><span class="line"><span class="comment">//增加排行榜里面的视频点击数</span></span><br><span class="line">cache.RedisClient.ZIncrBy(cache.TotalRankKey, <span class="number">1</span>, strconv.Itoa(<span class="keyword">int</span>(article.ID)))</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="如何实现查询分页功能?"><a href="#如何实现查询分页功能?" class="headerlink" title="如何实现查询分页功能?"></a>如何实现查询分页功能?</h2><p>定义好start和limit,start表示开始的index,limit表示数目。</p><p>下面就贴一下两种实现:ORM和mysql。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> err := model.DB.Limit(service.Limit).Offset(service.Start).Find(&articles).Error; err != <span class="literal">nil</span> {</span><br><span class="line"><span class="keyword">return</span> serializer.Response{</span><br><span class="line">Code: <span class="number">50000</span>,</span><br><span class="line">Msg: <span class="string">"数据库查询错误"</span>,</span><br><span class="line">Error: err.Error(),</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">select * from student limit(curPage-1)*pageSize,pageSize;</span><br></pre></td></tr></table></figure><p>ok 后面还有一个hitMaker,主要是对库的运用和算法的设计。感觉不值得讲。所以就不讲了。</p>]]></content>
<summary type="html">
<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>其实当初做完自己的博客之后就想着写一篇关于自己项目经历的文章。</p>
<p>毕竟这是一个经历,是我大学美好青春、热血挥洒的地方。哪怕它没那
</summary>
<category term="编程" scheme="http://jaxchan.top/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="面试" scheme="http://jaxchan.top/categories/%E7%BC%96%E7%A8%8B/%E9%9D%A2%E8%AF%95/"/>
<category term="GO" scheme="http://jaxchan.top/tags/GO/"/>
</entry>
<entry>
<title>Leetcode-TOP100-Easy:思路和代码</title>
<link href="http://jaxchan.top/2020/Leetcode-TOP100-Easy-%E6%80%9D%E8%B7%AF%E5%92%8C%E4%BB%A3%E7%A0%81.html/"/>
<id>http://jaxchan.top/2020/Leetcode-TOP100-Easy-%E6%80%9D%E8%B7%AF%E5%92%8C%E4%BB%A3%E7%A0%81.html/</id>
<published>2020-03-31T14:19:22.000Z</published>
<updated>2020-03-31T14:21:23.907Z</updated>
<content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>这两天把Leetcode的 <a href="https://leetcode.com/problemset/top-100-liked-questions/?difficulty=Easy" target="_blank" rel="noopener">Top-100-liked-questions - easy</a>题目做了。</p><p>下面就记一下思路和代码,当作记录。</p><p>可能因为刚上手吧,感觉也不简单。</p><p>当然先记一下探索出来的刷Leetcode的姿势。</p><p>后面的话,</p><ul><li>先把srp的报告写了,</li><li>还有一边学习强国。</li><li>天池那个baseline研究一下。</li><li>保研的信息继续收集和了解。!!!</li><li>实验室要补实验。</li></ul><p>这样的话,这个星期暂且做不了多少题。先把上面的事做了吧!</p><p>Have a good WEEK!</p><p>贴一下列表</p><div class="table-container"><table><thead><tr><th style="text-align:left"></th><th style="text-align:left"><strong>Title</strong></th><th style="text-align:left"><strong>Solution</strong></th><th style="text-align:left"><strong>Acceptance</strong></th><th style="text-align:left"><strong>Difficulty</strong></th><th style="text-align:left"><strong>Frequency</strong></th><th></th></tr></thead><tbody><tr><td style="text-align:left"></td><td style="text-align:left">1</td><td style="text-align:left"><a href="https://leetcode.com/problems/two-sum" target="_blank" rel="noopener">Two Sum</a></td><td style="text-align:left"></td><td style="text-align:left">45.2%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">20</td><td style="text-align:left"><a href="https://leetcode.com/problems/valid-parentheses" target="_blank" rel="noopener">Valid Parentheses</a></td><td style="text-align:left"></td><td style="text-align:left">38.2%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">21</td><td style="text-align:left"><a href="https://leetcode.com/problems/merge-two-sorted-lists" target="_blank" rel="noopener">Merge Two Sorted Lists</a></td><td style="text-align:left"></td><td style="text-align:left">51.7%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">53</td><td style="text-align:left"><a href="https://leetcode.com/problems/maximum-subarray" target="_blank" rel="noopener">Maximum Subarray</a></td><td style="text-align:left"></td><td style="text-align:left">45.9%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">70</td><td style="text-align:left"><a href="https://leetcode.com/problems/climbing-stairs" target="_blank" rel="noopener">Climbing Stairs</a></td><td style="text-align:left"></td><td style="text-align:left">46.3%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">101</td><td style="text-align:left"><a href="https://leetcode.com/problems/symmetric-tree" target="_blank" rel="noopener">Symmetric Tree</a></td><td style="text-align:left"></td><td style="text-align:left">45.8%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">104</td><td style="text-align:left"><a href="https://leetcode.com/problems/maximum-depth-of-binary-tree" target="_blank" rel="noopener">Maximum Depth of Binary Tree</a></td><td style="text-align:left"></td><td style="text-align:left">64.4%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">121</td><td style="text-align:left"><a href="https://leetcode.com/problems/best-time-to-buy-and-sell-stock" target="_blank" rel="noopener">Best Time to Buy and Sell Stock</a></td><td style="text-align:left"></td><td style="text-align:left">49.6%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">136</td><td style="text-align:left"><a href="https://leetcode.com/problems/single-number" target="_blank" rel="noopener">Single Number</a></td><td style="text-align:left"></td><td style="text-align:left">63.3%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">141</td><td style="text-align:left"><a href="https://leetcode.com/problems/linked-list-cycle" target="_blank" rel="noopener">Linked List Cycle</a></td><td style="text-align:left"></td><td style="text-align:left">39.9%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">155</td><td style="text-align:left"><a href="https://leetcode.com/problems/min-stack" target="_blank" rel="noopener">Min Stack</a></td><td style="text-align:left"></td><td style="text-align:left">41.4%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">160</td><td style="text-align:left"><a href="https://leetcode.com/problems/intersection-of-two-linked-lists" target="_blank" rel="noopener">Intersection of Two Linked Lists</a></td><td style="text-align:left"></td><td style="text-align:left">38.4%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">169</td><td style="text-align:left"><a href="https://leetcode.com/problems/majority-element" target="_blank" rel="noopener">Majority Element</a></td><td style="text-align:left"></td><td style="text-align:left">56.2%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">198</td><td style="text-align:left"><a href="https://leetcode.com/problems/house-robber" target="_blank" rel="noopener">House Robber</a></td><td style="text-align:left"></td><td style="text-align:left">41.6%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">206</td><td style="text-align:left"><a href="https://leetcode.com/problems/reverse-linked-list" target="_blank" rel="noopener">Reverse Linked List</a></td><td style="text-align:left"></td><td style="text-align:left">60.2%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">226</td><td style="text-align:left"><a href="https://leetcode.com/problems/invert-binary-tree" target="_blank" rel="noopener">Invert Binary Tree</a></td><td style="text-align:left"></td><td style="text-align:left">62.1%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">234</td><td style="text-align:left"><a href="https://leetcode.com/problems/palindrome-linked-list" target="_blank" rel="noopener">Palindrome Linked List</a></td><td style="text-align:left"></td><td style="text-align:left">38.2%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">283</td><td style="text-align:left"><a href="https://leetcode.com/problems/move-zeroes" target="_blank" rel="noopener">Move Zeroes</a></td><td style="text-align:left"></td><td style="text-align:left">56.5%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">437</td><td style="text-align:left"><a href="https://leetcode.com/problems/path-sum-iii" target="_blank" rel="noopener">Path Sum III</a></td><td style="text-align:left"></td><td style="text-align:left">45.1%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">448</td><td style="text-align:left"><a href="https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array" target="_blank" rel="noopener">Find All Numbers Disappeared in an Array</a></td><td style="text-align:left"></td><td style="text-align:left">55.3%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">543</td><td style="text-align:left"><a href="https://leetcode.com/problems/diameter-of-binary-tree" target="_blank" rel="noopener">Diameter of Binary Tree</a></td><td style="text-align:left"></td><td style="text-align:left">48.3%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">581</td><td style="text-align:left"><a href="https://leetcode.com/problems/shortest-unsorted-continuous-subarray" target="_blank" rel="noopener">Shortest Unsorted Continuous Subarray</a></td><td style="text-align:left"></td><td style="text-align:left">30.7%</td><td style="text-align:left"><strong>Easy</strong></td><td></td></tr><tr><td style="text-align:left"></td><td style="text-align:left">617</td><td style="text-align:left"><a href="https://leetcode.com/problems/merge-two-binary-trees" target="_blank" rel="noopener">Merge Two Binary Trees</a></td><td style="text-align:left"></td><td style="text-align:left">73.0%</td><td style="text-align:left"><strong>Easy</strong></td></tr></tbody></table></div><h1 id="刷Leetcode的姿势"><a href="#刷Leetcode的姿势" class="headerlink" title="刷Leetcode的姿势"></a>刷Leetcode的姿势</h1><p>正常来说,是直接在Leetcode网页直接写代码。</p><p>虽然说有playground可以调试,但是还是本地调试比较舒服。</p><p>只需要把playground的代码放在vs就好了,再重定义一下输入 <code><input.txt</code></p><p><img src="http://upload-images.jianshu.io/upload_images/15914329-820cdf925a70036b.png" alt="image-20200331191122908"></p><p>也要关掉SDL安全检查,不然得用scanf_s换scanf。</p><p><img src="http://upload-images.jianshu.io/upload_images/15914329-c1d33ecf737cd7c8.png" alt="image-20200331191146563"></p><p>但是要附上以下的头文件</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><vector></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><algorithm></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><ctype.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><string></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sstream></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br></pre></td></tr></table></figure><h1 id="1-两数之和"><a href="#1-两数之和" class="headerlink" title="1. 两数之和"></a><a href="https://leetcode-cn.com/problems/two-sum/" target="_blank" rel="noopener">1. 两数之和</a></h1><p>给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。</p><p>你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。</p><p>示例:</p><p>给定 nums = [2, 7, 11, 15], target = 9</p><p>因为 nums[0] + nums[1] = 2 + 7 = 9<br>所以返回 [0, 1]</p><p>定义字典,key为num,value为index.</p><p>遍历添加num,但是每次添加都检查一下target - num是否存在。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="built_in">vector</span><<span class="keyword">int</span>> <span class="title">twoSum</span><span class="params">(<span class="built_in">vector</span><<span class="keyword">int</span>>& nums, <span class="keyword">int</span> target)</span> </span>{</span><br><span class="line"> <span class="built_in">unordered_map</span><<span class="keyword">int</span>,<span class="keyword">int</span>>M;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>;i<nums.<span class="built_in">size</span>();i++){</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> ( M.<span class="built_in">find</span>(target-nums[i])!=M.<span class="built_in">end</span>() ){</span><br><span class="line"> <span class="keyword">return</span> { M[target-nums[i]],i};</span><br><span class="line"> }</span><br><span class="line"> M[nums[i]] = i;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> {};</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h1 id="20-有效的括号"><a href="#20-有效的括号" class="headerlink" title="20. 有效的括号"></a><a href="https://leetcode-cn.com/problems/valid-parentheses/" target="_blank" rel="noopener">20. 有效的括号</a></h1><p>给定一个只包括 ‘(‘,’)’,’{‘,’}’,’[‘,’]’ 的字符串,判断字符串是否有效。</p><p>有效字符串需满足:</p><p>左括号必须用相同类型的右括号闭合。<br>左括号必须以正确的顺序闭合。<br>注意空字符串可被认为是有效字符串。</p><p>示例 1:</p><p>输入: “()”<br>输出: true</p><p>定义一个stack,如果遇到( { [ 就直接压栈,遇到右边的就看看栈顶有没有相应的匹配元素,没有就报错。</p><p>最后栈不为空也报错。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"><span class="function"><span class="keyword">bool</span> <span class="title">isValid</span><span class="params">(<span class="built_in">string</span> s)</span> </span>{</span><br><span class="line"><span class="keyword">int</span> len = s.length();</span><br><span class="line"><span class="keyword">if</span> (len == <span class="number">0</span>) <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"><span class="keyword">if</span> (len == <span class="number">1</span>) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line"><span class="built_in">stack</span><<span class="keyword">char</span>> S;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < len; i++) {</span><br><span class="line"><span class="keyword">switch</span> (s[i]) {</span><br><span class="line"><span class="keyword">case</span> <span class="string">')'</span>:</span><br><span class="line"><span class="keyword">if</span> (S.empty()) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"><span class="keyword">if</span> (S.top() == <span class="string">'('</span>) {</span><br><span class="line">S.pop();</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">else</span> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"><span class="keyword">case</span> <span class="string">'}'</span>:</span><br><span class="line"><span class="keyword">if</span> (S.empty()) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"><span class="keyword">if</span> (S.top() == <span class="string">'{'</span>) {</span><br><span class="line">S.pop();</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">else</span> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"><span class="keyword">case</span> <span class="string">']'</span>:</span><br><span class="line"><span class="keyword">if</span> (S.empty()) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"><span class="keyword">if</span> (S.top() == <span class="string">'['</span>) {</span><br><span class="line">S.pop();</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">else</span> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"><span class="keyword">default</span>:</span><br><span class="line">S.push(s[i]);</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (!S.empty()) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"><span class="keyword">else</span> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">};</span><br></pre></td></tr></table></figure><h1 id="21-合并两个有序链表"><a href="#21-合并两个有序链表" class="headerlink" title="21. 合并两个有序链表"></a><a href="https://leetcode-cn.com/problems/merge-two-sorted-lists/" target="_blank" rel="noopener">21. 合并两个有序链表</a></h1><p>将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 </p><p>示例:</p><p>输入:1->2->4, 1->3->4<br>输出:1->1->2->3->4->4</p><p>递归。</p><ul><li>如果l1到尾了,就返回剩下的l2。</li><li>如果l2到尾了,就返回剩下的l1。</li><li>如果都没有到尾,小的list的next指向大的list。</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function">ListNode* <span class="title">mergeTwoLists</span><span class="params">(ListNode* l1, ListNode* l2)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(!l1) <span class="keyword">return</span> l2;</span><br><span class="line"> <span class="keyword">if</span> (!l2) <span class="keyword">return</span> l1;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span>(l1->val<l2->val){</span><br><span class="line"> l1-> next = mergeTwoLists(l1->next,l2);</span><br><span class="line"> <span class="keyword">return</span> l1;</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> l2-> next = mergeTwoLists(l1,l2->next);</span><br><span class="line"> <span class="keyword">return</span> l2;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h1 id="53-最大子序和"><a href="#53-最大子序和" class="headerlink" title="53. 最大子序和"></a><a href="https://leetcode-cn.com/problems/maximum-subarray/" target="_blank" rel="noopener">53. 最大子序和</a></h1><p>给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。</p><p>示例:</p><p>输入: [-2,1,-3,4,-1,2,1,-5,4],<br>输出: 6<br>解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。<br>进阶:</p><p>如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。</p><p>动态规划。</p><p>对于第i个值而言,要么是接上上一个连续子数组,要么不接,比较一下两种方式的值,取大的方式。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">maxSubArray</span><span class="params">(<span class="built_in">vector</span><<span class="keyword">int</span>>& nums)</span> </span>{</span><br><span class="line"> <span class="built_in">vector</span> <<span class="keyword">int</span>> dp;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i<nums.<span class="built_in">size</span>();i++){</span><br><span class="line"></span><br><span class="line"> <span class="comment">//先放第一个</span></span><br><span class="line"> <span class="keyword">if</span>(i==<span class="number">0</span>){</span><br><span class="line"> dp.push_back(nums[i]);</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">int</span> <span class="built_in">max</span> = nums[i];</span><br><span class="line"> <span class="keyword">if</span>( <span class="built_in">max</span> +dp[i<span class="number">-1</span>] ><span class="built_in">max</span> )</span><br><span class="line"> <span class="built_in">max</span>=<span class="built_in">max</span> +dp[i<span class="number">-1</span>];</span><br><span class="line"> </span><br><span class="line"> dp.push_back(<span class="built_in">max</span>);</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> *max_element(dp.<span class="built_in">begin</span>(),dp.<span class="built_in">end</span>());</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h1 id="70-爬楼梯"><a href="#70-爬楼梯" class="headerlink" title="70. 爬楼梯"></a><a href="https://leetcode-cn.com/problems/climbing-stairs/" target="_blank" rel="noopener">70. 爬楼梯</a></h1><p>假设你正在爬楼梯。需要 n 阶你才能到达楼顶。</p><p>每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?</p><p>注意:给定 n 是一个正整数。</p><p>示例 1:</p><p>输入: 2<br>输出: 2<br>解释: 有两种方法可以爬到楼顶。</p><ol><li>1 阶 + 1 阶</li><li>2 阶</li></ol><p>入门题了。</p><p>动态规划。对于第k个台阶而言,达到本台阶只有两种来源:一是来自k-1级,一是来自k-2级。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">climbStairs</span><span class="params">(<span class="keyword">int</span> n)</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (n==<span class="number">1</span> || n==<span class="number">2</span>)<span class="keyword">return</span> n;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">int</span> dp[<span class="number">1001</span>];</span><br><span class="line"> dp[<span class="number">1</span>] = <span class="number">1</span>;</span><br><span class="line"> dp[<span class="number">2</span>] = <span class="number">2</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">3</span>;i<=n;i++)</span><br><span class="line"> dp[i] = dp[i<span class="number">-2</span>]+ dp[i<span class="number">-1</span>];</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">return</span> dp[n];</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h1 id="101-对称二叉树"><a href="#101-对称二叉树" class="headerlink" title="101. 对称二叉树"></a><a href="https://leetcode-cn.com/problems/symmetric-tree/" target="_blank" rel="noopener">101. 对称二叉树</a></h1><p>给定一个二叉树,检查它是否是镜像对称的。</p><p>例如,二叉树 [1,2,2,3,4,4,3] 是对称的。</p><pre><code> 1 / \ 2 2 / \ / \3 4 4 3</code></pre><p>但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:</p><pre><code> 1 / \ 2 2 \ \ 3 3</code></pre><p>说明:</p><p>如果你可以运用递归和迭代两种方法解决这个问题,会很加分。</p><p>递归。不简单。</p><p>首先一棵树是对称的话,镜面位置的NULL和非NULL都是一样的。</p><p>所以</p><ul><li>如果都为NULL,就返回true</li><li><p>如果只有一个为NULL,另一个不为NULL,就返回false</p></li><li><p>最终的表达式:当前值相等 且 左子树的值相等 且 有右子树的值相等</p></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">bool</span> <span class="title">isSymmetric</span><span class="params">(TreeNode* root)</span> </span>{</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span>(root==<span class="literal">NULL</span>)<span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> <span class="keyword">return</span> isSymmetricHelp(root->left,root->right);</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">bool</span> <span class="title">isSymmetricHelp</span><span class="params">(TreeNode* l,TreeNode* r)</span></span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span>( (!l && !r)) <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> ( !l || !r ) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> ( l->val == r->val) && ( isSymmetricHelp(l->left,r->right) ) && ( isSymmetricHelp(l->right,r->left) );</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h1 id="104-二叉树的最大深度"><a href="#104-二叉树的最大深度" class="headerlink" title="104. 二叉树的最大深度"></a><a href="https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/" target="_blank" rel="noopener">104. 二叉树的最大深度</a></h1><p>给定一个二叉树,找出其最大深度。</p><p>二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。</p><p>说明: 叶子节点是指没有子节点的节点。</p><p>示例:<br>给定二叉树 [3,9,20,null,null,15,7],</p><pre><code> 3 / \ 9 20 / \ 15 7</code></pre><p> </p><p>老题了。</p><p>递归。每次往上返回的值 = max(左子树返回值,右子树返回值) + 1 </p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">maxDepth</span><span class="params">(TreeNode* root)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(!root)<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">return</span> <span class="built_in">max</span>(maxDepth(root->left),maxDepth(root->right))+<span class="number">1</span>;</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h1 id="121-买卖股票的最佳时机"><a href="#121-买卖股票的最佳时机" class="headerlink" title="121. 买卖股票的最佳时机"></a><a href="https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/" target="_blank" rel="noopener">121. 买卖股票的最佳时机</a></h1><p>给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。</p><p>如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。</p><p>注意:你不能在买入股票前卖出股票。</p><p>示例 1:</p><p>输入: [7,1,5,3,6,4]<br>输出: 5<br>解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。<br> 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。</p><p>简单的动态规划。</p><p>每次记录累计的股票价格的最低值。然后计算在这个最低值情况下,当天卖出的利润,如果利润比之前的利润有上升,就sold。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">maxProfit</span><span class="params">(<span class="built_in">vector</span><<span class="keyword">int</span>>& prices)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> inf = <span class="number">1e9</span>;</span><br><span class="line"> <span class="keyword">int</span> minprice = inf, maxprofit = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> price: prices) {</span><br><span class="line"> maxprofit = <span class="built_in">max</span>(maxprofit, price - minprice);</span><br><span class="line"> minprice = <span class="built_in">min</span>(price, minprice);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> maxprofit;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h1 id="136-只出现一次的数字"><a href="#136-只出现一次的数字" class="headerlink" title="136. 只出现一次的数字"></a><a href="https://leetcode-cn.com/problems/single-number/" target="_blank" rel="noopener">136. 只出现一次的数字</a></h1><p>给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。</p><p>说明:</p><p>你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?</p><p>示例 1:</p><p>输入: [2,2,1]<br>输出: 1</p><p>异或求不同。</p><h1 id="141-环形链表"><a href="#141-环形链表" class="headerlink" title="141. 环形链表"></a><a href="https://leetcode-cn.com/problems/linked-list-cycle/" target="_blank" rel="noopener">141. 环形链表</a></h1><p>给定一个链表,判断链表中是否有环。</p><p>为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。</p><p>虽然入门书可以用拓扑排序判断是否有环。</p><p>这里,用快慢指针判断是否有环更方便。</p><ul><li>如果无环,快指针很快就可以到终点。</li><li>如果有环,肯定会有快指针 = 慢指针的时候。</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">bool</span> <span class="title">hasCycle</span><span class="params">(ListNode *head)</span> </span>{</span><br><span class="line"> ListNode* fast = head;</span><br><span class="line"> ListNode* slow = head;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span>(fast!=<span class="literal">NULL</span> && fast->next!=<span class="literal">NULL</span>){</span><br><span class="line"> fast = fast->next->next;</span><br><span class="line"> slow = slow->next;</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span>(fast == slow){</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h1 id="155-最小栈"><a href="#155-最小栈" class="headerlink" title="155. 最小栈"></a><a href="https://leetcode-cn.com/problems/min-stack/" target="_blank" rel="noopener">155. 最小栈</a></h1><p>设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。</p><p>push(x) — 将元素 x 推入栈中。<br>pop() — 删除栈顶的元素。<br>top() — 获取栈顶元素。<br>getMin() — 检索栈中的最小元素。<br>示例:</p><p>MinStack minStack = new MinStack();<br>minStack.push(-2);<br>minStack.push(0);<br>minStack.push(-3);<br>minStack.getMin(); —> 返回 -3.<br>minStack.pop();<br>minStack.top(); —> 返回 0.<br>minStack.getMin(); —> 返回 -2.</p><p>定义两个栈就好了。</p><h1 id="160-相交链表"><a href="#160-相交链表" class="headerlink" title="160. 相交链表"></a><a href="https://leetcode-cn.com/problems/intersection-of-two-linked-lists/" target="_blank" rel="noopener">160. 相交链表</a></h1><p>编写一个程序,找到两个单链表AB相交的起始节点。</p><p>快慢指针,每个指针循环指向,也就是快指针都对A循环结束后,紧接着对B开始循环,如此往复。而慢指针从B开始。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="comment">//返回相交的节点</span></span><br><span class="line"> <span class="function">ListNode *<span class="title">getIntersectionNode</span><span class="params">(ListNode *headA, ListNode *headB)</span> </span>{</span><br><span class="line"> ListNode* cur_a = headA;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">while</span> (cur_a)</span><br><span class="line"> {</span><br><span class="line"> ListNode* cur_b = headB;</span><br><span class="line"> <span class="keyword">while</span> (cur_b)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (cur_a == cur_b)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span> cur_a;</span><br><span class="line"> }</span><br><span class="line"> cur_b = cur_b->next;</span><br><span class="line"> }</span><br><span class="line"> cur_a = cur_a->next;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="literal">nullptr</span>;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h1 id="169-多数元素"><a href="#169-多数元素" class="headerlink" title="169. 多数元素"></a><a href="https://leetcode-cn.com/problems/majority-element/" target="_blank" rel="noopener">169. 多数元素</a></h1><p>给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。</p><p>你可以假设数组是非空的,并且给定的数组总是存在多数元素。</p><p>示例 1:</p><p>输入: [3,2,3]<br>输出: 3</p><p>示例 2:</p><p>输入: [2,2,1,1,1,2,2]<br>输出: 2</p><p>hash。定义个字典,key存num,value存出现的次数。如果出现的次数大于n/2,就返回该key。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">majorityElement</span><span class="params">(<span class="built_in">vector</span><<span class="keyword">int</span>>& nums)</span> </span>{</span><br><span class="line"> <span class="built_in">unordered_map</span> <<span class="keyword">int</span>,<span class="keyword">int</span>> hash;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> n:nums) </span><br><span class="line"> <span class="keyword">if</span>(++ hash[n] > nums.<span class="built_in">size</span>()/<span class="number">2</span>) <span class="keyword">return</span> n; </span><br><span class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h1 id="198-打家劫舍"><a href="#198-打家劫舍" class="headerlink" title="198. 打家劫舍"></a><a href="https://leetcode-cn.com/problems/house-robber/" target="_blank" rel="noopener">198. 打家劫舍</a></h1><p>你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。</p><p>给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。</p><p>示例 1:</p><p>输入: [1,2,3,1]<br>输出: 4<br>解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。<br> 偷窃到的最高金额 = 1 + 3 = 4 。</p><p>简单的动态规划。</p><ul><li>如果选择偷k号房,那么就不能偷k-1号房。就等于k-2及以前的最大值 + 本次偷的价值。</li><li>如果不偷,就是k-1及以前的价值。</li></ul><p>每次保存当前最优值就好。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">rob</span><span class="params">(<span class="built_in">vector</span><<span class="keyword">int</span>>& nums)</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="built_in">vector</span><<span class="keyword">int</span>> dp;</span><br><span class="line"> <span class="keyword">int</span> len = nums.<span class="built_in">size</span>();</span><br><span class="line"> <span class="keyword">if</span>(len==<span class="number">0</span>) <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (len==<span class="number">1</span>) <span class="keyword">return</span> nums[<span class="number">0</span>];</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"> dp.push_back(nums[<span class="number">0</span>]);</span><br><span class="line"> dp.push_back(<span class="built_in">max</span>(nums[<span class="number">0</span>],nums[<span class="number">1</span>]));</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">2</span>;i<len;i++){</span><br><span class="line"> dp.push_back( <span class="built_in">max</span>( dp[i<span class="number">-2</span>] + nums[i],dp[i<span class="number">-1</span>] ) );</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> dp[len<span class="number">-1</span>];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h1 id="206-反转链表"><a href="#206-反转链表" class="headerlink" title="206. 反转链表"></a><a href="https://leetcode-cn.com/problems/reverse-linked-list/" target="_blank" rel="noopener">206. 反转链表</a></h1><p>反转一个单链表。</p><p>示例:</p><p>输入: 1->2->3->4->5->NULL<br>输出: 5->4->3->2->1->NULL<br>进阶:<br>你可以迭代或递归地反转链表。你能否用两种方法解决这道题?</p><p>经典题目了。</p><p>迭代。定义两个指针,cur指向当前的值(初始化为NULL),pre(我给它一个命名,叫<strong>冲锋指针</strong>)指向下一个值。不断反向就好了。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function">ListNode* <span class="title">reverseList</span><span class="params">(ListNode* head)</span> </span>{</span><br><span class="line"> ListNode *cur = <span class="literal">NULL</span>, *pre = head;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span>(pre != <span class="literal">NULL</span>){</span><br><span class="line"></span><br><span class="line"> ListNode* t = pre->next;</span><br><span class="line"></span><br><span class="line"> pre->next = cur;</span><br><span class="line"> cur = pre;</span><br><span class="line"> pre = t;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> cur;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h1 id="226-翻转二叉树"><a href="#226-翻转二叉树" class="headerlink" title="226. 翻转二叉树"></a><a href="https://leetcode-cn.com/problems/invert-binary-tree/" target="_blank" rel="noopener">226. 翻转二叉树</a></h1><p>翻转一棵二叉树。</p><p>示例:</p><p>输入:</p><pre><code> 4 / \ 2 7 / \ / \1 3 6 9</code></pre><p>输出:</p><pre><code> 4 / \ 7 2 / \ / \9 6 3 1</code></pre><p>树的题目基本都是递归完成的了。</p><p>递归的思想其实就是把零散的步骤看成一个整体步骤。</p><p>对于一棵树来说,只需要交换root的左子树和右子树。(对于子树来说也是这样)</p><p>所以算法步骤也很简单</p><ul><li>如果树为NULL,则返回NULL。不需要操作它的子树了。</li><li>取左子树。</li><li>取右子树,</li><li>交换。</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function">TreeNode* <span class="title">invertTree</span><span class="params">(TreeNode* root)</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span>(root==<span class="literal">NULL</span>) <span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line"> </span><br><span class="line"> TreeNode* left = invertTree(root->left);</span><br><span class="line"> TreeNode* right = invertTree(root->right);</span><br><span class="line"></span><br><span class="line"> root->right = left;</span><br><span class="line"> root->left = right;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">return</span> root;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h1 id="234-回文链表"><a href="#234-回文链表" class="headerlink" title="234. 回文链表"></a><a href="https://leetcode-cn.com/problems/palindrome-linked-list/" target="_blank" rel="noopener">234. 回文链表</a></h1><p>请判断一个链表是否为回文链表。</p><p><strong>示例 1:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">输入: 1->2</span><br><span class="line">输出: false</span><br></pre></td></tr></table></figure><p><strong>示例 2:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">输入: 1->2->2->1</span><br><span class="line">输出: true</span><br></pre></td></tr></table></figure><p><strong>进阶:</strong><br>你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?</p><p>最粗暴的想法就是存在数组里面,再遍历看看是不是。</p><p>但是如果要满足O(1)复杂度,需要</p><ul><li>用快慢指针,快指针走两步,慢指针走一步,找到链表的中点。</li><li>翻转链表后半段。</li><li>通过两个指针来判断是否是回文链表。</li></ul><p>我觉得没有太大的意义。就不贴代码了。</p><h1 id="283-移动零"><a href="#283-移动零" class="headerlink" title="283. 移动零"></a><a href="https://leetcode-cn.com/problems/move-zeroes/" target="_blank" rel="noopener">283. 移动零</a></h1><p>给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。</p><p>示例:</p><p>输入: [0,1,0,3,12]<br>输出: [1,3,12,0,0]<br>说明:</p><p>必须在原数组上操作,不能拷贝额外的数组。<br>尽量减少操作次数。</p><p>我的第一思路是冒泡排序的思路,O(n2)。</p><p>也可以遇到0就删掉,最后补充。</p><p>但作为算法,</p><ul><li>定义一个count计算非零量。</li><li>nums[count++] = nums[i](当前值),就是往前赋值。</li><li>最后末尾赋值为0</li></ul><h1 id="路径总和-III-有点难"><a href="#路径总和-III-有点难" class="headerlink" title="路径总和 III - 有点难"></a><a href="https://leetcode-cn.com/problems/path-sum-iii/" target="_blank" rel="noopener">路径总和 III</a> - 有点难</h1><p>给定一个二叉树,它的每个结点都存放着一个整数值。</p><p>找出路径和等于给定数值的路径总数。</p><p>路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。</p><p>二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8</span><br><span class="line"></span><br><span class="line"> 10</span><br><span class="line"> / \</span><br><span class="line"> 5 -3</span><br><span class="line"> / \ \</span><br><span class="line"> 3 2 11</span><br><span class="line"> / \ \</span><br><span class="line">3 -2 1</span><br><span class="line"></span><br><span class="line">返回 3。和等于 8 的路径有:</span><br><span class="line"></span><br><span class="line">1. 5 -> 3</span><br><span class="line">2. 5 -> 2 -> 1</span><br><span class="line">3. -3 -> 11</span><br></pre></td></tr></table></figure><p>这个还是没想明白。先留坑。</p><h1 id="448-找到所有数组中消失的数字"><a href="#448-找到所有数组中消失的数字" class="headerlink" title="448. 找到所有数组中消失的数字"></a><a href="https://leetcode-cn.com/problems/find-all-numbers-disappeared-in-an-array/" target="_blank" rel="noopener">448. 找到所有数组中消失的数字</a></h1><p>给定一个范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次。</p><p>找到所有在 [1, n] 范围之间没有出现在数组中的数字。</p><p>您能在不使用额外空间且时间复杂度为O(n)的情况下完成这个任务吗? 你可以假定返回的数组不算在额外空间内。</p><p>示例:</p><p>输入:<br>[4,3,2,7,8,2,3,1]</p><p>输出:<br>[5,6]</p><p>对出现的值,对其值表示的index上的值加一个offset代表这个值出现过。</p><p>再一个遍历看看哪个值没有超过这个offset,就知道缺谁了。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="built_in">vector</span><<span class="keyword">int</span>> <span class="title">findDisappearedNumbers</span><span class="params">(<span class="built_in">vector</span><<span class="keyword">int</span>>& nums)</span> </span>{</span><br><span class="line"> <span class="built_in">vector</span><<span class="keyword">int</span>> res;</span><br><span class="line"> <span class="keyword">if</span>(nums.empty()) <span class="keyword">return</span> nums;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i<nums.<span class="built_in">size</span>();i++)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">int</span> index=(nums[i]<span class="number">-1</span>)%nums.<span class="built_in">size</span>();</span><br><span class="line"> nums[index]+=nums.<span class="built_in">size</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i<nums.<span class="built_in">size</span>();i++)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span>(nums[i]<=nums.<span class="built_in">size</span>())</span><br><span class="line"> res.push_back(i+<span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> res;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h1 id="543-二叉树的直径"><a href="#543-二叉树的直径" class="headerlink" title="543. 二叉树的直径"></a><a href="https://leetcode-cn.com/problems/diameter-of-binary-tree/" target="_blank" rel="noopener">543. 二叉树的直径</a></h1><p>给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。</p><p>示例 :<br>给定二叉树返回 <strong>3</strong>, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"> 1</span><br><span class="line"> / \</span><br><span class="line"> 2 3</span><br><span class="line"> / \ </span><br><span class="line">4 5</span><br></pre></td></tr></table></figure><p>经典树的遍历了。</p><ul><li><p>正常计算深度。max( 左子树深度,右子树深度) +1</p></li><li><p>定义一个类变量maxD,计算所有遍历里面最大的直径,即 maxD = max(maxD, 左子树深度 + 右子树深度 )</p></li></ul><p>我用了一个更复杂的传多个值的方式实现,传深度和子节点最大的直径,贴一下吧。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">diameterOfBinaryTree</span><span class="params">(TreeNode* root)</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span>(root ==<span class="literal">NULL</span>)<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">else</span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">auto</span> a = helper(root->left);</span><br><span class="line"> <span class="keyword">auto</span> b = helper(root->right);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">int</span> diameter = <span class="built_in">max</span>(<span class="built_in">max</span>( a[<span class="number">1</span>],b[<span class="number">1</span>]),a[<span class="number">0</span>] + b[<span class="number">0</span>] );</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> diameter;</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="built_in">vector</span><<span class="keyword">int</span>> <span class="title">helper</span><span class="params">(TreeNode* root)</span></span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span>(root ==<span class="literal">NULL</span>)<span class="keyword">return</span> {<span class="number">0</span>,<span class="number">0</span>};</span><br><span class="line"> <span class="keyword">else</span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">auto</span> a = helper(root->left);</span><br><span class="line"> <span class="keyword">auto</span> b = helper(root->right);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">int</span> depth = <span class="built_in">max</span>(a[<span class="number">0</span>],b[<span class="number">0</span>]) + <span class="number">1</span> ;</span><br><span class="line"> <span class="keyword">int</span> diameter = <span class="built_in">max</span>(<span class="built_in">max</span>( a[<span class="number">1</span>],b[<span class="number">1</span>]),a[<span class="number">0</span>] + b[<span class="number">0</span>] );</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> {depth,diameter};</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h1 id="581-最短无序连续子数组"><a href="#581-最短无序连续子数组" class="headerlink" title="581. 最短无序连续子数组"></a><a href="https://leetcode-cn.com/problems/shortest-unsorted-continuous-subarray/" target="_blank" rel="noopener">581. 最短无序连续子数组</a></h1><p>给定一个整数数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。</p><p>你找到的子数组应是最短的,请输出它的长度。</p><p>示例 1:</p><p>输入: [2, 6, 4, 8, 10, 9, 15]<br>输出: 5<br>解释: 你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。<br>说明 :</p><p>输入的数组长度范围在 [1, 10,000]。<br>输入的数组可能包含重复元素 ,所以升序的意思是<=。</p><p>先排序是最快的做法。</p><p>但如果最好不排序,那寻找左右两边的privot值。</p><p>要保证整个数组是升序的,就不能出现峰值。</p><ul><li>左privot:最早出现的(从左到右)同时大于两边值的index</li><li>右privot:最早出现的(从右到左)同时小于两边值的index</li></ul><p>统计两个privot之间有多少个元素就可以了。</p><h1 id="617-合并二叉树"><a href="#617-合并二叉树" class="headerlink" title="617. 合并二叉树"></a><a href="https://leetcode-cn.com/problems/merge-two-binary-trees/" target="_blank" rel="noopener">617. 合并二叉树</a></h1><p>给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。</p><p>你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">输入: </span><br><span class="line">Tree 1 Tree 2 </span><br><span class="line"> 1 2 </span><br><span class="line"> / \ / \ </span><br><span class="line"> 3 2 1 3 </span><br><span class="line"> / \ \ </span><br><span class="line"> 5 4 7 </span><br><span class="line">输出: </span><br><span class="line">合并后的树:</span><br><span class="line"> 3</span><br><span class="line"> / \</span><br><span class="line"> 4 5</span><br><span class="line"> / \ \ </span><br><span class="line"> 5 4 7</span><br></pre></td></tr></table></figure><p>遇到树一般都是递归。</p><ul><li><p>如果t1或t2为空,就返回NULL。</p></li><li><p>如果都不为空,就将t2的值加到了t1</p></li><li>如果t1左节点为空,就t1->left指向t2->left。</li><li>如果t1右节点为空,就t1->right指向t2->right。</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function">TreeNode* <span class="title">mergeTrees</span><span class="params">(TreeNode* t1, TreeNode* t2)</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span>(t1==<span class="literal">NULL</span>) <span class="keyword">return</span> t2;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (t2==<span class="literal">NULL</span>) <span class="keyword">return</span> t1;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">return</span> help(t1,t2);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function">TreeNode* <span class="title">help</span><span class="params">(TreeNode* t1, TreeNode* t2)</span></span>{</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"> <span class="comment">//存在为空</span></span><br><span class="line"> <span class="keyword">if</span>(t1 == <span class="literal">NULL</span> || t2==<span class="literal">NULL</span>) <span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//都不为空</span></span><br><span class="line"> <span class="keyword">if</span>( t1 != <span class="literal">NULL</span> && t2 !=<span class="literal">NULL</span> )</span><br><span class="line"> t1->val += t2->val;</span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> ( help(t1->left,t2->left) ==<span class="literal">NULL</span>){</span><br><span class="line"> <span class="keyword">if</span>( t1->left == <span class="literal">NULL</span> )</span><br><span class="line"> t1->left = t2->left;</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> ( help(t1->right,t2->right) ==<span class="literal">NULL</span>){</span><br><span class="line"> <span class="keyword">if</span>( t1->right == <span class="literal">NULL</span> )</span><br><span class="line"> t1->right = t2->right;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> t1;</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">};</span><br></pre></td></tr></table></figure><p>看到解答里面有更清晰的思路,有那个合并多个链表的感觉。</p><p>值得学习一下。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function">TreeNode* <span class="title">mergeTrees</span><span class="params">(TreeNode* t1, TreeNode* t2)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(t1==<span class="literal">nullptr</span> && t2==<span class="literal">nullptr</span>) <span class="keyword">return</span> <span class="literal">nullptr</span>;</span><br><span class="line"> <span class="keyword">if</span>(t1==<span class="literal">nullptr</span>) <span class="keyword">return</span> t2;</span><br><span class="line"> <span class="keyword">if</span>(t2==<span class="literal">nullptr</span>) <span class="keyword">return</span> t1;</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> t1->val += t2->val;</span><br><span class="line"> t1->left = mergeTrees(t1->left, t2->left);</span><br><span class="line"> t1->right = mergeTrees(t1->right, t2->right);</span><br><span class="line"> <span class="keyword">return</span> t1;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>这两天把Leetcode的 <a href="https://leetcode.com/problemset/top-100-liked-q
</summary>
<category term="编程" scheme="http://jaxchan.top/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="保研" scheme="http://jaxchan.top/categories/%E7%BC%96%E7%A8%8B/%E4%BF%9D%E7%A0%94/"/>
<category term="OJ" scheme="http://jaxchan.top/tags/OJ/"/>
<category term="C++" scheme="http://jaxchan.top/tags/C/"/>
<category term="leetcode" scheme="http://jaxchan.top/tags/leetcode/"/>
</entry>
<entry>
<title>Oj上手:基本题型和思路</title>
<link href="http://jaxchan.top/2020/Oj%E4%B8%8A%E6%89%8B%EF%BC%9A%E5%9F%BA%E6%9C%AC%E9%A2%98%E5%9E%8B%E5%92%8C%E6%80%9D%E8%B7%AF.html/"/>
<id>http://jaxchan.top/2020/Oj%E4%B8%8A%E6%89%8B%EF%BC%9A%E5%9F%BA%E6%9C%AC%E9%A2%98%E5%9E%8B%E5%92%8C%E6%80%9D%E8%B7%AF.html/</id>
<published>2020-03-29T08:48:52.000Z</published>
<updated>2020-03-29T08:51:54.170Z</updated>
<content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>最近花了个四五天的时间看完了 <a href="http://www.cskaoyan.com/thread-647811-1-1.html" target="_blank" rel="noopener">《计算机考研—机试指南》</a> ,也算是大概入门了一下OJ。写一下入门笔记,以免反复查看,后来又忘掉。</p><p>这个书看起来很贴心,很详尽。但不一定十分适用,但用来入门还是很好的。毕竟学习是循序渐进的过程。</p><p>还用到了以下的入门资料:</p><p><a href="https://zhuanlan.zhihu.com/p/32685223" target="_blank" rel="noopener">总结 visual studio 手把手教刷 oj 的使用技巧</a></p><p><a href="https://jingyan.baidu.com/article/3ea51489933c0952e71bba52.html" target="_blank" rel="noopener">Visual Studio(VS2017)如何解决scanf的C4996错误?</a></p><p>再贴上一段王小波的话,</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">那一天我二十一岁,在我一生的黄金时代,我有好多奢望,我想爱,想吃,还想在一瞬间变成天上半明半暗的云,后来我才知道,生活就是个缓慢受锤的过程,人一天天老下去,奢望也一天天消逝,最后变得像挨了锤的牛一样,可是我过二十一岁生日时没有预见到这一点,我觉得自己会永远生猛下去,什么也锤不了我。</span><br></pre></td></tr></table></figure><hr><h1 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h1><ol><li>scanf会留换行符在缓冲区。接gets()的时候,要先加getchar()清掉换行符。</li><li>做题记得先计算时间复杂度。</li><li>不要在程序中混用printf 和cout,由于它们的输出机理不同,混用将非常<br>容易造成错误。</li></ol><h1 id="复杂度估计"><a href="#复杂度估计" class="headerlink" title="复杂度估计"></a>复杂度估计</h1><p>程序1 秒的运行时限,这也是最常见的时间限制。</p><p>所设计的算法复杂度不能超过百万级别,即不能超过一千万。即若算法的时间复杂度是O(n^2),<br>则该n(往往在题目中会给出数据范围)不应大于3000。</p><h1 id="入门问题"><a href="#入门问题" class="headerlink" title="入门问题"></a>入门问题</h1><h2 id="排序"><a href="#排序" class="headerlink" title="排序"></a>排序</h2><p>用快排。</p><p>自定义排序方法</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><algorithm></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"><span class="function"><span class="keyword">bool</span> <span class="title">cmp</span><span class="params">(<span class="keyword">int</span> a,<span class="keyword">int</span> b)</span> </span>{ </span><br><span class="line"> <span class="keyword">return</span> a<b }</span><br><span class="line"></span><br><span class="line">sort (buf,buf + n,cmp);</span><br></pre></td></tr></table></figure><p>结构体排序</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><algorithm></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><string.h></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">E</span> {</span></span><br><span class="line"><span class="keyword">char</span> name[<span class="number">101</span>];</span><br><span class="line"><span class="keyword">int</span> age;</span><br><span class="line"><span class="keyword">int</span> score;</span><br><span class="line"><span class="keyword">bool</span> <span class="keyword">operator</span> < (<span class="keyword">const</span> E &b) <span class="keyword">const</span> { </span><br><span class="line"> <span class="keyword">if</span> (score != b.score) <span class="keyword">return</span> score < b.score;</span><br><span class="line"> <span class="keyword">int</span> tmp = <span class="built_in">strcmp</span>(name,b.name);</span><br><span class="line"> <span class="keyword">if</span> (tmp != <span class="number">0</span>) <span class="keyword">return</span> tmp < <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">return</span> age < b.age;</span><br><span class="line">}</span><br><span class="line">}buf[<span class="number">1000</span>];</span><br><span class="line"></span><br><span class="line">sort(buf,buf + n);</span><br></pre></td></tr></table></figure><h2 id="日期类问题"><a href="#日期类问题" class="headerlink" title="日期类问题"></a>日期类问题</h2><h3 id="英文单词"><a href="#英文单词" class="headerlink" title="英文单词"></a>英文单词</h3><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">char</span> monthName[<span class="number">13</span>][<span class="number">20</span>] = {</span><br><span class="line"><span class="string">""</span>,</span><br><span class="line"><span class="string">"January"</span>,</span><br><span class="line"><span class="string">"February"</span>,</span><br><span class="line"><span class="string">"March"</span>,</span><br><span class="line"><span class="string">"April"</span>,</span><br><span class="line"><span class="string">"May"</span>,</span><br><span class="line"><span class="string">"June"</span>,</span><br><span class="line"><span class="string">"July"</span>,</span><br><span class="line"><span class="string">"August"</span>,</span><br><span class="line"><span class="string">"September"</span>,</span><br><span class="line"><span class="string">"October"</span>,</span><br><span class="line"><span class="string">"November"</span>,</span><br><span class="line"><span class="string">"December"</span></span><br><span class="line">}; <span class="comment">//月名每个月名对应下标1到12</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">char</span> weekName[<span class="number">7</span>][<span class="number">20</span>] = {</span><br><span class="line"><span class="string">"Sunday"</span>,</span><br><span class="line"><span class="string">"Monday"</span>,</span><br><span class="line"><span class="string">"Tuesday"</span>,</span><br><span class="line"><span class="string">"Wednesday"</span>,</span><br><span class="line"><span class="string">"Thursday"</span>,</span><br><span class="line"><span class="string">"Friday"</span>,</span><br><span class="line"><span class="string">"Saturday"</span></span><br><span class="line">}; <span class="comment">//周名每个周名对应下标0到6</span></span><br></pre></td></tr></table></figure><h3 id="闰年"><a href="#闰年" class="headerlink" title="闰年"></a>闰年</h3><p>闰年,每逢闰年2 月将会有29 天。</p><p>当年数不能被100 整除时若其能被4 整除则为闰年,或者其能被400 整除时也是闰年。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">define</span> ISYEAP(x) x % 100 != 0 && x % 4 == 0 || x % 400 == 0 ? 1 : 0</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> dayOfMonth[<span class="number">13</span>][<span class="number">2</span>] = {</span><br><span class="line"><span class="number">0</span>,<span class="number">0</span>,</span><br><span class="line"><span class="number">31</span>,<span class="number">31</span>,</span><br><span class="line"><span class="number">28</span>,<span class="number">29</span>,</span><br><span class="line"><span class="number">31</span>,<span class="number">31</span>,</span><br><span class="line"><span class="number">30</span>,<span class="number">30</span>,</span><br><span class="line"><span class="number">31</span>,<span class="number">31</span>,</span><br><span class="line"><span class="number">30</span>,<span class="number">30</span>,</span><br><span class="line"><span class="number">31</span>,<span class="number">31</span>,</span><br><span class="line"><span class="number">31</span>,<span class="number">31</span>,</span><br><span class="line"><span class="number">30</span>,<span class="number">30</span>,</span><br><span class="line"><span class="number">31</span>,<span class="number">31</span>,</span><br><span class="line"><span class="number">30</span>,<span class="number">30</span>,</span><br><span class="line"><span class="number">31</span>,<span class="number">31</span></span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">Date</span> {</span> <span class="comment">//日期类,方便日期的推移</span></span><br><span class="line"><span class="keyword">int</span> Day;</span><br><span class="line"><span class="keyword">int</span> Month;</span><br><span class="line"><span class="keyword">int</span> Year;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">nextDay</span><span class="params">()</span> </span>{ <span class="comment">//计算下一天的日期</span></span><br><span class="line"> Day ++;</span><br><span class="line"> <span class="keyword">if</span> (Day > dayOfMonth[Month][ ISYEAP(Year) ]) { </span><br><span class="line"> Day = <span class="number">1</span>;</span><br><span class="line"> Month ++; <span class="comment">//进入下一月</span></span><br><span class="line"> <span class="keyword">if</span> (Month > <span class="number">12</span>) { <span class="comment">//月数超过12</span></span><br><span class="line"> Month = <span class="number">1</span>;</span><br><span class="line"> Year ++; <span class="comment">//进入下一年</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h1 id="数据结构"><a href="#数据结构" class="headerlink" title="数据结构"></a>数据结构</h1><h2 id="栈Stack"><a href="#栈Stack" class="headerlink" title="栈Stack"></a>栈Stack</h2><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stack></span></span></span><br><span class="line"><span class="keyword">using</span> namesapce <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="built_in">stack</span><<span class="keyword">int</span>> S;</span><br><span class="line"></span><br><span class="line">S.push(i);</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> x = S.top();</span><br><span class="line">S.pop(); <span class="comment">//弹出</span></span><br></pre></td></tr></table></figure><h3 id="计算器"><a href="#计算器" class="headerlink" title="计算器"></a>计算器</h3><p>读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。</p><p>思路:<br>1.设立两个堆栈,一个用来保存运算符,另一个用来保存数字。<br>2.在表达式首尾添加标记运算符,该运算符运算优先级最低。<br>3.从左至右依次遍历字符串,若遍历到运算符,则将其与运算符栈栈顶元素<br>进行比较,若运算符栈栈顶运算符优先级小于该运算符或者此时运算符栈为空,<br>则将该运算符压入堆栈。遍历字符串中下一个元素。<br>4.若运算符栈栈顶运算符优先级大于该运算符,则弹出该栈顶运算符,再从<br>数字栈中依次弹出两个栈顶数字,完成弹出的运算符对应的运算得到结果后,再<br>将该结果压入数字栈,重复比较此时栈顶运算符与当前遍历到的运算符优先级,<br>视其优先级大小重复步骤3 或步骤4。<br>5.若遍历到表达式中的数字,则直接压入数字栈。<br>6.若运算符堆栈中仅存有两个运算符且栈顶元素为我们人为添加的标记运<br>算符,那么表达式运算结束,此时数字堆栈中唯一的数字即为表达式的值。</p><h2 id="优先队列"><a href="#优先队列" class="headerlink" title="优先队列"></a>优先队列</h2><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><queue></span></span></span><br><span class="line"></span><br><span class="line">priority_queue<<span class="keyword">int</span>> Q; <span class="comment">//最大堆</span></span><br><span class="line">priority_queue<<span class="keyword">int</span> , <span class="built_in">vector</span><<span class="keyword">int</span>> , greater<<span class="keyword">int</span>> > Q; <span class="comment">//最小堆</span></span><br><span class="line"></span><br><span class="line">Q.push(x);</span><br><span class="line"><span class="keyword">int</span> a = Q.top();</span><br><span class="line">Q.pop();</span><br></pre></td></tr></table></figure><h3 id="哈夫曼树"><a href="#哈夫曼树" class="headerlink" title="哈夫曼树"></a>哈夫曼树</h3><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">while</span>(Q.<span class="built_in">size</span>() > <span class="number">1</span>) { <span class="comment">//当堆中元素大于1个</span></span><br><span class="line"> <span class="keyword">int</span> a = Q.top();</span><br><span class="line"> Q.pop();</span><br><span class="line"> <span class="keyword">int</span> b = Q.top();</span><br><span class="line"> Q.pop(); <span class="comment">//取出堆中两个最小元素,他们为同一个结点的左右儿子,且该双亲结点</span></span><br><span class="line"> 的权值为它们的和</span><br><span class="line"> ans += a + b; <span class="comment">//该父亲结点必为非叶子结点,固累加其权值</span></span><br><span class="line"> Q.push(a + b); <span class="comment">//将该双亲结点的权值放回堆中</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="二叉树"><a href="#二叉树" class="headerlink" title="二叉树"></a>二叉树</h2><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">Node</span> {</span></span><br><span class="line">Node *lchild; <span class="comment">//指向其左儿子结点的指针,当其不存在左儿子时为NULL</span></span><br><span class="line">Node *rchild; <span class="comment">//指向其右儿子结点的指针,当其不存在右儿子时为NULL</span></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">*</span></span><br><span class="line"><span class="comment">*</span></span><br><span class="line"><span class="comment">其它结点信息*/</span></span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">preOrder</span> <span class="params">(Node *Tree)</span> </span>{</span><br><span class="line"> </span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%c"</span>,T -> c); <span class="comment">//遍历该结点,输出其字符信息</span></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (Tree -> lchild != <span class="literal">NULL</span>) <span class="comment">//递归遍历左子树</span></span><br><span class="line"> inOrder(Tree -> lchild);</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (Tree -> rchild != <span class="literal">NULL</span>) <span class="comment">//递归遍历右子树</span></span><br><span class="line"> inOrder(Tree -> rchild);</span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">inOrder</span> <span class="params">(Node *Tree)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (Tree -> lchild != <span class="literal">NULL</span>) <span class="comment">//递归遍历左子树</span></span><br><span class="line"> inOrder(Tree -> lchild);</span><br><span class="line"></span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%c"</span>,T -> c); <span class="comment">//遍历该结点,输出其字符信息</span></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (Tree -> rchild != <span class="literal">NULL</span>) <span class="comment">//递归遍历右子树</span></span><br><span class="line"> inOrder(Tree -> rchild);</span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">postOrder</span><span class="params">(Node *T)</span> </span>{ <span class="comment">//后序遍历</span></span><br><span class="line"> <span class="keyword">if</span> (T -> lchild != <span class="literal">NULL</span>) { <span class="comment">//若左子树不为空</span></span><br><span class="line"> postOrder(T -> lchild); <span class="comment">//递归遍历其左子树</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (T -> rchild != <span class="literal">NULL</span>) { <span class="comment">//若右子树不为空</span></span><br><span class="line"> postOrder(T -> rchild); <span class="comment">//递归遍历其右子树</span></span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%c"</span>,T -> c); <span class="comment">//遍历该结点,输出其字符信息</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="数论"><a href="#数论" class="headerlink" title="数论"></a>数论</h2><h3 id="最大公约数(GCD)"><a href="#最大公约数(GCD)" class="headerlink" title="最大公约数(GCD)"></a>最大公约数(GCD)</h3><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">gcd</span><span class="params">(<span class="keyword">int</span> a,<span class="keyword">int</span> b)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (b == <span class="number">0</span>) <span class="keyword">return</span> a; <span class="comment">//若b为零则最大公约数为a</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">return</span> gcd(b,a % b); <span class="comment">//否则,则改为求b与a%b的最大公约数</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="最小公倍数(LCM)"><a href="#最小公倍数(LCM)" class="headerlink" title="最小公倍数(LCM)"></a>最小公倍数(LCM)</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">a * b / gcd(a,b)</span><br></pre></td></tr></table></figure><h3 id="质数筛选"><a href="#质数筛选" class="headerlink" title="质数筛选"></a>质数筛选</h3><h4 id="判断单个数值是否为质数"><a href="#判断单个数值是否为质数" class="headerlink" title="判断单个数值是否为质数"></a>判断单个数值是否为质数</h4><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">bool</span> <span class="title">judge</span><span class="params">(<span class="keyword">int</span> x)</span> </span>{ <span class="comment">//判断一个数是否为素数</span></span><br><span class="line"> <span class="keyword">if</span> (x <= <span class="number">1</span>) <span class="keyword">return</span> <span class="literal">false</span>; <span class="comment">//若其小于等于1,必不是</span></span><br><span class="line"> <span class="keyword">int</span> bound = (<span class="keyword">int</span>)<span class="built_in">sqrt</span>(x) + <span class="number">1</span>; </span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">2</span>;i < bound;i ++) </span><br><span class="line"> <span class="keyword">if</span> (x % i == <span class="number">0</span>) <span class="keyword">return</span> <span class="literal">false</span>; <span class="comment">//依次枚举这些数能否整除x,若能则必不为素数</span></span><br><span class="line"> </span><br><span class="line"><span class="keyword">return</span> <span class="literal">true</span>; <span class="comment">//若均不能则为素数</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="对区间进行质数排查"><a href="#对区间进行质数排查" class="headerlink" title="对区间进行质数排查"></a>对区间进行质数排查</h4><p>对给定区间,产生该区间内的所有素数</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></span><br><span class="line"><span class="keyword">int</span> prime[<span class="number">10000</span>]; <span class="comment">//保存筛得的素数</span></span><br><span class="line"><span class="keyword">int</span> primeSize; <span class="comment">//保存的素数的个数</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">init</span><span class="params">()</span> </span>{ <span class="comment">//素数筛法</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>;i <= <span class="number">10000</span>;i ++) {</span><br><span class="line"> mark[i] = <span class="literal">false</span>;</span><br><span class="line"> } <span class="comment">//初始化,所有数字均没被标记</span></span><br><span class="line"></span><br><span class="line"> primeSize = <span class="number">0</span>; <span class="comment">//得到的素数个数为0</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">2</span>;i <= <span class="number">10000</span>;i ++) { <span class="comment">//依次遍历2到10000所有数字</span></span><br><span class="line"> <span class="keyword">if</span> (mark[i] == <span class="literal">true</span>) <span class="keyword">continue</span>; <span class="comment">//若该数字已经被标记,则跳过</span></span><br><span class="line"> prime[primeSize ++] = i; <span class="comment">//否则,又新得到一个新素数</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> j = i * i;j <= <span class="number">10000</span>;j += i) { <span class="comment">//并将该数的所有倍数均标记成非素数</span></span><br><span class="line"> mark[j] = <span class="literal">true</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="二分求幂"><a href="#二分求幂" class="headerlink" title="二分求幂"></a>二分求幂</h2><script type="math/tex; mode=display">\begin{aligned}&2^{31}=2^{1} * 2^{30}\\&=2^{1} * 2^{2 *} 2^{28}\\&=2^{1} * 2^{2} * 2^{4} * 2^{8} * 2^{16}\end{aligned}</script><h2 id="大数"><a href="#大数" class="headerlink" title="大数"></a>大数</h2><p>暂且放下,毕竟JAVA完美支持。</p><h2 id="图论"><a href="#图论" class="headerlink" title="图论"></a>图论</h2><p>图的表示有矩阵,也有链表。</p><h2 id="图的表示"><a href="#图的表示" class="headerlink" title="图的表示"></a>图的表示</h2><p>下面用vector代替链表实现。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><vector></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>; <span class="comment">//声明使用标准命名空间</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">Edge</span> {</span></span><br><span class="line"> <span class="keyword">int</span> nextNode;<span class="comment">//下一个结点编号</span></span><br><span class="line"> <span class="keyword">int</span> cost;<span class="comment">//该边的权重</span></span><br><span class="line"> Edge(<span class="keyword">int</span> nextNode,<span class="keyword">int</span> cost):nextNode(nextNode),cost(cost){}</span><br><span class="line"> </span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="built_in">vector</span><Edge> edge[N]; <span class="comment">//结点数量为N</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>;i < N;i ++) { <span class="comment">//遍历所有结点</span></span><br><span class="line"> edge[i].<span class="built_in">clear</span>(); <span class="comment">//清空其单链表</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//Insert</span></span><br><span class="line">edge[<span class="number">1</span>].push_back(Edge(<span class="number">1</span>,<span class="number">2</span>));</span><br><span class="line"></span><br><span class="line"><span class="comment">//读</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>;i < edge[<span class="number">2</span>].<span class="built_in">size</span>();i ++) { <span class="comment">//对edge[2]进行遍历,即对所有与结点2相邻的边进行遍历,edge[2].size()表示其大小</span></span><br><span class="line"> <span class="keyword">int</span> nextNode = edge[<span class="number">2</span>][i].nextNode; <span class="comment">//读出邻接结点</span></span><br><span class="line"> <span class="keyword">int</span> cost = edge[<span class="number">2</span>][i].cost; <span class="comment">//读出该边权值</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//删</span></span><br><span class="line">edge[<span class="number">1</span>].erase(edge[<span class="number">1</span>].<span class="built_in">begin</span>() + i,edge[<span class="number">1</span>].<span class="built_in">begin</span>() + i + <span class="number">1</span>);<span class="comment">// 即vector.erase(vector.begin() + 第一个要删除的元素编号,vector.begin() + 最后一个要删除元素的编号 + 1</span></span><br></pre></td></tr></table></figure><h2 id="前置知识-并查集"><a href="#前置知识-并查集" class="headerlink" title="前置知识: 并查集"></a>前置知识: 并查集</h2><p>这种数据结构用来表示集合信息,用以实现如确定某个集合含有哪些元素、判断某两个元素是否存在同一个集合中、求集合中元素的数量等问题。</p><p>要判断两个数字是否在一个集合中,我们只需判断它们是否在同一棵树中。则记录每一个node的root即可。</p><p>但同时,需要添加路径压缩,否则可能会退化成链表。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//用Tree[i]来表示结点i的父结点</span></span><br><span class="line"><span class="comment">//若Tree[i]为-1 则表示该结点不存在父结点,即结点i 为其所在树的根结点。</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> Tree[N]; <span class="comment">//所有的集合元素个数总和为N</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//根据父节点,查找树的根节点</span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">findRoot</span><span class="params">(<span class="keyword">int</span> x)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (Tree[x] == <span class="number">-1</span>) <span class="keyword">return</span> x; <span class="comment">//若当前结点为根结点则返回该结点号</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">return</span> findRoot(Tree[x]); <span class="comment">//否则递归查找其双亲结点的根结点</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//添加路径压缩,即所有的结点都指向所在树的根节点</span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">findRoot</span><span class="params">(<span class="keyword">int</span> x)</span> </span>{</span><br><span class="line"><span class="keyword">if</span> (Tree[x] == <span class="number">-1</span>) <span class="keyword">return</span> x;</span><br><span class="line"><span class="keyword">else</span> <span class="keyword">return</span> Tree[x] = findRoot(Tree[x]);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="最小生成树"><a href="#最小生成树" class="headerlink" title="最小生成树"></a>最小生成树</h2><p>Kruskal算法</p><ol><li><p>初始时所有结点属于孤立的集合。</p></li><li><p>按照<strong>边权递增</strong>顺序遍历所有的边,</p><p>若遍历到的边两个顶点仍分属不同的集合(该边即为连通这两个集合的边中权值最小的那条)则确定该边为最小生成树上的一条边,并将这两个顶点分属的集合合并。</p></li><li><p>遍历完所有边后,原图上所有结点属于同一个集合则被选取的边和原图中所有结点构成最小生成树;否则原图不连通,最小生成树不存在。</p></li></ol><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> ans = <span class="number">0</span>; <span class="comment">//最小生成树上边权的和,初始值为0</span></span><br><span class="line"><span class="comment">//n为结点数</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>;i <= n * (n - <span class="number">1</span>) / <span class="number">2</span>;i ++) { <span class="comment">//按照边权值递增顺序遍历所有的边</span></span><br><span class="line"> <span class="keyword">int</span> a = findRoot(edge[i].a);</span><br><span class="line"> <span class="keyword">int</span> b = findRoot(edge[i].b); <span class="comment">//查找该边两个顶点的集合信息</span></span><br><span class="line"> <span class="keyword">if</span> (a != b) { <span class="comment">//若它们属于不同集合,则选用该边</span></span><br><span class="line"> Tree[a] = b; <span class="comment">//合并两个集合</span></span><br><span class="line"> ans += edge[i].cost; <span class="comment">//累加该边权值</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="最短路径"><a href="#最短路径" class="headerlink" title="最短路径"></a>最短路径</h2><p>Floyd 算法: 只允许通过前k个结点,寻找更短的路径。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> k = <span class="number">1</span>;k <= n;k ++) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>;i <= n;i ++) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">1</span>;j <= n;j ++) {</span><br><span class="line"> <span class="keyword">if</span> (ans[i][k] == 无穷 || ans[k][j] == 无穷) <span class="keyword">continue</span>;</span><br><span class="line"> <span class="keyword">if</span> (ans[i][j] == 无穷 || ans[i][k] + ans[k][j] < ans[i][j])</span><br><span class="line"> ans[i][j] = ans[i][k] + ans[k][j];</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Dijkstra算法(解决单源最短路路径问题):</p><ol><li><p>初始化,集合K 中加入结点1,结点1 到结点1最短距离为0,到其它结点为无穷(或不确定)。</p></li><li><p>遍历与集合K 中结点直接相邻的边(U,V,C),其中U 属于集合K,V不属于集合K,</p><p>计算由结点1 出发按照已经得到的最短路到达U,再由U 经过<br>该边到达V 时的路径长度。比较所有与集合K 中结点直接相邻的非集合K 结点<br>该路径长度,其中路径长度最小的结点被确定为下一个最短路径确定的结点,其<br>最短路径长度即为这个路径长度,最后将该结点加入集合K。</p></li><li><p>若集合K 中已经包含了所有的点,算法结束;否则重复步骤2。</p></li></ol><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">bool</span> mark[<span class="number">101</span>];<span class="comment">//标记,当mark[j]为true时表示结点j的最短路径长度已经得到,该结点已经加入集合K</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> Dis[<span class="number">101</span>]; <span class="comment">//距离向量,当mark[i]为true时,表示已得的最短路径长度;否则,表示所有从结点1出发,经过已知的最短路径达到集合K中的某结点,再经过一条边到达结点i的路径中最短的距离</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>;i <= n;i ++) { <span class="comment">//初始化</span></span><br><span class="line"> Dis[i] = <span class="number">-1</span>; <span class="comment">//所有距离为-1,即不可达</span></span><br><span class="line"> mark[i] = <span class="literal">false</span>; <span class="comment">//所有结点不属于集合K</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> newP = <span class="number">1</span>; <span class="comment">//集合K中新加入的点为结点1</span></span><br><span class="line">Dis[newP] = <span class="number">0</span>; <span class="comment">//得到最近的点为结点1,长度为0</span></span><br><span class="line">mark[newP] = <span class="literal">true</span>; <span class="comment">//将结点1加入集合K</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>;i < n;i ++) { <span class="comment">//循环n-1次,按照最短路径递增的顺序确定其他n-1个点的最短路径长度</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>;j < edge[newP].<span class="built_in">size</span>();j ++) { <span class="comment">//遍历与该新加入集合K中的结点直接相邻的边</span></span><br><span class="line"> <span class="keyword">int</span> t = edge[newP][j].next; <span class="comment">//该边的另一个结点</span></span><br><span class="line"> <span class="keyword">int</span> c = edge[newP][j].c; <span class="comment">//该边的长度</span></span><br><span class="line"> <span class="keyword">if</span> (mark[t] == <span class="literal">true</span>) <span class="keyword">continue</span>; <span class="comment">//若另一个结点也属于集合K,则跳过</span></span><br><span class="line"> <span class="keyword">if</span> (Dis[t] == - <span class="number">1</span> || Dis[t] > Dis[newP] + c) <span class="comment">//若该结点尚不可达,或者该结点从新加入的结点经过一条边到达时比以往距离更短</span></span><br><span class="line"> Dis[t] = Dis[newP] + c; <span class="comment">//更新其距离信息</span></span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="comment">//要选择新的newP</span></span><br><span class="line"> <span class="keyword">int</span> <span class="built_in">min</span> = <span class="number">0x7ffffff</span>; <span class="comment">//最小值初始化为一个大整数,为找最小值做准备</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">1</span>;j <= n;j ++) { <span class="comment">//遍历所有结点</span></span><br><span class="line"> <span class="keyword">if</span> (mark[j] == <span class="literal">true</span>) <span class="keyword">continue</span>; <span class="comment">//若其属于集合K则跳过</span></span><br><span class="line"> <span class="keyword">if</span> (Dis[j] == <span class="number">-1</span>) <span class="keyword">continue</span>; <span class="comment">//若该结点仍不可达则跳过</span></span><br><span class="line"> <span class="keyword">if</span> (Dis[j] < <span class="built_in">min</span>) { <span class="comment">//若该结点经由结点1至集合K中的某点在经过一条边到达时距离小于当前最小值</span></span><br><span class="line"> <span class="built_in">min</span> = Dis[j]; <span class="comment">//更新其为最小值</span></span><br><span class="line"> newP = j; <span class="comment">//新加入的点暂定为该点</span></span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> mark[newP] = <span class="literal">true</span>;<span class="comment">// </span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="拓扑排序"><a href="#拓扑排序" class="headerlink" title="拓扑排序"></a>拓扑排序</h2><p>定义入度,逐渐摘下入度为0的结点。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><vector></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><queue></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="built_in">vector</span><<span class="keyword">int</span>> edge[<span class="number">501</span>]; </span><br><span class="line"><span class="built_in">queue</span><<span class="keyword">int</span>> Q; <span class="comment">//保存入度为0的结点的队列</span></span><br><span class="line"><span class="keyword">int</span> inDegree[<span class="number">501</span>]; <span class="comment">//统计每个结点的入度</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>;i < n;i ++) { <span class="comment">//初始化所有结点,注意本题结点编号由0到n-1</span></span><br><span class="line"> inDegree[i] = <span class="number">0</span>; <span class="comment">//初始化入度信息,所有结点入度均为0</span></span><br><span class="line"> edge[i].<span class="built_in">clear</span>(); <span class="comment">//清空邻接链表</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span> (Q.empty() == <span class="literal">false</span>) Q.pop(); <span class="comment">//清空队列</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span>(m --) {</span><br><span class="line"> <span class="keyword">int</span> a , b;</span><br><span class="line"> <span class="built_in">scanf</span> (<span class="string">"%d%d"</span>,&a,&b); <span class="comment">//读入一条由a指向b的有向边</span></span><br><span class="line"> inDegree[b] ++; <span class="comment">//又出现了一条弧头指向b的边,累加结点b的入度</span></span><br><span class="line"> edge[a].push_back(b); <span class="comment">//将b加入a的邻接链表</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//初步统计</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>;i < n;i ++) { <span class="comment">//统计所有结点的入度</span></span><br><span class="line"><span class="keyword">if</span> (inDegree[i] == <span class="number">0</span>) Q.push(i); <span class="comment">//若结点入度为0,则将其放入队列</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> cnt = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">while</span> (Q.empty() == <span class="literal">false</span>) {</span><br><span class="line"> <span class="keyword">int</span> nowP = Q.front(); </span><br><span class="line"> Q.pop();</span><br><span class="line"> </span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>;i < edge[nowP].<span class="built_in">size</span>();i ++) {</span><br><span class="line"> inDegree[ edge[nowP][i] ] --;</span><br><span class="line"> <span class="keyword">if</span> (inDegree[ edge[nowP][i] ] == <span class="number">0</span>) Q.push(edge[nowP][i]);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (cnt == n) <span class="built_in">puts</span>(<span class="string">"YES"</span>); <span class="comment">//若所有结点都能被确定拓扑序列,则原图为有向无环图</span></span><br><span class="line"><span class="keyword">else</span> <span class="built_in">puts</span>(<span class="string">"NO"</span>); <span class="comment">//否则,原图为非有向无环图</span></span><br></pre></td></tr></table></figure><h1 id="搜索"><a href="#搜索" class="headerlink" title="搜索"></a>搜索</h1><h2 id="枚举"><a href="#枚举" class="headerlink" title="枚举"></a>枚举</h2><p>暴力枚举。在时间允许的情况下不失为一种好方法。</p><h2 id="BFS"><a href="#BFS" class="headerlink" title="BFS"></a>BFS</h2><p>首先需要说明,这里所说的广度优先搜索,与利用广度优先搜索对图进行遍历有一定的差别。</p><p>以解决迷宫问题为例</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">刚开始Ignatius 被关在(0,0,0)的位置,离开城堡的门在(A-1,B-1,C-1)的位置,现在知道魔王将在T 分钟后回到城堡,Ignatius 每分钟能从一个坐标走到相邻的六个坐标中的其中一个.现在给你城堡的地图,请你计算出Ignatius 能否在魔王回来前离开城堡</span><br></pre></td></tr></table></figure><p>暴力搜索肯定是不许的,假设需要走10步,每次都要六个方位可以选择,那就是有$6^{10}$个结果。</p><p>因此需要剪枝,对同一个方块来说,<strong>后到的肯定没有先到的省时间</strong>,因此状态总数会被缩减为 A <em> B </em> C。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><queue></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"><span class="keyword">bool</span> mark[<span class="number">50</span>][<span class="number">50</span>][<span class="number">50</span>]; <span class="comment">//标记数组</span></span><br><span class="line"><span class="keyword">int</span> maze[<span class="number">50</span>][<span class="number">50</span>][<span class="number">50</span>]; <span class="comment">//保存立方体信息</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">N</span> {</span> <span class="comment">//状态结构体</span></span><br><span class="line"> <span class="keyword">int</span> x , y , z;</span><br><span class="line"> <span class="keyword">int</span> t;</span><br><span class="line"> N(<span class="keyword">int</span> x,<span class="keyword">int</span> y,<span class="keyword">int</span> z,<span class="keyword">int</span> t):x(x),y(y),z(z),t(t){}</span><br><span class="line">};</span><br><span class="line"><span class="built_in">queue</span><N> Q; <span class="comment">//队列,队列中的元素为状态,用来做BFS</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> go[][<span class="number">3</span>] = { <span class="comment">// 坐标变换数组, 由坐标(x,y,z) 扩展得到的新坐标均可通过(x+go[i][0],y+go[i][1],z+go[i][2])得到</span></span><br><span class="line"> <span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>,</span><br><span class="line"> <span class="number">-1</span>,<span class="number">0</span>,<span class="number">0</span>,</span><br><span class="line"> <span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,</span><br><span class="line"> <span class="number">0</span>,<span class="number">-1</span>,<span class="number">0</span>,</span><br><span class="line"> <span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,</span><br><span class="line"> <span class="number">0</span>,<span class="number">0</span>,<span class="number">-1</span></span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span>(Q.empty() == <span class="literal">false</span>) Q.pop(); <span class="comment">//清空队列</span></span><br><span class="line">mark[<span class="number">0</span>][<span class="number">0</span>][<span class="number">0</span>] = <span class="literal">true</span>; <span class="comment">//标记起点</span></span><br><span class="line">Q.push(N(<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>));</span><br><span class="line"></span><br><span class="line">int BFS(int a,int b,int c);//函数原型</span><br><span class="line"><span class="keyword">int</span> ans = BFS(A,B,C);</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">BFS</span><span class="params">(<span class="keyword">int</span> a,<span class="keyword">int</span> b,<span class="keyword">int</span> c)</span> </span>{</span><br><span class="line"> <span class="keyword">while</span>(Q.empty() == <span class="literal">false</span>) {</span><br><span class="line"> N now = Q.front(); <span class="comment">//得到队头状态</span></span><br><span class="line"> Q.pop(); <span class="comment">//从队列中弹出队头状态</span></span><br><span class="line"> </span><br><span class="line"> <span class="comment">//六个方位</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>;i < <span class="number">6</span>;i ++) {</span><br><span class="line"> <span class="keyword">int</span> nx = now.x + go[i][<span class="number">0</span>];</span><br><span class="line"> <span class="keyword">int</span> ny = now.y + go[i][<span class="number">1</span>];</span><br><span class="line"> <span class="keyword">int</span> nz = now.z + go[i][<span class="number">2</span>]; <span class="comment">//计算新坐标</span></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (nx < <span class="number">0</span> || nx >= a || ny < <span class="number">0</span> || ny >= b || nz < <span class="number">0</span> || nz >= c) <span class="keyword">continue</span>; <span class="comment">//若新坐标在立方体外,则丢弃该坐标</span></span><br><span class="line"> <span class="keyword">if</span> (maze[nx][ny][nz] == <span class="number">1</span>) <span class="keyword">continue</span>; <span class="comment">//若该位置为墙,则丢弃该坐标</span></span><br><span class="line"> <span class="keyword">if</span> (mark[nx][ny][nz] == <span class="literal">true</span>) <span class="keyword">continue</span>; <span class="comment">//若包含该坐标的状态已经被得到过,则丢弃该状态</span></span><br><span class="line"> <span class="keyword">if</span> (nx == a - <span class="number">1</span> && ny == b - <span class="number">1</span> && nz == c - <span class="number">1</span>) <span class="keyword">return</span> now.t + <span class="number">1</span>; <span class="comment">//到达终点的话,可以返回了</span></span><br><span class="line"> </span><br><span class="line"> Q.push(N(nx,ny,nz,now.t + <span class="number">1</span>));</span><br><span class="line"> mark[nx][ny][nz] = <span class="literal">true</span>; <span class="comment">//标记该坐标</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="递归和DFS"><a href="#递归和DFS" class="headerlink" title="递归和DFS"></a>递归和DFS</h2><p>暂不展开。</p><h1 id="动态规划"><a href="#动态规划" class="headerlink" title="动态规划"></a>动态规划</h1><p>关键是确定状态转移方程。</p><h2 id="最长递增子序列(LIS)"><a href="#最长递增子序列(LIS)" class="headerlink" title="最长递增子序列(LIS)"></a>最长递增子序列(LIS)</h2><h4 id="问题定义"><a href="#问题定义" class="headerlink" title="问题定义"></a>问题定义</h4><p>在一个已知的序列中,取出若干数组成新的序列,其中下标i1、i2…im 保持递增,即新数列中的各个数之间依旧保持原数列中的先后顺序,那么我们称新的序列为原序列的一个子序列。</p><p>若在子序列中,当下标ix > iy 时,aix > aiy ,那么我们称这个子序列为原序列的一个递增子序列。</p><p>最长递增子序列问题,就是在一个给定的原序列中,求得其最长递增子序列长度。</p><h4 id="解决思路"><a href="#解决思路" class="headerlink" title="解决思路"></a>解决思路</h4><p>用F[i]代表若递增子序列以ai 结束时它的最长长度。</p><ul><li><p>初始值:当i 较小,我们容易直接得出其值,如F[1] = 1</p></li><li><p>假设,F[1]到F[x-1]的值都已经确定。ax 都是紧跟在一个由ai(i <x)组成递增子序列之后。要求以ax 结尾的最长递增子序列长度,我们依次比较ax 与其之前<strong>所有的</strong>ai(i <x),若ai 小于ax,则说明ax 可以跟在以ai 结尾的递增子序列之后,形成一个新的递增子序列。</p></li></ul><p>因此递推公式为:</p><script type="math/tex; mode=display">\begin{array}{l}F[1]=1 \\F[i]=\max \left\{1, F[j]+1 | a j<a_{i} \& \& j<i\right\}\end{array}</script><h4 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h4><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">max</span><span class="params">(<span class="keyword">int</span> a,<span class="keyword">int</span> b)</span> </span>{<span class="keyword">return</span> a > b ? a : b;} <span class="comment">//取最大值函数</span></span><br><span class="line"><span class="keyword">int</span> <span class="built_in">list</span>[<span class="number">26</span>]; <span class="comment">//按袭击事件顺序保存各导弹高度</span></span><br><span class="line"><span class="keyword">int</span> dp[<span class="number">26</span>]; <span class="comment">//dp[i]保存以第i个导弹结尾的最长不增子序列长度</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>;i <= n;i ++) <span class="built_in">scanf</span> (<span class="string">"%d"</span>,&<span class="built_in">list</span>[i]);</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>;i <= n;i ++) { <span class="comment">//按照袭击时间顺序确定每一个dp[i]</span></span><br><span class="line"> <span class="keyword">int</span> tmax = <span class="number">1</span>; <span class="comment">//最大值的初始值为1,即以其结尾的最长不增子序列长度至少为1</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">1</span>;j < i;j ++) { <span class="comment">//遍历其前所有导弹高度</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">list</span>[i]<=<span class="built_in">list</span>[j]) { </span><br><span class="line"> tmax = <span class="built_in">max</span>(tmax,dp[j] + <span class="number">1</span>); </span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> dp[i] = tmax; <span class="comment">//将dp[i]保存为最大值</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> ans = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>;i <= n;i ++) {</span><br><span class="line">ans = <span class="built_in">max</span>(ans,dp[i]);</span><br><span class="line">} <span class="comment">//找到以每一个元素结尾的最长不增子序列中的最大值,该最大值即为答案</span></span><br></pre></td></tr></table></figure><h2 id="最长公共子序列(LCS"><a href="#最长公共子序列(LCS" class="headerlink" title="最长公共子序列(LCS)"></a>最长公共子序列(LCS)</h2><p>遇到再补充</p><h2 id="背包问题"><a href="#背包问题" class="headerlink" title="背包问题"></a>背包问题</h2><p>也暂且不展开</p>]]></content>
<summary type="html">
<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>最近花了个四五天的时间看完了 <a href="http://www.cskaoyan.com/thread-647811-1-1.html
</summary>
<category term="编程" scheme="http://jaxchan.top/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="保研" scheme="http://jaxchan.top/categories/%E7%BC%96%E7%A8%8B/%E4%BF%9D%E7%A0%94/"/>
<category term="OJ" scheme="http://jaxchan.top/tags/OJ/"/>
<category term="王小波" scheme="http://jaxchan.top/tags/%E7%8E%8B%E5%B0%8F%E6%B3%A2/"/>
<category term="C++" scheme="http://jaxchan.top/tags/C/"/>
</entry>
<entry>
<title>日记2:行不计路,食不计数对吗</title>
<link href="http://jaxchan.top/2020/%E6%97%A5%E8%AE%B02%EF%BC%9A%E8%A1%8C%E4%B8%8D%E8%AE%A1%E8%B7%AF%EF%BC%8C%E9%A3%9F%E4%B8%8D%E8%AE%A1%E6%95%B0%E5%AF%B9%E5%90%97.html/"/>
<id>http://jaxchan.top/2020/%E6%97%A5%E8%AE%B02%EF%BC%9A%E8%A1%8C%E4%B8%8D%E8%AE%A1%E8%B7%AF%EF%BC%8C%E9%A3%9F%E4%B8%8D%E8%AE%A1%E6%95%B0%E5%AF%B9%E5%90%97.html/</id>
<published>2020-03-10T16:05:08.000Z</published>
<updated>2020-03-10T16:07:41.498Z</updated>
<content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>昨天打完了美赛。挺累的,但是在这三四天,即时学习能力得到了不错的锻练。</p><p>今天给自己放了一假。</p><p>最近疯狂地沉迷周董的《<strong>一路向北</strong>》。</p><p>倒不是说喜欢里面的爱情故事。</p><p>而是喜欢R&B的感觉,</p><p>以及一路向北这四个字:北是荒凉,一路向北是自愿走向荒凉。</p><p>求学的路上确实是伙伴越来越少了。</p><p>这篇东西,也只是惯例,忙了一段时间后就随便写点东西以纪念。</p><h1 id="努力-收益模型"><a href="#努力-收益模型" class="headerlink" title="努力-收益模型"></a>努力-收益模型</h1><p>昨天中午吃饭,爸爸买了个新菜说贵了多少,但是吃起来也没有多特别。</p><p>妈妈说,“古人教落,行不计路,食不计数,哪能算得那么清楚;不过现在确实是走几步手机都算得清清楚楚。”</p><p>有意思。</p><p>我对做事是否需要在意结果,做事的出发点应该是利益还是兴趣,一直有很模糊的思考。</p><p>我的经验告诉我,其实做事情如果出发是利益,那更好办事。</p><p>想要考试考的绩点高一些而备考;想要拿奖而准备比赛;想要拿到合适的offer而准备面试…</p><p>但是后者就相当困难了,从兴趣出发,兴趣是时时刻刻都会变的,从兴趣出发的换句话说是为了开心愉悦而做;休息是令人愉悦的,玩耍也是令人愉悦的,所以为了愉悦而坚持做某个反人类事情可能就站不住脚。</p><p>但要认真考究起来,目标得到满足便是很高等的愉悦了。这种愉悦是持续长时间的,远比吃到一个甜品那种愉悦大得多。</p><p>所以,按照我的陈述,我做事情从来就要求有结果。</p><p>我一直会被一些听起来朗朗上口的话所误导,</p><p>当然说误导可能污蔑了这些话,那我更愿意说没有理解透彻这些话。</p><p>第一句是,<strong>尽最大的努力,作最坏的打算</strong>。</p><p>第二句就是我昨天听到的这句话,<strong>行不计路,食不计数</strong>。</p><p>它们本质上都是在描述一个道理:<strong>不要过分期待结果,甚至不要期待结果,但是要时刻为之而奋斗努力</strong>。</p><p>在我的理解里,它们都误人子弟。</p><p>首先我当然肯定这个道理对人心态的调整具有正向作用。</p><p>但是他影响了个人的 ”努力 - 收益”模型。</p><p>那我觉得哪句话才是对的呢?</p><p><strong>有怎样的能力、做多少的事,决定拿多少的酬劳。最好是毫厘不差。</strong></p><p>所以,在期待完成一件事的结果的时候,最好就是去估量自己的能力与价值。</p><p>只要评估得准,那所有结果都是可以欣然接受的。</p><h1 id="最近要做的事"><a href="#最近要做的事" class="headerlink" title="最近要做的事"></a>最近要做的事</h1><p>有必要copy一下上次说要做的事的列表</p><ul><li>[ ] 我要先把一篇tutorial写完</li><li>[x] 要再看两篇数模的论文</li><li>[x] 学习一下python可视化</li><li>[ ] 也不妨也看看实习和面试的东西</li><li>[x] 也不妨和大家多聊聊天</li></ul><p>我一直在延误对最重要的事的考虑,那就是实习、工作、读研。</p><p>所以,就开始做信息了解和分析吧!</p><p>然后,把tutorial的尾巴写完。开始做一篇科研论文的准备。开始看看天池杯。还有认真找女朋友。</p><p>列一下:</p><ul><li>了解各大厂实习、工作情况;了解面试要求以及技巧;<ul><li>可以多看看宣讲会</li><li>多看看知乎的分析</li><li>多看看一些大佬的blog</li></ul></li><li>把tutorial写完</li><li>做一下天池杯</li><li>找演化算法、优化算法的资料和阅读</li><li>找女朋友</li></ul>]]></content>
<summary type="html">
<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>昨天打完了美赛。挺累的,但是在这三四天,即时学习能力得到了不错的锻练。</p>
<p>今天给自己放了一假。</p>
<p>最近疯狂地沉迷周董
</summary>
<category term="日记" scheme="http://jaxchan.top/categories/%E6%97%A5%E8%AE%B0/"/>
<category term="生活" scheme="http://jaxchan.top/categories/%E6%97%A5%E8%AE%B0/%E7%94%9F%E6%B4%BB/"/>
<category term="努力" scheme="http://jaxchan.top/tags/%E5%8A%AA%E5%8A%9B/"/>
<category term="收获" scheme="http://jaxchan.top/tags/%E6%94%B6%E8%8E%B7/"/>
<category term="面试" scheme="http://jaxchan.top/tags/%E9%9D%A2%E8%AF%95/"/>
<category term="读研" scheme="http://jaxchan.top/tags/%E8%AF%BB%E7%A0%94/"/>
</entry>
<entry>
<title>python可视化</title>
<link href="http://jaxchan.top/2020/python%E5%8F%AF%E8%A7%86%E5%8C%96.html/"/>
<id>http://jaxchan.top/2020/python%E5%8F%AF%E8%A7%86%E5%8C%96.html/</id>
<published>2020-03-03T05:33:34.000Z</published>
<updated>2020-03-04T03:07:07.674Z</updated>
<content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>一直说要做一个python可视化的学习,今天就来认真学一学。</p><p>交互式的可视化起码我暂时都用不着,先学静态的。知乎搜了一些教程,先列出reference</p><p><a href="https://zhuanlan.zhihu.com/p/47588077" target="_blank" rel="noopener">Python 绘图,我只用 Matplotlib(二)</a><br><a href="https://zhuanlan.zhihu.com/p/53308606" target="_blank" rel="noopener">Matplotlib 可视化最有价值的 50 个图表(附完整 Python 源代码)</a></p><p>留下的都是我可以理解,觉得有用的。加了些许的备注。</p><h1 id="基本函数描绘"><a href="#基本函数描绘" class="headerlink" title="基本函数描绘"></a>基本函数描绘</h1><p>有时候需要描绘函数的图形,而不是数据分析,就要手动进行描绘。</p><h2 id="导入"><a href="#导入" class="headerlink" title="导入"></a>导入</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt <span class="comment"># 导入模块 matplotlib.pyplot,并简写成 plt </span></span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np <span class="comment"># 导入模块 numpy,并简写成 np</span></span><br></pre></td></tr></table></figure><h2 id="描绘直线"><a href="#描绘直线" class="headerlink" title="描绘直线"></a>描绘直线</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建一个点数为 8 x 6 的窗口, 并设置分辨率为 80像素/每英寸</span></span><br><span class="line">plt.figure(figsize=(<span class="number">8</span>, <span class="number">6</span>), dpi=<span class="number">80</span>)</span><br><span class="line"></span><br><span class="line">plt.title(<span class="string">"Matplotlib demo - two lines"</span>) </span><br><span class="line"></span><br><span class="line"><span class="comment"># 再创建一个规格为 1 x 1 的子图</span></span><br><span class="line">plt.subplot(<span class="number">111</span>)</span><br><span class="line"></span><br><span class="line">x = np.linspace(<span class="number">-2</span>, <span class="number">6</span>, <span class="number">50</span>)</span><br><span class="line">y1 = x + <span class="number">3</span> <span class="comment"># 曲线 y1</span></span><br><span class="line">y2 = <span class="number">3</span> - x <span class="comment"># 曲线 y2</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 绘制颜色为蓝色、宽度为 1 像素的连续曲线 y1</span></span><br><span class="line">plt.plot(x, y1, color=<span class="string">"blue"</span>, linewidth=<span class="number">1.0</span>, linestyle=<span class="string">"-"</span>)</span><br><span class="line"><span class="comment"># 绘制颜色为紫色、宽度为 2 像素的不连续曲线 y2</span></span><br><span class="line">plt.plot(x, y2, color=<span class="string">"#800080"</span>, linewidth=<span class="number">2.0</span>, linestyle=<span class="string">"--"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置横轴的上下限</span></span><br><span class="line">plt.xlim(<span class="number">-1</span>, <span class="number">6</span>)</span><br><span class="line"><span class="comment"># 设置纵轴的上下限</span></span><br><span class="line">plt.ylim(<span class="number">-2</span>, <span class="number">10</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置横轴标签</span></span><br><span class="line">plt.xlabel(<span class="string">"X"</span>)</span><br><span class="line"><span class="comment"># 设置纵轴标签</span></span><br><span class="line">plt.ylabel(<span class="string">"Y"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置横轴精准刻度</span></span><br><span class="line">plt.xticks([<span class="number">-1</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>],</span><br><span class="line"> [<span class="string">"-1m"</span>, <span class="string">"0m"</span>, <span class="string">"1m"</span>, <span class="string">"2m"</span>, <span class="string">"3m"</span>, <span class="string">"4m"</span>, <span class="string">"5m"</span>, <span class="string">"6m"</span>])</span><br><span class="line"><span class="comment"># 设置纵轴精准刻度</span></span><br><span class="line">plt.yticks([<span class="number">-2</span>, <span class="number">0</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">6</span>, <span class="number">8</span>, <span class="number">10</span>],</span><br><span class="line"> [<span class="string">"-2m"</span>, <span class="string">"0m"</span>, <span class="string">"2m"</span>, <span class="string">"4m"</span>, <span class="string">"6m"</span>, <span class="string">"8m"</span>, <span class="string">"10m"</span>])</span><br><span class="line"></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">左上角的标注</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="comment"># 绘制颜色为蓝色、宽度为 1 像素的连续曲线 y1</span></span><br><span class="line">plt.plot(x, y1, color=<span class="string">"blue"</span>, linewidth=<span class="number">1.0</span>, linestyle=<span class="string">"-"</span>, label=<span class="string">"y1"</span>)</span><br><span class="line"><span class="comment"># 绘制颜色为紫色、宽度为 2 像素的不连续曲线 y2</span></span><br><span class="line">plt.plot(x, y2, color=<span class="string">"#800080"</span>, linewidth=<span class="number">2.0</span>, linestyle=<span class="string">"--"</span>, label=<span class="string">"y2"</span>)</span><br><span class="line">plt.legend(loc=<span class="string">"upper left"</span>)</span><br><span class="line"></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">重要点的标注</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 绘制散点(3, 6)</span></span><br><span class="line">plt.scatter([<span class="number">3</span>], [<span class="number">6</span>], s=<span class="number">30</span>, color=<span class="string">"blue"</span>) <span class="comment"># s 为点的 size</span></span><br><span class="line"><span class="comment"># 对(3, 6)做标注</span></span><br><span class="line">plt.annotate(<span class="string">"(3, 6)"</span>,</span><br><span class="line"> xy=(<span class="number">3.3</span>, <span class="number">5.5</span>), <span class="comment"># 在(3.3, 5.5)上做标注</span></span><br><span class="line"> fontsize=<span class="number">16</span>, <span class="comment"># 设置字体大小为 16</span></span><br><span class="line"> xycoords=<span class="string">'data'</span>) <span class="comment"># xycoords='data' 是说基于数据的值来选位置</span></span><br><span class="line"></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">文字说明</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line">plt.text(<span class="number">3</span>,<span class="number">5</span>, <span class="string">"this point very important"</span>,</span><br><span class="line"> fontdict={<span class="string">'size'</span>: <span class="number">12</span>, <span class="string">'color'</span>: <span class="string">'red'</span>}) <span class="comment"># fontdict设置文本字体</span></span><br><span class="line"></span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-2efcbbe32818350c.png" alt="png"></p><h2 id="描绘多个子图"><a href="#描绘多个子图" class="headerlink" title="描绘多个子图"></a>描绘多个子图</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 计算正弦和余弦曲线上的点的 x 和 y 坐标 </span></span><br><span class="line">x = np.linspace(-np.pi, np.pi, <span class="number">1000</span>)</span><br><span class="line">y_sin = np.sin(x) </span><br><span class="line">y_cos = np.cos(x) </span><br><span class="line"><span class="comment"># 建立 subplot 网格,高为 2,宽为 1 </span></span><br><span class="line"><span class="comment"># 激活第一个 subplot</span></span><br><span class="line">plt.subplot(<span class="number">2</span>, <span class="number">1</span>, <span class="number">1</span>) </span><br><span class="line"><span class="comment"># 绘制第一个图像 </span></span><br><span class="line">plt.plot(x, y_sin) </span><br><span class="line">plt.title(<span class="string">'Sine'</span>) </span><br><span class="line"><span class="comment"># 将第二个 subplot 激活,并绘制第二个图像</span></span><br><span class="line">plt.subplot(<span class="number">2</span>, <span class="number">1</span>, <span class="number">2</span>) </span><br><span class="line">plt.plot(x, y_cos) </span><br><span class="line">plt.title(<span class="string">'Cosine'</span>) </span><br><span class="line"><span class="comment"># 展示图像</span></span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-8e3d2799c8a74139.png" alt="png"></p><h1 id="Matplotlib-几十个可视化图表"><a href="#Matplotlib-几十个可视化图表" class="headerlink" title="Matplotlib - 几十个可视化图表"></a>Matplotlib - 几十个可视化图表</h1><h2 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h2><p>在代码运行前先引入下面的设置内容。 当然,单独的图表,可以重新设置显示要素。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># !pip install brewer2mpl</span></span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> pandas <span class="keyword">as</span> pd</span><br><span class="line"><span class="keyword">import</span> matplotlib <span class="keyword">as</span> mpl</span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"><span class="keyword">import</span> seaborn <span class="keyword">as</span> sns</span><br><span class="line"><span class="keyword">import</span> warnings; warnings.filterwarnings(action=<span class="string">'once'</span>)</span><br><span class="line"></span><br><span class="line">large = <span class="number">22</span>; med = <span class="number">16</span>; small = <span class="number">12</span></span><br><span class="line">params = {<span class="string">'axes.titlesize'</span>: large,</span><br><span class="line"> <span class="string">'legend.fontsize'</span>: med,</span><br><span class="line"> <span class="string">'figure.figsize'</span>: (<span class="number">16</span>, <span class="number">10</span>),</span><br><span class="line"> <span class="string">'axes.labelsize'</span>: med,</span><br><span class="line"> <span class="string">'axes.titlesize'</span>: med,</span><br><span class="line"> <span class="string">'xtick.labelsize'</span>: med,</span><br><span class="line"> <span class="string">'ytick.labelsize'</span>: med,</span><br><span class="line"> <span class="string">'figure.titlesize'</span>: large}</span><br><span class="line">plt.rcParams.update(params)</span><br><span class="line">plt.style.use(<span class="string">'seaborn-whitegrid'</span>)</span><br><span class="line">sns.set_style(<span class="string">"white"</span>)</span><br><span class="line">%matplotlib inline</span><br><span class="line"></span><br><span class="line"><span class="comment"># Version</span></span><br><span class="line">print(mpl.__version__) <span class="comment">#> 3.0.0</span></span><br><span class="line">print(sns.__version__) <span class="comment">#> 0.9.0</span></span><br></pre></td></tr></table></figure><pre><code>3.1.30.10.0</code></pre><hr><h2 id="关联-(Correlation)"><a href="#关联-(Correlation)" class="headerlink" title="关联 (Correlation)"></a>关联 (Correlation)</h2><p>关联图表用于可视化2个或更多变量之间的关系。 也就是说,一个变量如何相对于另一个变化。</p><h3 id="散点图(Scatter-plot)"><a href="#散点图(Scatter-plot)" class="headerlink" title="散点图(Scatter plot)"></a>散点图(Scatter plot)</h3><p>散点图是用于研究两个变量之间关系的经典的和基本的图表。 如果数据中有多个组,则可能需要以不同颜色可视化每个组。 在 matplotlib 中,您可以使用 <code>plt.scatterplot()</code> 方便地执行此操作。</p><h4 id="本散点图的表达内容"><a href="#本散点图的表达内容" class="headerlink" title="本散点图的表达内容"></a>本散点图的表达内容</h4><p>看看在同一个category下的,人口和公司id之间的散点关系</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Import dataset </span></span><br><span class="line">midwest = pd.read_csv(<span class="string">"./midwest_filter.csv"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Prepare Data </span></span><br><span class="line"><span class="comment"># Create as many colors as there are unique midwest['category']</span></span><br><span class="line"><span class="comment"># 太多了,我截取了五个category</span></span><br><span class="line">categories = np.unique(midwest[<span class="string">'category'</span>])[<span class="number">0</span>:<span class="number">3</span>]</span><br><span class="line"><span class="comment">#tab10函数用于生成一个colormap</span></span><br><span class="line">colors = [plt.cm.tab10(i/float(len(categories)<span class="number">-1</span>)) <span class="keyword">for</span> i <span class="keyword">in</span> range(len(categories))]</span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw Plot for Each Category</span></span><br><span class="line">plt.figure(figsize=(<span class="number">16</span>, <span class="number">10</span>), dpi= <span class="number">80</span>, facecolor=<span class="string">'w'</span>, edgecolor=<span class="string">'k'</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> i, category <span class="keyword">in</span> enumerate(categories):</span><br><span class="line"> plt.scatter(<span class="string">'PID'</span>, <span class="string">'poptotal'</span>, </span><br><span class="line"> data=midwest.loc[midwest.category==category, :], </span><br><span class="line"> s=<span class="number">20</span>, cmap=colors[i], label=str(category))</span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"><span class="comment"># Decorations</span></span><br><span class="line">plt.gca().set(xlim=(<span class="number">600</span>, <span class="number">800</span>), ylim=(<span class="number">0</span>, <span class="number">90000</span>),</span><br><span class="line"> xlabel=<span class="string">'PID'</span>, ylabel=<span class="string">'Population'</span>)</span><br><span class="line"></span><br><span class="line">plt.xticks(fontsize=<span class="number">12</span>); plt.yticks(fontsize=<span class="number">12</span>)</span><br><span class="line">plt.title(<span class="string">"Scatterplot of Midwest PID vs Population"</span>, fontsize=<span class="number">22</span>)</span><br><span class="line">plt.legend(fontsize=<span class="number">12</span>) </span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-eafd629563694284.png" alt="png"></p><h3 id="带边界的气泡图(Bubble-plot-with-Encircling)"><a href="#带边界的气泡图(Bubble-plot-with-Encircling)" class="headerlink" title="带边界的气泡图(Bubble plot with Encircling)"></a>带边界的气泡图(Bubble plot with Encircling)</h3><p>有时,您希望在边界内显示一组点以强调其重要性。 在这个例子中,你从数据框中获取记录,并用下面代码中描述的 <code>encircle()</code> 来使边界显示出来。</p><h4 id="本气泡图目的"><a href="#本气泡图目的" class="headerlink" title="本气泡图目的"></a>本气泡图目的</h4><p>在我们使用散点图(同一个category下的面积和人口关系)后,想要给 属性state = IN 条件下的数据圈出标注。<br>其实就是画一个多边形</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> matplotlib <span class="keyword">import</span> patches</span><br><span class="line"><span class="keyword">from</span> scipy.spatial <span class="keyword">import</span> ConvexHull</span><br><span class="line"><span class="keyword">import</span> warnings; warnings.simplefilter(<span class="string">'ignore'</span>)</span><br><span class="line">sns.set_style(<span class="string">"white"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Step 1: Prepare Data</span></span><br><span class="line">midwest = pd.read_csv(<span class="string">"./midwest_filter.csv"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># As many colors as there are unique midwest['category']</span></span><br><span class="line">categories = np.unique(midwest[<span class="string">'category'</span>])</span><br><span class="line">colors = [plt.cm.tab10(i/float(len(categories)<span class="number">-1</span>)) <span class="keyword">for</span> i <span class="keyword">in</span> range(len(categories))]</span><br><span class="line"></span><br><span class="line"><span class="comment"># Step 2: Draw Scatterplot with unique color for each category</span></span><br><span class="line">fig = plt.figure(figsize=(<span class="number">16</span>, <span class="number">10</span>), dpi= <span class="number">80</span>, facecolor=<span class="string">'w'</span>, edgecolor=<span class="string">'k'</span>) </span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> i, category <span class="keyword">in</span> enumerate(categories):</span><br><span class="line"> plt.scatter(<span class="string">'area'</span>, <span class="string">'poptotal'</span>, data=midwest.loc[midwest.category==category, :], </span><br><span class="line"> s=<span class="string">'dot_size'</span>, cmap=colors[i], label=str(category), </span><br><span class="line"> edgecolors=<span class="string">'black'</span>, linewidths=<span class="number">.5</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># Step 3: Encircling</span></span><br><span class="line"><span class="comment"># https://stackoverflow.com/questions/44575681/how-do-i-encircle-different-data-sets-in-scatter-plot</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">encircle</span><span class="params">(x,y, ax=None, **kw)</span>:</span></span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">not</span> ax: ax=plt.gca()</span><br><span class="line"> p = np.c_[x,y]</span><br><span class="line"> hull = ConvexHull(p)</span><br><span class="line"> poly = plt.Polygon(p[hull.vertices,:], **kw)</span><br><span class="line"> ax.add_patch(poly)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Select data to be encircled</span></span><br><span class="line">midwest_encircle_data = midwest.loc[midwest.state==<span class="string">'IN'</span>, :] </span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw polygon surrounding vertices </span></span><br><span class="line">encircle(midwest_encircle_data.area, midwest_encircle_data.poptotal, ec=<span class="string">"k"</span>, fc=<span class="string">"gold"</span>, alpha=<span class="number">0.1</span>)</span><br><span class="line">encircle(midwest_encircle_data.area, midwest_encircle_data.poptotal, ec=<span class="string">"firebrick"</span>, fc=<span class="string">"none"</span>, linewidth=<span class="number">1.5</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Step 4: Decorations</span></span><br><span class="line">plt.gca().set(xlim=(<span class="number">0.0</span>, <span class="number">0.1</span>), ylim=(<span class="number">0</span>, <span class="number">90000</span>),</span><br><span class="line"> xlabel=<span class="string">'Area'</span>, ylabel=<span class="string">'Population'</span>)</span><br><span class="line"></span><br><span class="line">plt.xticks(fontsize=<span class="number">12</span>); plt.yticks(fontsize=<span class="number">12</span>)</span><br><span class="line">plt.title(<span class="string">"Bubble Plot with Encircling"</span>, fontsize=<span class="number">22</span>)</span><br><span class="line">plt.legend(fontsize=<span class="number">12</span>) </span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-a56854dad395a36d.png" alt="png"></p><h3 id="抖动图-(Jittering-with-stripplot)"><a href="#抖动图-(Jittering-with-stripplot)" class="headerlink" title="抖动图 (Jittering with stripplot)"></a>抖动图 (Jittering with stripplot)</h3><p>通常,多个数据点具有完全相同的 X 和 Y 值。 结果,多个点绘制会重叠并隐藏。 为避免这种情况,请将数据点稍微抖动,以便您可以直观地看到它们。 使用 seaborn 的 <code>stripplot()</code> 很方便实现这个功能。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Import Data</span></span><br><span class="line">df = pd.read_csv(<span class="string">"./mpg_ggplot2.csv"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw Stripplot</span></span><br><span class="line">fig, ax = plt.subplots(figsize=(<span class="number">16</span>,<span class="number">10</span>), dpi= <span class="number">80</span>) </span><br><span class="line">sns.stripplot(df.cty, df.hwy, jitter=<span class="number">0.25</span>, size=<span class="number">8</span>, ax=ax, linewidth=<span class="number">.5</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Decorations</span></span><br><span class="line">plt.title(<span class="string">'Use jittered plots to avoid overlapping of points'</span>, fontsize=<span class="number">22</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-0b960b28825d565e.png" alt="png"></p><h3 id="计数图-(Counts-Plot)"><a href="#计数图-(Counts-Plot)" class="headerlink" title="计数图 (Counts Plot)"></a>计数图 (Counts Plot)</h3><p>避免点重叠问题的另一个选择是增加点的大小,这取决于该点中有多少点。 因此,点的大小越大,其周围的点的集中度越高。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Import Data</span></span><br><span class="line">df = pd.read_csv(<span class="string">"./mpg_ggplot2.csv"</span>)</span><br><span class="line">df_counts = df.groupby([<span class="string">'hwy'</span>, <span class="string">'cty'</span>]).size().reset_index(name=<span class="string">'counts'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw Stripplot</span></span><br><span class="line">fig, ax = plt.subplots(figsize=(<span class="number">16</span>,<span class="number">10</span>), dpi= <span class="number">80</span>) </span><br><span class="line">sns.stripplot(df_counts.cty, df_counts.hwy, size=df_counts.counts*<span class="number">2</span>, ax=ax)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Decorations</span></span><br><span class="line">plt.title(<span class="string">'Counts Plot - Size of circle is bigger as more points overlap'</span>, fontsize=<span class="number">22</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-8ac6d0ef30a81a08.png" alt="png"></p><h3 id="边缘直方图-(Marginal-Histogram)"><a href="#边缘直方图-(Marginal-Histogram)" class="headerlink" title="边缘直方图 (Marginal Histogram)"></a>边缘直方图 (Marginal Histogram)</h3><p>边缘直方图具有沿 X 和 Y 轴变量的直方图。 这用于可视化 X 和 Y 之间的关系以及单独的 X 和 Y 的单变量分布。 这种图经常用于探索性数据分析(EDA)。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Import Data</span></span><br><span class="line">df = pd.read_csv(<span class="string">"./mpg_ggplot2.csv"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Create Fig and gridspec</span></span><br><span class="line">fig = plt.figure(figsize=(<span class="number">16</span>, <span class="number">10</span>), dpi= <span class="number">80</span>)</span><br><span class="line">grid = plt.GridSpec(<span class="number">4</span>, <span class="number">4</span>, hspace=<span class="number">0.5</span>, wspace=<span class="number">0.2</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Define the axes</span></span><br><span class="line">ax_main = fig.add_subplot(grid[:<span class="number">-1</span>, :<span class="number">-1</span>])</span><br><span class="line">ax_right = fig.add_subplot(grid[:<span class="number">-1</span>, <span class="number">-1</span>], xticklabels=[], yticklabels=[])</span><br><span class="line">ax_bottom = fig.add_subplot(grid[<span class="number">-1</span>, <span class="number">0</span>:<span class="number">-1</span>], xticklabels=[], yticklabels=[])</span><br><span class="line"></span><br><span class="line"><span class="comment"># Scatterplot on main ax</span></span><br><span class="line">ax_main.scatter(<span class="string">'displ'</span>, <span class="string">'hwy'</span>, s=df.cty*<span class="number">4</span>, c=df.manufacturer.astype(<span class="string">'category'</span>).cat.codes, alpha=<span class="number">.9</span>, data=df, cmap=<span class="string">"tab10"</span>, edgecolors=<span class="string">'gray'</span>, linewidths=<span class="number">.5</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># histogram on the right</span></span><br><span class="line">ax_bottom.hist(df.displ, <span class="number">40</span>, histtype=<span class="string">'stepfilled'</span>, orientation=<span class="string">'vertical'</span>, color=<span class="string">'deeppink'</span>)</span><br><span class="line">ax_bottom.invert_yaxis()</span><br><span class="line"></span><br><span class="line"><span class="comment"># histogram in the bottom</span></span><br><span class="line">ax_right.hist(df.hwy, <span class="number">40</span>, histtype=<span class="string">'stepfilled'</span>, orientation=<span class="string">'horizontal'</span>, color=<span class="string">'deeppink'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Decorations</span></span><br><span class="line">ax_main.set(title=<span class="string">'Scatterplot with Histograms \n displ vs hwy'</span>, xlabel=<span class="string">'displ'</span>, ylabel=<span class="string">'hwy'</span>)</span><br><span class="line">ax_main.title.set_fontsize(<span class="number">20</span>)</span><br><span class="line"><span class="keyword">for</span> item <span class="keyword">in</span> ([ax_main.xaxis.label, ax_main.yaxis.label] + ax_main.get_xticklabels() + ax_main.get_yticklabels()):</span><br><span class="line"> item.set_fontsize(<span class="number">14</span>)</span><br><span class="line"></span><br><span class="line">xlabels = ax_main.get_xticks().tolist()</span><br><span class="line">ax_main.set_xticklabels(xlabels)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-de9bb8df72387de5.png" alt="png"></p><h3 id="相关图-(Correllogram)"><a href="#相关图-(Correllogram)" class="headerlink" title="相关图 (Correllogram)"></a>相关图 (Correllogram)</h3><p>相关图用于直观地查看给定数据框(或二维数组)中所有可能的数值变量对之间的相关度量。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Import Dataset</span></span><br><span class="line">df = pd.read_csv(<span class="string">"./mtcars.csv"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Plot</span></span><br><span class="line">plt.figure(figsize=(<span class="number">12</span>,<span class="number">10</span>), dpi= <span class="number">80</span>)</span><br><span class="line">sns.heatmap(df.corr(), xticklabels=df.corr().columns, yticklabels=df.corr().columns, cmap=<span class="string">'RdYlGn'</span>, center=<span class="number">0</span>, annot=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Decorations</span></span><br><span class="line">plt.title(<span class="string">'Correlogram of mtcars'</span>, fontsize=<span class="number">22</span>)</span><br><span class="line">plt.xticks(fontsize=<span class="number">12</span>)</span><br><span class="line">plt.yticks(fontsize=<span class="number">12</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-fe72c4e804cee78d.png" alt="png"></p><h3 id="矩阵图-(Pairwise-Plot)"><a href="#矩阵图-(Pairwise-Plot)" class="headerlink" title="矩阵图 (Pairwise Plot)"></a>矩阵图 (Pairwise Plot)</h3><p>矩阵图是探索性分析中的最爱,用于理解所有可能的数值变量对之间的关系。 它是双变量分析的必备工具。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Load Dataset</span></span><br><span class="line">df = pd.read_csv(<span class="string">"./iris.csv"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Plot</span></span><br><span class="line">plt.figure(figsize=(<span class="number">10</span>,<span class="number">8</span>), dpi= <span class="number">80</span>)</span><br><span class="line">sns.pairplot(df, kind=<span class="string">"scatter"</span>, hue=<span class="string">"species"</span>, plot_kws=dict(s=<span class="number">80</span>, edgecolor=<span class="string">"white"</span>, linewidth=<span class="number">2.5</span>))</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-091734a023187249.png" alt="png"></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Load Dataset</span></span><br><span class="line">df = pd.read_csv(<span class="string">"./iris.csv"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Plot</span></span><br><span class="line">plt.figure(figsize=(<span class="number">10</span>,<span class="number">8</span>), dpi= <span class="number">80</span>)</span><br><span class="line">sns.pairplot(df, kind=<span class="string">"reg"</span>, hue=<span class="string">"species"</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-bb9ce8f71da7ba1e.png" alt="png"></p><h2 id="偏差-(Deviation)"><a href="#偏差-(Deviation)" class="headerlink" title="偏差 (Deviation)"></a>偏差 (Deviation)</h2><h3 id="发散型条形图-(Diverging-Bars)"><a href="#发散型条形图-(Diverging-Bars)" class="headerlink" title="发散型条形图 (Diverging Bars)"></a>发散型条形图 (Diverging Bars)</h3><p>如果您想根据单个指标查看项目的变化情况,并可视化此差异的顺序和数量,那么散型条形图 (Diverging Bars) 是一个很好的工具。 它有助于快速区分数据中组的性能,并且非常直观,并且可以立即传达这一点。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Prepare Data</span></span><br><span class="line">df = pd.read_csv(<span class="string">"./mtcars.csv"</span>)</span><br><span class="line">x = df.loc[:, [<span class="string">'mpg'</span>]]</span><br><span class="line">df[<span class="string">'mpg_z'</span>] = (x - x.mean())/x.std()</span><br><span class="line">df[<span class="string">'colors'</span>] = [<span class="string">'red'</span> <span class="keyword">if</span> x < <span class="number">0</span> <span class="keyword">else</span> <span class="string">'green'</span> <span class="keyword">for</span> x <span class="keyword">in</span> df[<span class="string">'mpg_z'</span>]]</span><br><span class="line">df.sort_values(<span class="string">'mpg_z'</span>, inplace=<span class="literal">True</span>)</span><br><span class="line">df.reset_index(inplace=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw plot</span></span><br><span class="line">plt.figure(figsize=(<span class="number">14</span>,<span class="number">10</span>), dpi= <span class="number">80</span>)</span><br><span class="line">plt.hlines(y=df.index, xmin=<span class="number">0</span>, xmax=df.mpg_z, color=df.colors, alpha=<span class="number">0.4</span>, linewidth=<span class="number">5</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Decorations</span></span><br><span class="line">plt.gca().set(ylabel=<span class="string">'$Model$'</span>, xlabel=<span class="string">'$Mileage$'</span>)</span><br><span class="line">plt.yticks(df.index, df.cars, fontsize=<span class="number">12</span>)</span><br><span class="line">plt.title(<span class="string">'Diverging Bars of Car Mileage'</span>, fontdict={<span class="string">'size'</span>:<span class="number">20</span>})</span><br><span class="line">plt.grid(linestyle=<span class="string">'--'</span>, alpha=<span class="number">0.5</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-b14cee7f12e7ebc2.png" alt="png"></p><h3 id="发散型文本-(Diverging-Texts)"><a href="#发散型文本-(Diverging-Texts)" class="headerlink" title="发散型文本 (Diverging Texts)"></a>发散型文本 (Diverging Texts)</h3><p>发散型文本 (Diverging Texts)与发散型条形图 (Diverging Bars)相似,如果你想以一种漂亮和可呈现的方式显示图表中每个项目的价值,就可以使用这种方法。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Prepare Data</span></span><br><span class="line">df = pd.read_csv(<span class="string">"./mtcars.csv"</span>)</span><br><span class="line">x = df.loc[:, [<span class="string">'mpg'</span>]]</span><br><span class="line">df[<span class="string">'mpg_z'</span>] = (x - x.mean())/x.std()</span><br><span class="line">df[<span class="string">'colors'</span>] = [<span class="string">'red'</span> <span class="keyword">if</span> x < <span class="number">0</span> <span class="keyword">else</span> <span class="string">'green'</span> <span class="keyword">for</span> x <span class="keyword">in</span> df[<span class="string">'mpg_z'</span>]]</span><br><span class="line">df.sort_values(<span class="string">'mpg_z'</span>, inplace=<span class="literal">True</span>)</span><br><span class="line">df.reset_index(inplace=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw plot</span></span><br><span class="line">plt.figure(figsize=(<span class="number">14</span>,<span class="number">14</span>), dpi= <span class="number">80</span>)</span><br><span class="line">plt.hlines(y=df.index, xmin=<span class="number">0</span>, xmax=df.mpg_z)</span><br><span class="line"><span class="keyword">for</span> x, y, tex <span class="keyword">in</span> zip(df.mpg_z, df.index, df.mpg_z):</span><br><span class="line"> t = plt.text(x, y, round(tex, <span class="number">2</span>), horizontalalignment=<span class="string">'right'</span> <span class="keyword">if</span> x < <span class="number">0</span> <span class="keyword">else</span> <span class="string">'left'</span>, </span><br><span class="line"> verticalalignment=<span class="string">'center'</span>, fontdict={<span class="string">'color'</span>:<span class="string">'red'</span> <span class="keyword">if</span> x < <span class="number">0</span> <span class="keyword">else</span> <span class="string">'green'</span>, <span class="string">'size'</span>:<span class="number">14</span>})</span><br><span class="line"></span><br><span class="line"><span class="comment"># Decorations </span></span><br><span class="line">plt.yticks(df.index, df.cars, fontsize=<span class="number">12</span>)</span><br><span class="line">plt.title(<span class="string">'Diverging Text Bars of Car Mileage'</span>, fontdict={<span class="string">'size'</span>:<span class="number">20</span>})</span><br><span class="line">plt.grid(linestyle=<span class="string">'--'</span>, alpha=<span class="number">0.5</span>)</span><br><span class="line">plt.xlim(<span class="number">-2.5</span>, <span class="number">2.5</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-752e5112d93a5797.png" alt="png"></p><h3 id="带标记的发散型棒棒糖图-(Diverging-Lollipop-Chart-with-Markers)"><a href="#带标记的发散型棒棒糖图-(Diverging-Lollipop-Chart-with-Markers)" class="headerlink" title="带标记的发散型棒棒糖图 (Diverging Lollipop Chart with Markers)"></a>带标记的发散型棒棒糖图 (Diverging Lollipop Chart with Markers)</h3><p>带标记的棒棒糖图通过强调您想要引起注意的任何重要数据点并在图表中适当地给出推理,提供了一种对差异进行可视化的灵活方式。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Prepare Data</span></span><br><span class="line">df = pd.read_csv(<span class="string">"./mtcars.csv"</span>)</span><br><span class="line">x = df.loc[:, [<span class="string">'mpg'</span>]]</span><br><span class="line">df[<span class="string">'mpg_z'</span>] = (x - x.mean())/x.std()</span><br><span class="line">df[<span class="string">'colors'</span>] = <span class="string">'black'</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># color fiat differently</span></span><br><span class="line">df.loc[df.cars == <span class="string">'Fiat X1-9'</span>, <span class="string">'colors'</span>] = <span class="string">'darkorange'</span></span><br><span class="line">df.sort_values(<span class="string">'mpg_z'</span>, inplace=<span class="literal">True</span>)</span><br><span class="line">df.reset_index(inplace=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw plot</span></span><br><span class="line"><span class="keyword">import</span> matplotlib.patches <span class="keyword">as</span> patches</span><br><span class="line"></span><br><span class="line">plt.figure(figsize=(<span class="number">14</span>,<span class="number">16</span>), dpi= <span class="number">80</span>)</span><br><span class="line">plt.hlines(y=df.index, xmin=<span class="number">0</span>, xmax=df.mpg_z, color=df.colors, alpha=<span class="number">0.4</span>, linewidth=<span class="number">1</span>)</span><br><span class="line">plt.scatter(df.mpg_z, df.index, color=df.colors, s=[<span class="number">600</span> <span class="keyword">if</span> x == <span class="string">'Fiat X1-9'</span> <span class="keyword">else</span> <span class="number">300</span> <span class="keyword">for</span> x <span class="keyword">in</span> df.cars], alpha=<span class="number">0.6</span>)</span><br><span class="line">plt.yticks(df.index, df.cars)</span><br><span class="line">plt.xticks(fontsize=<span class="number">12</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Annotate</span></span><br><span class="line">plt.annotate(<span class="string">'Mercedes Models'</span>, xy=(<span class="number">0.0</span>, <span class="number">11.0</span>), xytext=(<span class="number">1.0</span>, <span class="number">11</span>), xycoords=<span class="string">'data'</span>, </span><br><span class="line"> fontsize=<span class="number">15</span>, ha=<span class="string">'center'</span>, va=<span class="string">'center'</span>,</span><br><span class="line"> bbox=dict(boxstyle=<span class="string">'square'</span>, fc=<span class="string">'firebrick'</span>),</span><br><span class="line"> arrowprops=dict(arrowstyle=<span class="string">'-[, widthB=2.0, lengthB=1.5'</span>, lw=<span class="number">2.0</span>, color=<span class="string">'steelblue'</span>), color=<span class="string">'white'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Add Patches</span></span><br><span class="line">p1 = patches.Rectangle((<span class="number">-2.0</span>, <span class="number">-1</span>), width=<span class="number">.3</span>, height=<span class="number">3</span>, alpha=<span class="number">.2</span>, facecolor=<span class="string">'red'</span>)</span><br><span class="line">p2 = patches.Rectangle((<span class="number">1.5</span>, <span class="number">27</span>), width=<span class="number">.8</span>, height=<span class="number">5</span>, alpha=<span class="number">.2</span>, facecolor=<span class="string">'green'</span>)</span><br><span class="line">plt.gca().add_patch(p1)</span><br><span class="line">plt.gca().add_patch(p2)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Decorate</span></span><br><span class="line">plt.title(<span class="string">'Diverging Bars of Car Mileage'</span>, fontdict={<span class="string">'size'</span>:<span class="number">20</span>})</span><br><span class="line">plt.grid(linestyle=<span class="string">'--'</span>, alpha=<span class="number">0.5</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-0db28dbab5856b7c.png" alt="png"></p><h3 id="面积图-(Area-Chart)"><a href="#面积图-(Area-Chart)" class="headerlink" title="面积图 (Area Chart)"></a>面积图 (Area Chart)</h3><p>通过对轴和线之间的区域进行着色,面积图不仅强调峰和谷,而且还强调高点和低点的持续时间。 高点持续时间越长,线下面积越大。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> pandas <span class="keyword">as</span> pd</span><br><span class="line"></span><br><span class="line"><span class="comment"># Prepare Data</span></span><br><span class="line">df = pd.read_csv(<span class="string">"./economics.csv"</span>, parse_dates=[<span class="string">'date'</span>]).head(<span class="number">100</span>)</span><br><span class="line">x = np.arange(df.shape[<span class="number">0</span>])</span><br><span class="line">y_returns = (df.psavert.diff().fillna(<span class="number">0</span>)/df.psavert.shift(<span class="number">1</span>)).fillna(<span class="number">0</span>) * <span class="number">100</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Plot</span></span><br><span class="line">plt.figure(figsize=(<span class="number">16</span>,<span class="number">10</span>), dpi= <span class="number">80</span>)</span><br><span class="line">plt.fill_between(x[<span class="number">1</span>:], y_returns[<span class="number">1</span>:], <span class="number">0</span>, where=y_returns[<span class="number">1</span>:] >= <span class="number">0</span>, facecolor=<span class="string">'green'</span>, interpolate=<span class="literal">True</span>, alpha=<span class="number">0.7</span>)</span><br><span class="line">plt.fill_between(x[<span class="number">1</span>:], y_returns[<span class="number">1</span>:], <span class="number">0</span>, where=y_returns[<span class="number">1</span>:] <= <span class="number">0</span>, facecolor=<span class="string">'red'</span>, interpolate=<span class="literal">True</span>, alpha=<span class="number">0.7</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Annotate</span></span><br><span class="line">plt.annotate(<span class="string">'Peak \n1975'</span>, xy=(<span class="number">94.0</span>, <span class="number">21.0</span>), xytext=(<span class="number">88.0</span>, <span class="number">28</span>),</span><br><span class="line"> bbox=dict(boxstyle=<span class="string">'square'</span>, fc=<span class="string">'firebrick'</span>),</span><br><span class="line"> arrowprops=dict(facecolor=<span class="string">'steelblue'</span>, shrink=<span class="number">0.05</span>), fontsize=<span class="number">15</span>, color=<span class="string">'white'</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># Decorations</span></span><br><span class="line">xtickvals = [str(m)[:<span class="number">3</span>].upper()+<span class="string">"-"</span>+str(y) <span class="keyword">for</span> y,m <span class="keyword">in</span> zip(df.date.dt.year, df.date.dt.month_name())]</span><br><span class="line">plt.gca().set_xticks(x[::<span class="number">6</span>])</span><br><span class="line">plt.gca().set_xticklabels(xtickvals[::<span class="number">6</span>], rotation=<span class="number">90</span>, fontdict={<span class="string">'horizontalalignment'</span>: <span class="string">'center'</span>, <span class="string">'verticalalignment'</span>: <span class="string">'center_baseline'</span>})</span><br><span class="line">plt.ylim(<span class="number">-35</span>,<span class="number">35</span>)</span><br><span class="line">plt.xlim(<span class="number">1</span>,<span class="number">100</span>)</span><br><span class="line">plt.title(<span class="string">"Month Economics Return %"</span>, fontsize=<span class="number">22</span>)</span><br><span class="line">plt.ylabel(<span class="string">'Monthly returns %'</span>)</span><br><span class="line">plt.grid(alpha=<span class="number">0.5</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-ac4b1a90f07e94d7.png" alt="png"></p><h2 id="排序-(Ranking)"><a href="#排序-(Ranking)" class="headerlink" title="排序 (Ranking)"></a>排序 (Ranking)</h2><h3 id="有序条形图-(Ordered-Bar-Chart)"><a href="#有序条形图-(Ordered-Bar-Chart)" class="headerlink" title="有序条形图 (Ordered Bar Chart)"></a>有序条形图 (Ordered Bar Chart)</h3><p>有序条形图有效地传达了项目的排名顺序。 但是,在图表上方添加度量标准的值,用户可以从图表本身获取精确信息。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Prepare Data</span></span><br><span class="line">df_raw = pd.read_csv(<span class="string">"./mpg_ggplot2.csv"</span>)</span><br><span class="line">df = df_raw[[<span class="string">'cty'</span>, <span class="string">'manufacturer'</span>]].groupby(<span class="string">'manufacturer'</span>).apply(<span class="keyword">lambda</span> x: x.mean())</span><br><span class="line">df.sort_values(<span class="string">'cty'</span>, inplace=<span class="literal">True</span>)</span><br><span class="line">df.reset_index(inplace=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw plot</span></span><br><span class="line"><span class="keyword">import</span> matplotlib.patches <span class="keyword">as</span> patches</span><br><span class="line"></span><br><span class="line">fig, ax = plt.subplots(figsize=(<span class="number">16</span>,<span class="number">10</span>), facecolor=<span class="string">'white'</span>, dpi= <span class="number">80</span>)</span><br><span class="line">ax.vlines(x=df.index, ymin=<span class="number">0</span>, ymax=df.cty, color=<span class="string">'firebrick'</span>, alpha=<span class="number">0.7</span>, linewidth=<span class="number">20</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Annotate Text</span></span><br><span class="line"><span class="keyword">for</span> i, cty <span class="keyword">in</span> enumerate(df.cty):</span><br><span class="line"> ax.text(i, cty+<span class="number">0.5</span>, round(cty, <span class="number">1</span>), horizontalalignment=<span class="string">'center'</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># Title, Label, Ticks and Ylim</span></span><br><span class="line">ax.set_title(<span class="string">'Bar Chart for Highway Mileage'</span>, fontdict={<span class="string">'size'</span>:<span class="number">22</span>})</span><br><span class="line">ax.set(ylabel=<span class="string">'Miles Per Gallon'</span>, ylim=(<span class="number">0</span>, <span class="number">30</span>))</span><br><span class="line">plt.xticks(df.index, df.manufacturer.str.upper(), rotation=<span class="number">60</span>, horizontalalignment=<span class="string">'right'</span>, fontsize=<span class="number">12</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Add patches to color the X axis labels</span></span><br><span class="line">p1 = patches.Rectangle((<span class="number">.57</span>, <span class="number">-0.005</span>), width=<span class="number">.33</span>, height=<span class="number">.13</span>, alpha=<span class="number">.1</span>, facecolor=<span class="string">'green'</span>, transform=fig.transFigure)</span><br><span class="line">p2 = patches.Rectangle((<span class="number">.124</span>, <span class="number">-0.005</span>), width=<span class="number">.446</span>, height=<span class="number">.13</span>, alpha=<span class="number">.1</span>, facecolor=<span class="string">'red'</span>, transform=fig.transFigure)</span><br><span class="line">fig.add_artist(p1)</span><br><span class="line">fig.add_artist(p2)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-869facf85bf9f14d.png" alt="png"></p><h3 id="棒棒糖图-(Lollipop-Chart)"><a href="#棒棒糖图-(Lollipop-Chart)" class="headerlink" title="棒棒糖图 (Lollipop Chart)"></a>棒棒糖图 (Lollipop Chart)</h3><p>棒棒糖图表以一种视觉上令人愉悦的方式提供与有序条形图类似的目的。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Prepare Data</span></span><br><span class="line">df_raw = pd.read_csv(<span class="string">"./mpg_ggplot2.csv"</span>)</span><br><span class="line">df = df_raw[[<span class="string">'cty'</span>, <span class="string">'manufacturer'</span>]].groupby(<span class="string">'manufacturer'</span>).apply(<span class="keyword">lambda</span> x: x.mean())</span><br><span class="line">df.sort_values(<span class="string">'cty'</span>, inplace=<span class="literal">True</span>)</span><br><span class="line">df.reset_index(inplace=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw plot</span></span><br><span class="line">fig, ax = plt.subplots(figsize=(<span class="number">16</span>,<span class="number">10</span>), dpi= <span class="number">80</span>)</span><br><span class="line">ax.vlines(x=df.index, ymin=<span class="number">0</span>, ymax=df.cty, color=<span class="string">'firebrick'</span>, alpha=<span class="number">0.7</span>, linewidth=<span class="number">2</span>)</span><br><span class="line">ax.scatter(x=df.index, y=df.cty, s=<span class="number">75</span>, color=<span class="string">'firebrick'</span>, alpha=<span class="number">0.7</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Title, Label, Ticks and Ylim</span></span><br><span class="line">ax.set_title(<span class="string">'Lollipop Chart for Highway Mileage'</span>, fontdict={<span class="string">'size'</span>:<span class="number">22</span>})</span><br><span class="line">ax.set_ylabel(<span class="string">'Miles Per Gallon'</span>)</span><br><span class="line">ax.set_xticks(df.index)</span><br><span class="line">ax.set_xticklabels(df.manufacturer.str.upper(), rotation=<span class="number">60</span>, fontdict={<span class="string">'horizontalalignment'</span>: <span class="string">'right'</span>, <span class="string">'size'</span>:<span class="number">12</span>})</span><br><span class="line">ax.set_ylim(<span class="number">0</span>, <span class="number">30</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Annotate</span></span><br><span class="line"><span class="keyword">for</span> row <span class="keyword">in</span> df.itertuples():</span><br><span class="line"> ax.text(row.Index, row.cty+<span class="number">.5</span>, s=round(row.cty, <span class="number">2</span>), horizontalalignment= <span class="string">'center'</span>, verticalalignment=<span class="string">'bottom'</span>, fontsize=<span class="number">14</span>)</span><br><span class="line"></span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-c595501fe9bad139.png" alt="png"></p><h2 id="分布-(Distribution)"><a href="#分布-(Distribution)" class="headerlink" title="分布 (Distribution)"></a>分布 (Distribution)</h2><h3 id="连续变量的直方图-(Histogram-for-Continuous-Variable)"><a href="#连续变量的直方图-(Histogram-for-Continuous-Variable)" class="headerlink" title="连续变量的直方图 (Histogram for Continuous Variable)"></a>连续变量的直方图 (Histogram for Continuous Variable)</h3><p>直方图显示给定变量的频率分布。 下面的图表示基于类型变量对频率条进行分组,从而更好地了解连续变量和类型变量。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Import Data</span></span><br><span class="line">df = pd.read_csv(<span class="string">"./mpg_ggplot2.csv"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Prepare data</span></span><br><span class="line">x_var = <span class="string">'displ'</span></span><br><span class="line">groupby_var = <span class="string">'class'</span></span><br><span class="line">df_agg = df.loc[:, [x_var, groupby_var]].groupby(groupby_var)</span><br><span class="line">vals = [df[x_var].values.tolist() <span class="keyword">for</span> i, df <span class="keyword">in</span> df_agg]</span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw</span></span><br><span class="line">plt.figure(figsize=(<span class="number">16</span>,<span class="number">9</span>), dpi= <span class="number">80</span>)</span><br><span class="line">colors = [plt.cm.Spectral(i/float(len(vals)<span class="number">-1</span>)) <span class="keyword">for</span> i <span class="keyword">in</span> range(len(vals))]</span><br><span class="line">n, bins, patches = plt.hist(vals, <span class="number">30</span>, stacked=<span class="literal">True</span>, density=<span class="literal">False</span>, color=colors[:len(vals)])</span><br><span class="line"></span><br><span class="line"><span class="comment"># Decoration</span></span><br><span class="line">plt.legend({group:col <span class="keyword">for</span> group, col <span class="keyword">in</span> zip(np.unique(df[groupby_var]).tolist(), colors[:len(vals)])})</span><br><span class="line">plt.title(<span class="string">f"Stacked Histogram of $<span class="subst">{x_var}</span>$ colored by $<span class="subst">{groupby_var}</span>$"</span>, fontsize=<span class="number">22</span>)</span><br><span class="line">plt.xlabel(x_var)</span><br><span class="line">plt.ylabel(<span class="string">"Frequency"</span>)</span><br><span class="line">plt.ylim(<span class="number">0</span>, <span class="number">25</span>)</span><br><span class="line">plt.xticks(ticks=bins[::<span class="number">3</span>], labels=[round(b,<span class="number">1</span>) <span class="keyword">for</span> b <span class="keyword">in</span> bins[::<span class="number">3</span>]])</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-73e61d43f7bd055e.png" alt="png"></p><h3 id="密度图-(Density-Plot)"><a href="#密度图-(Density-Plot)" class="headerlink" title="密度图 (Density Plot)"></a>密度图 (Density Plot)</h3><p>密度图是一种常用工具,用于可视化连续变量的分布。 通过“响应”变量对它们进行分组,您可以检查 X 和 Y 之间的关系。以下情况用于表示目的,以描述城市里程的分布如何随着汽缸数的变化而变化。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Import Data</span></span><br><span class="line">df = pd.read_csv(<span class="string">"./mpg_ggplot2.csv"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw Plot</span></span><br><span class="line">plt.figure(figsize=(<span class="number">16</span>,<span class="number">10</span>), dpi= <span class="number">80</span>)</span><br><span class="line">sns.kdeplot(df.loc[df[<span class="string">'cyl'</span>] == <span class="number">4</span>, <span class="string">"cty"</span>], shade=<span class="literal">True</span>, color=<span class="string">"g"</span>, label=<span class="string">"Cyl=4"</span>, alpha=<span class="number">.7</span>)</span><br><span class="line">sns.kdeplot(df.loc[df[<span class="string">'cyl'</span>] == <span class="number">5</span>, <span class="string">"cty"</span>], shade=<span class="literal">True</span>, color=<span class="string">"deeppink"</span>, label=<span class="string">"Cyl=5"</span>, alpha=<span class="number">.7</span>)</span><br><span class="line">sns.kdeplot(df.loc[df[<span class="string">'cyl'</span>] == <span class="number">6</span>, <span class="string">"cty"</span>], shade=<span class="literal">True</span>, color=<span class="string">"dodgerblue"</span>, label=<span class="string">"Cyl=6"</span>, alpha=<span class="number">.7</span>)</span><br><span class="line">sns.kdeplot(df.loc[df[<span class="string">'cyl'</span>] == <span class="number">8</span>, <span class="string">"cty"</span>], shade=<span class="literal">True</span>, color=<span class="string">"orange"</span>, label=<span class="string">"Cyl=8"</span>, alpha=<span class="number">.7</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Decoration</span></span><br><span class="line">plt.title(<span class="string">'Density Plot of City Mileage by n_Cylinders'</span>, fontsize=<span class="number">22</span>)</span><br><span class="line">plt.legend()</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-6048d364464a4563.png" alt="png"></p><h3 id="箱形图-(Box-Plot)"><a href="#箱形图-(Box-Plot)" class="headerlink" title="箱形图 (Box Plot)"></a>箱形图 (Box Plot)</h3><p>箱形图是一种可视化分布的好方法,记住中位数、第25个第45个四分位数和异常值。 但是,您需要注意解释可能会扭曲该组中包含的点数的框的大小。 因此,手动提供每个框中的观察数量可以帮助克服这个缺点。</p><p>例如,左边的前两个框具有相同大小的框,即使它们的值分别是5和47。 因此,写入该组中的观察数量是必要的。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Import Data</span></span><br><span class="line">df = pd.read_csv(<span class="string">"./mpg_ggplot2.csv"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw Plot</span></span><br><span class="line">plt.figure(figsize=(<span class="number">13</span>,<span class="number">10</span>), dpi= <span class="number">80</span>)</span><br><span class="line">sns.boxplot(x=<span class="string">'class'</span>, y=<span class="string">'hwy'</span>, data=df, notch=<span class="literal">False</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Add N Obs inside boxplot (optional)</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">add_n_obs</span><span class="params">(df,group_col,y)</span>:</span></span><br><span class="line"> medians_dict = {grp[<span class="number">0</span>]:grp[<span class="number">1</span>][y].median() <span class="keyword">for</span> grp <span class="keyword">in</span> df.groupby(group_col)}</span><br><span class="line"> xticklabels = [x.get_text() <span class="keyword">for</span> x <span class="keyword">in</span> plt.gca().get_xticklabels()]</span><br><span class="line"> n_obs = df.groupby(group_col)[y].size().values</span><br><span class="line"> <span class="keyword">for</span> (x, xticklabel), n_ob <span class="keyword">in</span> zip(enumerate(xticklabels), n_obs):</span><br><span class="line"> plt.text(x, medians_dict[xticklabel]*<span class="number">1.01</span>, <span class="string">"#obs : "</span>+str(n_ob), horizontalalignment=<span class="string">'center'</span>, fontdict={<span class="string">'size'</span>:<span class="number">14</span>}, color=<span class="string">'white'</span>)</span><br><span class="line"></span><br><span class="line">add_n_obs(df,group_col=<span class="string">'class'</span>,y=<span class="string">'hwy'</span>) </span><br><span class="line"></span><br><span class="line"><span class="comment"># Decoration</span></span><br><span class="line">plt.title(<span class="string">'Box Plot of Highway Mileage by Vehicle Class'</span>, fontsize=<span class="number">22</span>)</span><br><span class="line">plt.ylim(<span class="number">10</span>, <span class="number">40</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-e81de642836a787e.png" alt="png"></p><h3 id="人口金字塔-(Population-Pyramid)"><a href="#人口金字塔-(Population-Pyramid)" class="headerlink" title="人口金字塔 (Population Pyramid)"></a>人口金字塔 (Population Pyramid)</h3><p>人口金字塔可用于显示由数量排序的组的分布。 或者它也可以用于显示人口的逐级过滤,因为它在下面用于显示有多少人通过营销渠道的每个阶段。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Read data</span></span><br><span class="line">df = pd.read_csv(<span class="string">"./email_campaign_funnel.csv"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw Plot</span></span><br><span class="line">plt.figure(figsize=(<span class="number">13</span>,<span class="number">10</span>), dpi= <span class="number">80</span>)</span><br><span class="line">group_col = <span class="string">'Gender'</span></span><br><span class="line">order_of_bars = df.Stage.unique()[::<span class="number">-1</span>]</span><br><span class="line">colors = [plt.cm.Spectral(i/float(len(df[group_col].unique())<span class="number">-1</span>)) <span class="keyword">for</span> i <span class="keyword">in</span> range(len(df[group_col].unique()))]</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> c, group <span class="keyword">in</span> zip(colors, df[group_col].unique()):</span><br><span class="line"> sns.barplot(x=<span class="string">'Users'</span>, y=<span class="string">'Stage'</span>, data=df.loc[df[group_col]==group, :], order=order_of_bars, color=c, label=group)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Decorations </span></span><br><span class="line">plt.xlabel(<span class="string">"$Users$"</span>)</span><br><span class="line">plt.ylabel(<span class="string">"Stage of Purchase"</span>)</span><br><span class="line">plt.yticks(fontsize=<span class="number">12</span>)</span><br><span class="line">plt.title(<span class="string">"Population Pyramid of the Marketing Funnel"</span>, fontsize=<span class="number">22</span>)</span><br><span class="line">plt.legend()</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-216a1d282ac91769.png" alt="png"></p><h3 id="分类图-(Categorical-Plots)"><a href="#分类图-(Categorical-Plots)" class="headerlink" title="分类图 (Categorical Plots)"></a>分类图 (Categorical Plots)</h3><p>由 seaborn库 提供的分类图可用于可视化彼此相关的2个或更多分类变量的计数分布。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Load Dataset</span></span><br><span class="line">titanic = pd.read_csv(<span class="string">"./titanic.csv"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Plot</span></span><br><span class="line">g = sns.catplot(<span class="string">"alive"</span>, col=<span class="string">"deck"</span>, col_wrap=<span class="number">4</span>,</span><br><span class="line"> data=titanic[titanic.deck.notnull()],</span><br><span class="line"> kind=<span class="string">"count"</span>, height=<span class="number">3.5</span>, aspect=<span class="number">.8</span>, </span><br><span class="line"> palette=<span class="string">'tab20'</span>)</span><br><span class="line"></span><br><span class="line">fig.suptitle(<span class="string">'sf'</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-882f696c5d319cd3.png" alt="png"></p><h2 id="组成-(Composition)"><a href="#组成-(Composition)" class="headerlink" title="组成 (Composition)"></a>组成 (Composition)</h2><h3 id="华夫饼图-(Waffle-Chart)"><a href="#华夫饼图-(Waffle-Chart)" class="headerlink" title="华夫饼图 (Waffle Chart)"></a>华夫饼图 (Waffle Chart)</h3><p>可以使用 pywaffle包 创建华夫饼图,并用于显示更大群体中的组的组成。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#! pip install pywaffle</span></span><br><span class="line"><span class="comment"># Reference: https://stackoverflow.com/questions/41400136/how-to-do-waffle-charts-in-python-square-piechart</span></span><br><span class="line"><span class="keyword">from</span> pywaffle <span class="keyword">import</span> Waffle</span><br><span class="line"></span><br><span class="line"><span class="comment"># Import</span></span><br><span class="line">df_raw = pd.read_csv(<span class="string">"./mpg_ggplot2.csv"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Prepare Data</span></span><br><span class="line">df = df_raw.groupby(<span class="string">'class'</span>).size().reset_index(name=<span class="string">'counts'</span>)</span><br><span class="line">n_categories = df.shape[<span class="number">0</span>]</span><br><span class="line">colors = [plt.cm.inferno_r(i/float(n_categories)) <span class="keyword">for</span> i <span class="keyword">in</span> range(n_categories)]</span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw Plot and Decorate</span></span><br><span class="line">fig = plt.figure(</span><br><span class="line"> FigureClass=Waffle,</span><br><span class="line"> plots={</span><br><span class="line"> <span class="string">'111'</span>: {</span><br><span class="line"> <span class="string">'values'</span>: df[<span class="string">'counts'</span>],</span><br><span class="line"> <span class="string">'labels'</span>: [<span class="string">"{0} ({1})"</span>.format(n[<span class="number">0</span>], n[<span class="number">1</span>]) <span class="keyword">for</span> n <span class="keyword">in</span> df[[<span class="string">'class'</span>, <span class="string">'counts'</span>]].itertuples()],</span><br><span class="line"> <span class="string">'legend'</span>: {<span class="string">'loc'</span>: <span class="string">'upper left'</span>, <span class="string">'bbox_to_anchor'</span>: (<span class="number">1.05</span>, <span class="number">1</span>), <span class="string">'fontsize'</span>: <span class="number">12</span>},</span><br><span class="line"> <span class="string">'title'</span>: {<span class="string">'label'</span>: <span class="string">'# Vehicles by Class'</span>, <span class="string">'loc'</span>: <span class="string">'center'</span>, <span class="string">'fontsize'</span>:<span class="number">18</span>}</span><br><span class="line"> },</span><br><span class="line"> },</span><br><span class="line"> rows=<span class="number">7</span>,</span><br><span class="line"> colors=colors,</span><br><span class="line"> figsize=(<span class="number">16</span>, <span class="number">9</span>)</span><br><span class="line">)</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-bf1efe56ba90c1f8.png" alt="png"></p><h3 id="饼图-(Pie-Chart)"><a href="#饼图-(Pie-Chart)" class="headerlink" title="饼图 (Pie Chart)"></a>饼图 (Pie Chart)</h3><p>饼图是显示组成的经典方式。 然而,现在通常不建议使用它,因为馅饼部分的面积有时会变得误导。 因此,如果您要使用饼图,强烈建议明确记下饼图每个部分的百分比或数字。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Import</span></span><br><span class="line">df_raw = pd.read_csv(<span class="string">"https://github.com/selva86/datasets/raw/master/mpg_ggplot2.csv"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Prepare Data</span></span><br><span class="line">df = df_raw.groupby(<span class="string">'class'</span>).size().reset_index(name=<span class="string">'counts'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw Plot</span></span><br><span class="line">fig, ax = plt.subplots(figsize=(<span class="number">12</span>, <span class="number">7</span>), subplot_kw=dict(aspect=<span class="string">"equal"</span>), dpi= <span class="number">80</span>)</span><br><span class="line"></span><br><span class="line">data = df[<span class="string">'counts'</span>]</span><br><span class="line">categories = df[<span class="string">'class'</span>]</span><br><span class="line">explode = [<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0.1</span>,<span class="number">0</span>]</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">func</span><span class="params">(pct, allvals)</span>:</span></span><br><span class="line"> absolute = int(pct/<span class="number">100.</span>*np.sum(allvals))</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"{:.1f}% ({:d} )"</span>.format(pct, absolute)</span><br><span class="line"></span><br><span class="line">wedges, texts, autotexts = ax.pie(data, </span><br><span class="line"> autopct=<span class="keyword">lambda</span> pct: func(pct, data),</span><br><span class="line"> textprops=dict(color=<span class="string">"w"</span>), </span><br><span class="line"> colors=plt.cm.Dark2.colors,</span><br><span class="line"> startangle=<span class="number">140</span>,</span><br><span class="line"> explode=explode)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Decoration</span></span><br><span class="line">ax.legend(wedges, categories, title=<span class="string">"Vehicle Class"</span>, loc=<span class="string">"center left"</span>, bbox_to_anchor=(<span class="number">1</span>, <span class="number">0</span>, <span class="number">0.5</span>, <span class="number">1</span>))</span><br><span class="line">plt.setp(autotexts, size=<span class="number">10</span>, weight=<span class="number">700</span>)</span><br><span class="line">ax.set_title(<span class="string">"Class of Vehicles: Pie Chart"</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-d6860fc3a7600962.png" alt="png"></p><h3 id="条形图-(Bar-Chart)"><a href="#条形图-(Bar-Chart)" class="headerlink" title="条形图 (Bar Chart)"></a>条形图 (Bar Chart)</h3><p>条形图是基于计数或任何给定指标可视化项目的经典方式。 在下面的图表中,我为每个项目使用了不同的颜色,但您通常可能希望为所有项目选择一种颜色,除非您按组对其进行着色。 颜色名称存储在下面代码中的all_colors中。 您可以通过在<code>plt.plot()</code>中设置颜色参数来更改条的颜色。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> random</span><br><span class="line"></span><br><span class="line"><span class="comment"># Import Data</span></span><br><span class="line">df_raw = pd.read_csv(<span class="string">"./mpg_ggplot2.csv"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Prepare Data</span></span><br><span class="line">df = df_raw.groupby(<span class="string">'manufacturer'</span>).size().reset_index(name=<span class="string">'counts'</span>)</span><br><span class="line">n = df[<span class="string">'manufacturer'</span>].unique().__len__()+<span class="number">1</span></span><br><span class="line">all_colors = list(plt.cm.colors.cnames.keys())</span><br><span class="line">random.seed(<span class="number">100</span>)</span><br><span class="line">c = random.choices(all_colors, k=n)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Plot Bars</span></span><br><span class="line">plt.figure(figsize=(<span class="number">16</span>,<span class="number">10</span>), dpi= <span class="number">80</span>)</span><br><span class="line">plt.bar(df[<span class="string">'manufacturer'</span>], df[<span class="string">'counts'</span>], color=c, width=<span class="number">.5</span>)</span><br><span class="line"><span class="keyword">for</span> i, val <span class="keyword">in</span> enumerate(df[<span class="string">'counts'</span>].values):</span><br><span class="line"> plt.text(i, val, float(val), horizontalalignment=<span class="string">'center'</span>, verticalalignment=<span class="string">'bottom'</span>, fontdict={<span class="string">'fontweight'</span>:<span class="number">500</span>, <span class="string">'size'</span>:<span class="number">12</span>})</span><br><span class="line"></span><br><span class="line"><span class="comment"># Decoration</span></span><br><span class="line">plt.gca().set_xticklabels(df[<span class="string">'manufacturer'</span>], rotation=<span class="number">60</span>, horizontalalignment= <span class="string">'right'</span>)</span><br><span class="line">plt.title(<span class="string">"Number of Vehicles by Manaufacturers"</span>, fontsize=<span class="number">22</span>)</span><br><span class="line">plt.ylabel(<span class="string">'# Vehicles'</span>)</span><br><span class="line">plt.ylim(<span class="number">0</span>, <span class="number">45</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-2640d6152c6dcf4a.png" alt="png"></p><h2 id="变化-(Change)"><a href="#变化-(Change)" class="headerlink" title="变化 (Change)"></a>变化 (Change)</h2><h3 id="带波峰波谷标记的时序图-(Time-Series-with-Peaks-and-Troughs-Annotated)"><a href="#带波峰波谷标记的时序图-(Time-Series-with-Peaks-and-Troughs-Annotated)" class="headerlink" title="带波峰波谷标记的时序图 (Time Series with Peaks and Troughs Annotated)"></a>带波峰波谷标记的时序图 (Time Series with Peaks and Troughs Annotated)</h3><p>下面的时间序列绘制了所有峰值和低谷,并注释了所选特殊事件的发生。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Import Data</span></span><br><span class="line">df = pd.read_csv(<span class="string">'https://github.com/selva86/datasets/raw/master/AirPassengers.csv'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Get the Peaks and Troughs</span></span><br><span class="line">data = df[<span class="string">'traffic'</span>].values</span><br><span class="line">doublediff = np.diff(np.sign(np.diff(data)))</span><br><span class="line">peak_locations = np.where(doublediff == <span class="number">-2</span>)[<span class="number">0</span>] + <span class="number">1</span></span><br><span class="line"></span><br><span class="line">doublediff2 = np.diff(np.sign(np.diff(<span class="number">-1</span>*data)))</span><br><span class="line">trough_locations = np.where(doublediff2 == <span class="number">-2</span>)[<span class="number">0</span>] + <span class="number">1</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw Plot</span></span><br><span class="line">plt.figure(figsize=(<span class="number">16</span>,<span class="number">10</span>), dpi= <span class="number">80</span>)</span><br><span class="line">plt.plot(<span class="string">'date'</span>, <span class="string">'traffic'</span>, data=df, color=<span class="string">'tab:blue'</span>, label=<span class="string">'Air Traffic'</span>)</span><br><span class="line">plt.scatter(df.date[peak_locations], df.traffic[peak_locations], marker=mpl.markers.CARETUPBASE, color=<span class="string">'tab:green'</span>, s=<span class="number">100</span>, label=<span class="string">'Peaks'</span>)</span><br><span class="line">plt.scatter(df.date[trough_locations], df.traffic[trough_locations], marker=mpl.markers.CARETDOWNBASE, color=<span class="string">'tab:red'</span>, s=<span class="number">100</span>, label=<span class="string">'Troughs'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Annotate</span></span><br><span class="line"><span class="keyword">for</span> t, p <span class="keyword">in</span> zip(trough_locations[<span class="number">1</span>::<span class="number">5</span>], peak_locations[::<span class="number">3</span>]):</span><br><span class="line"> plt.text(df.date[p], df.traffic[p]+<span class="number">15</span>, df.date[p], horizontalalignment=<span class="string">'center'</span>, color=<span class="string">'darkgreen'</span>)</span><br><span class="line"> plt.text(df.date[t], df.traffic[t]<span class="number">-35</span>, df.date[t], horizontalalignment=<span class="string">'center'</span>, color=<span class="string">'darkred'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Decoration</span></span><br><span class="line">plt.ylim(<span class="number">50</span>,<span class="number">750</span>)</span><br><span class="line">xtick_location = df.index.tolist()[::<span class="number">6</span>]</span><br><span class="line">xtick_labels = df.date.tolist()[::<span class="number">6</span>]</span><br><span class="line">plt.xticks(ticks=xtick_location, labels=xtick_labels, rotation=<span class="number">90</span>, fontsize=<span class="number">12</span>, alpha=<span class="number">.7</span>)</span><br><span class="line">plt.title(<span class="string">"Peak and Troughs of Air Passengers Traffic (1949 - 1969)"</span>, fontsize=<span class="number">22</span>)</span><br><span class="line">plt.yticks(fontsize=<span class="number">12</span>, alpha=<span class="number">.7</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Lighten borders</span></span><br><span class="line">plt.gca().spines[<span class="string">"top"</span>].set_alpha(<span class="number">.0</span>)</span><br><span class="line">plt.gca().spines[<span class="string">"bottom"</span>].set_alpha(<span class="number">.3</span>)</span><br><span class="line">plt.gca().spines[<span class="string">"right"</span>].set_alpha(<span class="number">.0</span>)</span><br><span class="line">plt.gca().spines[<span class="string">"left"</span>].set_alpha(<span class="number">.3</span>)</span><br><span class="line"></span><br><span class="line">plt.legend(loc=<span class="string">'upper left'</span>)</span><br><span class="line">plt.grid(axis=<span class="string">'y'</span>, alpha=<span class="number">.3</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-b990bfa669bd957d.png" alt="png"></p><h3 id="多个时间序列-(Multiple-Time-Series)"><a href="#多个时间序列-(Multiple-Time-Series)" class="headerlink" title="多个时间序列 (Multiple Time Series)"></a>多个时间序列 (Multiple Time Series)</h3><p>您可以绘制多个时间序列,在同一图表上测量相同的值,如下所示。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Import Data</span></span><br><span class="line">df = pd.read_csv(<span class="string">'./mortality.csv'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Define the upper limit, lower limit, interval of Y axis and colors</span></span><br><span class="line">y_LL = <span class="number">100</span></span><br><span class="line">y_UL = int(df.iloc[:, <span class="number">1</span>:].max().max()*<span class="number">1.1</span>)</span><br><span class="line">y_interval = <span class="number">400</span></span><br><span class="line">mycolors = [<span class="string">'tab:red'</span>, <span class="string">'tab:blue'</span>, <span class="string">'tab:green'</span>, <span class="string">'tab:orange'</span>] </span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw Plot and Annotate</span></span><br><span class="line">fig, ax = plt.subplots(<span class="number">1</span>,<span class="number">1</span>,figsize=(<span class="number">16</span>, <span class="number">9</span>), dpi= <span class="number">80</span>) </span><br><span class="line"></span><br><span class="line">columns = df.columns[<span class="number">1</span>:] </span><br><span class="line"><span class="keyword">for</span> i, column <span class="keyword">in</span> enumerate(columns):</span><br><span class="line"> <span class="comment"># 原文此处有误,Python数据之道 备注</span></span><br><span class="line"> <span class="comment"># 访问 liyangbit.com , 查看本文完整内容</span></span><br><span class="line"> plt.plot(df.date.values, df[column].values, lw=<span class="number">1.5</span>, color=mycolors[i]) </span><br><span class="line"> plt.text(df.shape[<span class="number">0</span>]+<span class="number">1</span>, df[column].values[<span class="number">-1</span>], column, fontsize=<span class="number">14</span>, color=mycolors[i])</span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw Tick lines </span></span><br><span class="line"><span class="keyword">for</span> y <span class="keyword">in</span> range(y_LL, y_UL, y_interval): </span><br><span class="line"> plt.hlines(y, xmin=<span class="number">0</span>, xmax=<span class="number">71</span>, colors=<span class="string">'black'</span>, alpha=<span class="number">0.3</span>, linestyles=<span class="string">"--"</span>, lw=<span class="number">0.5</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Decorations </span></span><br><span class="line">plt.tick_params(axis=<span class="string">"both"</span>, which=<span class="string">"both"</span>, bottom=<span class="literal">False</span>, top=<span class="literal">False</span>, </span><br><span class="line"> labelbottom=<span class="literal">True</span>, left=<span class="literal">False</span>, right=<span class="literal">False</span>, labelleft=<span class="literal">True</span>) </span><br><span class="line"></span><br><span class="line"><span class="comment"># Lighten borders</span></span><br><span class="line">plt.gca().spines[<span class="string">"top"</span>].set_alpha(<span class="number">.3</span>)</span><br><span class="line">plt.gca().spines[<span class="string">"bottom"</span>].set_alpha(<span class="number">.3</span>)</span><br><span class="line">plt.gca().spines[<span class="string">"right"</span>].set_alpha(<span class="number">.3</span>)</span><br><span class="line">plt.gca().spines[<span class="string">"left"</span>].set_alpha(<span class="number">.3</span>)</span><br><span class="line"></span><br><span class="line">plt.title(<span class="string">'Number of Deaths from Lung Diseases in the UK (1974-1979)'</span>, fontsize=<span class="number">22</span>)</span><br><span class="line">plt.yticks(range(y_LL, y_UL, y_interval), [str(y) <span class="keyword">for</span> y <span class="keyword">in</span> range(y_LL, y_UL, y_interval)], fontsize=<span class="number">12</span>) </span><br><span class="line">plt.xticks(range(<span class="number">0</span>, df.shape[<span class="number">0</span>], <span class="number">12</span>), df.date.values[::<span class="number">12</span>], horizontalalignment=<span class="string">'left'</span>, fontsize=<span class="number">12</span>) </span><br><span class="line">plt.ylim(y_LL, y_UL) </span><br><span class="line">plt.xlim(<span class="number">-2</span>, <span class="number">80</span>) </span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-81d0b50987fd3bbd.png" alt="png"></p><h3 id="使用辅助-Y-轴来绘制不同范围的图形-(Plotting-with-different-scales-using-secondary-Y-axis)"><a href="#使用辅助-Y-轴来绘制不同范围的图形-(Plotting-with-different-scales-using-secondary-Y-axis)" class="headerlink" title="使用辅助 Y 轴来绘制不同范围的图形 (Plotting with different scales using secondary Y axis)"></a>使用辅助 Y 轴来绘制不同范围的图形 (Plotting with different scales using secondary Y axis)</h3><p>如果要显示在同一时间点测量两个不同数量的两个时间序列,则可以在右侧的辅助Y轴上再绘制第二个系列。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Import Data</span></span><br><span class="line">df = pd.read_csv(<span class="string">"./economics.csv"</span>)</span><br><span class="line"></span><br><span class="line">x = df[<span class="string">'date'</span>]</span><br><span class="line">y1 = df[<span class="string">'psavert'</span>]</span><br><span class="line">y2 = df[<span class="string">'unemploy'</span>]</span><br><span class="line"></span><br><span class="line"><span class="comment"># Plot Line1 (Left Y Axis)</span></span><br><span class="line">fig, ax1 = plt.subplots(<span class="number">1</span>,<span class="number">1</span>,figsize=(<span class="number">16</span>,<span class="number">9</span>), dpi= <span class="number">80</span>)</span><br><span class="line">ax1.plot(x, y1, color=<span class="string">'tab:red'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Plot Line2 (Right Y Axis)</span></span><br><span class="line">ax2 = ax1.twinx() <span class="comment"># instantiate a second axes that shares the same x-axis</span></span><br><span class="line">ax2.plot(x, y2, color=<span class="string">'tab:blue'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Decorations</span></span><br><span class="line"><span class="comment"># ax1 (left Y axis)</span></span><br><span class="line">ax1.set_xlabel(<span class="string">'Year'</span>, fontsize=<span class="number">20</span>)</span><br><span class="line">ax1.tick_params(axis=<span class="string">'x'</span>, rotation=<span class="number">0</span>, labelsize=<span class="number">12</span>)</span><br><span class="line">ax1.set_ylabel(<span class="string">'Personal Savings Rate'</span>, color=<span class="string">'tab:red'</span>, fontsize=<span class="number">20</span>)</span><br><span class="line">ax1.tick_params(axis=<span class="string">'y'</span>, rotation=<span class="number">0</span>, labelcolor=<span class="string">'tab:red'</span> )</span><br><span class="line">ax1.grid(alpha=<span class="number">.4</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># ax2 (right Y axis)</span></span><br><span class="line">ax2.set_ylabel(<span class="string">"# Unemployed (1000's)"</span>, color=<span class="string">'tab:blue'</span>, fontsize=<span class="number">20</span>)</span><br><span class="line">ax2.tick_params(axis=<span class="string">'y'</span>, labelcolor=<span class="string">'tab:blue'</span>)</span><br><span class="line">ax2.set_xticks(np.arange(<span class="number">0</span>, len(x), <span class="number">60</span>))</span><br><span class="line">ax2.set_xticklabels(x[::<span class="number">60</span>], rotation=<span class="number">90</span>, fontdict={<span class="string">'fontsize'</span>:<span class="number">10</span>})</span><br><span class="line">ax2.set_title(<span class="string">"Personal Savings Rate vs Unemployed: Plotting in Secondary Y Axis"</span>, fontsize=<span class="number">22</span>)</span><br><span class="line">fig.tight_layout()</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-370e407fab36a59e.png" alt="png"></p><h2 id="分组-(Groups)"><a href="#分组-(Groups)" class="headerlink" title="分组 (Groups)"></a>分组 (Groups)</h2><h3 id="树状图-(Dendrogram)"><a href="#树状图-(Dendrogram)" class="headerlink" title="树状图 (Dendrogram)"></a>树状图 (Dendrogram)</h3><p>树形图基于给定的距离度量将相似的点组合在一起,并基于点的相似性将它们组织在树状链接中。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> scipy.cluster.hierarchy <span class="keyword">as</span> shc</span><br><span class="line"></span><br><span class="line"><span class="comment"># Import Data</span></span><br><span class="line">df = pd.read_csv(<span class="string">'./USArrests.csv'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Plot</span></span><br><span class="line">plt.figure(figsize=(<span class="number">16</span>, <span class="number">10</span>), dpi= <span class="number">80</span>) </span><br><span class="line">plt.title(<span class="string">"USArrests Dendograms"</span>, fontsize=<span class="number">22</span>) </span><br><span class="line">dend = shc.dendrogram(shc.linkage(df[[<span class="string">'Murder'</span>, <span class="string">'Assault'</span>, <span class="string">'UrbanPop'</span>, <span class="string">'Rape'</span>]], method=<span class="string">'ward'</span>), labels=df.State.values, color_threshold=<span class="number">100</span>) </span><br><span class="line">plt.xticks(fontsize=<span class="number">12</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-ecb696839eb9ffbf.png" alt="png"></p><h3 id="簇状图-(Cluster-Plot)"><a href="#簇状图-(Cluster-Plot)" class="headerlink" title="簇状图 (Cluster Plot)"></a>簇状图 (Cluster Plot)</h3><p>簇状图 (Cluster Plot)可用于划分属于同一群集的点。 下面是根据USArrests数据集将美国各州分为5组的代表性示例。 此图使用“谋杀”和“攻击”列作为X和Y轴。 或者,您可以将第一个到主要组件用作X轴和Y轴。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> sklearn.cluster <span class="keyword">import</span> AgglomerativeClustering</span><br><span class="line"><span class="keyword">from</span> scipy.spatial <span class="keyword">import</span> ConvexHull</span><br><span class="line"></span><br><span class="line"><span class="comment"># Import Data</span></span><br><span class="line">df = pd.read_csv(<span class="string">'./USArrests.csv'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Agglomerative Clustering</span></span><br><span class="line">cluster = AgglomerativeClustering(n_clusters=<span class="number">5</span>, affinity=<span class="string">'euclidean'</span>, linkage=<span class="string">'ward'</span>) </span><br><span class="line">cluster.fit_predict(df[[<span class="string">'Murder'</span>, <span class="string">'Assault'</span>, <span class="string">'UrbanPop'</span>, <span class="string">'Rape'</span>]]) </span><br><span class="line"></span><br><span class="line"><span class="comment"># Plot</span></span><br><span class="line">plt.figure(figsize=(<span class="number">14</span>, <span class="number">10</span>), dpi= <span class="number">80</span>) </span><br><span class="line">plt.scatter(df.iloc[:,<span class="number">0</span>], df.iloc[:,<span class="number">1</span>], c=cluster.labels_, cmap=<span class="string">'tab10'</span>) </span><br><span class="line"></span><br><span class="line"><span class="comment"># Encircle</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">encircle</span><span class="params">(x,y, ax=None, **kw)</span>:</span></span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">not</span> ax: ax=plt.gca()</span><br><span class="line"> p = np.c_[x,y]</span><br><span class="line"> hull = ConvexHull(p)</span><br><span class="line"> poly = plt.Polygon(p[hull.vertices,:], **kw)</span><br><span class="line"> ax.add_patch(poly)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Draw polygon surrounding vertices </span></span><br><span class="line">encircle(df.loc[cluster.labels_ == <span class="number">0</span>, <span class="string">'Murder'</span>], df.loc[cluster.labels_ == <span class="number">0</span>, <span class="string">'Assault'</span>], ec=<span class="string">"k"</span>, fc=<span class="string">"gold"</span>, alpha=<span class="number">0.2</span>, linewidth=<span class="number">0</span>)</span><br><span class="line">encircle(df.loc[cluster.labels_ == <span class="number">1</span>, <span class="string">'Murder'</span>], df.loc[cluster.labels_ == <span class="number">1</span>, <span class="string">'Assault'</span>], ec=<span class="string">"k"</span>, fc=<span class="string">"tab:blue"</span>, alpha=<span class="number">0.2</span>, linewidth=<span class="number">0</span>)</span><br><span class="line">encircle(df.loc[cluster.labels_ == <span class="number">2</span>, <span class="string">'Murder'</span>], df.loc[cluster.labels_ == <span class="number">2</span>, <span class="string">'Assault'</span>], ec=<span class="string">"k"</span>, fc=<span class="string">"tab:red"</span>, alpha=<span class="number">0.2</span>, linewidth=<span class="number">0</span>)</span><br><span class="line">encircle(df.loc[cluster.labels_ == <span class="number">3</span>, <span class="string">'Murder'</span>], df.loc[cluster.labels_ == <span class="number">3</span>, <span class="string">'Assault'</span>], ec=<span class="string">"k"</span>, fc=<span class="string">"tab:green"</span>, alpha=<span class="number">0.2</span>, linewidth=<span class="number">0</span>)</span><br><span class="line">encircle(df.loc[cluster.labels_ == <span class="number">4</span>, <span class="string">'Murder'</span>], df.loc[cluster.labels_ == <span class="number">4</span>, <span class="string">'Assault'</span>], ec=<span class="string">"k"</span>, fc=<span class="string">"tab:orange"</span>, alpha=<span class="number">0.2</span>, linewidth=<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Decorations</span></span><br><span class="line">plt.xlabel(<span class="string">'Murder'</span>); plt.xticks(fontsize=<span class="number">12</span>)</span><br><span class="line">plt.ylabel(<span class="string">'Assault'</span>); plt.yticks(fontsize=<span class="number">12</span>)</span><br><span class="line">plt.title(<span class="string">'Agglomerative Clustering of USArrests (5 Groups)'</span>, fontsize=<span class="number">22</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-6fccc0619497f94d.png" alt="png"></p><h1 id="动态排名数据可视化"><a href="#动态排名数据可视化" class="headerlink" title="动态排名数据可视化"></a>动态排名数据可视化</h1><h3 id="将历史数据排名转化为动态柱状图图表"><a href="#将历史数据排名转化为动态柱状图图表" class="headerlink" title="将历史数据排名转化为动态柱状图图表"></a>将历史数据排名转化为动态柱状图图表</h3><p>见github地址:<a href="https://github.com/Jannchie/Historical-ranking-data-visualization-based-on-d3.js" target="_blank" rel="noopener">动态排名数据可视化-将历史数据排名转化为动态柱状图图表</a></p><p><img src="http://upload-images.jianshu.io/upload_images/15914329-c4c0733d0514ca63.png" alt="image-20200303132124173"></p>]]></content>
<summary type="html">
<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>一直说要做一个python可视化的学习,今天就来认真学一学。</p>
<p>交互式的可视化起码我暂时都用不着,先学静态的。知乎搜了一些教程,
</summary>
<category term="学习" scheme="http://jaxchan.top/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="编程" scheme="http://jaxchan.top/categories/%E5%AD%A6%E4%B9%A0/%E7%BC%96%E7%A8%8B/"/>
<category term="python" scheme="http://jaxchan.top/tags/python/"/>
<category term="可视化" scheme="http://jaxchan.top/tags/%E5%8F%AF%E8%A7%86%E5%8C%96/"/>
</entry>
<entry>
<title>日记1:关于生活态度的很杂的话</title>
<link href="http://jaxchan.top/2020/%E6%97%A5%E8%AE%B01%EF%BC%9A%E5%85%B3%E4%BA%8E%E7%94%9F%E6%B4%BB%E6%80%81%E5%BA%A6%E7%9A%84%E5%BE%88%E6%9D%82%E7%9A%84%E8%AF%9D.html/"/>
<id>http://jaxchan.top/2020/%E6%97%A5%E8%AE%B01%EF%BC%9A%E5%85%B3%E4%BA%8E%E7%94%9F%E6%B4%BB%E6%80%81%E5%BA%A6%E7%9A%84%E5%BE%88%E6%9D%82%E7%9A%84%E8%AF%9D.html/</id>
<published>2020-03-01T16:35:45.000Z</published>
<updated>2020-03-01T16:36:47.464Z</updated>
<content type="html"><![CDATA[<h1 id="PART1-我觉得缺了些什么"><a href="#PART1-我觉得缺了些什么" class="headerlink" title="PART1: 我觉得缺了些什么"></a>PART1: 我觉得缺了些什么</h1><p>今天是三月份的第一天。</p><p>二月份的24号开学,到现在已经整一个星期了。</p><p>我总是 总是觉得,缺了点什么,但是又说不上来缺了什么。</p><p>可能和在学校做的事情相差无几,但是就是少了一些应有的味道。</p><p>人是群居动物,果真没有错,一个人走得快,一堆人走得远,果真也是没有错。</p><p>我尝试描述一下,我的生活缺了些什么</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">我刚开始想 生活缺了什么的时候</span><br><span class="line">就开始对比在家的生活和在学校生活的差别</span><br><span class="line">那自然是按照时间线索</span><br><span class="line">第一件事 早起肯定是要和舍友拥挤刷牙 一边吹水的</span><br><span class="line">但其实这是一件不好的事 不值得用来怀念</span><br><span class="line">因此我也也就没有写</span><br><span class="line">我是想说 有一些很特别的事 虽然他它很特别 很有味道 但是它终究是没有多好的事</span><br><span class="line">譬如说 之前在我朋友圈很红火的关于海中早餐炒粉的怀念</span><br><span class="line">其实我怎么说呢 我是真的一点一点都不怀念那个炒粉 还有汤粉 还有糯米鸡</span><br><span class="line">我怀念的是 高中的感觉 拼搏的 纯粹的时光以及那一堆好朋友</span><br><span class="line">扯了这么远,我是在这篇日记插播了另一个论点</span><br><span class="line">当我们喜欢一个东西 怀念一段时光 我们分得清楚我们喜欢的是什么 (感情也是这样</span><br></pre></td></tr></table></figure><p>1.</p><p>缺了些和同龄人的争论</p><p>我是一个经常与别人交流的人 我希望听他们各种各样的故事</p><p>也经常好像满不在意地给出一些建议和反馈 或者 给出一些非常搞笑的评论</p><p>然后再给出我认认真真的建议</p><p>我觉得我是一个离不开社交的人 分辨得清楚一点 我是一个不能不和别人交流的人</p><p>2.</p><p>确实是缺了些自由感</p><p>我是一个极其追求自由的人 </p><p>比如说今天吃什么 今晚吃什么</p><p>虽然我经常说随便 或者说经常在纠结要吃什么</p><p>但是在家就少了这种纠结</p><p>哦对</p><p>与其说我少了些自由感 还不如说我少了纠结 因为我遇到的问题实在是太少了 相对于上学来说 我遇到的事情少之又少 也因此没什么纠结的地方</p><p>其实这也是不好的 以前的学期我上学就是等于忙得要死 现在突然闲下来 要干的正事好像也没有多大的动力 必须完成的动力去做 可能还没有什么压力吧</p><p>这样说的话 我是缺了些犹豫和纠结</p><p>3.</p><p>也没有了</p><h1 id="PART2-关于我的生活态度"><a href="#PART2-关于我的生活态度" class="headerlink" title="PART2: 关于我的生活态度"></a>PART2: 关于我的生活态度</h1><p>很久之前我在朋友圈说过关于生命力的个人阐述,我贴一下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">在boring的中国文学与文化通选课里,</span><br><span class="line">黄教授批评了广州的天气,</span><br><span class="line">说几乎不变的气候抑制了人类感触的天性,</span><br><span class="line">说若有四季轮转,方可感受到生命周期的流转。</span><br><span class="line"></span><br><span class="line">今天广州便给足了面子,</span><br><span class="line">和煦的阳光、拂面的风…所有的美好形容词在我脑海里涌了上来。</span><br><span class="line">从酷热到舒适的天气变化,让人感到生命力的存在。</span><br><span class="line"></span><br><span class="line">我一直觉得,变化才是感受生命力的主要因素。</span><br><span class="line">校道的封禁和开垦。</span><br><span class="line">理发店再见和7-11、水果店你好。</span><br><span class="line">新生的报道让学区从冷清到繁忙。</span><br><span class="line">小黄车的没落让青柠和鲜橙降临。</span><br><span class="line"></span><br><span class="line">可能准确来说,新鲜感带来的朦胧美意让人感到迫近幸福。</span><br><span class="line"></span><br><span class="line">我常在想,</span><br><span class="line">要是明天也是这样的天气,我应该不会有那么多赞叹。</span><br><span class="line">要是习惯了新生的存在,应该不再对他们刷卡的手忙脚乱觉得呆萌可爱。</span><br><span class="line">要是习惯了走那条绕路的校道,也不再觉得麻烦,只是走而已。</span><br><span class="line"></span><br><span class="line">生命的活力也是这样陨落的,在习以为常和感触麻木当中。</span><br><span class="line"></span><br><span class="line">我有时候觉得自己是一个追猎新鲜感的可怜动物。虽然现在来说,我也是追求生命的律动。</span><br><span class="line"></span><br><span class="line">我收益于此,不轻易沉迷上瘾活动,</span><br><span class="line">也受限于此,很容易感到无聊与厌倦。</span><br><span class="line"></span><br><span class="line">我也应该改掉这坏习惯,</span><br><span class="line">不能因为习惯了,带来的感受不强了,就否认了某项的价值。</span><br><span class="line">所以,</span><br><span class="line">如果明天是像今天这样的好天气,我就继续像今天一样赞叹它!</span><br></pre></td></tr></table></figure><p>其实我一直没能想清楚,追求新鲜感到底是好还是不好。</p><p>好奇 是好还是不好</p><p>好学 是好还是不好</p><p>热于尝试新的生活方式 接触新的内容 实践新的技术到底是好还是不好</p><p>我觉得上述的问题 在我这里都是好的</p><p>但对于<strong>感情</strong>来说 这个又因为环境的原因我又不能说好 又不能说不好 一直都被世道裹挟着 也因而没有想清楚</p><p><img src="http://upload-images.jianshu.io/upload_images/15914329-35f12abd6e8124f1.jpg" style="zoom:50%;" /></p><p>其实也经不起推敲 生活琐碎之事明明是那么多 每天也是要吃饭睡觉 总不能不睡觉就当作是新鲜</p><p>所以说</p><p>其实对于感情这一块 根本就没有答案</p><p>只有遇到了对的人 无论是做什么重复的事 也会觉得甘之如饴 那也就不需要讨论这个感情是否需要新鲜感的事了</p><p>当然了 感情还是需要保鲜的</p><h1 id="PART3-我最近想做的事"><a href="#PART3-我最近想做的事" class="headerlink" title="PART3: 我最近想做的事"></a>PART3: 我最近想做的事</h1><p>这个blog始终是一个不完整的blog。首先它没有评论功能,而且它的图床没有用我个人的图床,而是用第三方的。但是我最近,起码是在自己买vps之前我都不打算改进了。</p><p>本周内吧:</p><ul><li>我要先把一篇tutorial写完</li><li>要再看两篇数模的论文</li><li>学习一下python可视化</li><li>也不妨也看看实习和面试的东西</li><li>也不妨和大家多聊聊天</li></ul>]]></content>
<summary type="html">
<h1 id="PART1-我觉得缺了些什么"><a href="#PART1-我觉得缺了些什么" class="headerlink" title="PART1: 我觉得缺了些什么"></a>PART1: 我觉得缺了些什么</h1><p>今天是三月份的第一天。</p>
<p>二
</summary>
<category term="日记" scheme="http://jaxchan.top/categories/%E6%97%A5%E8%AE%B0/"/>
<category term="生活" scheme="http://jaxchan.top/categories/%E6%97%A5%E8%AE%B0/%E7%94%9F%E6%B4%BB/"/>
<category term="面试" scheme="http://jaxchan.top/tags/%E9%9D%A2%E8%AF%95/"/>
<category term="日记" scheme="http://jaxchan.top/tags/%E6%97%A5%E8%AE%B0/"/>
<category term="新鲜感" scheme="http://jaxchan.top/tags/%E6%96%B0%E9%B2%9C%E6%84%9F/"/>
<category term="数模" scheme="http://jaxchan.top/tags/%E6%95%B0%E6%A8%A1/"/>
</entry>
<entry>
<title>开学:今天天气很好,适合养龙</title>
<link href="http://jaxchan.top/2020/%E5%BC%80%E5%AD%A6%EF%BC%9A%E4%BB%8A%E5%A4%A9%E5%A4%A9%E6%B0%94%E5%BE%88%E5%A5%BD%EF%BC%8C%E9%80%82%E5%90%88%E5%85%BB%E9%BE%99.html/"/>
<id>http://jaxchan.top/2020/%E5%BC%80%E5%AD%A6%EF%BC%9A%E4%BB%8A%E5%A4%A9%E5%A4%A9%E6%B0%94%E5%BE%88%E5%A5%BD%EF%BC%8C%E9%80%82%E5%90%88%E5%85%BB%E9%BE%99.html/</id>
<published>2020-02-26T03:33:45.000Z</published>
<updated>2020-02-28T11:52:59.828Z</updated>
<content type="html"><![CDATA[<h1 id="没用的话"><a href="#没用的话" class="headerlink" title="没用的话"></a>没用的话</h1><p>前天是2.24,是学校开学的第一天,为了升旗很早就起床了。没想到昨天和今天也很早就自然醒,也许调整生物钟也只需要早起一两天就会调整回去。</p><p>昨天我跟妈妈说今天天气很好,妈妈说这几天天气都很好。我说,如果我在学校,每每我看到天空我就会说,”今天天气很好”,然后舍友就会说”知道了你说天气很好说了十几遍了”。妈妈大笑。</p><p>我只有周四才有两门课,所以我都没感觉到开学了和没开学的区别在哪里,只是该做事情还在做,该打的游戏的还在打。</p><p>最近和舍友一起在讨论工作、读研和出国的利弊,我一直都在纠结,开学后我觉得要认真考虑好做出抉择了。放假便感觉所有事情都存档了,开学便把存档重新拿出来。然后上学期没有思考清楚的东西作出选择的东西,现在又要去真正地抉择,但也好,上学期纠结的东西有些现在已经完全不纠结了。</p><p>最近可以做的事就是:看看各位导师;看看各个就业岗位要求;少刷抖音多刷知乎</p><p><img src="http://upload-images.jianshu.io/upload_images/15914329-14fa3dfa4abaff4a.jpg" alt=""></p><center>开学升旗后拍的日出</center><h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>要开始准备美赛的东西了。对于建模我只有模糊的想法,没有很入门,现在就先看这个题目和优秀论文感受一下,看看后面学什么比较合适。</p><p>看完之后觉得… 要学习画画(开玩笑) 要学解方程(到时候交给别人吧?) 要学数据可视化(简单学学) 还有多看看科普文章</p><p>后面再看一两篇感受一下。</p><h1 id="原题"><a href="#原题" class="headerlink" title="原题"></a>原题</h1><p>查看 <strong><a href="https://github.com/zouzhenhong98/2019MCM" target="_blank" rel="noopener">2019MCM</a></strong></p><p><img src="http://upload-images.jianshu.io/upload_images/15914329-9aaa9144c291de30.png" alt=""></p><h1 id="读题"><a href="#读题" class="headerlink" title="读题"></a>读题</h1><h2 id="问题描述"><a href="#问题描述" class="headerlink" title="问题描述"></a>问题描述</h2><p>分析龙的特性、行为、习惯、饮食和与环境的交互。</p><p>完成以下基本问题:</p><ol><li>龙的生态环境(需求)是什么?龙的生态影响是什么?</li><li>龙的能源(体能)支出是多少</li><li>卡路里摄入的需求量是多少?</li><li>养三条龙 需要多大的地方?</li><li>需要多大的社区来 给三条龙 提供各种各样的援助?</li></ol><p>关于迁徙事件,<strong>气候条件对你的分析有多重要</strong>?</p><ul><li>在干旱地区、温暖地区、北极(极寒) 之间发生迁徙行为时,所需要的资源变化</li></ul><p>完成分析后,写一封两页的信给《冰与火之歌》的作者,告诉他如何保持现代的生态基础,尤其是由干旱地区到温热地区或者到北极地区。</p><h2 id="给定条件"><a href="#给定条件" class="headerlink" title="给定条件"></a>给定条件</h2><ol><li>三条龙</li><li>孵化出来时,很小,大概是10kg,一年后大概是30kg-40kg</li><li>一生都会成长,成长程度取决于 饲喂的食物的<strong>质量</strong>和<strong>数量</strong></li><li>活在当今时代</li></ol><h2 id="建议假设"><a href="#建议假设" class="headerlink" title="建议假设"></a>建议假设</h2><p>假设原则:<strong>应该清楚假设与 功能性、大小、饮食、改变等特性的联系性</strong></p><p>题目给出了一些假设建议:</p><ol><li>龙飞得很远</li><li>呼吸火</li><li>抵御巨大创伤</li></ol><hr><h1 id="优秀论文阅读"><a href="#优秀论文阅读" class="headerlink" title="优秀论文阅读"></a>优秀论文阅读</h1><h2 id="前提假设"><a href="#前提假设" class="headerlink" title="前提假设"></a>前提假设</h2><ul><li>龙的生长、成熟遵循基本的生物规则。</li><li>龙是恒温动物。</li><li>龙会飞和承受巨伤,不会因为物理、化学、生物攻击而轻易死亡。飞行满足空气动力学。成熟的龙是地球最大的生物。龙会喷火。</li><li>龙汲取的能量要满足基本生活和成长的消耗。</li><li>龙出生的长度为30-40cm。根据爬行动物幼体和电视剧推测。</li><li>龙一旦进入新的生态圈,那便编程该圈最顶级的消费者。但龙不会给生物圈造成致命的损坏。并且人类可以有效地控制龙。</li></ul><h2 id="符号"><a href="#符号" class="headerlink" title="符号"></a>符号</h2><p><img src="http://upload-images.jianshu.io/upload_images/15914329-6b374807954327fe.png" alt=""></p><h2 id="Dragon’s-Physical-Characteristics-and-Diet"><a href="#Dragon’s-Physical-Characteristics-and-Diet" class="headerlink" title="Dragon’s Physical Characteristics and Diet"></a>Dragon’s Physical Characteristics and Diet</h2><p>假设龙在25℃的温带环境,可以从环境获取充足食物。根据形态学,生物不可能无限生长,所以龙成熟之后,weight和lengt0 ( shoulder to hip ) 都会被限制。</p><h3 id="Dragon’s-Weight-Logistic-Growth-Model"><a href="#Dragon’s-Weight-Logistic-Growth-Model" class="headerlink" title="Dragon’s Weight Logistic Growth Model"></a>Dragon’s Weight Logistic Growth Model</h3><p>由于体型和环境容量限制,龙的体重会逐渐被限制增长。</p><p>暂假设龙的成长不会被环境和体型限制,因此体重满足:</p><script type="math/tex; mode=display">\frac{d W(t)}{d t}=r W(t)</script><p>现补充形态限制,</p><script type="math/tex; mode=display">\frac{d W(t)}{d t}=r W(t)\left(1-\frac{W(t)}{W_{\max }}\right)</script><p>又因:多数有机体在温度较高的环境而体型变小,假设温度对龙的成长的影响是线性的,故更新为</p><script type="math/tex; mode=display">\frac{d W(t)}{d t}=r W(t)\left(1-\frac{W(t)}{W_{\max }}-\sigma T\right)</script><p>假设龙出生为10kg,即W(0) = 10. 故有如下加权一阶非线性微分方程</p><script type="math/tex; mode=display">\left\{\begin{array}{l}{\frac{d W(t)}{d t}=r W(t)\left(1-\frac{W(t)}{W_{\max }}-\sigma T\right)} \\{W(0)=10}\end{array}\right.</script><p>为了方便求解,令$\alpha=1-\sigma T,\sigma=0.04$ , 故可求解为:</p><script type="math/tex; mode=display">W(t)=10 \alpha W_{\max } \frac{e^{\alpha r t}}{\alpha K+10 e^{\alpha r t-1}}</script><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">K是什么?</span><br></pre></td></tr></table></figure><p>现在我们求解一下参数r </p><p><img src="http://upload-images.jianshu.io/upload_images/15914329-bebee1573679f0dc.png" alt=""></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">不知道怎么来的??</span><br></pre></td></tr></table></figure><p>因此 r 的范围是 20 - 30,单位是 kg/year </p><p>综上所述,有以下参数</p><p><img src="http://upload-images.jianshu.io/upload_images/15914329-da49b3a25f79b56c.png" alt=""></p><p>可以画出W(t)的图:</p><p><img src="http://upload-images.jianshu.io/upload_images/15914329-1b9cd54962589a2a.png" alt=""></p><p>最大值为15ton</p><h3 id="Dragon’s-Length-Analysis-Based-on-Analogy"><a href="#Dragon’s-Length-Analysis-Based-on-Analogy" class="headerlink" title="Dragon’s Length Analysis Based on Analogy"></a>Dragon’s Length Analysis Based on Analogy</h3><p>把龙假设为圆柱体,长为L米,直径为D米,底面积为S。</p><p> <img src="http://upload-images.jianshu.io/upload_images/15914329-3f2fcc9df2e3ffde.png" alt=""></p><p>由于重力的影响,假设圆柱体弯曲度为C米,根据机械学有</p><script type="math/tex; mode=display">\frac{C}{L} \propto \frac{W L^{3}}{S d^{2}}</script><p>且C/L为定值</p><p>假设密度均等,固有</p><script type="math/tex; mode=display">W \propto S L, S \propto d^{2}</script><p>根据上述两个式子得</p><script type="math/tex; mode=display">W=k L^{4}</script><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">这个W是怎么推出来的?</span><br></pre></td></tr></table></figure><p>根据电视剧可以得初生龙为0.7m~0.9m,而W(0) = 10 可算k</p><p>可画出如下的图</p><p><img src="http://upload-images.jianshu.io/upload_images/15914329-8d317252c542c690.png" alt=""></p><h3 id="Dragon’s-Energy-Expenditure-and-Caloric-Intake"><a href="#Dragon’s-Energy-Expenditure-and-Caloric-Intake" class="headerlink" title="Dragon’s Energy Expenditure and Caloric Intake"></a>Dragon’s Energy Expenditure and Caloric Intake</h3><p>根据假设,龙是恒温的肉食动物。故龙的能量摄入至少等于龙的能量消耗,而可认为龙的能量消耗主要等于飞行和喷火。</p><h4 id="Dragon’s-Diet-and-Energy-Consumption-during-Flight"><a href="#Dragon’s-Diet-and-Energy-Consumption-during-Flight" class="headerlink" title="Dragon’s Diet and Energy Consumption during Flight"></a>Dragon’s Diet and Energy Consumption during Flight</h4><p>在此章节不考虑龙喷火。</p><p>北方人摄入2000cal/day, 假设能量设如与身体重量成正比,可估算成熟龙需要摄入400,000cal/day</p><p>同理,</p><p>冰原狼食用12kg/day的肉,假设肉的消耗量与身体重量成正比,可估算龙食用的肉为900kg/day. 假设羊咩咩重100kg,那么龙每天需要消耗羊 9pcs/day</p><p>麻雀在飞行时,消耗脂肪0.08g/hour. 假设此消耗与身体重量成正比,可估算龙飞行时消耗脂肪80kg/hour</p><p><img src="http://upload-images.jianshu.io/upload_images/15914329-763457b3c4eb3bf5.png" alt="" style="zoom: 80%;" /></p><h4 id="Dragon’s-Fire-Chemical-Kinetics-Model"><a href="#Dragon’s-Fire-Chemical-Kinetics-Model" class="headerlink" title="Dragon’s Fire Chemical Kinetics Model"></a>Dragon’s Fire Chemical Kinetics Model</h4><ul><li><strong>估算龙火焰的温度</strong></li></ul><p>根据电视剧龙烧军队时,盔甲融化和蒸发的场景,假设盔甲由铁组成,铁的熔点是1538℃,沸点是2862℃。可以肯定,火焰温度比铁的沸点要高。()</p><ul><li><strong>龙的火焰气体的化学组成成分</strong></li></ul><p>查表发现乙醚的沸点与铁的沸点相似。f因此假设龙的气体为乙醚。</p><ul><li><strong>乙醚的生成</strong></li></ul><p>醚的最简单制备方法是在高温和浓硫酸的催化下将<strong>无水乙醇</strong>脱水成醚。假设龙自身可以生成催化剂,</p><script type="math/tex; mode=display">2 \mathrm{CH}_{3} \mathrm{CH}_{2} \mathrm{OH}\left(\mathrm{C}_{2} \mathrm{H}_{6} \mathrm{O}\right) \frac{\text { Speceial Catalyst }}{\text { Concentrated } \mathrm{H}_{2} \mathrm{SO}_{4}} \mathrm{CH}_{3} \mathrm{CH}_{2} \mathrm{OCH}_{2} \mathrm{CH}_{3}\left(\mathrm{C}_{4} \mathrm{H}_{10} \mathrm{O}\right) \uparrow+\mathrm{H}_{2} \mathrm{O} \uparrow</script><ul><li><strong>重构龙的口腔结构</strong></li></ul><p>腺体A负责产生硫酸,腺体B产生无水乙醇,腺体C作为化学反应的容器。可估计硫酸来自胃酸以及含硫氨基酸,这些需要肉。而肉的分解又会产生无水酒精。</p><p><img src="http://upload-images.jianshu.io/upload_images/15914329-7ddbe5877ce04540.png" alt="" /></p><ul><li><p><strong>估计喷火的能量消耗</strong></p><p>可以根据火焰燃烧的温度以及C的容量来估算能量消耗。</p><ul><li>V:根据电视剧,腺体C的大小估计和人类的胃差不多大。</li><li>Q:即为乙醚在100kPa和25℃下的燃烧热。</li><li>$\rho$ : 乙醚的液体密度</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">此处暂略,是化学题。</span><br></pre></td></tr></table></figure><p>可算得喷火的能量消耗$\Sigma=Q \rho V / M=19716.72 k J$。假设一天C只充能一次,那一天就要$\Sigma$的能量。</p></li></ul><h2 id="Dragon-Sheep-Habitat-Model"><a href="#Dragon-Sheep-Habitat-Model" class="headerlink" title="Dragon-Sheep-Habitat Model"></a>Dragon-Sheep-Habitat Model</h2><h3 id="模型分析"><a href="#模型分析" class="headerlink" title="模型分析"></a>模型分析</h3><p>假设:</p><p>龙的范围只是该生物圈的范围。</p><p>龙是顶级的消费者。</p><p>该生物圈等价为只有羊。</p><p>故龙进入该生物圈后,存在:</p><script type="math/tex; mode=display">\left\{\begin{array}{l}{\frac{d N(t)}{d t}=p N(t)\left(1-\frac{N(t)}{K}\right)-a} \\{N(0)=K}\end{array}\right.</script><p>其中N(t)表示羊的数量;p为常量,表示羊繁殖原本规律;K表示龙未进入生物群时候达到生态平衡时,羊的数量;a是成年龙每天要吃的羊数量。</p><p>根据上面分析,a=9,也可以设超参数p=0.01.</p><p>根据不同的K值,方程有不同的解。有的解最终可能导致羊的数量变为0,有的会使得羊和龙达到生态平衡。结果如下:</p><p><img src="http://upload-images.jianshu.io/upload_images/15914329-aab1f9136b238cf0.png" alt=""></p><p>又假设羊的平衡数量K与面积成正比,再查资料可求解以下方程的参数b:</p><p><img src="http://upload-images.jianshu.io/upload_images/15914329-30860305ebe502b8.png" alt=""></p><p>故当K取5000(最后会平衡为3800),可求出生物圈的面积大小。</p><p>故得出结论</p><ul><li>龙的栖息地起码400km²</li><li>开始起码要有4000头羊。根据食物链传播能量损失,可以等价为:</li></ul><p><img src="http://upload-images.jianshu.io/upload_images/15914329-a953e838ed098bbe.png" alt=""></p><h2 id="Impact-of-Three-Regions-on-Dragon’s-Survival"><a href="#Impact-of-Three-Regions-on-Dragon’s-Survival" class="headerlink" title="Impact of Three Regions on Dragon’s Survival"></a>Impact of Three Regions on Dragon’s Survival</h2><h3 id="Difference-in-Daily-Energy-Intake-of-Dragons-in-Three-Regions"><a href="#Difference-in-Daily-Energy-Intake-of-Dragons-in-Three-Regions" class="headerlink" title="Difference in Daily Energy Intake of Dragons in Three Regions"></a>Difference in Daily Energy Intake of Dragons in Three Regions</h3><p>根据人的数据,龙在严寒地区新陈代谢是温带的1.3倍,龙在热带是温带的0.9倍。</p><p>9羊估计是460,000cal,可以计算在严寒地区和热带的cal消耗量,以及相对应羊的销号数量。</p><h3 id="Three-Regions’-Capability-about-Self-Recovery-and-Supporting-Dragons"><a href="#Three-Regions’-Capability-about-Self-Recovery-and-Supporting-Dragons" class="headerlink" title="Three Regions’ Capability about Self-Recovery and Supporting Dragons"></a>Three Regions’ Capability about Self-Recovery and Supporting Dragons</h3><p>温带的恢复能力最强,其他两个地区较弱,可以相应调参。根据不同的参数,可以得出不同环境的容量。</p><p><img src="http://upload-images.jianshu.io/upload_images/15914329-e88ffc2ad1cebc27.png" alt=""></p><h2 id="Sensitivity-Analysis"><a href="#Sensitivity-Analysis" class="headerlink" title="Sensitivity Analysis"></a>Sensitivity Analysis</h2><p>分析参数的敏感度。</p><h2 id="Model-Evaluation-and-Further-Discussion"><a href="#Model-Evaluation-and-Further-Discussion" class="headerlink" title="Model Evaluation and Further Discussion"></a>Model Evaluation and Further Discussion</h2><h3 id="Evaluation-of-Models"><a href="#Evaluation-of-Models" class="headerlink" title="Evaluation of Models"></a>Evaluation of Models</h3><p>分析自己模型哪里好哪里不好。</p><h3 id="Further-Discussion"><a href="#Further-Discussion" class="headerlink" title="Further Discussion"></a>Further Discussion</h3><p>模型的现实意义。</p>]]></content>
<summary type="html">
<h1 id="没用的话"><a href="#没用的话" class="headerlink" title="没用的话"></a>没用的话</h1><p>前天是2.24,是学校开学的第一天,为了升旗很早就起床了。没想到昨天和今天也很早就自然醒,也许调整生物钟也只需要早起一两天就
</summary>
<category term="美赛" scheme="http://jaxchan.top/categories/%E7%BE%8E%E8%B5%9B/"/>
<category term="日记" scheme="http://jaxchan.top/categories/%E7%BE%8E%E8%B5%9B/%E6%97%A5%E8%AE%B0/"/>
<category term="学习" scheme="http://jaxchan.top/tags/%E5%AD%A6%E4%B9%A0/"/>
<category term="生活" scheme="http://jaxchan.top/tags/%E7%94%9F%E6%B4%BB/"/>
</entry>
<entry>
<title>GO笔记</title>
<link href="http://jaxchan.top/2020/GO%E7%AC%94%E8%AE%B0.html/"/>
<id>http://jaxchan.top/2020/GO%E7%AC%94%E8%AE%B0.html/</id>
<published>2020-02-21T06:56:34.000Z</published>
<updated>2020-02-28T10:56:30.904Z</updated>
<content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>记录Go学习过程中关于package 调用-再封装的知识点。</p><h1 id="package注意事项"><a href="#package注意事项" class="headerlink" title="package注意事项"></a>package注意事项</h1><ul><li>一个文件目录下的go文件隶属同一个pakcage</li><li>如果不用<strong>go mod</strong>,绝对路径:那项目应该创在 <strong>$GOPATH</strong> 或者 <strong>$GOPATH</strong> 的src下</li><li>可以使用相对路径</li><li>对于结构体,大写属性才对外可见。<em>如name对外包不可见,Name可见。</em></li></ul><h1 id="init-函数"><a href="#init-函数" class="headerlink" title="init() 函数"></a>init() 函数</h1><ul><li>在导入main前被执行</li><li>无返回无参数</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">init</span><span class="params">()</span></span>{</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>一个go文件下可以有多个init()函数,先写先被调用。</li><li><p>同个package下的不同go文件,是对<strong>go文件名</strong>排序执行。</p></li><li><p>对不同的package,</p><ul><li>若package间无依赖,按照import顺序执行</li><li>否则,先从最深处执行。</li></ul></li><li><p>import _ “package”: 下划线表示导入只执行init</p></li></ul><h1 id="package-time"><a href="#package-time" class="headerlink" title="package - time"></a>package - time</h1><ul><li>导入</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="string">"time"</span></span><br></pre></td></tr></table></figure><ul><li>获取当前时间</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">t1 := time.Now()</span><br></pre></td></tr></table></figure><ul><li>时间格式化(time对象转string) : Jan 2 15:04:05 2006 </li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">s1 := t1.Format(<span class="string">"2006年1月2日 15:04:05"</span>)</span><br><span class="line"><span class="comment">//如果已经设置好了Format</span></span><br><span class="line">s1:= t1.String()</span><br></pre></td></tr></table></figure><ul><li>string转time对象 <strong>(需要提前设置好格式)</strong></li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">t2:= time.Parse(s1)</span><br></pre></td></tr></table></figure><ul><li>time对象获取具体 年月日 时分秒数据</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">year,month,day := t1.Date()</span><br><span class="line">hour,min,sec := t1.Date()</span><br><span class="line"></span><br><span class="line"><span class="comment">//也可以分别获取 </span></span><br><span class="line">year:=t1.Year()</span><br><span class="line"></span><br><span class="line"><span class="comment">//周几</span></span><br><span class="line">t1.Weekday()</span><br><span class="line"></span><br><span class="line"><span class="comment">//一年过了几天</span></span><br><span class="line">t1.YearDay()</span><br></pre></td></tr></table></figure><ul><li>获取时间戳 与1970年1月1日0:00:00的时间差</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">t1.Unix() <span class="comment">//秒为单位</span></span><br></pre></td></tr></table></figure><ul><li>时间加减</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">t1.Add( <span class="number">2</span> * time.Hour ) <span class="comment">// 以秒为单位</span></span><br></pre></td></tr></table></figure><ul><li>程序睡眠</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">time.Sleep( <span class="number">3</span> * time.Second )</span><br></pre></td></tr></table></figure><h1 id="package-rand"><a href="#package-rand" class="headerlink" title="package - rand"></a>package - rand</h1><ul><li>设置种子</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rand.Seed(time.Now().Unix())</span><br></pre></td></tr></table></figure><ul><li>随机整数</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rand.Intn(<span class="number">10</span>) <span class="comment">//[0,9] 返回int 注意time.Sleep(int64)</span></span><br></pre></td></tr></table></figure><h1 id="package-os-关于文件"><a href="#package-os-关于文件" class="headerlink" title="package - os 关于文件"></a>package - os 关于文件</h1><ul><li><p>获取文件基本信息</p><ul><li>使用 os.Stat(文件名) 获取 </li><li>文件大小是byte格式的 <em>uint8</em> , 一个字母就是一个byte</li></ul></li><li><p>创建文件的时候,需要给出权限</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">r 004 //读</span><br><span class="line">w 002 //写</span><br><span class="line">x 001 //执行</span><br><span class="line">- 000 //无</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">tyepe - owner - group - others</span><br><span class="line">0777 所有权限 //os.ModePerm</span><br></pre></td></tr></table></figure></li><li><p>相对路径与绝对路径</p></li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//判断是否为绝对路径</span></span><br><span class="line">fileName := <span class="string">"./a.txt"</span></span><br><span class="line">filepath.IsAbs(fileName)</span><br><span class="line"></span><br><span class="line"><span class="comment">//相对路径转为绝对路几个</span></span><br><span class="line">absPath,err := filePath.Abs(fileName)</span><br></pre></td></tr></table></figure><ul><li>获取父目录</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">path.Join( 绝对路径, <span class="string">".."</span>)</span><br></pre></td></tr></table></figure><ul><li>创建文件夹</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//单个创建</span></span><br><span class="line">err:=os.Mkdir(路径,os.ModePerm)</span><br><span class="line"><span class="comment">//递归创建</span></span><br><span class="line">err:=os.MkdirAll(路径,os.ModePerm)</span><br></pre></td></tr></table></figure><ul><li>创建文件</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//默认权限是0666 如果已经存在会置空</span></span><br><span class="line">file,err := os.Create(路径)</span><br></pre></td></tr></table></figure><ul><li>打开文件</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//默认是只读</span></span><br><span class="line">file,err := os.Open(路径)</span><br><span class="line"></span><br><span class="line"><span class="comment">//指定权限,也要指定创建的权限(若不存在就要使用)</span></span><br><span class="line">file,err := os.OpenFile( 路径,os.RDONLY||os.WRONLY,os.ModePerm)</span><br><span class="line"></span><br><span class="line"><span class="comment">//记得关闭</span></span><br><span class="line"><span class="keyword">defer</span> file.Close()</span><br></pre></td></tr></table></figure><ul><li>删除文件或者文件夹</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//删除文件或者空文件夹</span></span><br><span class="line">err:=os.Remove(路径) </span><br><span class="line"></span><br><span class="line"><span class="comment">//递归删除</span></span><br><span class="line">err:=os.RemoveAll(路径)</span><br></pre></td></tr></table></figure><h1 id="package-io"><a href="#package-io" class="headerlink" title="package - io"></a>package - io</h1><ul><li>读取数据<ul><li>使用Read()方法是会记录当前指针的,所以多次调用就会往后读取数据。</li><li>读完了err为EOF</li><li>指定位置需要使用 WriteAt</li></ul></li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//打开文件</span></span><br><span class="line">fileName := 文件路径</span><br><span class="line">file,err:=os.Open(fileName)</span><br><span class="line"><span class="keyword">if</span> err!=<span class="literal">nil</span>{</span><br><span class="line"> fmt.Println(err)</span><br><span class="line"> <span class="keyword">return</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">defer</span> file.Close()</span><br><span class="line"></span><br><span class="line"><span class="comment">//创建存储切片 </span></span><br><span class="line">bs := <span class="built_in">make</span>([]<span class="keyword">byte</span>,<span class="number">4</span>,<span class="number">4</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">//读取数据 </span></span><br><span class="line">n,err:=file.Read(bs)</span><br><span class="line"><span class="comment">//bs里面存的是ASCII编码数值 需要转为string</span></span><br><span class="line">s1 := <span class="keyword">string</span>(bs)</span><br></pre></td></tr></table></figure><p>使用ioutil也很方便,会一次性读完</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bs,err:=ioutil.ReadFile(srcPath)</span><br></pre></td></tr></table></figure><p>更普遍的写法:</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">bs:=<span class="built_in">make</span>([]<span class="keyword">byte</span>,<span class="number">1024</span>,<span class="number">1024</span>)</span><br><span class="line">n,err:=file.Read(bs)</span><br><span class="line"><span class="keyword">var</span> data <span class="keyword">string</span></span><br><span class="line"><span class="keyword">if</span> err!=EOF{</span><br><span class="line"> data = <span class="keyword">string</span>(bs[:n])</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>写操作</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">//打开文件</span></span><br><span class="line">fileName := 路径</span><br><span class="line"><span class="comment">//如果追加,要加os.O_APPEND</span></span><br><span class="line">file,err:=os.OpenFile(fileName,os.O_Create|os.O_WRONLY,os.ModePerm)</span><br><span class="line"><span class="keyword">if</span> err!=<span class="literal">nil</span>{</span><br><span class="line"> }</span><br><span class="line"><span class="keyword">defer</span> file.Close()</span><br><span class="line"></span><br><span class="line"><span class="comment">//写入数据</span></span><br><span class="line">bs:=[]<span class="keyword">byte</span>{<span class="number">65</span>,<span class="number">66</span>,<span class="number">67</span>,<span class="number">68</span>}</span><br><span class="line">n,err:=file.Write(bs)</span><br><span class="line"></span><br><span class="line"><span class="comment">//也可以直接写入String</span></span><br><span class="line">n,err := file.Write(<span class="keyword">byte</span>[](<span class="string">"测试"</span>) )</span><br><span class="line">n,err := file.WriteString(<span class="string">"测试"</span>)</span><br></pre></td></tr></table></figure><p>也可以用ioutil,会一次性写完</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">err:=ioutil.WriteFile(dstPath,bs,os.ModePerm)</span><br></pre></td></tr></table></figure><ul><li>文件copy</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//File都是io.File对象</span></span><br><span class="line">io.Copy(srcFile,dstFile)</span><br></pre></td></tr></table></figure><h1 id="package-bufferio"><a href="#package-bufferio" class="headerlink" title="package - bufferio"></a>package - bufferio</h1><ul><li>创建缓冲,减少访问磁盘的次数。</li><li>读入。只有 <strong>读取的文件的大小</strong> 远大于 <strong>缓冲区的大小</strong> 的时候才有效。</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">//先创文件</span></span><br><span class="line">file,err:=os.Open(filePath)</span><br><span class="line"><span class="keyword">defer</span> file.Close()</span><br><span class="line"></span><br><span class="line"><span class="comment">//创立缓冲区 default size=4096</span></span><br><span class="line"><span class="comment">//如果从键盘读入,那file应该为os.Stdin</span></span><br><span class="line">b1 := bufio.NewReader(file)</span><br><span class="line"></span><br><span class="line"><span class="comment">//把数据读入p</span></span><br><span class="line">p:= <span class="built_in">make</span>(<span class="keyword">byte</span>[],<span class="number">1024</span>,<span class="number">1024</span>)</span><br><span class="line">n,err:=b1.Read(p)</span><br><span class="line"></span><br><span class="line"><span class="comment">//如果只想读行,但不建议使用</span></span><br><span class="line">data,flag,err:=b1.ReadLine()</span><br><span class="line"></span><br><span class="line"><span class="comment">//指定分隔符</span></span><br><span class="line">s1,err:=b1.ReadString(<span class="string">'\n'</span>)</span><br></pre></td></tr></table></figure><ul><li>写出。</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">file,err:=os.OpenFile(...)</span><br><span class="line"><span class="keyword">defer</span> ...</span><br><span class="line">w1:=bufio.NewWriter(file)</span><br><span class="line">n,err:=w1.WriteString(<span class="string">"测试"</span>)</span><br><span class="line"><span class="comment">//必须刷新缓冲区,才会写入文件</span></span><br><span class="line">w1.Flush()</span><br></pre></td></tr></table></figure><h1 id="package-ioutil"><a href="#package-ioutil" class="headerlink" title="package - ioutil"></a>package - ioutil</h1><ul><li>一次性读完数据</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//读出是byte[]类型</span></span><br><span class="line">data,err:=ioutil.ReadFile(filePath)</span><br></pre></td></tr></table></figure><ul><li>一次性写入数据</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ioutil.WriteFile(filePath,<span class="keyword">byte</span>[](<span class="string">"测试"</span>),os.ModePerm)</span><br></pre></td></tr></table></figure><ul><li>创建临时目录和临时文件夹</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//第二个参数是prefix</span></span><br><span class="line">dir,err := ioutil.TempDir(路径,<span class="string">"Test"</span>)</span><br><span class="line"><span class="keyword">defer</span> os.Remove(dir)</span><br><span class="line"></span><br><span class="line">file,err := ioutil.TempFile(路径,<span class="string">"Test"</span>)</span><br><span class="line"><span class="keyword">defer</span> os.Remove(file.Name()) <span class="comment">//file.Name()是绝对路径</span></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>记录Go学习过程中关于package 调用-再封装的知识点。</p>
<h1 id="package注意事项"><a href="#pack
</summary>
<category term="编程" scheme="http://jaxchan.top/categories/%E7%BC%96%E7%A8%8B/"/>
<category term="go" scheme="http://jaxchan.top/tags/go/"/>
</entry>
<entry>
<title>我的博客的前世今生</title>
<link href="http://jaxchan.top/2020/%E6%88%91%E7%9A%84%E5%8D%9A%E5%AE%A2%E7%9A%84%E5%89%8D%E4%B8%96%E4%BB%8A%E7%94%9F.html/"/>
<id>http://jaxchan.top/2020/%E6%88%91%E7%9A%84%E5%8D%9A%E5%AE%A2%E7%9A%84%E5%89%8D%E4%B8%96%E4%BB%8A%E7%94%9F.html/</id>
<published>2020-02-20T15:35:45.000Z</published>
<updated>2020-02-28T11:54:18.513Z</updated>
<content type="html"><![CDATA[<h1 id="为什么要搭博客"><a href="#为什么要搭博客" class="headerlink" title="为什么要搭博客"></a>为什么要搭博客</h1><p>有很多原因,总的来说便是反正闲着也是闲着。</p><p><img src="http://upload-images.jianshu.io/upload_images/15914329-0c1027fbe037348b.png" alt="我做的东西" style="zoom:67%;" /></p><p>但也可以深究,</p><ul><li>我常常觉得,要是有某个功能的网站/软件就好了。<ul><li>于是这个blog可能常常出现新功能,新活动..(如果我有空的话</li></ul></li><li>学习了某项软件技术,我常觉得得不到实践与施展。<ul><li>所以这里有的东西可能就是为了技术而生,而不是为了应用而生。</li></ul></li><li>我作为一个软件工程的学生,两三年下来半件成品没有,实在过意不去。<ul><li><strong>这个blog是直接使用Hexo搭建,放在github上托管的。</strong></li><li><strong>事实上我自己已经做了一个半成品的博客,因为维护麻烦而放弃。</strong><ul><li>网站的前后端代码都开源,欢迎给star。<ul><li><a href="https://github.com/JaxChan25/borderland" target="_blank" rel="noopener">后端</a></li><li><a href="https://github.com/JaxChan25/borderland-FE" target="_blank" rel="noopener">前端</a></li></ul></li></ul></li></ul></li></ul><p><img src="http://upload-images.jianshu.io/upload_images/15914329-1a88334c206dab47.png" alt="之前自己搭的博客"></p><h1 id="这个博客有什么内容"><a href="#这个博客有什么内容" class="headerlink" title="这个博客有什么内容"></a>这个博客有什么内容</h1><p>我倒没有想清楚,我对它只有一个要求,就是好看。</p><p>只有一些模糊的内容设想,</p><p>关于我个人的笔录:</p><ul><li>我的生活随感</li><li>我的学习笔记</li><li>我的匿名留言箱</li></ul><p>关于社交活动类型:</p><ul><li>致力于解决华工单身率过高的问题</li></ul><p><strong>但现在已经不用后端了,所以社交活动类型的活动想法是实现不了了。</strong></p><h1 id="这个博客会开通多久"><a href="#这个博客会开通多久" class="headerlink" title="这个博客会开通多久"></a>这个博客会开通多久</h1><p>现在东西都放在github,也没什么地方需要花钱的。所以会一直开。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">之前的说法:</span><br><span class="line">毕竟时间很宝贵,而且开服务器、买存储和流量都是钱,</span><br><span class="line"></span><br><span class="line">当有一天我觉得与其折腾自己,还不如发条朋友圈来得简单实在,我就不再运营了。</span><br></pre></td></tr></table></figure><p><img src="http://upload-images.jianshu.io/upload_images/15914329-f32f2a77e727ca34.png" alt="record" style="zoom: 50%;" /></p><h1 id="特别感谢"><a href="#特别感谢" class="headerlink" title="特别感谢"></a>特别感谢</h1><p>感谢同学 <a href="https://github.com/LinZong" target="_blank" rel="noopener">林总</a> 一直给予技术上的支持。</p><p>感谢 <a href="https://github.com/bydmm" target="_blank" rel="noopener">ChengKa</a> <a href="https://github.com/biaochenxuying" target="_blank" rel="noopener">biaochenxuying</a> 的前后端教程。</p><p>感谢同学 <a href="https://github.com/faujnuliaug" target="_blank" rel="noopener">范某</a> 的协作开发。</p>]]></content>
<summary type="html">
<h1 id="为什么要搭博客"><a href="#为什么要搭博客" class="headerlink" title="为什么要搭博客"></a>为什么要搭博客</h1><p>有很多原因,总的来说便是反正闲着也是闲着。</p>
<p><img src="http://uplo
</summary>
<category term="建站日记" scheme="http://jaxchan.top/categories/%E5%BB%BA%E7%AB%99%E6%97%A5%E8%AE%B0/"/>
<category term="学习" scheme="http://jaxchan.top/tags/%E5%AD%A6%E4%B9%A0/"/>
<category term="生活" scheme="http://jaxchan.top/tags/%E7%94%9F%E6%B4%BB/"/>
<category term="golang" scheme="http://jaxchan.top/tags/golang/"/>
<category term="vue" scheme="http://jaxchan.top/tags/vue/"/>
</entry>
</feed>