-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
525 lines (444 loc) · 166 KB
/
search.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
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>Java链表实现</title>
<url>/2024/11/03/Java%E9%93%BE%E8%A1%A8%E5%AE%9E%E7%8E%B0/</url>
<content><![CDATA[<h1 id="Java-链表实现"><a href="#Java-链表实现" class="headerlink" title="Java 链表实现"></a>Java 链表实现</h1><h4 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h4><div class="highlight-container" data-rel="Java"><figure class="iseeu highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> LinkList;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Node</span> {</span><br><span class="line"> <span class="type">int</span> data;</span><br><span class="line"> Node next;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Node</span><span class="params">(<span class="type">int</span> data)</span> {</span><br><span class="line"> <span class="built_in">this</span>.data = data;</span><br><span class="line"> <span class="built_in">this</span>.next = <span class="literal">null</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">Init</span><span class="params">(Node head, <span class="type">int</span> length)</span> {</span><br><span class="line"> <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> <span class="type">Node</span> <span class="variable">newHead</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="keyword">while</span> (i < length) {</span><br><span class="line"> <span class="type">Node</span> <span class="variable">tmp</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Node</span>(<span class="number">0</span>);</span><br><span class="line"> tmp.next = <span class="literal">null</span>;</span><br><span class="line"> newHead.next = tmp;</span><br><span class="line"> newHead = newHead.next;</span><br><span class="line"> i++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">Print</span><span class="params">(Node head)</span> {</span><br><span class="line"> <span class="type">Node</span> <span class="variable">newHead</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="keyword">while</span> (newHead != <span class="literal">null</span>) {</span><br><span class="line"> System.out.println(newHead.data);</span><br><span class="line"> newHead = newHead.next;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">Insert</span><span class="params">(Node head, <span class="type">int</span> index, <span class="type">int</span> data)</span> {</span><br><span class="line"> <span class="type">Node</span> <span class="variable">newHead</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span> (i < index && newHead != <span class="literal">null</span>) {</span><br><span class="line"> newHead = newHead.next;</span><br><span class="line"> i++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (newHead == <span class="literal">null</span>) {</span><br><span class="line"> System.out.println(<span class="string">"索引超过长度"</span>);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="type">Node</span> <span class="variable">tmp</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Node</span>(data);</span><br><span class="line"> tmp.next = newHead.next;</span><br><span class="line"> newHead.next = tmp;</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="type">int</span> <span class="title function_">Delete</span><span class="params">(Node head, <span class="type">int</span> index)</span> {</span><br><span class="line"> <span class="type">int</span> res;</span><br><span class="line"> <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line"> <span class="type">Node</span> <span class="variable">newHead</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="keyword">while</span> (i < index && newHead != <span class="literal">null</span>) {</span><br><span class="line"> newHead = newHead.next;</span><br><span class="line"> i++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (newHead == <span class="literal">null</span>) {</span><br><span class="line"> System.out.println(<span class="string">"索引超过长度,无法删除"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> res = newHead.next.data;</span><br><span class="line"> newHead.next = newHead.next.next;</span><br><span class="line"> <span class="keyword">return</span> res;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="type">int</span> <span class="title function_">Find</span><span class="params">(Node head, <span class="type">int</span> index)</span> {</span><br><span class="line"> <span class="type">Node</span> <span class="variable">newHead</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span> (i < index && newHead != <span class="literal">null</span>) {</span><br><span class="line"> newHead = newHead.next;</span><br><span class="line"> i++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (newHead == <span class="literal">null</span>) {</span><br><span class="line"> System.out.println(<span class="string">"索引超过长度,无法查找"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> newHead.data;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">Alter</span><span class="params">(Node head, <span class="type">int</span> index, <span class="type">int</span> data)</span> {</span><br><span class="line"> <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> <span class="type">Node</span> <span class="variable">newHead</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="keyword">while</span> (i < index && newHead != <span class="literal">null</span>) {</span><br><span class="line"> newHead = newHead.next;</span><br><span class="line"> i++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (newHead == <span class="literal">null</span>) {</span><br><span class="line"> System.out.println(<span class="string">"索引超过长度,无法更改"</span>);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> newHead.data = data;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="type">int</span> <span class="title function_">GetLength</span><span class="params">(Node head)</span> {</span><br><span class="line"> <span class="type">Node</span> <span class="variable">newHead</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="type">int</span> <span class="variable">length</span> <span class="operator">=</span> -<span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span> (newHead != <span class="literal">null</span>) {</span><br><span class="line"> length++;</span><br><span class="line"> newHead = newHead.next;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> length;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<p>主要实现了对链表的初始化以及增删查改等,未实现排序,逆序等功能</p>
]]></content>
<categories>
<category>技术向</category>
</categories>
<tags>
<tag>Java</tag>
</tags>
</entry>
<entry>
<title>Java链表拓展--排序,翻转</title>
<url>/2024/11/03/Java%E9%93%BE%E8%A1%A8%E6%8B%93%E5%B1%95-%E6%8E%92%E5%BA%8F%EF%BC%8C%E7%BF%BB%E8%BD%AC/</url>
<content><![CDATA[<h1 id="Java链表排序"><a href="#Java链表排序" class="headerlink" title="Java链表排序"></a>Java链表排序</h1><div class="highlight-container" data-rel="Java"><figure class="iseeu highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">SortList</span><span class="params">(Node head)</span> {</span><br><span class="line"> <span class="type">Node</span> <span class="variable">newHead</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> ArrayList<Integer> SortArray = <span class="keyword">new</span> <span class="title class_">ArrayList</span><>();</span><br><span class="line"> <span class="keyword">while</span> (newHead != <span class="literal">null</span>) {</span><br><span class="line"> SortArray.add(newHead.data);</span><br><span class="line"> newHead = newHead.next;</span><br><span class="line"> }</span><br><span class="line"> SortArray.sort(Comparator.naturalOrder());</span><br><span class="line"> newHead = head;</span><br><span class="line"> <span class="keyword">while</span> (newHead != <span class="literal">null</span>){</span><br><span class="line"> newHead.data = SortArray.get(i);</span><br><span class="line"> newHead = newHead.next;</span><br><span class="line"> i++;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<h4 id="排序采用了先转为数组,对数组进行排序再给链表重新赋值的方法"><a href="#排序采用了先转为数组,对数组进行排序再给链表重新赋值的方法" class="headerlink" title="排序采用了先转为数组,对数组进行排序再给链表重新赋值的方法"></a>排序采用了先转为数组,对数组进行排序再给链表重新赋值的方法</h4><h1 id="Java链表反转"><a href="#Java链表反转" class="headerlink" title="Java链表反转"></a>Java链表反转</h1><div class="highlight-container" data-rel="Java"><figure class="iseeu highlight java"><table><tr><td class="code"><pre><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">Reverse</span><span class="params">(Node head)</span> {</span><br><span class="line"> <span class="type">Node</span> <span class="variable">pre</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"> <span class="type">Node</span> <span class="variable">cur</span> <span class="operator">=</span> head.next;</span><br><span class="line"> <span class="type">Node</span> <span class="variable">next</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Node</span>(<span class="number">0</span>);</span><br><span class="line"> <span class="keyword">while</span>(cur != <span class="literal">null</span>){</span><br><span class="line"> next = cur.next;</span><br><span class="line"> cur.next = pre;</span><br><span class="line"> pre = cur;</span><br><span class="line"> cur = next;</span><br><span class="line"> }</span><br><span class="line"><span class="comment">// return pre;</span></span><br><span class="line"> head.next = pre;</span><br><span class="line"> }</span><br></pre></td></tr></table></figure></div>
<h4 id="反转采用了三个节点依次翻转"><a href="#反转采用了三个节点依次翻转" class="headerlink" title="反转采用了三个节点依次翻转"></a>反转采用了三个节点依次翻转</h4><h1 id="链表类完整代码"><a href="#链表类完整代码" class="headerlink" title="链表类完整代码"></a>链表类完整代码</h1><div class="highlight-container" data-rel="Java"><figure class="iseeu highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> LinkList;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Array;</span><br><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"><span class="keyword">import</span> java.util.Comparator;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Node</span> {</span><br><span class="line"> <span class="type">int</span> data;</span><br><span class="line"> Node next;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Node</span><span class="params">(<span class="type">int</span> data)</span> {</span><br><span class="line"> <span class="built_in">this</span>.data = data;</span><br><span class="line"> <span class="built_in">this</span>.next = <span class="literal">null</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">Init</span><span class="params">(Node head, <span class="type">int</span> length)</span> {</span><br><span class="line"> <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> <span class="type">Node</span> <span class="variable">newHead</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="keyword">while</span> (i < length) {</span><br><span class="line"> <span class="type">Node</span> <span class="variable">tmp</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Node</span>(<span class="number">0</span>);</span><br><span class="line"> tmp.next = <span class="literal">null</span>;</span><br><span class="line"> newHead.next = tmp;</span><br><span class="line"> newHead = newHead.next;</span><br><span class="line"> i++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">Print</span><span class="params">(Node head)</span> {</span><br><span class="line"> <span class="type">Node</span> <span class="variable">newHead</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="keyword">while</span> (newHead != <span class="literal">null</span>) {</span><br><span class="line"> System.out.println(newHead.data);</span><br><span class="line"> newHead = newHead.next;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">Insert</span><span class="params">(Node head, <span class="type">int</span> index, <span class="type">int</span> data)</span> {</span><br><span class="line"> <span class="type">Node</span> <span class="variable">newHead</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span> (i < index && newHead != <span class="literal">null</span>) {</span><br><span class="line"> newHead = newHead.next;</span><br><span class="line"> i++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (newHead == <span class="literal">null</span>) {</span><br><span class="line"> System.out.println(<span class="string">"索引超过长度"</span>);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="type">Node</span> <span class="variable">tmp</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Node</span>(data);</span><br><span class="line"> tmp.next = newHead.next;</span><br><span class="line"> newHead.next = tmp;</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="type">int</span> <span class="title function_">Delete</span><span class="params">(Node head, <span class="type">int</span> index)</span> {</span><br><span class="line"> <span class="type">int</span> res;</span><br><span class="line"> <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line"> <span class="type">Node</span> <span class="variable">newHead</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="keyword">while</span> (i < index && newHead != <span class="literal">null</span>) {</span><br><span class="line"> newHead = newHead.next;</span><br><span class="line"> i++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (newHead == <span class="literal">null</span>) {</span><br><span class="line"> System.out.println(<span class="string">"索引超过长度,无法删除"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> res = newHead.next.data;</span><br><span class="line"> newHead.next = newHead.next.next;</span><br><span class="line"> <span class="keyword">return</span> res;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="type">int</span> <span class="title function_">Find</span><span class="params">(Node head, <span class="type">int</span> index)</span> {</span><br><span class="line"> <span class="type">Node</span> <span class="variable">newHead</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span> (i < index && newHead != <span class="literal">null</span>) {</span><br><span class="line"> newHead = newHead.next;</span><br><span class="line"> i++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (newHead == <span class="literal">null</span>) {</span><br><span class="line"> System.out.println(<span class="string">"索引超过长度,无法查找"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> newHead.data;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">Alter</span><span class="params">(Node head, <span class="type">int</span> index, <span class="type">int</span> data)</span> {</span><br><span class="line"> <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> <span class="type">Node</span> <span class="variable">newHead</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="keyword">while</span> (i < index && newHead != <span class="literal">null</span>) {</span><br><span class="line"> newHead = newHead.next;</span><br><span class="line"> i++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (newHead == <span class="literal">null</span>) {</span><br><span class="line"> System.out.println(<span class="string">"索引超过长度,无法更改"</span>);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> newHead.data = data;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">SortList</span><span class="params">(Node head)</span> {</span><br><span class="line"> <span class="type">Node</span> <span class="variable">newHead</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> ArrayList<Integer> SortArray = <span class="keyword">new</span> <span class="title class_">ArrayList</span><>();</span><br><span class="line"> <span class="keyword">while</span> (newHead != <span class="literal">null</span>) {</span><br><span class="line"> SortArray.add(newHead.data);</span><br><span class="line"> newHead = newHead.next;</span><br><span class="line"> }</span><br><span class="line"> SortArray.sort(Comparator.naturalOrder());</span><br><span class="line"> newHead = head;</span><br><span class="line"> <span class="keyword">while</span> (newHead != <span class="literal">null</span>){</span><br><span class="line"> newHead.data = SortArray.get(i);</span><br><span class="line"> newHead = newHead.next;</span><br><span class="line"> i++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">Reverse</span><span class="params">(Node head)</span> {</span><br><span class="line"> <span class="type">Node</span> <span class="variable">pre</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"> <span class="type">Node</span> <span class="variable">cur</span> <span class="operator">=</span> head.next;</span><br><span class="line"> <span class="type">Node</span> <span class="variable">next</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Node</span>(<span class="number">0</span>);</span><br><span class="line"> <span class="keyword">while</span>(cur != <span class="literal">null</span>){</span><br><span class="line"> next = cur.next;</span><br><span class="line"> cur.next = pre;</span><br><span class="line"> pre = cur;</span><br><span class="line"> cur = next;</span><br><span class="line"> }</span><br><span class="line"><span class="comment">// return pre;</span></span><br><span class="line"> head.next = pre;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="type">int</span> <span class="title function_">GetLength</span><span class="params">(Node head)</span> {</span><br><span class="line"> <span class="type">Node</span> <span class="variable">newHead</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="type">int</span> <span class="variable">length</span> <span class="operator">=</span> -<span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span> (newHead != <span class="literal">null</span>) {</span><br><span class="line"> length++;</span><br><span class="line"> newHead = newHead.next;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> length;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
]]></content>
<categories>
<category>技术向</category>
</categories>
<tags>
<tag>Java</tag>
</tags>
</entry>
<entry>
<title>二叉树实现-初始化,层序遍历(广搜)</title>
<url>/2024/11/03/%E4%BA%8C%E5%8F%89%E6%A0%91%E5%AE%9E%E7%8E%B0-%E5%88%9D%E5%A7%8B%E5%8C%96%EF%BC%8C%E5%B1%82%E5%BA%8F%E9%81%8D%E5%8E%86%EF%BC%88%E5%B9%BF%E6%90%9C%EF%BC%89/</url>
<content><![CDATA[<h1 id="Java二叉树实现"><a href="#Java二叉树实现" class="headerlink" title="Java二叉树实现"></a>Java二叉树实现</h1><h2 id="初始化(满二叉树)"><a href="#初始化(满二叉树)" class="headerlink" title="初始化(满二叉树)"></a>初始化(满二叉树)</h2><div class="highlight-container" data-rel="Java"><figure class="iseeu highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">FBTreeInit</span><span class="params">(TreeNode root, <span class="type">int</span> height)</span> {</span><br><span class="line"> root.Val = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">if</span> (height == <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> root.Left = <span class="keyword">new</span> <span class="title class_">TreeNode</span>(<span class="number">0</span>);</span><br><span class="line"> root.Right = <span class="keyword">new</span> <span class="title class_">TreeNode</span>(<span class="number">0</span>);</span><br><span class="line"> FBTreeInit(root.Left, height - <span class="number">1</span>);</span><br><span class="line"> FBTreeInit(root.Right, height - <span class="number">1</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<h2 id="广度优先搜索"><a href="#广度优先搜索" class="headerlink" title="广度优先搜索"></a>广度优先搜索</h2><div class="highlight-container" data-rel="Java"><figure class="iseeu highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">loTraversal</span><span class="params">(TreeNode root)</span> {</span><br><span class="line"> ArrayList<TreeNode> loTArray = <span class="keyword">new</span> <span class="title class_">ArrayList</span><>();</span><br><span class="line"> loTArray.add(root);</span><br><span class="line"> <span class="keyword">while</span> (!loTArray.isEmpty()) {</span><br><span class="line"> <span class="type">int</span> <span class="variable">length</span> <span class="operator">=</span> loTArray.size();</span><br><span class="line"> TreeNode node;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i < length; i++) {</span><br><span class="line"> node = loTArray.removeFirst();</span><br><span class="line"> System.out.println(node.Val);</span><br><span class="line"> <span class="keyword">if</span> (node.Left != <span class="literal">null</span>) {</span><br><span class="line"> loTArray.add(node.Left);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (node.Right != <span class="literal">null</span>) {</span><br><span class="line"> loTArray.add(node.Right);</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></div>
<h3 id="二叉树类代码"><a href="#二叉树类代码" class="headerlink" title="二叉树类代码"></a>二叉树类代码</h3><div class="highlight-container" data-rel="Java"><figure class="iseeu highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> TwoTree;</span><br><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TreeNode</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> Val;</span><br><span class="line"> <span class="keyword">public</span> <span class="type">TreeNode</span> <span class="variable">Left</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="type">TreeNode</span> <span class="variable">Right</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">TreeNode</span><span class="params">()</span> {</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">TreeNode</span><span class="params">(<span class="type">int</span> val)</span> {</span><br><span class="line"> <span class="built_in">this</span>.Val = val;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// height从根节点为0开始</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">FBTreeInit</span><span class="params">(TreeNode root, <span class="type">int</span> height)</span> {</span><br><span class="line"> root.Val = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">if</span> (height == <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> root.Left = <span class="keyword">new</span> <span class="title class_">TreeNode</span>(<span class="number">0</span>);</span><br><span class="line"> root.Right = <span class="keyword">new</span> <span class="title class_">TreeNode</span>(<span class="number">0</span>);</span><br><span class="line"> FBTreeInit(root.Left, height - <span class="number">1</span>);</span><br><span class="line"> FBTreeInit(root.Right, height - <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">loTraversal</span><span class="params">(TreeNode root)</span> {</span><br><span class="line"> ArrayList<TreeNode> loTArray = <span class="keyword">new</span> <span class="title class_">ArrayList</span><>();</span><br><span class="line"> loTArray.add(root);</span><br><span class="line"> <span class="keyword">while</span> (!loTArray.isEmpty()) {</span><br><span class="line"> <span class="type">int</span> <span class="variable">length</span> <span class="operator">=</span> loTArray.size();</span><br><span class="line"> TreeNode node;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i < length; i++) {</span><br><span class="line"> node = loTArray.removeFirst();</span><br><span class="line"> System.out.println(node.Val);</span><br><span class="line"> <span class="keyword">if</span> (node.Left != <span class="literal">null</span>) {</span><br><span class="line"> loTArray.add(node.Left);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (node.Right != <span class="literal">null</span>) {</span><br><span class="line"> loTArray.add(node.Right);</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></div>
]]></content>
<categories>
<category>技术向</category>
</categories>
<tags>
<tag>Java</tag>
</tags>
</entry>
<entry>
<title>说明介绍</title>
<url>/2024/11/03/%E8%AF%B4%E6%98%8E%E4%BB%8B%E7%BB%8D/</url>
<content><![CDATA[<h2 id="说明"><a href="#说明" class="headerlink" title="说明"></a>说明</h2><p>先说一下为啥这几篇文章全是Java的,只是因为java和数据结构快要结课考试了,</p>
<p>后续会更新一些go以及其他方面的内容</p>
<h2 id="个人说明"><a href="#个人说明" class="headerlink" title="个人说明"></a>个人说明</h2><p>姓名:卢普希</p>
<p>爱好:略:)</p>
<p>太原理工大学在读大二软件工程学生,水平比较菜,写写博客记录一下自己写的或者做的一些小东西</p>
]]></content>
<categories>
<category>生活向</category>
</categories>
<tags>
<tag>life</tag>
</tags>
</entry>
<entry>
<title>Go的ai对话网页详解-第一天</title>
<url>/2024/11/04/Go%E7%9A%84ai%E5%AF%B9%E8%AF%9D%E7%BD%91%E9%A1%B5%E8%AF%A6%E8%A7%A3-%E7%AC%AC%E4%B8%80%E5%A4%A9/</url>
<content><![CDATA[<h1 id="Go-ai对话网页"><a href="#Go-ai对话网页" class="headerlink" title="Go ai对话网页"></a>Go ai对话网页</h1><p>本项目初期采用Gin框架,现在开源的项目中已采用了我自己写的Gwe框架,仿照了Gin的方法名称,可以一键切换。</p>
<p>项目目录采用GitHub开源的<a class="link" href="https://github.com/golang-standards/project-layout/blob/master/README_zh.md" >https://github.com/golang-standards/project-layout/blob/master/README_zh.md <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a></p>
<p><img
lazyload
src="/images/loading.svg"
data-src="/images/%E9%A1%B9%E7%9B%AE%E7%9B%AE%E5%BD%95.png"
alt="项目目录"
></p>
<h4 id="ai问答网页-其实就是一个比较简单的后端服务,前端传过来的消息经过后端处理成模型需要的输入格式再传给模型,接收模型返回的对话,前端显示即可。"><a href="#ai问答网页-其实就是一个比较简单的后端服务,前端传过来的消息经过后端处理成模型需要的输入格式再传给模型,接收模型返回的对话,前端显示即可。" class="headerlink" title="ai问答网页 其实就是一个比较简单的后端服务,前端传过来的消息经过后端处理成模型需要的输入格式再传给模型,接收模型返回的对话,前端显示即可。"></a>ai问答网页 其实就是一个比较简单的后端服务,前端传过来的消息经过后端处理成模型需要的输入格式再传给模型,接收模型返回的对话,前端显示即可。</h4><h2 id="前置条件"><a href="#前置条件" class="headerlink" title="前置条件"></a>前置条件</h2><p>采用ollama部署大模型模型,请提前下载ollama以及工具链langchaingo</p>
<div class="highlight-container" data-rel="Shell"><figure class="iseeu highlight shell"><table><tr><td class="code"><pre><span class="line">go install github.com/tmc/langchaingo/llms@latest</span><br></pre></td></tr></table></figure></div>
<p>前置操作需要安装gin框架,后续不用,也可使用原生的net/http进行操作</p>
<p>最后的main.go文件中其实只有短短几行</p>
<div class="highlight-container" data-rel="Go"><figure class="iseeu highlight go"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"> <span class="string">"ai_web/internal/middleware"</span></span><br><span class="line"> <span class="comment">//"github.com/gin-gonic/gin"</span></span><br><span class="line"> gin <span class="string">"ai_web/Gwe/Gwe"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"> r := gin.New()</span><br><span class="line"></span><br><span class="line"> <span class="comment">//r.Use(middleware.Cors())</span></span><br><span class="line"> r.Use(middleware.Router(r))</span><br><span class="line"> err := r.Run(<span class="string">":8080"</span>)</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"> <span class="built_in">panic</span>(err)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<p>这里使用gin初始化了一个不带log和recovery的引擎,之后加入两个中间件,跨域和路由,最后开启服务即可,我这里把跨越中间件注释掉主要是因为我是在本地测试的,好像是不需要这个,不是很懂。</p>
<p>internal目录结构如下</p>
<p><img
lazyload
src="/images/loading.svg"
data-src="/images/internal.png"
alt="internal"
></p>
<div class="highlight-container" data-rel="Go"><figure class="iseeu highlight go"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> middleware</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"> gin <span class="string">"ai_web/Gwe/Gwe"</span></span><br><span class="line"> <span class="string">"ai_web/internal/controller"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Router</span><span class="params">(r *gin.Engine)</span></span> gin.HandlerFunc {</span><br><span class="line"></span><br><span class="line"> chat := controller.Chat{}</span><br><span class="line"> mainGroup := r.Group(<span class="string">"/"</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"> mainGroup.POST(<span class="string">"/chat"</span>, chat.Dochat)</span><br><span class="line"> <span class="comment">//mainGroup.POST("/login", Nuser.Login)</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<p>路由的逻辑很简单,就是在/chat路径上起个路由就好了,这里遵循Restful API的风格,使用POST请求,具体Dochat的细节等第二天的文章吧。</p>
]]></content>
<categories>
<category>技术向</category>
</categories>
<tags>
<tag>Go</tag>
</tags>
</entry>
<entry>
<title>Go的ai对话网页详解-第二天</title>
<url>/2024/11/06/Go%E7%9A%84ai%E5%AF%B9%E8%AF%9D%E7%BD%91%E9%A1%B5%E8%AF%A6%E8%A7%A3-%E7%AC%AC%E4%BA%8C%E5%A4%A9/</url>
<content><![CDATA[<h1 id="第二天-–-Dochat回调函数详解"><a href="#第二天-–-Dochat回调函数详解" class="headerlink" title="第二天 – Dochat回调函数详解"></a>第二天 – Dochat回调函数详解</h1><p>先把函数贴上来</p>
<div class="highlight-container" data-rel="Go"><figure class="iseeu highlight go"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(this *Chat)</span></span> Dochat(c *gin.Context) {</span><br><span class="line"> <span class="keyword">var</span> body model.Chat</span><br><span class="line"> err := c.ShouldBindJSON(&body)</span><br><span class="line"> <span class="comment">//fmt.Println(body.Text)</span></span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"> c.JSON(http.StatusBadRequest, gin.H{</span><br><span class="line"> <span class="string">"msg"</span>: err.Error(),</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 class="comment">//open, err := sql.Open("sqlite3", "C:\\Users\\lkpalu\\GolandProjects\\ai_web\\internal\\SQL\\message.db")</span></span><br><span class="line"> <span class="comment">//if err != nil {</span></span><br><span class="line"> <span class="comment">// log.Println("打开数据库失败")</span></span><br><span class="line"> <span class="comment">//}</span></span><br><span class="line"> <span class="comment">//defer open.Close()</span></span><br><span class="line"> <span class="comment">//_, err = open.Exec("INSERT INTO messages(name,time,text) VALUES (?,?,?)", user.U.Name, time.Now(), body.Text)</span></span><br><span class="line"> prompt := util.CreatePrompt()</span><br><span class="line"></span><br><span class="line"> data := <span class="keyword">map</span>[<span class="type">string</span>]any{</span><br><span class="line"> <span class="string">"text"</span>: body.Text,</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> messages, err := prompt.FormatMessages(data)</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"> c.JSON(http.StatusBadRequest, gin.H{</span><br><span class="line"> <span class="string">"msg"</span>: err.Error(),</span><br><span class="line"> })</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//fmt.Println(messages)</span></span><br><span class="line"> contents := []llms.MessageContent{</span><br><span class="line"> llms.TextParts(messages[<span class="number">0</span>].GetType(), messages[<span class="number">0</span>].GetContent()),</span><br><span class="line"> llms.TextParts(messages[<span class="number">1</span>].GetType(), messages[<span class="number">1</span>].GetContent()),</span><br><span class="line"> }</span><br><span class="line"> llm := util.CteateModel(c, <span class="string">"qwen"</span>)</span><br><span class="line"> resp, err := llm.GenerateContent(context.Background(), contents)</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"> c.JSON(http.StatusBadRequest, gin.H{</span><br><span class="line"> <span class="string">"msg"</span>: err.Error(),</span><br><span class="line"> })</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> c.JSON(http.StatusOK, gin.H{</span><br><span class="line"> <span class="string">"code"</span>: <span class="number">0</span>,</span><br><span class="line"> <span class="string">"msg"</span>: <span class="string">"ok"</span>,</span><br><span class="line"> <span class="string">"data"</span>: resp.Choices[<span class="number">0</span>].Content,</span><br><span class="line"> })</span><br><span class="line"> <span class="comment">//fmt.Println(resp.Choices[0].Content)</span></span><br><span class="line"> <span class="comment">//_, err = open.Exec("INSERT INTO messages(name,time,text) VALUES (?,?,?)", "AI", time.Now(), resp.Choices[0].Content)</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<h4 id="函数逻辑"><a href="#函数逻辑" class="headerlink" title="函数逻辑"></a>函数逻辑</h4><p>这个函数中就是对于前端的json接收以及处理的一个过程,一开始的ShouldBindJSON方法让前端</p>
<div class="highlight-container" data-rel="Json"><figure class="iseeu highlight json"><table><tr><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"></span><br><span class="line"> “text” <span class="punctuation">:</span> messages</span><br><span class="line"></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure></div>
<p>绑定到结构体中,结构体格式如下</p>
<div class="highlight-container" data-rel="Go"><figure class="iseeu highlight go"><table><tr><td class="code"><pre><span class="line"><span class="keyword">type</span> Chat <span class="keyword">struct</span> {</span><br><span class="line"> Text <span class="type">string</span> <span class="string">`json:"text"`</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<p><code>json:"text"</code>是go中在json字符串中的键名称,json中会把<strong>Text</strong>这个键变为<strong>text</strong></p>
<p>绑定之后初始化提词器模板,将结构体中的消息放入模板中格式化,变为格式化语句,再将格式化语句按照大模型的输入要求传入模型中</p>
<p>最后返回大模型的回答内容,即<strong>resp.Choices[0].Content</strong></p>
<p>这样一个Dochat就完成了。</p>
<h4 id="模板初始化"><a href="#模板初始化" class="headerlink" title="模板初始化"></a>模板初始化</h4><p>**util.CreatePrompt()**这个函数为初始化模板的函数,代码如下</p>
<div class="highlight-container" data-rel="Go"><figure class="iseeu highlight go"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">CreatePrompt</span><span class="params">()</span></span> prompts.ChatPromptTemplate {</span><br><span class="line"> <span class="keyword">return</span> prompts.NewChatPromptTemplate([]prompts.MessageFormatter{</span><br><span class="line"> prompts.NewSystemMessagePromptTemplate(<span class="string">""</span>, <span class="literal">nil</span>),</span><br><span class="line"> prompts.NewHumanMessagePromptTemplate(<span class="string">"{{ .text }}"</span>, []<span class="type">string</span>{</span><br><span class="line"> <span class="string">"text"</span>,</span><br><span class="line"> }),</span><br><span class="line"> })</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<p>这里初始化的时候不需要给系统提示词,因为我们并不需要给模型一个具体场景下的角色,</p>
<p>人类的提示词即我们在前端输入的语句,这里使用go语言的模板初始化,代表这里要填的内容为后续<strong>text</strong>的内容</p>
<h4 id="大模型初始化"><a href="#大模型初始化" class="headerlink" title="大模型初始化"></a>大模型初始化</h4><p>**util.CteateModel(c, “qwen”)**这个函数为初始化大模型的函数,代码如下</p>
<div class="highlight-container" data-rel="Go"><figure class="iseeu highlight go"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">CteateModel</span><span class="params">(c *gin.Context, ModelName <span class="type">string</span>)</span></span> *ollama.LLM {</span><br><span class="line"> llm, err := ollama.New(ollama.WithModel(ModelName))</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"> c.JSON(http.StatusInternalServerError, gin.H{</span><br><span class="line"> <span class="string">"msg"</span>: err.Error(),</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><span class="line"> <span class="keyword">return</span> llm</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<p>就是调用接口**ollama.New()**创建一个大模型的指针即可</p>
<h1 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h1><p>Dochat中就是接收前端消息,初始化消息模型,初始化大模型,把前端消息格式化后传入给大模型再返回大模型的消息即可</p>
]]></content>
<categories>
<category>技术向</category>
</categories>
<tags>
<tag>Go</tag>
</tags>
</entry>
<entry>
<title>http模拟RPC-go</title>
<url>/2024/11/06/http%E6%A8%A1%E6%8B%9FRPC-go/</url>
<content><![CDATA[<h2 id="记录"><a href="#记录" class="headerlink" title="记录"></a>记录</h2><h4 id="服务端"><a href="#服务端" class="headerlink" title="服务端"></a>服务端</h4><div class="highlight-container" data-rel="Go"><figure class="iseeu highlight go"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"> <span class="string">"fmt"</span></span><br><span class="line"> <span class="string">"github.com/gin-gonic/gin"</span></span><br><span class="line"> <span class="string">"log"</span></span><br><span class="line"> <span class="string">"strconv"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> PrintInfo <span class="keyword">struct</span> {</span><br><span class="line"> A <span class="type">string</span> <span class="string">`json:"a"`</span></span><br><span class="line"> B <span class="type">string</span> <span class="string">`json:"b"`</span></span><br><span class="line"> <span class="comment">//PrintInfos string `json:"print_info"`</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">RpcS</span><span class="params">()</span></span> {</span><br><span class="line"> <span class="keyword">var</span> Prints PrintInfo</span><br><span class="line"> r := gin.Default()</span><br><span class="line"> r.POST(<span class="string">"/"</span>, <span class="function"><span class="keyword">func</span><span class="params">(c *gin.Context)</span></span> {</span><br><span class="line"> c.ShouldBindJSON(&Prints)</span><br><span class="line"> d, _ := strconv.Atoi(Prints.A)</span><br><span class="line"> e, _ := strconv.Atoi(Prints.B)</span><br><span class="line"> f := d + e</span><br><span class="line"> log.Println(d, e)</span><br><span class="line"> c.JSON(<span class="number">200</span>, gin.H{</span><br><span class="line"> <span class="comment">//"c": strconv.Itoa(strconv.Atoi(Prints.a) + strconv.Atoi(Prints.b)),</span></span><br><span class="line"> <span class="string">"D"</span>: f,</span><br><span class="line"> })</span><br><span class="line"> })</span><br><span class="line"> fmt.Println(<span class="string">"start"</span>)</span><br><span class="line"> r.Run(<span class="string">":8080"</span>)</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"> RpcS()</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<h4 id="客户端"><a href="#客户端" class="headerlink" title="客户端"></a>客户端</h4><div class="highlight-container" data-rel="Go"><figure class="iseeu highlight go"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"> <span class="string">"bytes"</span></span><br><span class="line"> <span class="string">"encoding/json"</span></span><br><span class="line"> <span class="string">"fmt"</span></span><br><span class="line"> <span class="string">"log"</span></span><br><span class="line"> <span class="string">"net/http"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> msg <span class="keyword">struct</span> {</span><br><span class="line"> <span class="comment">//Message string `json:"message"`</span></span><br><span class="line"> D <span class="type">int</span> <span class="string">`json:"d"`</span></span><br><span class="line">}</span><br><span class="line"><span class="keyword">type</span> PrintInfo <span class="keyword">struct</span> {</span><br><span class="line"> A <span class="type">string</span> <span class="string">`json:"a"`</span></span><br><span class="line"> B <span class="type">string</span> <span class="string">`json:"b"`</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"> Prints := PrintInfo{</span><br><span class="line"> <span class="comment">//PrintInfos: "Hello World",</span></span><br><span class="line"> A: <span class="string">"1"</span>,</span><br><span class="line"> B: <span class="string">"2"</span>,</span><br><span class="line"> }</span><br><span class="line"> marshal, _ := json.Marshal(Prints)</span><br><span class="line"> <span class="comment">//fmt.Println(marshal)</span></span><br><span class="line"> resp, err := http.Post(<span class="string">"http://localhost:8080"</span>, <span class="string">"application/json"</span>, bytes.NewBuffer(marshal)) <span class="comment">// 添加了http://前缀以确保URL格式正确</span></span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"> log.Fatalf(<span class="string">"无法获取响应: %v"</span>, err) <span class="comment">// 使用log.Fatalf来处理错误并终止程序</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">defer</span> resp.Body.Close()</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> resp.StatusCode != http.StatusOK {</span><br><span class="line"> log.Fatalf(<span class="string">"服务器返回错误状态码: %d"</span>, resp.StatusCode)</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> m msg</span><br><span class="line"> <span class="keyword">if</span> err := json.NewDecoder(resp.Body).Decode(&m); err != <span class="literal">nil</span> {</span><br><span class="line"> log.Fatalf(<span class="string">"无法解码响应体: %v"</span>, err)</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> fmt.Println(m.D)</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
]]></content>
<categories>
<category>技术向</category>
</categories>
<tags>
<tag>Go</tag>
</tags>
</entry>
<entry>
<title>初探net/rpc</title>
<url>/2024/11/06/%E5%88%9D%E6%8E%A2net-rpc/</url>
<content><![CDATA[<h4 id="服务端"><a href="#服务端" class="headerlink" title="服务端"></a>服务端</h4><div class="highlight-container" data-rel="Go"><figure class="iseeu highlight go"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"> <span class="string">"net"</span></span><br><span class="line"> <span class="string">"net/rpc"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> HelloWorldService <span class="keyword">struct</span>{}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(h *HelloWorldService)</span></span> Hello(args <span class="type">string</span>, reply *<span class="type">string</span>) <span class="type">error</span> {</span><br><span class="line"> *reply = <span class="string">"hello,"</span> + args</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"> <span class="comment">//1.监听</span></span><br><span class="line"> listen, err := net.Listen(<span class="string">"tcp"</span>, <span class="string">"localhost:1234"</span>)</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"> <span class="built_in">panic</span>(err)</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//2.注册rpc服务</span></span><br><span class="line"> _ = rpc.RegisterName(<span class="string">"HelloWorldService"</span>, &HelloWorldService{})</span><br><span class="line"> <span class="comment">//3.将tcp监听接管为rpc服务</span></span><br><span class="line"> accept, _ := listen.Accept()</span><br><span class="line"> rpc.ServeConn(accept)</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<h4 id="客户端"><a href="#客户端" class="headerlink" title="客户端"></a>客户端</h4><div class="highlight-container" data-rel="Go"><figure class="iseeu highlight go"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"> <span class="string">"fmt"</span></span><br><span class="line"> <span class="string">"net/rpc"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"> <span class="comment">//1.创建客户端连接</span></span><br><span class="line"> dial, _ := rpc.Dial(<span class="string">"tcp"</span>, <span class="string">"localhost:1234"</span>)</span><br><span class="line"> <span class="comment">//2.调用远程服务端方法</span></span><br><span class="line"> <span class="keyword">var</span> reply <span class="type">string</span></span><br><span class="line"> err := dial.Call(<span class="string">"HelloWorldService.Hello"</span>, <span class="string">"lkpalu"</span>, &reply)</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"> <span class="built_in">panic</span>(err)</span><br><span class="line"> }</span><br><span class="line"> fmt.Println(reply)</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
]]></content>
<categories>
<category>技术向</category>
</categories>
<tags>
<tag>Go</tag>
</tags>
</entry>
<entry>
<title>GRPC初探--proto文件的编写</title>
<url>/2024/11/07/GRPC%E5%88%9D%E6%8E%A2-proto%E6%96%87%E4%BB%B6%E7%9A%84%E7%BC%96%E5%86%99/</url>
<content><![CDATA[<h1 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h1><p>proto文件为protoc buffer文件,这是一种高效的文件格式,由Google出品,现在流行的语法为proto3,</p>
<div class="highlight-container" data-rel="Protobuf"><figure class="iseeu highlight protobuf"><table><tr><td class="code"><pre><span class="line">syntax = <span class="string">"proto3"</span>;</span><br><span class="line"><span class="keyword">option</span> go_package = <span class="string">"github.com/lkpalu/grpc-go-example/proto"</span>;</span><br><span class="line"><span class="keyword">package</span> Server;</span><br><span class="line"></span><br><span class="line"><span class="keyword">message </span><span class="title class_">Request</span> {</span><br><span class="line"> <span class="type">string</span> messages = <span class="number">1</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">message </span><span class="title class_">Response</span> {</span><br><span class="line"> <span class="type">string</span> messages = <span class="number">1</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">service </span><span class="title class_">New</span>{</span><br><span class="line"> <span class="function"><span class="keyword">rpc</span> Hello (Request) <span class="keyword">returns</span> (Response)</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<h4 id="第一句指定该文件的语法版本可选proto3-proto2"><a href="#第一句指定该文件的语法版本可选proto3-proto2" class="headerlink" title="第一句指定该文件的语法版本可选proto3/proto2"></a>第一句指定该文件的语法版本可选proto3/proto2</h4><h4 id="第二句指定由proto文件生成的go文件所在包目录"><a href="#第二句指定由proto文件生成的go文件所在包目录" class="headerlink" title="第二句指定由proto文件生成的go文件所在包目录"></a>第二句指定由proto文件生成的go文件所在包目录</h4><h4 id="第三句指定生成的go文件的package"><a href="#第三句指定生成的go文件的package" class="headerlink" title="第三句指定生成的go文件的package"></a>第三句指定生成的go文件的package</h4><h2 id="message"><a href="#message" class="headerlink" title="message"></a>message</h2><p>meassage类似不同语言中的结构体</p>
<p>用于定义发送消息和接收消息的内容类型</p>
<p>格式为<strong>变量类型 变量 = id</strong></p>
<p>初次接触的朋友可能不了解这个id是用来做什么的,这个其实是文件在序列化和反序列化时的排序</p>
<h2 id="service"><a href="#service" class="headerlink" title="service"></a>service</h2><p>service类似不同语言的接口或抽象类,用来规定服务端的函数</p>
<p>内部的rpc为函数定义,即远程调用的函数,特别注意,流式服务需要指明传入参数stream或传出参数stream</p>
<p>如</p>
<div class="highlight-container" data-rel="Protobuf"><figure class="iseeu highlight protobuf"><table><tr><td class="code"><pre><span class="line"><span class="keyword">service </span><span class="title class_">New</span>{</span><br><span class="line"> <span class="function"><span class="keyword">rpc</span> Hello (Request) <span class="keyword">returns</span> (Response)</span>;</span><br><span class="line"> <span class="function"><span class="keyword">rpc</span> Hello2 (stream Request) <span class="keyword">returns</span> (stream Response)</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<h1 id="代码生成"><a href="#代码生成" class="headerlink" title="代码生成"></a>代码生成</h1><p>在proto文件目录中运行</p>
<div class="highlight-container" data-rel="Shell"><figure class="iseeu highlight shell"><table><tr><td class="code"><pre><span class="line">protoc --go_out=. --go-grpc_out=. your_proto_file.proto</span><br></pre></td></tr></table></figure></div>
<p>会生成两个文件并且目录结构如下</p>
<p><img
lazyload
src="/images/loading.svg"
data-src="/images/proto.png"
alt="proto"
></p>
<p>目录结构和刚才指定的go_package相同</p>
]]></content>
<categories>
<category>技术向</category>
</categories>
<tags>
<tag>Go</tag>
</tags>
</entry>
<entry>
<title>离散数学不同关系之间的联系</title>
<url>/2024/11/07/%E7%A6%BB%E6%95%A3%E6%95%B0%E5%AD%A6%E4%B8%8D%E5%90%8C%E5%85%B3%E7%B3%BB%E4%B9%8B%E9%97%B4%E7%9A%84%E8%81%94%E7%B3%BB/</url>
<content><![CDATA[<h1 id="不同关系的定义"><a href="#不同关系的定义" class="headerlink" title="不同关系的定义"></a>不同关系的定义</h1><h3 id="恒等关系"><a href="#恒等关系" class="headerlink" title="恒等关系:"></a>恒等关系:</h3><p>恒等关系,是满足且只满足自身与自身的关系,对应关系矩阵是<a class="link" href="https://baike.baidu.com/item/%E5%8D%95%E4%BD%8D%E7%9F%A9%E9%98%B5/0?fromModule=lemma_inlink" >单位矩阵 <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a>。 [2]</p>
<p>设A={a,b,c},则其上关系R={<a,a>,<b,b>,<c,c>},<strong>关系矩阵为单位矩阵</strong>。恒等关系满足<strong>自反性、对称性、反对称性</strong>等性质。</p>
<h3 id="相容关系"><a href="#相容关系" class="headerlink" title="相容关系"></a>相容关系</h3><p>指集合A上具有自反性与对称性的二元关系。</p>
<h3 id="等价关系"><a href="#等价关系" class="headerlink" title="等价关系"></a>等价关系</h3><p>等价关系定义为:设R是非空集合A上的二元关系,若R是<strong>自反的、对称的、传递的</strong>,则称R是A上的等价关系。</p>
<h3 id="拟序关系"><a href="#拟序关系" class="headerlink" title="拟序关系"></a>拟序关系</h3><p>设R为非空集合A上的关系。如果R是<strong>反自反,反对称和传递的</strong>,则称R是A的拟序关系</p>
<h3 id="偏序关系"><a href="#偏序关系" class="headerlink" title="偏序关系"></a>偏序关系</h3><p>设R为非空集合A上的关系。如果R是<strong>自反,反对称和传递的</strong>,则称R是A的拟序关系</p>
<h3 id="全序关系"><a href="#全序关系" class="headerlink" title="全序关系"></a>全序关系</h3><p>设< A,<= >是一个<strong>偏序关系</strong>,若对任意x,y属于A,总有x <= y,或y <= x之一成立,则成关系<=为全序关系或线序关系</p>
<h3 id="良序关系"><a href="#良序关系" class="headerlink" title="良序关系"></a>良序关系</h3><p>设< A,<= >是一<strong>偏序集</strong>,若对A的任何一个非空子集都有最小元,则称<=为良序关系</p>
<h1 id="—————————————–"><a href="#—————————————–" class="headerlink" title="—————————————–"></a>—————————————–</h1><p>以上为离散数学中不同关系的定义</p>
<p>由此</p>
<p><strong>恒等关系既是等价关系又是偏序关系</strong></p>
]]></content>
<tags>
<tag>离散数学</tag>
</tags>
</entry>
<entry>
<title>GRPC初探--简单客户端,服务端编写</title>
<url>/2024/11/07/GRPC%E5%88%9D%E6%8E%A2-%E7%AE%80%E5%8D%95%E5%AE%A2%E6%88%B7%E7%AB%AF%EF%BC%8C%E6%9C%8D%E5%8A%A1%E7%AB%AF%E7%BC%96%E5%86%99/</url>
<content><![CDATA[<h2 id="服务端"><a href="#服务端" class="headerlink" title="服务端"></a>服务端</h2><div class="highlight-container" data-rel="Go"><figure class="iseeu highlight go"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"> pb <span class="string">"NewGrpc/proto/github.com/lkpalu/grpc-go/proto"</span></span><br><span class="line"> <span class="string">"context"</span></span><br><span class="line"> <span class="string">"google.golang.org/grpc"</span></span><br><span class="line"> <span class="string">"log"</span></span><br><span class="line"> <span class="string">"net"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> newServer <span class="keyword">struct</span> {</span><br><span class="line"> pb.UnimplementedNewServer</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *newServer)</span></span> Hello(ctx context.Context, re *pb.Request) (*pb.Response, <span class="type">error</span>) {</span><br><span class="line"> <span class="keyword">return</span> &pb.Response{</span><br><span class="line"> Messages: <span class="string">"Hello World"</span> + re.Messages,</span><br><span class="line"> }, <span class="literal">nil</span></span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"> <span class="comment">//n := newServer{}</span></span><br><span class="line"> grpcServer := grpc.NewServer()</span><br><span class="line"> pb.RegisterNewServer(grpcServer, &newServer{})</span><br><span class="line"> lis, err := net.Listen(<span class="string">"tcp"</span>, <span class="string">":8080"</span>)</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"> log.Fatalf(<span class="string">"failed to listen: %v"</span>, err)</span><br><span class="line"> }</span><br><span class="line"> err = grpcServer.Serve(lis)</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"> log.Fatalf(<span class="string">"failed to serve: %v"</span>, err)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<p>服务端实现定义的接口即可</p>
<h2 id="客户端"><a href="#客户端" class="headerlink" title="客户端"></a>客户端</h2><div class="highlight-container" data-rel="Go"><figure class="iseeu highlight go"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"> pb <span class="string">"NewGrpc/proto/github.com/lkpalu/grpc-go/proto"</span></span><br><span class="line"> <span class="string">"context"</span></span><br><span class="line"> <span class="string">"fmt"</span></span><br><span class="line"> <span class="string">"google.golang.org/grpc"</span></span><br><span class="line"> <span class="string">"google.golang.org/grpc/credentials/insecure"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"> m := pb.Request{</span><br><span class="line"> Messages: <span class="string">"lkpalu"</span>,</span><br><span class="line"> }</span><br><span class="line"> conn, err := grpc.NewClient(<span class="string">"localhost:8080"</span>, grpc.WithTransportCredentials(insecure.NewCredentials()))</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"> <span class="built_in">panic</span>(err)</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">defer</span> conn.Close()</span><br><span class="line"> client := pb.NewNewClient(conn)</span><br><span class="line"> resp, err := client.Hello(context.Background(), &m)</span><br><span class="line"> fmt.Println(resp.Messages)</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<p>客户端直接调用即可</p>
]]></content>
<tags>
<tag>Go</tag>
</tags>
</entry>
<entry>
<title>proto文件类型补充</title>
<url>/2024/11/10/proto%E6%96%87%E4%BB%B6%E7%B1%BB%E5%9E%8B%E8%A1%A5%E5%85%85/</url>
<content><![CDATA[<h2 id="proto文件类型及语法"><a href="#proto文件类型及语法" class="headerlink" title="proto文件类型及语法"></a>proto文件类型及语法</h2><p>proto文件的类型上次写了message和service,此外还有map和enum</p>
<p>代码如下</p>
<h4 id="map"><a href="#map" class="headerlink" title="map"></a>map</h4><div class="highlight-container" data-rel="Protobuf"><figure class="iseeu highlight protobuf"><table><tr><td class="code"><pre><span class="line"><span class="keyword">message </span><span class="title class_">Pong</span>{</span><br><span class="line"> <span class="type">string</span> message = <span class="number">1</span>;</span><br><span class="line"> Test t = <span class="number">2</span>;</span><br><span class="line"> map<<span class="type">string</span>, <span class="type">int32</span>> m = <span class="number">3</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<h4 id="enum"><a href="#enum" class="headerlink" title="enum"></a>enum</h4><div class="highlight-container" data-rel="Protobuf"><figure class="iseeu highlight protobuf"><table><tr><td class="code"><pre><span class="line"><span class="keyword">enum </span><span class="title class_">Test</span>{</span><br><span class="line"> A = <span class="number">0</span>;</span><br><span class="line"> B = <span class="number">1</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<p>生成的go语言代码如下</p>
<div class="highlight-container" data-rel="Go"><figure class="iseeu highlight go"><table><tr><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">//enum类型</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Test <span class="type">int32</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> (</span><br><span class="line"> Test_A Test = <span class="number">0</span></span><br><span class="line"> Test_B Test = <span class="number">1</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">// Enum value maps for Test.</span></span><br><span class="line"><span class="keyword">var</span> (</span><br><span class="line"> Test_name = <span class="keyword">map</span>[<span class="type">int32</span>]<span class="type">string</span>{</span><br><span class="line"> <span class="number">0</span>: <span class="string">"A"</span>,</span><br><span class="line"> <span class="number">1</span>: <span class="string">"B"</span>,</span><br><span class="line"> }</span><br><span class="line"> Test_value = <span class="keyword">map</span>[<span class="type">string</span>]<span class="type">int32</span>{</span><br><span class="line"> <span class="string">"A"</span>: <span class="number">0</span>,</span><br><span class="line"> <span class="string">"B"</span>: <span class="number">1</span>,</span><br><span class="line"> }</span><br><span class="line">)</span><br></pre></td></tr></table></figure></div>
<div class="highlight-container" data-rel="Go"><figure class="iseeu highlight go"><table><tr><td class="code"><pre><span class="line"><span class="comment">//Pong结构体</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Pong <span class="keyword">struct</span> {</span><br><span class="line"> state protoimpl.MessageState</span><br><span class="line"> sizeCache protoimpl.SizeCache</span><br><span class="line"> unknownFields protoimpl.UnknownFields</span><br><span class="line"></span><br><span class="line"> Message <span class="type">string</span> <span class="string">`protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`</span></span><br><span class="line"> T Test <span class="string">`protobuf:"varint,2,opt,name=t,proto3,enum=Server.Test" json:"t,omitempty"`</span></span><br><span class="line"> M <span class="keyword">map</span>[<span class="type">string</span>]<span class="type">int32</span> <span class="string">`protobuf:"bytes,3,rep,name=m,proto3" json:"m,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<p>定义的enum类型会定义为int32的常量</p>
<h2 id="补充语法"><a href="#补充语法" class="headerlink" title="补充语法"></a>补充语法</h2><p>上次在proto中未提到import,</p>
<p>proto中也支持import导入其他文件中定义的数据类型</p>
<div class="highlight-container" data-rel="Protobuf"><figure class="iseeu highlight protobuf"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="string">"base.proto"</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="string">"google/protobuf/empty.proto"</span>;</span><br></pre></td></tr></table></figure></div>
<h4 id="注意"><a href="#注意" class="headerlink" title="注意"></a>注意</h4><p>在生成代码时需要同时为多个proto文件生成代码,否则会出现找不到数据类型的情况</p>
]]></content>
<tags>
<tag>Go</tag>
</tags>
</entry>
<entry>
<title>Java栈与队列的实现</title>
<url>/2024/11/12/Java%E6%A0%88%E4%B8%8E%E9%98%9F%E5%88%97%E7%9A%84%E5%AE%9E%E7%8E%B0/</url>
<content><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>栈与队列的实现采用动态分配内存,保证了使用的灵活性</p>
<h2 id="栈"><a href="#栈" class="headerlink" title="栈"></a>栈</h2><div class="highlight-container" data-rel="Java"><figure class="iseeu highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> Stack;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Stack</span> {</span><br><span class="line"> <span class="type">int</span> <span class="variable">length</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> <span class="type">int</span>[] arr;</span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Stack</span><span class="params">()</span> {</span><br><span class="line"> <span class="built_in">this</span>.length = <span class="number">0</span>;</span><br><span class="line"> arr = <span class="keyword">new</span> <span class="title class_">int</span>[<span class="built_in">this</span>.length];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Stack</span><span class="params">(<span class="type">int</span> length)</span> {</span><br><span class="line"> <span class="built_in">this</span>.length = length;</span><br><span class="line"> arr = <span class="keyword">new</span> <span class="title class_">int</span>[<span class="built_in">this</span>.length];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">Push</span><span class="params">(<span class="type">int</span> val)</span> {</span><br><span class="line"> <span class="built_in">this</span>.length++;</span><br><span class="line"> <span class="type">int</span>[] tmp = <span class="keyword">new</span> <span class="title class_">int</span>[<span class="built_in">this</span>.length];</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;i <<span class="built_in">this</span>.length - <span class="number">1</span>;i++) {</span><br><span class="line"> tmp[i] = arr[i];</span><br><span class="line"> }</span><br><span class="line"> tmp[<span class="built_in">this</span>.length - <span class="number">1</span>] = val;</span><br><span class="line"><span class="comment">// System.out.println(Arrays.toString(tmp));</span></span><br><span class="line"> arr = tmp;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">GetLength</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>.length;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">Pop</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">int</span> <span class="variable">val</span> <span class="operator">=</span> <span class="built_in">this</span>.arr[<span class="built_in">this</span>.length - <span class="number">1</span>];</span><br><span class="line"> <span class="built_in">this</span>.length--;</span><br><span class="line"> <span class="type">int</span>[] tmp = <span class="keyword">new</span> <span class="title class_">int</span>[<span class="built_in">this</span>.length];</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;i<<span class="built_in">this</span>.length;i++) {</span><br><span class="line"> tmp[i] = arr[i];</span><br><span class="line"> }</span><br><span class="line"> arr = tmp;</span><br><span class="line"> <span class="keyword">return</span> val;</span><br><span class="line"> }</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">toString</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"Queue{"</span> +</span><br><span class="line"> <span class="string">"length="</span> + length +</span><br><span class="line"> <span class="string">", arr="</span> + Arrays.toString(arr) +</span><br><span class="line"> <span class="string">'}'</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<h2 id="队列"><a href="#队列" class="headerlink" title="队列"></a>队列</h2><div class="highlight-container" data-rel="Java"><figure class="iseeu highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> Queue;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Queue</span> {</span><br><span class="line"> <span class="type">int</span>[] arr;</span><br><span class="line"> <span class="type">int</span> length;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Queue</span><span class="params">()</span> {</span><br><span class="line"> <span class="built_in">this</span>.length = <span class="number">0</span>;</span><br><span class="line"> <span class="built_in">this</span>.arr = <span class="keyword">new</span> <span class="title class_">int</span>[<span class="built_in">this</span>.length];</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Queue</span><span class="params">(<span class="type">int</span> length)</span> {</span><br><span class="line"> <span class="built_in">this</span>.length = length;</span><br><span class="line"> <span class="built_in">this</span>.arr = <span class="keyword">new</span> <span class="title class_">int</span>[<span class="built_in">this</span>.length];</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">Push</span><span class="params">(<span class="type">int</span> val)</span> {</span><br><span class="line"> <span class="built_in">this</span>.length++;</span><br><span class="line"> <span class="type">int</span>[] tmp = <span class="keyword">new</span> <span class="title class_">int</span>[<span class="built_in">this</span>.length];</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i < <span class="built_in">this</span>.length - <span class="number">1</span>; i++) {</span><br><span class="line"> tmp[i] = arr[i];</span><br><span class="line"> }</span><br><span class="line"> tmp[<span class="built_in">this</span>.length - <span class="number">1</span>] = val;</span><br><span class="line"> arr = tmp;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">LPush</span><span class="params">(<span class="type">int</span> val)</span> {</span><br><span class="line"> <span class="built_in">this</span>.length++;</span><br><span class="line"> <span class="type">int</span>[] tmp = <span class="keyword">new</span> <span class="title class_">int</span>[<span class="built_in">this</span>.length];</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i < <span class="built_in">this</span>.length - <span class="number">1</span>; i++) {</span><br><span class="line"> tmp[i+<span class="number">1</span>] = arr[i];</span><br><span class="line"> }</span><br><span class="line"> tmp[<span class="number">0</span>] = val;</span><br><span class="line"> arr = tmp;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">Pop</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">int</span> <span class="variable">val</span> <span class="operator">=</span> <span class="built_in">this</span>.arr[<span class="number">0</span>];</span><br><span class="line"> <span class="built_in">this</span>.length--;</span><br><span class="line"> <span class="type">int</span>[] tmp = <span class="keyword">new</span> <span class="title class_">int</span>[<span class="built_in">this</span>.length];</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i < <span class="built_in">this</span>.length; i++) {</span><br><span class="line"> tmp[i] = arr[i + <span class="number">1</span>];</span><br><span class="line"> }</span><br><span class="line"> arr = tmp;</span><br><span class="line"> <span class="keyword">return</span> val;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">RPop</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">int</span> <span class="variable">val</span> <span class="operator">=</span> <span class="built_in">this</span>.arr[<span class="built_in">this</span>.length - <span class="number">1</span>];</span><br><span class="line"> <span class="built_in">this</span>.length--;</span><br><span class="line"> <span class="type">int</span>[] tmp = <span class="keyword">new</span> <span class="title class_">int</span>[<span class="built_in">this</span>.length];</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i < <span class="built_in">this</span>.length; i++) {</span><br><span class="line"> tmp[i] = arr[i];</span><br><span class="line"> }</span><br><span class="line"> arr = tmp;</span><br><span class="line"> <span class="keyword">return</span> val;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">GetLength</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>.length;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">toString</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"Queue{"</span> +</span><br><span class="line"> <span class="string">"arr="</span> + Arrays.toString(arr) +</span><br><span class="line"> <span class="string">", length="</span> + length +</span><br><span class="line"> <span class="string">'}'</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
]]></content>
<tags>
<tag>Java</tag>
</tags>
</entry>
<entry>
<title>记一次minikube start的经历</title>
<url>/2024/11/15/%E8%AE%B0%E4%B8%80%E6%AC%A1minikube-start%E7%9A%84%E7%BB%8F%E5%8E%86/</url>
<content><![CDATA[<h2 id="minikube"><a href="#minikube" class="headerlink" title="minikube"></a>minikube</h2><p>昨天在运行minikube start的时候因为网络问题太慢了,想着找个国内源,但按照网上的方法后面添加阿里的镜像源后提示找不到镜像源,后来试了好几次都不行,直接把wifi换成手机热点了,速度快了不少,也是等了十几分钟下好了,但之后下载完预处理文件后又报错,提示网络问题,今天换了wifi,挂了tz之后发现中途依然会报错,但最后会成功,就记录以下这样一个简短的经历吧。</p>
]]></content>
<tags>
<tag>k8s</tag>
</tags>
</entry>
<entry>
<title>lk-本地音乐播放器</title>
<url>/2024/11/19/lk-%E6%9C%AC%E5%9C%B0%E9%9F%B3%E4%B9%90%E6%92%AD%E6%94%BE%E5%99%A8/</url>
<content><![CDATA[<h4 id="项目地址"><a href="#项目地址" class="headerlink" title="项目地址"></a>项目地址</h4><p><a class="link" href="https://github.com/lkpalu/lk-musicplayer" >https://github.com/lkpalu/lk-musicplayer <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a></p>
<h2 id="说明"><a href="#说明" class="headerlink" title="说明"></a>说明</h2><p>这个音乐播放器应该是我前两天突然想写的一个应用,因为我平时也听本地歌曲,但本地的播放器都不是那么快速的能够让我听到歌,正好最近了解了cobra这个命令行库,就有了这个命令行本地音乐播放器了</p>
<h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p>从github上面把项目克隆下来之后,文件夹里面会有两个lk,一个是lk.exe为windows的64位x86软件,另一个位lk是Linux下的64位x86软件,arm架构的目前还在编译中,克隆下来之后把当前目录添加到系统环境变量中,然后在系统环境变量中添加Mytool变量,路径依然为当前目录,最后在config.json中将root改为你想放置数据库文件的地方就可以正常使用了。</p>
<h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><p>基本的几个使用方法仓库里已经说明了,这里主要说明一下命令行的参数</p>
<p>1.随机播放模式</p>
<div class="highlight-container" data-rel="Shell"><figure class="iseeu highlight shell"><table><tr><td class="code"><pre><span class="line">lk play -r</span><br></pre></td></tr></table></figure></div>
<p>2.顺序播放</p>
<div class="highlight-container" data-rel="Shell"><figure class="iseeu highlight shell"><table><tr><td class="code"><pre><span class="line">lk play -o</span><br></pre></td></tr></table></figure></div>
<p>3.循环播放</p>
<div class="highlight-container" data-rel="Shell"><figure class="iseeu highlight shell"><table><tr><td class="code"><pre><span class="line">lk play [index] -l [count]</span><br></pre></td></tr></table></figure></div>
<p>[index]为需要播放的歌曲序号</p>
<p>[count]为需要循环的次数</p>
<p>这两个默认参数不填index为1</p>
<p>count为0表示无限循环</p>
<p>4.删除</p>
<div class="highlight-container" data-rel="Shell"><figure class="iseeu highlight shell"><table><tr><td class="code"><pre><span class="line">lk rm [index]</span><br></pre></td></tr></table></figure></div>
<div class="highlight-container" data-rel="Shell"><figure class="iseeu highlight shell"><table><tr><td class="code"><pre><span class="line">lk rm -a</span><br></pre></td></tr></table></figure></div>
<p>-a 表示删除整个歌单</p>
<p>5.排序</p>
<div class="highlight-container" data-rel="Shell"><figure class="iseeu highlight shell"><table><tr><td class="code"><pre><span class="line">lk sort</span><br></pre></td></tr></table></figure></div>
<p>默认删除完歌曲后会重新排序但有时也需要手动排序(序号不连续时,理论不需要手动排序)</p>
<h2 id="之后会带来源码讲解"><a href="#之后会带来源码讲解" class="headerlink" title="之后会带来源码讲解"></a>之后会带来源码讲解</h2>]]></content>
<tags>
<tag>Go</tag>
</tags>
</entry>
<entry>
<title>红黑树c语言实现</title>
<url>/2024/12/02/%E7%BA%A2%E9%BB%91%E6%A0%91/</url>
<content><![CDATA[<h1 id="红黑树"><a href="#红黑树" class="headerlink" title="红黑树"></a>红黑树</h1><h2 id="定义"><a href="#定义" class="headerlink" title="定义"></a>定义</h2><p>(叶子节点包含空节点)</p>
<p>1.每个节点是红的或者黑的</p>
<p>2.根节点是黑的</p>
<p>3.每个叶子节点是黑的</p>
<p>4.如果一个节点是红的,则他的两个儿子都是黑的</p>
<p>5.对每个节点,从该节点到其子孙节点的所有路径上包含相同数目的黑节点</p>
<p><img
lazyload
src="/images/loading.svg"
data-src="/images/rbtree/define.jpg"
alt="旋转"
></p>
<h3 id="节点定义"><a href="#节点定义" class="headerlink" title="节点定义"></a>节点定义</h3><div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">rtbtree</span>{</span></span><br><span class="line"></span><br><span class="line"> <span class="type">int</span> key;</span><br><span class="line"></span><br><span class="line"> <span class="type">void</span>* value;</span><br><span class="line"></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">rtbtree</span>* <span class="title">left</span>;</span></span><br><span class="line"></span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">rtbtree</span>* <span class="title">right</span>;</span></span><br><span class="line"></span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">rtbtree</span>* <span class="title">parent</span>;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="type">unsigned</span> <span class="type">char</span> color;</span><br><span class="line"></span><br><span class="line">};</span><br></pre></td></tr></table></figure></div>
<h3 id="关键节点定义"><a href="#关键节点定义" class="headerlink" title="关键节点定义"></a>关键节点定义</h3><div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">rbtree</span>{</span></span><br><span class="line"> rbtree_node* root;</span><br><span class="line"> rbtree_node* nil;</span><br><span class="line">}rbtree;</span><br></pre></td></tr></table></figure></div>
<p>这里定义nil节点为所有的叶子节点</p>
<p>根据上面定义的节点来看,迁移性非常差,做出如下修改</p>
<div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> RBTREE_ENTRY(name,type) \</span></span><br><span class="line"><span class="meta"> struct name{ \</span></span><br><span class="line"><span class="meta"> struct type *left; \</span></span><br><span class="line"><span class="meta"> struct type *right; \</span></span><br><span class="line"><span class="meta"> struct type *parent; \</span></span><br><span class="line"><span class="meta"> unsigned char color; \</span></span><br><span class="line"><span class="meta"> }</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="type">int</span> KEY_TYPE; </span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">rbtree_node</span>{</span></span><br><span class="line"> KEY_TYPE key;</span><br><span class="line"> <span class="type">void</span>* value;</span><br><span class="line"><span class="meta">#<span class="keyword">if</span> 0</span></span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">type</span> <span class="title">left</span>;</span> </span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">type</span> <span class="title">right</span>;</span> </span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">type</span> <span class="title">parent</span>;</span> </span><br><span class="line"> <span class="type">unsigned</span> <span class="type">char</span> color; </span><br><span class="line"><span class="meta">#<span class="keyword">else</span></span></span><br><span class="line"> RBTREE_ENTRY(,rbtree_node) node;</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">}rbtree_node;</span><br></pre></td></tr></table></figure></div>
<p>这种定义方法可以帮助定义不同类型的红黑树,以及在线程中减少代码量</p>
<h2 id="旋转"><a href="#旋转" class="headerlink" title="旋转"></a>旋转</h2><p>用于红黑树性质被破环的时候,需要进行调整,使树重新满足定义</p>
<p>1.左旋</p>
<p>2.右旋</p>
<p><img
lazyload
src="/images/loading.svg"
data-src="/images/rbtree/%E6%97%8B%E8%BD%AC.png"
alt="旋转"
></p>
<p>图中左侧树经过左旋转为右侧,右侧经过左旋转为左侧,左右旋转可逆</p>
<p>图中的x为上图定义的一个<strong>rbtree_node</strong>,</p>
<p>左旋中以x作为轴心,右旋以y作为轴心</p>
<p>左旋代码</p>
<div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">retree_left_rotate</span><span class="params">(rbtree *T, rbtree_node *x)</span></span><br><span class="line">{</span><br><span class="line"> rbtree_node *y = x->right;</span><br><span class="line"> <span class="comment">//1</span></span><br><span class="line"> x->right = y->left;</span><br><span class="line"> <span class="keyword">if</span> (y->left != T->nil)</span><br><span class="line"> {</span><br><span class="line"> y->left->parent = x;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//2</span></span><br><span class="line"> y->parent = x->parent;</span><br><span class="line"> <span class="keyword">if</span> (x->parent == T->nil) <span class="comment">// x为root节点</span></span><br><span class="line"> {</span><br><span class="line"> <span class="comment">// 翻转之后root节点为y</span></span><br><span class="line"> T->root = y;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (x == x->parent->left) <span class="comment">// x为左节点</span></span><br><span class="line"> {</span><br><span class="line"> x->parent->left = y;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span><span class="comment">// x为右节点</span></span><br><span class="line"> {</span><br><span class="line"> x->parent->right = y;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//3</span></span><br><span class="line"> y->left = x;</span><br><span class="line"> x->parent = y;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<p>右旋代码</p>
<div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">retree_right_rotate</span><span class="params">(rbtree *T, rbtree_node *y)</span></span><br><span class="line">{</span><br><span class="line"> rbtree_node* x = y->left;</span><br><span class="line"> <span class="comment">//1</span></span><br><span class="line"> y->left = x->right;</span><br><span class="line"> <span class="keyword">if</span>(x != T->nil)<span class="comment">//x不为叶子节点,叶子节点为nil,不用更改</span></span><br><span class="line"> {</span><br><span class="line"> y->parent = x;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//2</span></span><br><span class="line"> x->parent = y->parent;</span><br><span class="line"> <span class="keyword">if</span>(y->parent == T->nil)<span class="comment">//y为root节点</span></span><br><span class="line"> {</span><br><span class="line"> T->root = x;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(y == y->parent->left)<span class="comment">//y为左节点</span></span><br><span class="line"> {</span><br><span class="line"> y->parent->left = x;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span><span class="comment">//y为右节点</span></span><br><span class="line"> {</span><br><span class="line"> y->parent->right = x;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//3</span></span><br><span class="line"> x->right = y;</span><br><span class="line"> y->parent = x;</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<p>左旋右旋代码基本相同,看着上面的图就很容易理解了</p>
<h2 id="插入"><a href="#插入" class="headerlink" title="插入"></a>插入</h2><p>插入操作为基本的二叉排序树的插入,即比较当前节点与插入节点的值,大的走右边,小的走左边</p>
<p>重点为直接插入之后的上色极其调整</p>
<p>红黑树在插入之前本身就是一颗红黑树</p>
<p>证明:归纳法</p>
<div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">rbtree_insert</span><span class="params">(rbtree *T, rbtree_node *z)</span></span><br><span class="line">{</span><br><span class="line"> rbtree_node *x = T->root;</span><br><span class="line"> <span class="keyword">while</span> (x != T->nil)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (z->key < x->key)</span><br><span class="line"> {</span><br><span class="line"> x = x->left;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (z->key > x->key)</span><br><span class="line"> {</span><br><span class="line"> x = x->right;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> <span class="comment">// 这里的else是z->key == x->key,由于红黑树为定义key相同的情况,</span></span><br><span class="line"> <span class="comment">// 具体情况具体分析,可以丢弃,插入,或者更改z->key,这里直接退出,不进行插入</span></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">if</span> (x == T->nil) <span class="comment">// 没有树的情况</span></span><br><span class="line"> {</span><br><span class="line"> T->root = z;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (z->key < x->parent->key)</span><br><span class="line"> {</span><br><span class="line"> x->parent->left = z;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> x->parent->right = z;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> z->parent = x->parent;</span><br><span class="line"> z->color = RED;</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"> 1.不改变黑色节点个数,满足第五条性质</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> rbtree_insert_fixup(T, z);</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<p>在插入节点之后,会遇到三种情况,需要进行旋转操作使树重新符合红黑树定义</p>
<p>1.叔节点为红色</p>
<p><img
lazyload
src="/images/loading.svg"
data-src="/images/rbtree/1.png"
alt="1"
></p>
<p>这种情况需要把父节点和叔父节点调整为黑色,祖父节点调整为红色,不需要进行旋转</p>
<div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="code"><pre><span class="line">y->color = BLACK;</span><br><span class="line">z->parent->color = BLACK;</span><br><span class="line">z->parent->parent->color = RED;</span><br><span class="line">z = z->parent->parent;<span class="comment">//回溯</span></span><br></pre></td></tr></table></figure></div>
<p>2.叔节点为黑色,当前节点为右孩子</p>
<p><img
lazyload
src="/images/loading.svg"
data-src="/images/rbtree/2.png"
alt="2"
></p>
<p>这种需要进行两次旋转造作,先进性一次操作转为情况3</p>
<p>需要以z的父节点为轴进行左旋</p>
<div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="code"><pre><span class="line"><span class="keyword">if</span>(z == z->parent->right)</span><br><span class="line">{</span><br><span class="line">z = z->parent;</span><br><span class="line">retree_left_rotate(T,z);</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
<p>3..叔节点为黑色,当前节点为左孩子</p>
<p>将父节点变黑色,祖父变红色后进行右旋操作</p>
<div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="code"><pre><span class="line">z->parent->color = BLACK;</span><br><span class="line">z->parent->parent->color = RED;</span><br><span class="line">retree_right_rotate(T, z->parent->parent);</span><br></pre></td></tr></table></figure></div>
<p>插入即可完成</p>
<h4 id="完整代码"><a href="#完整代码" class="headerlink" title="完整代码"></a>完整代码</h4><div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">rbtree_insert_fixup</span><span class="params">(rbtree *T, rbtree_node *z)</span></span><br><span class="line">{</span><br><span class="line"> <span class="comment">//z为红色节点(重点)</span></span><br><span class="line"> <span class="comment">//z需要时刻保持为红色节点</span></span><br><span class="line"></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"> 1.z的父节点为红色</span></span><br><span class="line"><span class="comment"> 2.z的祖父节点为黑色</span></span><br><span class="line"><span class="comment"> 3.z的叔父未知</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">while</span>(z->parent == RED)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span>(z->parent == z->parent->parent->left)</span><br><span class="line"> {</span><br><span class="line"> rbtree_node* y = z->parent->parent->right;</span><br><span class="line"> <span class="keyword">if</span>(y->color == RED)</span><br><span class="line"> {</span><br><span class="line"> y->color = BLACK;</span><br><span class="line"> z->parent->color = BLACK;</span><br><span class="line"> z->parent->parent->color = RED;</span><br><span class="line"> z = z->parent->parent;<span class="comment">//回溯</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {<span class="comment">//y为黑色</span></span><br><span class="line"> <span class="keyword">if</span>(z == z->parent->right)</span><br><span class="line"> {</span><br><span class="line"> z = z->parent;</span><br><span class="line"> retree_left_rotate(T,z);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> z->parent->color = BLACK;</span><br><span class="line"> z->parent->parent->color = RED;</span><br><span class="line"> retree_right_rotate(T, z->parent->parent);</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></div>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>红黑树是一种时间复杂度极高的k,v存储,被广泛应用于互联网各方面,实现相对复杂</p>
]]></content>
<tags>
<tag>C/C++</tag>
</tags>
</entry>
<entry>
<title>B树与B+树</title>
<url>/2024/12/03/B%E6%A0%91%E4%B8%8EB-%E6%A0%91/</url>
<content><![CDATA[<h2 id="B树"><a href="#B树" class="headerlink" title="B树"></a>B树</h2><p>限制:所有的叶子节点在同一层</p>
<h3 id="定义"><a href="#定义" class="headerlink" title="定义"></a>定义</h3><p><img
lazyload
src="/images/loading.svg"
data-src="/images/btree/Btree.png"
alt="btree"
></p>
<h4 id="B树,B-B-树"><a href="#B树,B-B-树" class="headerlink" title="B树,B-,B+树"></a>B树,B-,B+树</h4><p>B/B-树为同一东西</p>
<p>btree:所有节点存储数据</p>
<p>b+tree:叶子节点存储数据,内节点索引</p>
<p>难点:</p>
<p>1.根节点分叉</p>
<p>2.节点分裂,先分裂再添加</p>
<div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><stdio.h></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><stdlib.h></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> SUB_M 3 <span class="comment">// SUB_M = m/2</span></span></span><br><span class="line"><span class="comment">// 节点定义</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">btree_node</span></span></span><br><span class="line"><span class="class">{</span></span><br><span class="line"> <span class="comment">// int keys[SUB_M * 2 - 1]; // 5</span></span><br><span class="line"> <span class="type">int</span> *keys;</span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">btree_node</span> *<span class="title">childrens</span>[<span class="title">SUB_M</span> * 2];</span> <span class="comment">// 6</span></span><br><span class="line"> <span class="type">int</span> num;</span><br><span class="line"> <span class="type">int</span> leaf;</span><br><span class="line">} btree_node;</span><br><span class="line"><span class="comment">// 树定义</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">btree</span></span></span><br><span class="line"><span class="class">{</span></span><br><span class="line"> btree_node *root;</span><br><span class="line">} btree;</span><br><span class="line"></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 class="comment">*/</span></span><br><span class="line">btree_node *<span class="title function_">btree_create_node</span><span class="params">(<span class="type">int</span> leaf)</span></span><br><span class="line">{</span><br><span class="line"> btree_node *node = (btree_node *)<span class="built_in">calloc</span>(<span class="number">1</span>, <span class="keyword">sizeof</span>(btree_node));</span><br><span class="line"> <span class="keyword">if</span> (node == <span class="literal">NULL</span>)</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line"> node->leaf = leaf;</span><br><span class="line"> node->keys = (<span class="type">int</span> *)<span class="built_in">calloc</span>(SUB_M * <span class="number">2</span> - <span class="number">1</span>, <span class="keyword">sizeof</span>(<span class="type">int</span>));</span><br><span class="line"> <span class="comment">// node->childrens = (btree_node **)calloc(SUB_M * 2, sizeof(btree_node *));</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < SUB_M * <span class="number">2</span>; i++)</span><br><span class="line"> {</span><br><span class="line"> node->childrens[i] = (btree_node *)<span class="built_in">calloc</span>(<span class="number">1</span>, <span class="keyword">sizeof</span>(btree_node));</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> node->num = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">return</span> node;</span><br><span class="line">}</span><br><span class="line"><span class="type">void</span> <span class="title function_">btree_destory_node</span><span class="params">(btree_node *node)</span></span><br><span class="line">{</span><br><span class="line"> <span class="keyword">if</span> (node == <span class="literal">NULL</span>)</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> <span class="built_in">free</span>(node->keys);</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < SUB_M * <span class="number">2</span>; i++)</span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">free</span>(node->childrens[i]);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">free</span>(node);</span><br><span class="line">}</span><br><span class="line"><span class="comment">/**分裂</span></span><br><span class="line"><span class="comment"> * x为分裂的父节点,i为分裂节点对于父节点的位置</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">btree_split_child</span><span class="params">(btree *T, btree_node *x, <span class="type">int</span> idx)</span></span><br><span class="line">{</span><br><span class="line"> btree_node *y = x->childrens[idx];</span><br><span class="line"> btree_node *z = btree_create_node(y->leaf);</span><br><span class="line"> z->num = SUB_M - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">0</span>; j < SUB_M - <span class="number">1</span>; j++)</span><br><span class="line"> {</span><br><span class="line"> z->keys[j] = y->keys[j + SUB_M];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (y->leaf == <span class="number">0</span>) <span class="comment">// 内节点</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < SUB_M; i++)</span><br><span class="line"> {</span><br><span class="line"> z->childrens[i] = y->childrens[i + SUB_M];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="type">int</span> i = <span class="number">0</span>;</span><br><span class="line"> y->num = SUB_M;</span><br><span class="line"> <span class="keyword">for</span> (i = x->num; i >= idx + <span class="number">1</span>; i--)</span><br><span class="line"> {</span><br><span class="line"> x->childrens[i + <span class="number">1</span>] = x->childrens[i];</span><br><span class="line"> }</span><br><span class="line"> x->childrens[i + <span class="number">1</span>] = z;</span><br><span class="line"> <span class="keyword">for</span> (i = x->num - <span class="number">1</span>; i >= idx; i--)</span><br><span class="line"> {</span><br><span class="line"> x->keys[i + <span class="number">1</span>] = x->keys[i];</span><br><span class="line"> }</span><br><span class="line"> x->keys[i] = y->keys[SUB_M];</span><br><span class="line"> x->num++;</span><br><span class="line">}</span><br><span class="line"><span class="type">void</span> <span class="title function_">btree_insert</span><span class="params">(btree *T)</span></span><br><span class="line">{</span><br><span class="line"> btree_node *r = T->root;</span><br><span class="line"> <span class="keyword">if</span> (r->num == SUB_M * <span class="number">2</span> - <span class="number">1</span>)</span><br><span class="line"> {</span><br><span class="line"> btree_node *node = btree_create_node(<span class="number">0</span>);</span><br><span class="line"> T->root = node;</span><br><span class="line"> node->childrens[<span class="number">0</span>] = r;</span><br><span class="line"> btree_split_child(T, node, <span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="type">void</span> <span class="title function_">btree_merge</span><span class="params">(btree *T, btree_node *x, <span class="type">int</span> idx)</span></span><br><span class="line">{</span><br><span class="line"> btree_node *left = x->childrens[idx];</span><br><span class="line"> btree_node *right = x->childrens[idx + <span class="number">1</span>];</span><br><span class="line"></span><br><span class="line"> left->keys[left->num] = x->keys[idx];</span><br><span class="line"> <span class="type">int</span> i = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (i = <span class="number">0</span>; i < right->num; i++)</span><br><span class="line"> {</span><br><span class="line"> left->keys[i + SUB_M] = right->keys[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (!left->leaf)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">for</span> (i = <span class="number">0</span>; i < SUB_M; i++)</span><br><span class="line"> {</span><br><span class="line"> left->childrens[i + SUB_M] = right->childrens[i];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> left->num += SUB_M;</span><br><span class="line"> btree_destory_node(right);</span><br><span class="line"> <span class="keyword">for</span> (i = idx + <span class="number">1</span>; i < x->num; i++)</span><br><span class="line"> {</span><br><span class="line"> x->keys[i - <span class="number">1</span>] = x->keys[i];</span><br><span class="line"> x->childrens[i] = x->childrens[i + <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"><span class="type">int</span> <span class="title function_">main</span><span class="params">()</span></span><br><span class="line">{</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>
]]></content>
<tags>
<tag>C/C++</tag>
</tags>
</entry>
<entry>
<title>linux网络编程-tcp基础</title>
<url>/2024/12/05/linux%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B-tcp%E5%9F%BA%E7%A1%80/</url>
<content><![CDATA[<div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><stdio.h></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><string.h></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><errno.h></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><unistd.h></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><sys/socket.h></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><netinet/in.h></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><arpa/inet.h></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><pthread.h></span></span></span><br><span class="line"><span class="type">void</span> *<span class="title function_">client_thread</span><span class="params">(<span class="type">void</span> *args)</span></span><br><span class="line">{</span><br><span class="line"> <span class="type">char</span> buf[<span class="number">128</span>];</span><br><span class="line"> <span class="type">int</span> clientfd = *(<span class="type">int</span> *)args;</span><br><span class="line"> <span class="keyword">while</span> (<span class="number">1</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="type">int</span> count = recv(clientfd, buf, <span class="number">128</span>, <span class="number">0</span>);</span><br><span class="line"> <span class="keyword">if</span> (count == <span class="number">0</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"> send(clientfd, buf, count, <span class="number">0</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"clientfd %d,count %d,buffer:%s"</span>, clientfd, count, buf); <span class="comment">// sockfd = 3,clientfd = 4,0 == stdin,1 == stdout,2 == stderror,描述符依次增加</span></span><br><span class="line"> }</span><br><span class="line"> close(clientfd);</span><br><span class="line">}</span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">()</span></span><br><span class="line">{</span><br><span class="line"> <span class="type">int</span> sockfd = socket(AF_INET, SOCK_STREAM, <span class="number">0</span>); <span class="comment">// 创建套接字,AF_INET表示ipv4协议,SOCK_STREAM表示提供可靠服务</span></span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">sockaddr_in</span> <span class="title">serveraddr</span>;</span> <span class="comment">// 创建服务端地址结构体</span></span><br><span class="line"> <span class="built_in">memset</span>(&serveraddr, <span class="number">0</span>, <span class="keyword">sizeof</span>(<span class="keyword">struct</span> sockaddr_in));</span><br><span class="line"> serveraddr.sin_family = AF_INET; <span class="comment">// 设置协议为ipv4</span></span><br><span class="line"> serveraddr.sin_port = htons(<span class="number">8080</span>); <span class="comment">// 设置端口为8080,hton系列函数为字节序转换函数,将本地小端存储转化为网络大端存储,htons是short类型的转换</span></span><br><span class="line"> serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); <span class="comment">// htonl是long类型的转换,INADDR_ANY表示让主机自动获取当前ip地址</span></span><br><span class="line"> <span class="comment">// struct sockaddr_in是struct sockaddr的同等替换,操作更简单</span></span><br><span class="line"></span><br><span class="line"> <span class="type">int</span> is = bind(sockfd, (<span class="keyword">struct</span> sockaddr *)&serveraddr, <span class="keyword">sizeof</span>(<span class="keyword">struct</span> sockaddr)); <span class="comment">// 连接,将服务地址绑定到套接字中,失败则返回-1</span></span><br><span class="line"> <span class="keyword">if</span> (is == <span class="number">-1</span>)</span><br><span class="line"> {</span><br><span class="line"> perror(<span class="string">"bind error"</span>); <span class="comment">// perror报错</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">-1</span>; <span class="comment">// 错误退出</span></span><br><span class="line"> }</span><br><span class="line"> listen(sockfd, <span class="number">10</span>); <span class="comment">// 监听服务连接,10表示监听个数</span></span><br><span class="line"><span class="meta">#<span class="keyword">if</span> 0</span></span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">sockaddr_in</span> <span class="title">cltaddr</span>;</span></span><br><span class="line"> <span class="built_in">memset</span>(&cltaddr, <span class="number">0</span>, <span class="keyword">sizeof</span>(<span class="keyword">struct</span> sockaddr_in));</span><br><span class="line"> <span class="type">socklen_t</span> len = <span class="keyword">sizeof</span>(<span class="keyword">struct</span> sockaddr_in);</span><br><span class="line"> <span class="type">int</span> clientfd = accept(sockfd, (<span class="keyword">struct</span> sockaddr *)&cltaddr, &len); <span class="comment">// 接收阻塞</span></span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"accept\n"</span>);</span><br><span class="line"> <span class="type">char</span> buf[<span class="number">128</span>];</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">if</span> 0</span></span><br><span class="line"> <span class="keyword">while</span> (<span class="number">1</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="type">int</span> count = recv(clientfd,buf,<span class="number">128</span>,<span class="number">0</span>);</span><br><span class="line"> send(clientfd,buf,count,<span class="number">0</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"sockfd:%d,clientfd %d,count %d,buffer:%s"</span>,sockfd,clientfd,count,buf);<span class="comment">//sockfd = 3,clientfd = 4,0 == stdin,1 == stdout,2 == stderror,描述符依次增加</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> getchar(); <span class="comment">// 使程序阻塞,防止程序直接退出</span></span><br><span class="line"> close(sockfd);</span><br><span class="line"> close(clientfd);</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">else</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">else</span></span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> (<span class="number">1</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">sockaddr_in</span> <span class="title">cltaddr</span>;</span></span><br><span class="line"> <span class="built_in">memset</span>(&cltaddr, <span class="number">0</span>, <span class="keyword">sizeof</span>(<span class="keyword">struct</span> sockaddr_in));</span><br><span class="line"> <span class="type">socklen_t</span> len = <span class="keyword">sizeof</span>(<span class="keyword">struct</span> sockaddr_in);</span><br><span class="line"> <span class="type">int</span> clientfd = accept(sockfd, (<span class="keyword">struct</span> sockaddr *)&cltaddr, &len); <span class="comment">// 接收阻塞</span></span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"accept\n"</span>);</span><br><span class="line"> <span class="type">pthread_t</span> thid;</span><br><span class="line"> pthread_create(&thid, <span class="literal">NULL</span>, client_thread, &clientfd);</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="meta">#<span class="keyword">endif</span></span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure></div>
<p>1.time_wait<br>服务端主动断开连接</p>
<p>2.close_wait<br>客户端已断开连接,服务端即将被close掉,但中途被其他部分阻塞</p>
<p>一请求一线程<br>缺点:不利于多并发,c10k问题</p>
]]></content>
<tags>
<tag>C/C++</tag>
</tags>
</entry>
<entry>
<title>布隆过滤器简单实现</title>
<url>/2024/12/05/%E5%B8%83%E9%9A%86%E8%BF%87%E6%BB%A4%E5%99%A8%E7%AE%80%E5%8D%95%E5%AE%9E%E7%8E%B0/</url>
<content><![CDATA[<h2 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h2><p>布隆过滤器是一种通过散列表,快速判断元素是否存在的一种结构,这篇重要是简单说明一下布隆过滤器是什么以及他的简单实现</p>
<h3 id="内部结构"><a href="#内部结构" class="headerlink" title="内部结构"></a>内部结构</h3><p>布隆过滤器其内部其实就是一个位图,这个位图非常大,是存储数据的几倍</p>
<p>位图简单来说就是不存储数值,每个存储单元只存储0/1的数组</p>
<p>c语言中可以用char的数组进行实现</p>
<p>数据在插入或者查询时会经过多个哈希函数的运算,得到的结果求模,最后得到每个位置的索引,将索引置1</p>
<p>这样就完成了插入操作,查询时只需要判断对应索引是否为1即可,若有一个为0则元素不存在,但所有索引</p>
<p>都为1并不代表元素存在,因为数值经过哈希取模之后肯定是会插入相同索引的,这样就引出了布隆过滤器一个</p>
<p>比较重要的指标–<strong>假阳率</strong>,假阳率代表着每次查询的确切程度,一般来说,哈希函数越多,位图越大,假阳率就会</p>
<p>越低,置信度也就越高这里给出一张官方图</p>
<p><img
lazyload
src="/images/loading.svg"
data-src="/images/bulong/bulong.png"
alt="布隆过滤器"
></p>
<p><em>p:假阳率</em></p>
<p><em>n:插入的数据总量</em></p>
<p><em>m:位图的大小</em></p>
<p><em>k:哈希函数的数量</em></p>
<p>可以看出布隆过滤器中存储数据越多,置信度越低,位图越大,哈希函数越多,置信度越高</p>
<p>但哈希函数只是在一定范围内越多越好,公式如下</p>
<p><em>P</em>(<em>t</em> <em>r</em> <em>u</em> <em>e</em> )≈(1−<em>e</em> −<em>m</em> <em>nk</em> )<em>k</em></p>
<p>在也经常作为一道面试题考察</p>
<p>可以登录网站<a class="link" href="https://hur.st/bloomfilter/?n=4000&p=100&m=&k=" >Bloom filter calculator <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a></p>
<p>来进行计算</p>
<p>这里进行一个简单实现,内部只有三个哈希函数,这里哈希函数只是用来模拟生成哈希值的函数</p>
<h2 id="代码简单实现"><a href="#代码简单实现" class="headerlink" title="代码简单实现"></a>代码简单实现</h2><div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><stdlib.h></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><string.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">bitmap</span></span><br><span class="line">{</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="built_in">bitmap</span>(<span class="type">int</span> mapLength);</span><br><span class="line"></span><br><span class="line"><span class="keyword">protected</span>:</span><br><span class="line"> <span class="type">int</span> mapLength;</span><br><span class="line"> <span class="type">char</span> *map;</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">h1</span><span class="params">(<span class="type">int</span> n)</span></span>;</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">h2</span><span class="params">(<span class="type">int</span> n)</span></span>;</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">h3</span><span class="params">(<span class="type">int</span> n)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">insert</span><span class="params">(<span class="type">int</span> n)</span></span>;</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">qeary</span><span class="params">(<span class="type">int</span> n)</span></span>;</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line">bitmap::<span class="built_in">bitmap</span>(<span class="type">int</span> mapLength)</span><br><span class="line">{</span><br><span class="line"> <span class="keyword">this</span>->mapLength = mapLength;</span><br><span class="line"> <span class="keyword">this</span>->map = (<span class="type">char</span> *)<span class="built_in">malloc</span>(<span class="built_in">sizeof</span>(<span class="type">char</span>) * mapLength);</span><br><span class="line"> <span class="built_in">memset</span>(<span class="keyword">this</span>->map, <span class="number">0</span>, <span class="built_in">sizeof</span>(<span class="type">char</span>));</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">bitmap::insert</span><span class="params">(<span class="type">int</span> n)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="type">int</span> a = <span class="keyword">this</span>-><span class="built_in">h1</span>(n);</span><br><span class="line"> <span class="type">int</span> b = <span class="keyword">this</span>-><span class="built_in">h2</span>(n);</span><br><span class="line"> <span class="type">int</span> c = <span class="keyword">this</span>-><span class="built_in">h3</span>(n);</span><br><span class="line"></span><br><span class="line"> a %= <span class="keyword">this</span>->mapLength;</span><br><span class="line"> b %= <span class="keyword">this</span>->mapLength;</span><br><span class="line"> c %= <span class="keyword">this</span>->mapLength;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">this</span>->map[a] = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">this</span>->map[b] = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">this</span>->map[c] = <span class="number">1</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">bitmap::qeary</span><span class="params">(<span class="type">int</span> n)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="type">int</span> a = <span class="keyword">this</span>-><span class="built_in">h1</span>(n);</span><br><span class="line"> <span class="type">int</span> b = <span class="keyword">this</span>-><span class="built_in">h2</span>(n);</span><br><span class="line"> <span class="type">int</span> c = <span class="keyword">this</span>-><span class="built_in">h3</span>(n);</span><br><span class="line"></span><br><span class="line"> a %= <span class="keyword">this</span>->mapLength;</span><br><span class="line"> b %= <span class="keyword">this</span>->mapLength;</span><br><span class="line"> c %= <span class="keyword">this</span>->mapLength;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">this</span>->map[a] && <span class="keyword">this</span>->map[b] && <span class="keyword">this</span>->map[c])</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><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">bitmap::h1</span><span class="params">(<span class="type">int</span> n)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">return</span> n;</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">bitmap::h2</span><span class="params">(<span class="type">int</span> n)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">return</span> n + <span class="number">1</span>;</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">bitmap::h3</span><span class="params">(<span class="type">int</span> n)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">return</span> n - <span class="number">1</span>;</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> bitmap *b = <span class="keyword">new</span> <span class="built_in">bitmap</span>(<span class="number">100</span>);</span><br><span class="line"> b-><span class="built_in">insert</span>(<span class="number">10</span>);</span><br><span class="line"> <span class="keyword">if</span>(b-><span class="built_in">qeary</span>(<span class="number">10</span>))</span><br><span class="line"> {</span><br><span class="line"> std::cout << <span class="string">"查询成功"</span> << std::endl;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure></div>
<p>实际的哈希函数应该是足够分散的,并不是想这个一样是连续的</p>
]]></content>
<tags>
<tag>C/C++</tag>
</tags>
</entry>
<entry>
<title>select,poll,epoll的探索</title>
<url>/2024/12/06/select-poll-epoll%E7%9A%84%E6%8E%A2%E7%B4%A2/</url>
<content><![CDATA[<h2 id="select"><a href="#select" class="headerlink" title="select"></a>select</h2><p>今天写的这三个主要是为了解决普通网络编程中一个连接创建一个线程处理的方式,这种方式不适合高并发的情况,select可以在单线程中处理多个请求</p>
<p>缺点:</p>
<p>1.参数较多,有五个参数,都需要单独进行管理</p>
<p>2.每次吧待检测io集合,复制进内核,影响性能</p>
<p>3.对io的数量有限制,最大1024</p>
<div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="code"><pre><span class="line"><span class="comment">// select</span></span><br><span class="line"> <span class="comment">// int nearby = select(maxfd,rset,wset,eset,time_out);</span></span><br><span class="line"> <span class="comment">// maxfd表示最大的连接序号,用于内部遍历判断该连接是否可读可写</span></span><br><span class="line"> <span class="comment">// rset为可读集合,内部为bit数组</span></span><br><span class="line"> <span class="comment">// wset为可写集合</span></span><br><span class="line"> <span class="comment">// eset为错误集合</span></span><br><span class="line"> <span class="comment">// timeout为超时时间</span></span><br><span class="line"> <span class="comment">// 该函数在请求可读或可写时都会返回,若不可读可写,超时时间后返回</span></span><br><span class="line"> <span class="type">int</span> maxfd = sockfd;</span><br><span class="line"> fd_set rset, rfds;</span><br><span class="line"> FD_ZERO(&rfds);</span><br><span class="line"> FD_SET(sockfd, &rfds);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// int nready = select(maxfd + 1, rset, NULL, NULL, NULL);</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> (<span class="number">1</span>)</span><br><span class="line"> {</span><br><span class="line"> rset = rfds;</span><br><span class="line"> <span class="type">int</span> nready = select(maxfd + <span class="number">1</span>, &rset, <span class="literal">NULL</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line"> <span class="keyword">if</span> (FD_ISSET(sockfd, &rset))</span><br><span class="line"> {</span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">sockaddr_in</span> <span class="title">cltaddr</span>;</span></span><br><span class="line"> <span class="built_in">memset</span>(&cltaddr, <span class="number">0</span>, <span class="keyword">sizeof</span>(<span class="keyword">struct</span> sockaddr_in));</span><br><span class="line"> <span class="type">socklen_t</span> len = <span class="keyword">sizeof</span>(<span class="keyword">struct</span> sockaddr_in);</span><br><span class="line"> <span class="type">int</span> clientfd = accept(sockfd, (<span class="keyword">struct</span> sockaddr *)&cltaddr, &len); <span class="comment">// 接收阻塞</span></span><br><span class="line"> maxfd = clientfd;</span><br><span class="line"> FD_SET(clientfd, &rfds);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = sockfd + <span class="number">1</span>; i <= maxfd; i++)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (FD_ISSET(i, &rset))</span><br><span class="line"> {</span><br><span class="line"> <span class="type">char</span> buf[<span class="number">128</span>] = {<span class="number">0</span>};</span><br><span class="line"></span><br><span class="line"> <span class="type">int</span> count = recv(i, buf, <span class="number">128</span>, <span class="number">0</span>);</span><br><span class="line"> <span class="keyword">if</span> (count == <span class="number">0</span>)</span><br><span class="line"> {</span><br><span class="line"> FD_CLR(i, &rfds);</span><br><span class="line"> close(i);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> send(i, buf, count, <span class="number">0</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"clientfd %d,count %d,buffer:%s"</span>, i, count, buf);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br></pre></td></tr></table></figure></div>
<h2 id="poll"><a href="#poll" class="headerlink" title="poll"></a>poll</h2><p>解决了select参数过多的问题,简化了函数参数,但因为底层仍是select,依然没有解决每次都要复制以及对io有数量限制的问题</p>
<div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="code"><pre><span class="line"><span class="comment">// int nready = poll(fds, maxfd+1, -1);</span></span><br><span class="line"> <span class="comment">// 简化了select的参数</span></span><br><span class="line"> <span class="comment">// 底层还是select,没用改善select多次复制的缺点</span></span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">pollfd</span> <span class="title">fds</span>[1024] =</span> {<span class="number">0</span>}; <span class="comment">// 保持和select最大连接数一致</span></span><br><span class="line"></span><br><span class="line"> fds[sockfd].fd = sockfd;</span><br><span class="line"> fds[sockfd].events = POLLIN;</span><br><span class="line"></span><br><span class="line"> <span class="type">int</span> maxfd = sockfd; <span class="comment">// 非必须,缩短循环次数</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> (<span class="number">1</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="type">int</span> nready = poll(fds, maxfd + <span class="number">1</span>, <span class="number">-1</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (fds[sockfd].revents & POLLIN)</span><br><span class="line"> {</span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">sockaddr_in</span> <span class="title">cltaddr</span>;</span></span><br><span class="line"> <span class="built_in">memset</span>(&cltaddr, <span class="number">0</span>, <span class="keyword">sizeof</span>(<span class="keyword">struct</span> sockaddr_in));</span><br><span class="line"> <span class="type">socklen_t</span> len = <span class="keyword">sizeof</span>(<span class="keyword">struct</span> sockaddr_in);</span><br><span class="line"> <span class="type">int</span> clientfd = accept(sockfd, (<span class="keyword">struct</span> sockaddr *)&cltaddr, &len); <span class="comment">// 接收阻塞</span></span><br><span class="line"> maxfd = clientfd;</span><br><span class="line"> fds[clientfd].fd = clientfd;</span><br><span class="line"> fds[clientfd].events = POLLIN;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = sockfd + <span class="number">1</span>; i <= maxfd; i++)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (fds[i].revents & POLLIN)</span><br><span class="line"> {</span><br><span class="line"> <span class="type">char</span> buf[<span class="number">128</span>] = {<span class="number">0</span>};</span><br><span class="line"></span><br><span class="line"> <span class="type">int</span> count = recv(i, buf, <span class="number">128</span>, <span class="number">0</span>);</span><br><span class="line"> <span class="keyword">if</span> (count == <span class="number">0</span>)</span><br><span class="line"> {</span><br><span class="line"> fds[i].fd = <span class="number">-1</span>;</span><br><span class="line"> fds[i].events = <span class="number">0</span>;</span><br><span class="line"> close(i);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> send(i, buf, count, <span class="number">0</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"clientfd %d,count %d,buffer:%s"</span>, i, count, buf);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br></pre></td></tr></table></figure></div>
<h2 id="epoll"><a href="#epoll" class="headerlink" title="epoll"></a>epoll</h2><p>相较于select和poll,epoll是事件驱动,支持两种触发方式,LT(水平触发),ET(边沿触发),epoll对与io只需要复制一次,不需要每次都进行复制,大大提高了性能</p>
<div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="code"><pre><span class="line"><span class="type">int</span> epfd = epoll_create(<span class="number">1</span>);<span class="comment">// 函数中的size是为了兼容旧的接口,大于一即可,内部已经不再使用传入的size,返回一个用于epoll的句柄</span></span><br><span class="line"></span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">epoll_event</span> <span class="title">ev</span>;</span></span><br><span class="line"> ev.events = EPOLLIN;</span><br><span class="line"> ev.data.fd = sockfd;</span><br><span class="line"></span><br><span class="line"> epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);<span class="comment">//kv绑定,一个fd绑定一个event</span></span><br><span class="line"></span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">epoll_event</span> <span class="title">events</span>[1024] =</span> {<span class="number">0</span>};</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> (<span class="number">1</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="type">int</span> nready = epoll_wait(epfd, events, <span class="number">1024</span>, <span class="number">-1</span>);</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < nready; i++)</span><br><span class="line"> {</span><br><span class="line"> <span class="type">int</span> connfd = events[i].data.fd;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (sockfd == connfd)</span><br><span class="line"> {</span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">sockaddr_in</span> <span class="title">cltaddr</span>;</span></span><br><span class="line"> <span class="built_in">memset</span>(&cltaddr, <span class="number">0</span>, <span class="keyword">sizeof</span>(<span class="keyword">struct</span> sockaddr_in));</span><br><span class="line"> <span class="type">socklen_t</span> len = <span class="keyword">sizeof</span>(<span class="keyword">struct</span> sockaddr_in);</span><br><span class="line"> <span class="type">int</span> clientfd = accept(sockfd, (<span class="keyword">struct</span> sockaddr *)&cltaddr, &len); <span class="comment">// 接收阻塞</span></span><br><span class="line"> ev.events = EPOLLIN | EPOLLET;<span class="comment">//默认为水平触发,不需要 | EPOOLET</span></span><br><span class="line"> ev.data.fd = clientfd;</span><br><span class="line"> epoll_ctl(epfd, EPOLL_CTL_ADD, clientfd, &ev);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (events[i].events & EPOLLIN)</span><br><span class="line"> {</span><br><span class="line"> <span class="type">char</span> buf[<span class="number">128</span>] = {<span class="number">0</span>};</span><br><span class="line"></span><br><span class="line"> <span class="type">int</span> count = recv(connfd, buf, <span class="number">128</span>, <span class="number">0</span>);</span><br><span class="line"> <span class="keyword">if</span> (count == <span class="number">0</span>)</span><br><span class="line"> {</span><br><span class="line"> epoll_ctl(epfd, EPOLL_CTL_DEL, connfd, <span class="literal">NULL</span>);</span><br><span class="line"> close(i);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> send(connfd, buf, count, <span class="number">0</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"clientfd %d,count %d,buffer:%s"</span>, connfd, count, buf);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br></pre></td></tr></table></figure></div>
<p>水平触发:读取多次,直到读不到数据</p>
<p>边沿触发:只读取一次,下次发送时,从原先数据位读取后一位开始读取数据</p>
]]></content>
<tags>
<tag>C/C++</tag>
</tags>
</entry>
</search>