<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>课程作业 on 蛋蛋忧桑</title><link>https://dandansad.com/tags/%E8%AF%BE%E7%A8%8B%E4%BD%9C%E4%B8%9A/</link><description>Recent content in 课程作业 on 蛋蛋忧桑</description><generator>Hugo -- gohugo.io</generator><language>zh</language><lastBuildDate>Sat, 07 Jun 2025 01:05:58 +0800</lastBuildDate><atom:link href="https://dandansad.com/tags/%E8%AF%BE%E7%A8%8B%E4%BD%9C%E4%B8%9A/index.xml" rel="self" type="application/rss+xml"/><item><title>MapReduce工作原理及基础编程</title><link>https://dandansad.com/2025/06/07/mapreduce%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%E5%8F%8A%E5%9F%BA%E7%A1%80%E7%BC%96%E7%A8%8B/</link><pubDate>Sat, 07 Jun 2025 01:05:58 +0800</pubDate><guid>https://dandansad.com/2025/06/07/mapreduce%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%E5%8F%8A%E5%9F%BA%E7%A1%80%E7%BC%96%E7%A8%8B/</guid><description>&lt;h2 id="概念介绍"&gt;&lt;a href="#%e6%a6%82%e5%bf%b5%e4%bb%8b%e7%bb%8d" class="header-anchor"&gt;&lt;/a&gt;概念介绍
&lt;/h2&gt;&lt;p&gt;MapReduce 是一种用于处理和生成大规模数据集的编程模型。&lt;/p&gt;
&lt;p&gt;它将整个计算过程分为两个核心阶段：&lt;strong&gt;Map（映射）&lt;/strong&gt; 和 &lt;strong&gt;Reduce（归并）&lt;/strong&gt;。在 Map 阶段，数据被分成小块并并行处理，提取出中间的键值对结果；在 Reduce 阶段，框架会将所有具有相同键的数据聚合起来，由用户定义的逻辑进行归并处理，最终输出结果。&lt;/p&gt;
&lt;p&gt;MapReduce 的核心优势是：&lt;strong&gt;可扩展性强、适合大数据分布式处理、编程模型简单，框架自动负责数据的调度与容错。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;通俗地说，它就像是一条流水线：先把原料（大数据）切碎并加工（Map），然后将相同类型的零件集中起来装配成品（Reduce）。&lt;/p&gt;
&lt;h2 id="执行流程"&gt;&lt;a href="#%e6%89%a7%e8%a1%8c%e6%b5%81%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;执行流程
&lt;/h2&gt;&lt;p&gt;实际上MapReduce有三个阶段：Map（映射）、Shuffle（派发）、Reduce（规约）。&lt;/p&gt;
&lt;p&gt;在 &lt;strong&gt;Map 阶段&lt;/strong&gt;，每条输入数据（通常是一行文本）被送入用户自定义的 &lt;code&gt;Mapper&lt;/code&gt; 类中进行处理。开发者在这个阶段编写逻辑，将每条原始数据“映射”为一组中间键值对（key-value），例如统计词频时，把一句话拆分成每个词，并赋予每个词一个初始计数（如 key 为单词，value 为 1）。这些中间结果不会立即输出，而是会经过分区、排序和归组。&lt;/p&gt;
&lt;p&gt;接下来是 &lt;strong&gt;Shuffle 阶段&lt;/strong&gt;，这是 &lt;strong&gt;MapReduce 框架自动完成&lt;/strong&gt;的核心过程。框架会将所有 &lt;code&gt;Mapper&lt;/code&gt; 输出的 key 按照值进行聚合，也就是说，把所有具有相同 key 的记录集中在一起，并将它们分发给相应的 &lt;code&gt;Reducer&lt;/code&gt;。这个阶段还涉及网络传输（跨节点数据移动）、排序（对 key 进行字典序排列）以及归组（将相同 key 的 value 组成集合），是整个 MapReduce 中性能和资源消耗最多的一部分。&lt;/p&gt;
&lt;p&gt;最后是 &lt;strong&gt;Reduce 阶段&lt;/strong&gt;，所有已经被聚合并排序好的数据会输入到开发者自定义的 &lt;code&gt;Reducer&lt;/code&gt; 中。Reducer 接收的是某一个 key 以及与它相关联的所有 value 列表，开发者在这个阶段编写聚合逻辑，如累加、求平均、取最大值等。处理后的结果会以最终输出的形式写入 HDFS 或本地文件系统，形成最终的数据处理结果。&lt;/p&gt;
&lt;p&gt;所以说，根据以上叙述我们可以得知：在实际的编程中，我们要做的就是编写Map和Reduce操作的代码。同时我们也可以理解到，Map的处理过程应当是&lt;code&gt;(行号, 一行文本)&lt;/code&gt; → &lt;code&gt;(key, value)&lt;/code&gt;；Reduce的处理过程应当是&lt;code&gt;(key, values)&lt;/code&gt; → &lt;code&gt;(key, value)&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id="编程思想"&gt;&lt;a href="#%e7%bc%96%e7%a8%8b%e6%80%9d%e6%83%b3" class="header-anchor"&gt;&lt;/a&gt;编程思想
&lt;/h2&gt;&lt;p&gt;在编写相关Java代码时，我认为最重要的就是理清楚输入输出类型和输入到输出的处理过程，也即&lt;code&gt;(行号, 一行文本)&lt;/code&gt; 是怎么变到 &lt;code&gt;(key, value)&lt;/code&gt;的，&lt;code&gt;(key, values)&lt;/code&gt; 又是怎么变到 &lt;code&gt;(key, value)&lt;/code&gt;的。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;标准Mapper类&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; org.apache.hadoop.io.*;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; org.apache.hadoop.mapreduce.Mapper;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; java.io.IOException;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MyMapper&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; Mapper {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; Text outKey &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Text();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; IntWritable outValue &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; IntWritable();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;@Override&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(LongWritable key, Text value, Context context)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;throws&lt;/span&gt; IOException, InterruptedException {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 1. 读取一行文本&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; String line &lt;span style="color:#f92672"&gt;=&lt;/span&gt; value.&lt;span style="color:#a6e22e"&gt;toString&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 2. 分割字段（假设是以逗号分隔的 CSV）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; String&lt;span style="color:#f92672"&gt;[]&lt;/span&gt; fields &lt;span style="color:#f92672"&gt;=&lt;/span&gt; line.&lt;span style="color:#a6e22e"&gt;split&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;,&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 3. 做简单校验&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (fields.&lt;span style="color:#a6e22e"&gt;length&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; 2) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; String someKey &lt;span style="color:#f92672"&gt;=&lt;/span&gt; fields&lt;span style="color:#f92672"&gt;[&lt;/span&gt;0&lt;span style="color:#f92672"&gt;]&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// 例如：用户ID&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; someValue &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Integer.&lt;span style="color:#a6e22e"&gt;parseInt&lt;/span&gt;(fields&lt;span style="color:#f92672"&gt;[&lt;/span&gt;1&lt;span style="color:#f92672"&gt;]&lt;/span&gt;); &lt;span style="color:#75715e"&gt;// 例如：交易金额&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 4. 设置输出&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; outKey.&lt;span style="color:#a6e22e"&gt;set&lt;/span&gt;(someKey);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; outValue.&lt;span style="color:#a6e22e"&gt;set&lt;/span&gt;(someValue);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 5. 输出 key-value 对&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; context.&lt;span style="color:#a6e22e"&gt;write&lt;/span&gt;(outKey, outValue);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;标准Reducer类&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; org.apache.hadoop.io.*;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; org.apache.hadoop.mapreduce.Reducer;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; java.io.IOException;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MyReducer&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; Reducer {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; IntWritable result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; IntWritable();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;@Override&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;reduce&lt;/span&gt;(Text key, Iterable values, Context context)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;throws&lt;/span&gt; IOException, InterruptedException {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; sum &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (IntWritable val : values) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sum &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; val.&lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(); &lt;span style="color:#75715e"&gt;// 累加所有值&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; result.&lt;span style="color:#a6e22e"&gt;set&lt;/span&gt;(sum);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; context.&lt;span style="color:#a6e22e"&gt;write&lt;/span&gt;(key, result); &lt;span style="color:#75715e"&gt;// 输出结果&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;标准Driver类&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; org.apache.hadoop.conf.Configuration;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; org.apache.hadoop.fs.Path;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; org.apache.hadoop.io.*;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; org.apache.hadoop.mapreduce.Job;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; org.apache.hadoop.mapreduce.lib.input.*;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; org.apache.hadoop.mapreduce.lib.output.*;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MyDriver&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;(String&lt;span style="color:#f92672"&gt;[]&lt;/span&gt; args) &lt;span style="color:#66d9ef"&gt;throws&lt;/span&gt; Exception {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (args.&lt;span style="color:#a6e22e"&gt;length&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; 2) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Usage: MyDriver &amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.&lt;span style="color:#a6e22e"&gt;exit&lt;/span&gt;(&lt;span style="color:#f92672"&gt;-&lt;/span&gt;1);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Configuration conf &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Configuration();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Job job &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Job.&lt;span style="color:#a6e22e"&gt;getInstance&lt;/span&gt;(conf, &lt;span style="color:#e6db74"&gt;&amp;#34;My MapReduce Job&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; job.&lt;span style="color:#a6e22e"&gt;setJarByClass&lt;/span&gt;(MyDriver.&lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; job.&lt;span style="color:#a6e22e"&gt;setMapperClass&lt;/span&gt;(MyMapper.&lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; job.&lt;span style="color:#a6e22e"&gt;setReducerClass&lt;/span&gt;(MyReducer.&lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; job.&lt;span style="color:#a6e22e"&gt;setMapOutputKeyClass&lt;/span&gt;(Text.&lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; job.&lt;span style="color:#a6e22e"&gt;setMapOutputValueClass&lt;/span&gt;(IntWritable.&lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; job.&lt;span style="color:#a6e22e"&gt;setOutputKeyClass&lt;/span&gt;(Text.&lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; job.&lt;span style="color:#a6e22e"&gt;setOutputValueClass&lt;/span&gt;(IntWritable.&lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; FileInputFormat.&lt;span style="color:#a6e22e"&gt;addInputPath&lt;/span&gt;(job, &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Path(args&lt;span style="color:#f92672"&gt;[&lt;/span&gt;0&lt;span style="color:#f92672"&gt;]&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; FileOutputFormat.&lt;span style="color:#a6e22e"&gt;setOutputPath&lt;/span&gt;(job, &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Path(args&lt;span style="color:#f92672"&gt;[&lt;/span&gt;1&lt;span style="color:#f92672"&gt;]&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.&lt;span style="color:#a6e22e"&gt;exit&lt;/span&gt;(job.&lt;span style="color:#a6e22e"&gt;waitForCompletion&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;) &lt;span style="color:#f92672"&gt;?&lt;/span&gt; 0 : 1);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;实际上，按照以上标准代码，我们需要做的就是修改&lt;strong&gt;输入输出的Key/Value类型&lt;/strong&gt;和&lt;strong&gt;数据处理逻辑&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id="常见的输入和输出-keyvalue-类型"&gt;&lt;a href="#%e5%b8%b8%e8%a7%81%e7%9a%84%e8%be%93%e5%85%a5%e5%92%8c%e8%be%93%e5%87%ba-keyvalue-%e7%b1%bb%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;常见的输入和输出 Key/Value 类型
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;类型&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
					&lt;th&gt;用途示例&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;LongWritable&lt;/td&gt;
					&lt;td&gt;长整型（64位）&lt;/td&gt;
					&lt;td&gt;输入 key，通常表示文本行的字节偏移量（offset）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;IntWritable&lt;/td&gt;
					&lt;td&gt;整型（32位）&lt;/td&gt;
					&lt;td&gt;常用于输出 value，如计数、数值统计&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Text&lt;/td&gt;
					&lt;td&gt;字符串类型，Hadoop自带字符串类型&lt;/td&gt;
					&lt;td&gt;输入或输出的 key/value，多用于字符串数据&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;DoubleWritable&lt;/td&gt;
					&lt;td&gt;双精度浮点型&lt;/td&gt;
					&lt;td&gt;处理小数值，如评分、权重等&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;FloatWritable&lt;/td&gt;
					&lt;td&gt;单精度浮点型&lt;/td&gt;
					&lt;td&gt;同上，较少用&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;BooleanWritable&lt;/td&gt;
					&lt;td&gt;布尔型&lt;/td&gt;
					&lt;td&gt;标记型字段&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;NullWritable&lt;/td&gt;
					&lt;td&gt;空值类型&lt;/td&gt;
					&lt;td&gt;不输出 key 或 value 时用，比如只输出 key&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>Hadoop配置——两个节点（master和slave1）</title><link>https://dandansad.com/2025/05/29/hadoop%E9%85%8D%E7%BD%AE-%E4%B8%A4%E4%B8%AA%E8%8A%82%E7%82%B9master%E5%92%8Cslave1/</link><pubDate>Thu, 29 May 2025 14:42:14 +0800</pubDate><guid>https://dandansad.com/2025/05/29/hadoop%E9%85%8D%E7%BD%AE-%E4%B8%A4%E4%B8%AA%E8%8A%82%E7%82%B9master%E5%92%8Cslave1/</guid><description>&lt;h2 id="配置要求"&gt;&lt;a href="#%e9%85%8d%e7%bd%ae%e8%a6%81%e6%b1%82" class="header-anchor"&gt;&lt;/a&gt;配置要求
&lt;/h2&gt;&lt;p&gt;目标是配置一个基本的 Hadoop 分布式集群：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;一台主节点：&lt;code&gt;master&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;一台从节点：&lt;code&gt;slave1&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;支持：HDFS + YARN&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Java 已配置&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Hadoop 已安装成功，路径在 &lt;code&gt;/opt/hadoop&lt;/code&gt;（你可替换为实际路径）&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;使用 &lt;code&gt;hadoop version&lt;/code&gt; 命令测试&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;注：前置参考资料在文末，建议先按照前置参考资料进行安装配置到 &lt;code&gt;hadoop version&lt;/code&gt; 命令成功执行步骤，再继续参照本文章。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="修改hostshostname"&gt;&lt;a href="#%e4%bf%ae%e6%94%b9hostshostname" class="header-anchor"&gt;&lt;/a&gt;修改hosts、hostname
&lt;/h2&gt;&lt;p&gt;hosts: /etc/hosts
集群所有主机IP地址与对应主机名
格式：IP（空）主机名&lt;/p&gt;
&lt;p&gt;hostname: /etc/hostname
主节点命名为master，子节点命名为slave1
把主机名直接写入此文件（只能保留一个名字），定义本机的主机名（可能需要重启生效）
使用 &lt;code&gt;sudo hostnamectl set-hostname 新主机名&lt;/code&gt; 设置（即时生效）
使用 &lt;code&gt;hostname&lt;/code&gt; 命令查看当前主机名&lt;/p&gt;
&lt;h2 id="ssh-配置免密"&gt;&lt;a href="#ssh-%e9%85%8d%e7%bd%ae%e5%85%8d%e5%af%86" class="header-anchor"&gt;&lt;/a&gt;SSH 配置免密
&lt;/h2&gt;&lt;h4 id="1-生成-ssh-密钥对如果尚未生成"&gt;&lt;a href="#1-%e7%94%9f%e6%88%90-ssh-%e5%af%86%e9%92%a5%e5%af%b9%e5%a6%82%e6%9e%9c%e5%b0%9a%e6%9c%aa%e7%94%9f%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;&lt;strong&gt;1. 生成 SSH 密钥对&lt;/strong&gt;（如果尚未生成）
&lt;/h4&gt;&lt;p&gt;在每台机器上执行：&lt;code&gt;ssh-keygen -t rsa&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;一路回车即可（不要设置密码短语）。&lt;/p&gt;
&lt;h4 id="2-将自己的公钥添加到目标机器的-authorized_"&gt;&lt;a href="#2-%e5%b0%86%e8%87%aa%e5%b7%b1%e7%9a%84%e5%85%ac%e9%92%a5%e6%b7%bb%e5%8a%a0%e5%88%b0%e7%9b%ae%e6%a0%87%e6%9c%ba%e5%99%a8%e7%9a%84-authorized_" class="header-anchor"&gt;&lt;/a&gt;&lt;strong&gt;2. 将自己的公钥添加到目标机器的 authorized_keys 中&lt;/strong&gt;
&lt;/h4&gt;&lt;p&gt;在 &lt;code&gt;master&lt;/code&gt; 上执行以下命令，把自己的公钥发给 &lt;code&gt;slave1&lt;/code&gt; ：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh-copy-id root@localhost
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh-copy-id root@slave1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;同理，在 &lt;code&gt;slave1&lt;/code&gt; 上执行：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh-copy-id root@localhost
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh-copy-id root@master
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;从每台机器尝试 ssh 到其他机器（包括自己）进行验证：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh root@localhost
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh root@master
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh root@slave1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="配置hadoop的配置文件"&gt;&lt;a href="#%e9%85%8d%e7%bd%aehadoop%e7%9a%84%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;配置Hadoop的配置文件
&lt;/h2&gt;&lt;h3 id="1-core-sitexml"&gt;&lt;a href="#1-core-sitexml" class="header-anchor"&gt;&lt;/a&gt;1. core-site.xml
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; hadoop.tmp.dir
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; file:/opt/hadoop/tmp
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; location to store temporary files
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fs.defaultFS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; hdfs://master:9000
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-hdfs-sitexml"&gt;&lt;a href="#2-hdfs-sitexml" class="header-anchor"&gt;&lt;/a&gt;2. hdfs-site.xml
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dfs.replication
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dfs.namenode.name.dir
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; file:/opt/hadoop/tmp/dfs/name
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dfs.datanode.data.dir
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; file:/opt/hadoop/tmp/dfs/data
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-mapred-sitexml"&gt;&lt;a href="#3-mapred-sitexml" class="header-anchor"&gt;&lt;/a&gt;3. mapred-site.xml
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mapreduce.framework.name
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; yarn
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; yarn.app.mapreduce.am.env
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; HADOOP_MAPRED_HOME&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/opt/hadoop
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mapreduce.map.env
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; HADOOP_MAPRED_HOME&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/opt/hadoop
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mapreduce.reduce.env
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; HADOOP_MAPRED_HOME&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/opt/hadoop
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="4-yarn-sitexml"&gt;&lt;a href="#4-yarn-sitexml" class="header-anchor"&gt;&lt;/a&gt;4. yarn-site.xml
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; yarn.resourcemanager.hostname
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; master
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; yarn.nodemanager.aux-services
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mapreduce_shuffle
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="5-workers以前叫-slaves"&gt;&lt;a href="#5-workers%e4%bb%a5%e5%89%8d%e5%8f%ab-slaves" class="header-anchor"&gt;&lt;/a&gt;5. workers（以前叫 slaves）
&lt;/h3&gt;&lt;p&gt;列出所有的从节点（一个 hostname 一行）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;slave1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="复制配置文件"&gt;&lt;a href="#%e5%a4%8d%e5%88%b6%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;复制配置文件
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;scp -r /opt/hadoop/etc/hadoop/ root@slave1:/opt/hadoop/etc/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="启动-hadoop"&gt;&lt;a href="#%e5%90%af%e5%8a%a8-hadoop" class="header-anchor"&gt;&lt;/a&gt;启动 Hadoop
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hdfs namenode -format
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;start-dfs.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;start-yarn.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="验证是否成功"&gt;&lt;a href="#%e9%aa%8c%e8%af%81%e6%98%af%e5%90%a6%e6%88%90%e5%8a%9f" class="header-anchor"&gt;&lt;/a&gt;验证是否成功
&lt;/h2&gt;&lt;p&gt;在 master 和 slave1 分别运行：&lt;code&gt;jps &lt;/code&gt;你应该看到：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;master&lt;/strong&gt; 节点有：&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;NameNode&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;SecondaryNameNode&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ResourceManager&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;slave1&lt;/strong&gt; 节点有：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;DataNode&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;NodeManager&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/05/image-5.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/05/image-6.png"&gt;&lt;/p&gt;
&lt;p&gt;然后运行以下命令进行测试，检查是否有问题：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hdfs dfs -ls /
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hdfs dfs -mkdir /testdir
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hdfs dfs -ls /
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;echo &lt;span style="color:#e6db74"&gt;&amp;#34;Hello Hadoop&amp;#34;&lt;/span&gt; &amp;gt; hello.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hdfs dfs -put hello.txt /testdir/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hdfs dfs -ls /testdir/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hdfs dfs -cat /testdir/hello.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hdfs dfs -get /testdir/hello.txt ./hello_from_hdfs.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hdfs dfs -rm /testdir/hello.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hdfs dfs -rmdir /testdir
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hdfs dfsadmin -report
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;如果出现问题请先检查防火墙是否开放相应端口。&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 开放端口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; p in &lt;span style="color:#ae81ff"&gt;9000&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;9870&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;50010..50020&lt;span style="color:#f92672"&gt;}&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;50075&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8088&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8042&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;9864&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;9866&lt;/span&gt; 9867; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; firewall-cmd --permanent --add-port&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;p&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;/tcp; &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; firewall-cmd --reload
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 关闭端口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; p in &lt;span style="color:#ae81ff"&gt;9000&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;9870&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;50010..50020&lt;span style="color:#f92672"&gt;}&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;50075&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8088&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8042&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;9864&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;9866&lt;/span&gt; 9867; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; firewall-cmd --permanent --remove-port&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;p&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;/tcp; &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; firewall-cmd --reload
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;注意：经过后期实践，发现以上端口没有涵盖Hadoop的所有所需开放端口，最方便的解决方法是暂时关闭防火墙。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="前置参考资料"&gt;&lt;a href="#%e5%89%8d%e7%bd%ae%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99" class="header-anchor"&gt;&lt;/a&gt;前置参考资料
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://dandansad.com/2025/05/22/%e5%ae%89%e8%a3%85hadoop/" target="_blank" rel="noopener"
 &gt;https://dandansad.com/2025/05/22/%e5%ae%89%e8%a3%85hadoop/&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Redis常用操作</title><link>https://dandansad.com/2025/05/25/redis%E5%B8%B8%E7%94%A8%E6%93%8D%E4%BD%9C/</link><pubDate>Sun, 25 May 2025 14:26:00 +0800</pubDate><guid>https://dandansad.com/2025/05/25/redis%E5%B8%B8%E7%94%A8%E6%93%8D%E4%BD%9C/</guid><description>&lt;h2 id="通用命令"&gt;&lt;a href="#%e9%80%9a%e7%94%a8%e5%91%bd%e4%bb%a4" class="header-anchor"&gt;&lt;/a&gt;通用命令
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1. KEYS 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：根据通配符匹配，列出所有符合条件的 key。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KEYS user:* &lt;span style="color:#75715e"&gt;# 匹配所有以 user: 开头的 key&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：匹配的 key 列表
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;注意：遍历全库，性能差，**生产环境建议使用 SCAN 命令替代**。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2. DEL &lt;span style="color:#f92672"&gt;[&lt;/span&gt;key ...&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：删除一个或多个指定的 key。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; DEL user:1001 &lt;span style="color:#75715e"&gt;# 删除 key 为 user:1001 的数据&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; DEL key1 key2 key3 &lt;span style="color:#75715e"&gt;# 批量删除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：成功删除的 key 数量
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;3. EXISTS &lt;span style="color:#f92672"&gt;[&lt;/span&gt;key ...&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：检查指定的 key 是否存在。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; EXISTS user:1001 &lt;span style="color:#75715e"&gt;# 判断 user:1001 是否存在&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; EXISTS key1 key2 &lt;span style="color:#75715e"&gt;# 多个 key，返回存在的数量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：存在的 key 数量（0 表示全部不存在）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;4. EXPIRE 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：为指定的 key 设置过期时间（单位：秒）。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; EXPIRE user:1001 &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 设置 user:1001 60 秒后过期&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：1 表示设置成功；0 表示 key 不存在或设置失败
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;5. TTL 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：查看 key 剩余的过期时间（单位：秒）。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TTL user:1001
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - 正数：剩余秒数
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - -1：key 存在但没有设置过期时间
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - -2：key 不存在
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="string类型常见命令"&gt;&lt;a href="#string%e7%b1%bb%e5%9e%8b%e5%b8%b8%e8%a7%81%e5%91%bd%e4%bb%a4" class="header-anchor"&gt;&lt;/a&gt;String类型常见命令
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1. SET 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：设置指定 key 的字符串值，如果 key 已存在则覆盖。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SET user:1001:name &lt;span style="color:#e6db74"&gt;&amp;#34;Alice&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：OK（设置成功）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2. GET 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：获取指定 key 的字符串值。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; GET user:1001:name
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：对应的字符串值，或 nil（key 不存在）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;3. MSET ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：同时设置多个 key 的值。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MSET a &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; b &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; c &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：OK（全部设置成功）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;4. MGET ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：同时获取多个 key 的值。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MGET a b c
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：按顺序返回对应的值，key 不存在则返回 nil
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;5. INCR 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：将 key 的值加 1（必须是整数），初始值不存在视为 0。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; INCR counter
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：递增后的结果（整数）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;6. INCRBY 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：将 key 的值增加指定的整数值。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; INCRBY score &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：递增后的结果（整数）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;7. INCRBYFLOAT 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：将 key 的值增加指定的浮点数值。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; INCRBYFLOAT price 1.5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：递增后的结果（浮点数）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;8. SETNX 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：当 key 不存在时设置 key 的值（NX &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Not eXists）。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SETNX lock &lt;span style="color:#e6db74"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - 1：设置成功（key 原本不存在）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - 0：未设置（key 已存在）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;9. SETEX 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：设置 key 的值并同时指定过期时间（秒）。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SETEX temp:code &lt;span style="color:#ae81ff"&gt;300&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;xyz123&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：OK
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="key的层级格式"&gt;&lt;a href="#key%e7%9a%84%e5%b1%82%e7%ba%a7%e6%a0%bc%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;key的层级格式
&lt;/h2&gt;&lt;p&gt;Redis 的 key 可以用 &lt;code&gt;:&lt;/code&gt; 做分隔符（区分层级），但这只是“命名规范”，实际存储并不是按照层级结构来实现的。&lt;/p&gt;
&lt;p&gt;举一个层级结构的例子：&lt;code&gt;项目名:业务名:类型:id&lt;/code&gt;&lt;/p&gt;
&lt;h2 id="hash类型常见命令"&gt;&lt;a href="#hash%e7%b1%bb%e5%9e%8b%e5%b8%b8%e8%a7%81%e5%91%bd%e4%bb%a4" class="header-anchor"&gt;&lt;/a&gt;Hash类型常见命令
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1. HSET 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：设置哈希表 key 中字段 field 的值。如果字段已存在则覆盖。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; HSET user:1001 name &lt;span style="color:#e6db74"&gt;&amp;#34;Alice&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - 1：新建字段
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - 0：更新已有字段
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2. HGET 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：获取哈希表 key 中指定字段的值。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; HGET user:1001 name
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：字段的值，或 nil（字段不存在）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;3. HMSET ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;（⚠️ Redis 4.0 起被标记为过时，推荐用 HSET 替代）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：同时设置多个字段的值。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; HMSET user:1001 name &lt;span style="color:#e6db74"&gt;&amp;#34;Alice&amp;#34;&lt;/span&gt; age &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：OK
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;4. HMGET ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：同时获取多个字段的值。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; HMGET user:1001 name age
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：按顺序返回字段值，字段不存在返回 nil
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;5. HGETALL 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：获取哈希表 key 中所有字段和值（键值对形式）。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; HGETALL user:1001
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：一个扁平数组（field1, value1, field2, value2, ...）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;6. HKEYS 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：获取哈希表 key 中所有字段（field）。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; HKEYS user:1001
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：字段列表（不包含值）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;7. HVALS 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：获取哈希表 key 中所有值（value）。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; HVALS user:1001
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：值的列表（不包含字段）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;8. HINCRBY 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：将哈希表 key 中指定字段的整数值加上增量。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; HINCRBY user:1001 age &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：递增后的整数值
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;9. HSETNX 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：仅当字段不存在时设置值（NX &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Not eXists）。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; HSETNX user:1001 age &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - 1：设置成功（字段不存在）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - 0：未设置（字段已存在）
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;List类型常见命令&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1. LPUSH &lt;span style="color:#f92672"&gt;[&lt;/span&gt;value2 ...&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：将一个或多个元素从左侧推入列表（即头部）。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; LPUSH mylist a b c &lt;span style="color:#75715e"&gt;# 列表变成 [c, b, a]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：操作后列表的长度
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2. LPOP 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：从左侧弹出（移除）并返回列表的第一个元素。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; LPOP mylist
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：被弹出的元素，或 nil（列表为空）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;3. RPUSH &lt;span style="color:#f92672"&gt;[&lt;/span&gt;value2 ...&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：将一个或多个元素从右侧推入列表（即尾部）。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RPUSH mylist x y z &lt;span style="color:#75715e"&gt;# 列表变成 [..., x, y, z]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：操作后列表的长度
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;4. RPOP 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：从右侧弹出（移除）并返回列表的最后一个元素。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RPOP mylist
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：被弹出的元素，或 nil（列表为空）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;5. LRANGE 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：获取列表指定范围内的元素（闭区间，支持负数索引）。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; LRANGE mylist &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 获取索引 0 到 2 的元素&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; LRANGE mylist &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; -1 &lt;span style="color:#75715e"&gt;# 获取整个列表&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：元素列表
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;6. BLPOP &lt;span style="color:#f92672"&gt;[&lt;/span&gt;key2 ...&lt;span style="color:#f92672"&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：从左侧弹出元素，若列表为空则阻塞等待，直到超时或有值。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; BLPOP mylist &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 最多等待 5 秒直到有元素可弹出&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：一个包含 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;key, value&lt;span style="color:#f92672"&gt;]&lt;/span&gt; 的数组，或 nil（超时）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;7. BRPOP &lt;span style="color:#f92672"&gt;[&lt;/span&gt;key2 ...&lt;span style="color:#f92672"&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：从右侧弹出元素，若列表为空则阻塞等待，直到超时或有值。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; BRPOP mylist &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：一个包含 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;key, value&lt;span style="color:#f92672"&gt;]&lt;/span&gt; 的数组，或 nil（超时）
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Set类型常见命令&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1. SADD &lt;span style="color:#f92672"&gt;[&lt;/span&gt;member2 ...&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：向集合添加一个或多个成员（去重，不允许重复元素）。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SADD myset a b c
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：成功添加的元素数量（已存在的不计入）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2. SREM &lt;span style="color:#f92672"&gt;[&lt;/span&gt;member2 ...&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：从集合中移除一个或多个指定成员。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SREM myset a b
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：成功移除的成员数量
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;3. SCARD 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：获取集合中元素的数量。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SCARD myset
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：集合的大小（元素个数）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;4. SISMEMBER 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：判断某个值是否是集合的成员。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SISMEMBER myset a
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - 1：是成员
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - 0：不是成员
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;5. SMEMBERS 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：返回集合中的所有元素。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SMEMBERS myset
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：元素列表（无序）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;6. SINTER &lt;span style="color:#f92672"&gt;[&lt;/span&gt;...&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：返回所有给定集合的交集。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SINTER set1 set2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：交集成员列表（仅在两个集合中都存在的元素）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;7. SDIFF &lt;span style="color:#f92672"&gt;[&lt;/span&gt;...&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：返回在 key1 中但不在其他集合中的元素（差集）。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SDIFF set1 set2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：差集成员列表（存在于 set1，但不在 set2 中）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;8. SUNION &lt;span style="color:#f92672"&gt;[&lt;/span&gt;...&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：返回所有给定集合的并集。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SUNION set1 set2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：并集成员列表（所有唯一元素）
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;SortedSet类型常见命令&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1. ZADD &lt;span style="color:#f92672"&gt;[&lt;/span&gt;score2 member2 ...&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：向有序集合添加一个或多个成员，并设置分数。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ZADD leaderboard &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; user1 &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt; user2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：成功添加的新成员数量（已存在的更新分数但不计入）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2. ZREM &lt;span style="color:#f92672"&gt;[&lt;/span&gt;member2 ...&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：移除一个或多个成员。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ZREM leaderboard user1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：成功移除的成员数量
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;3. ZSCORE 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：获取指定成员的分数。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ZSCORE leaderboard user2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：分数（字符串类型），或 nil（成员不存在）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;4. ZRANK 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：返回指定成员的排名（从小到大，0 开始）。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ZRANK leaderboard user2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：排名索引，或 nil（成员不存在）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;5. ZCARD 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：返回有序集合中的成员数量。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ZCARD leaderboard
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：成员总数
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;6. ZCOUNT 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：统计分数在指定范围内的成员数量。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ZCOUNT leaderboard &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：符合条件的成员数量
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;7. ZINCRBY 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：为指定成员的分数增加指定值（可为负）。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ZINCRBY leaderboard &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; user2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：增加后的分数
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;8. ZRANGE &lt;span style="color:#f92672"&gt;[&lt;/span&gt;WITHSCORES&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：按索引范围获取成员（从低分到高分）。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ZRANGE leaderboard &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ZRANGE leaderboard &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; WITHSCORES
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：成员列表，或成员+分数列表（如果加了 WITHSCORES）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;9. ZRANGEBYSCORE &lt;span style="color:#f92672"&gt;[&lt;/span&gt;WITHSCORES&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：按分数范围获取成员（可指定区间范围）。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ZRANGEBYSCORE leaderboard &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：符合条件的成员列表，默认按分数升序排列
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;10. ZINTER ... &lt;span style="color:#f92672"&gt;[&lt;/span&gt;AGGREGATE SUM|MIN|MAX&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;（Redis 6.2 起支持简化命令：ZINTERSTORE destination key1 key2 ...）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：求多个有序集合的交集，可合并分数。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ZINTER &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; zset1 zset2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：交集中成员及其计算后的分数
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;11. ZDIFF ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;（Redis 6.2+ 支持）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：返回第一个集合中存在、其余集合中不存在的成员。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ZDIFF &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; zset1 zset2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：差集成员列表（不含分数）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;12. ZUNION ... &lt;span style="color:#f92672"&gt;[&lt;/span&gt;AGGREGATE SUM|MIN|MAX&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;（Redis 6.2 起支持简化命令：ZUNIONSTORE destination key1 key2 ...）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;作用：求多个有序集合的并集，可合并分数。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;示例：
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ZUNION &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; zset1 zset2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;返回值：并集中所有成员及其合并分数
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>NoSQL数据库的四大类型</title><link>https://dandansad.com/2025/05/24/nosql%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9A%84%E5%9B%9B%E5%A4%A7%E7%B1%BB%E5%9E%8B/</link><pubDate>Sat, 24 May 2025 23:50:37 +0800</pubDate><guid>https://dandansad.com/2025/05/24/nosql%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9A%84%E5%9B%9B%E5%A4%A7%E7%B1%BB%E5%9E%8B/</guid><description>&lt;h2 id="什么是nosql"&gt;&lt;a href="#%e4%bb%80%e4%b9%88%e6%98%afnosql" class="header-anchor"&gt;&lt;/a&gt;什么是NoSQL？
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;NoSQL&lt;/strong&gt; 是 &lt;strong&gt;&amp;ldquo;Not Only SQL&amp;rdquo;&lt;/strong&gt; 的缩写（起初也有另一种解释为“No SQL”），表示“不仅仅是 SQL”。它泛指一类 &lt;strong&gt;非关系型数据库&lt;/strong&gt;，与传统的关系型数据库（如 MySQL、PostgreSQL）不同，它们通常不使用固定的表结构（没有严格的“表、行、列”模型），而是采用更灵活的数据模型来存储数据。&lt;/p&gt;
&lt;h2 id="nosql-的设计理念"&gt;&lt;a href="#nosql-%e7%9a%84%e8%ae%be%e8%ae%a1%e7%90%86%e5%bf%b5" class="header-anchor"&gt;&lt;/a&gt;NoSQL 的设计理念
&lt;/h2&gt;&lt;p&gt;NoSQL 的出现是为了解决传统关系型数据库在以下几个方面的不足：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;可扩展性差&lt;/strong&gt;：关系型数据库在处理海量数据、分布式存储和高并发时难以扩展。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;灵活性不足&lt;/strong&gt;：数据结构固定（表结构定义死），变更麻烦。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;性能瓶颈&lt;/strong&gt;：对海量数据的读写性能不够友好，尤其是在互联网、大数据场景下。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;NoSQL 数据库的目标是更好地支持 &lt;strong&gt;高并发访问、大数据存储、灵活的数据结构&lt;/strong&gt;，常用于互联网公司、分布式系统、大数据处理等领域。&lt;/p&gt;
&lt;h2 id="nosql数据库的四大类型"&gt;&lt;a href="#nosql%e6%95%b0%e6%8d%ae%e5%ba%93%e7%9a%84%e5%9b%9b%e5%a4%a7%e7%b1%bb%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;NoSQL数据库的四大类型
&lt;/h2&gt;&lt;h3 id="1-键值型key-value-store"&gt;&lt;a href="#1-%e9%94%ae%e5%80%bc%e5%9e%8bkey-value-store" class="header-anchor"&gt;&lt;/a&gt;1. 键值型（Key-Value Store）
&lt;/h3&gt;&lt;p&gt;这类数据库把数据存成一对对的“键”和“值”，就像一个超大号的字典或哈希表。你通过 key 查找对应的 value，速度非常快，适合做缓存、会话数据等简单存取操作，但不支持复杂查询。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;适用场景：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;缓存系统（如 Redis 缓存用户信息）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;会话状态存储&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;配置管理&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-文档型document-store"&gt;&lt;a href="#2-%e6%96%87%e6%a1%a3%e5%9e%8bdocument-store" class="header-anchor"&gt;&lt;/a&gt;2. 文档型（Document Store）
&lt;/h3&gt;&lt;p&gt;文档型数据库把每条记录存成一个结构化的文档（如 JSON），每个文档可以拥有不同的字段，非常灵活。它支持根据文档中的字段进行查询，是 NoSQL 中功能较强、用得最广的一类，常用于 Web 系统、内容管理等场景。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;适用场景：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;内容管理系统（CMS）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;用户资料、日志、评论系统&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;灵活业务模型（字段常变）&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3-列族型column-family-store"&gt;&lt;a href="#3-%e5%88%97%e6%97%8f%e5%9e%8bcolumn-family-store" class="header-anchor"&gt;&lt;/a&gt;3. 列族型（Column-Family Store）
&lt;/h3&gt;&lt;p&gt;这类数据库按“列”而不是“行”来存储数据，适合处理大规模结构化数据。每一列族就像一个独立的表，可高效读取某一类数据。它在写入和读取性能上非常出色，常用于大数据分析、日志处理、时间序列数据等。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;适用场景：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;实时分析（如用户行为记录）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;时间序列数据&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;日志和传感器数据存储&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="4-图数据库graph-database"&gt;&lt;a href="#4-%e5%9b%be%e6%95%b0%e6%8d%ae%e5%ba%93graph-database" class="header-anchor"&gt;&lt;/a&gt;4. 图数据库（Graph Database）
&lt;/h3&gt;&lt;p&gt;图数据库使用“节点”和“边”来表示数据及其关系，非常适合处理复杂的网络关系，比如社交网络、推荐系统等。它能快速进行“找朋友的朋友”这种关系链查询，是建模复杂关系结构的利器。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;适用场景：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;社交网络、推荐系统&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;知识图谱&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;网络拓扑分析、安全风控&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="对比表"&gt;&lt;a href="#%e5%af%b9%e6%af%94%e8%a1%a8" class="header-anchor"&gt;&lt;/a&gt;对比表
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;类型&lt;/th&gt;
					&lt;th&gt;数据模型&lt;/th&gt;
					&lt;th&gt;优势&lt;/th&gt;
					&lt;th&gt;缺点&lt;/th&gt;
					&lt;th&gt;示例&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;键值型&lt;/td&gt;
					&lt;td&gt;Key-Value&lt;/td&gt;
					&lt;td&gt;极致性能，简单易用&lt;/td&gt;
					&lt;td&gt;只能按 key 查&lt;/td&gt;
					&lt;td&gt;Redis, DynamoDB&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;文档型&lt;/td&gt;
					&lt;td&gt;JSON/BSON 文档&lt;/td&gt;
					&lt;td&gt;灵活结构，支持查询&lt;/td&gt;
					&lt;td&gt;不支持多文档事务、JOIN&lt;/td&gt;
					&lt;td&gt;MongoDB, CouchDB&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;列族型&lt;/td&gt;
					&lt;td&gt;表 + 列簇&lt;/td&gt;
					&lt;td&gt;适合海量数据分析&lt;/td&gt;
					&lt;td&gt;学习曲线高，调优复杂&lt;/td&gt;
					&lt;td&gt;Cassandra, HBase&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;图数据库&lt;/td&gt;
					&lt;td&gt;节点 + 边&lt;/td&gt;
					&lt;td&gt;关系建模强、查询高效&lt;/td&gt;
					&lt;td&gt;不适合无关系数据&lt;/td&gt;
					&lt;td&gt;Neo4j, ArangoDB&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="nosql-vs-sql-对比"&gt;&lt;a href="#nosql-vs-sql-%e5%af%b9%e6%af%94" class="header-anchor"&gt;&lt;/a&gt;NoSQL vs SQL 对比
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;特性&lt;/th&gt;
					&lt;th&gt;NoSQL&lt;/th&gt;
					&lt;th&gt;SQL（关系型数据库）&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;数据结构&lt;/td&gt;
					&lt;td&gt;灵活（文档、键值、图等）&lt;/td&gt;
					&lt;td&gt;表结构，模式固定&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;可扩展性&lt;/td&gt;
					&lt;td&gt;易水平扩展（分布式）&lt;/td&gt;
					&lt;td&gt;多为垂直扩展&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;事务支持&lt;/td&gt;
					&lt;td&gt;一般不强制支持 ACID&lt;/td&gt;
					&lt;td&gt;严格支持 ACID&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;查询语言&lt;/td&gt;
					&lt;td&gt;没有统一标准，通常基于 API&lt;/td&gt;
					&lt;td&gt;使用标准 SQL&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;适用场景&lt;/td&gt;
					&lt;td&gt;海量数据、高并发、动态数据结构&lt;/td&gt;
					&lt;td&gt;数据一致性强、结构清晰场景&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;常见代表&lt;/td&gt;
					&lt;td&gt;MongoDB、Redis、Cassandra等&lt;/td&gt;
					&lt;td&gt;MySQL、PostgreSQL、Oracle等&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="nosql-的应用场景"&gt;&lt;a href="#nosql-%e7%9a%84%e5%ba%94%e7%94%a8%e5%9c%ba%e6%99%af" class="header-anchor"&gt;&lt;/a&gt;NoSQL 的应用场景
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;社交网络系统（用户关系、动态结构）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;实时分析（大数据场景下的读写性能）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;内容管理系统（CMS）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;缓存系统（如 Redis）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;日志、传感器、监控数据存储（时序数据）&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>访问控制策略</title><link>https://dandansad.com/2025/05/08/%E8%AE%BF%E9%97%AE%E6%8E%A7%E5%88%B6%E7%AD%96%E7%95%A5/</link><pubDate>Thu, 08 May 2025 14:32:12 +0800</pubDate><guid>https://dandansad.com/2025/05/08/%E8%AE%BF%E9%97%AE%E6%8E%A7%E5%88%B6%E7%AD%96%E7%95%A5/</guid><description>&lt;h2 id="1-dacdiscretionary-access-control"&gt;&lt;a href="#1-dacdiscretionary-access-control" class="header-anchor"&gt;&lt;/a&gt;1. DAC（Discretionary Access Control）
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;自主访问控制&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="核心特点"&gt;&lt;a href="#%e6%a0%b8%e5%bf%83%e7%89%b9%e7%82%b9" class="header-anchor"&gt;&lt;/a&gt;核心特点：
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;资源拥有者决定权限&lt;/strong&gt;：用户对其拥有的资源（如文件）有控制权，可以授予或撤销他人的访问权限。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;权限可继承/传播&lt;/strong&gt;：被授权的用户可以继续把权限授予其他用户（这可能导致“权限扩散”）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="举例"&gt;&lt;a href="#%e4%b8%be%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;举例：
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;用户 A 拥有一个文件 &lt;code&gt;file.txt&lt;/code&gt;，他设置权限让用户 B 也能读取它。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;用户 B 如果有权，也可以把这个文件分享给用户 C。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="类似系统"&gt;&lt;a href="#%e7%b1%bb%e4%bc%bc%e7%b3%bb%e7%bb%9f" class="header-anchor"&gt;&lt;/a&gt;类似系统：
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;类 Unix 的系统默认使用 DAC&lt;/strong&gt;，通过 &lt;code&gt;chmod&lt;/code&gt;、&lt;code&gt;chown&lt;/code&gt; 控制文件权限。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="2-macmandatory-access-control"&gt;&lt;a href="#2-macmandatory-access-control" class="header-anchor"&gt;&lt;/a&gt;2. MAC（Mandatory Access Control）
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;强制访问控制&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="核心特点-1"&gt;&lt;a href="#%e6%a0%b8%e5%bf%83%e7%89%b9%e7%82%b9-1" class="header-anchor"&gt;&lt;/a&gt;核心特点：
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;系统控制访问权限&lt;/strong&gt;：用户无权修改自己的资源权限，所有访问规则由系统策略统一定义。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;基于安全标签（level）&lt;/strong&gt;：对象（资源）和主体（用户）都有安全级别，比如“机密”、“受限”、“公开”，系统强制根据这些级别控制访问。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="举例-1"&gt;&lt;a href="#%e4%b8%be%e4%be%8b-1" class="header-anchor"&gt;&lt;/a&gt;举例：
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;一个“秘密”级别的文件只有“秘密”级别或更高级别的用户才能访问，不能随意共享。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;用户即使拥有文件，也无法更改其访问权限。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="类似系统-1"&gt;&lt;a href="#%e7%b1%bb%e4%bc%bc%e7%b3%bb%e7%bb%9f-1" class="header-anchor"&gt;&lt;/a&gt;类似系统：
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;SELinux（Security-Enhanced Linux）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;AppArmor（Ubuntu 上使用）
这些系统就使用了 MAC 模型。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="3-rbacrole-based-access-control"&gt;&lt;a href="#3-rbacrole-based-access-control" class="header-anchor"&gt;&lt;/a&gt;3. RBAC（Role-Based Access Control）
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;基于角色的访问控制&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="核心特点-2"&gt;&lt;a href="#%e6%a0%b8%e5%bf%83%e7%89%b9%e7%82%b9-2" class="header-anchor"&gt;&lt;/a&gt;核心特点：
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;以“角色”为中心&lt;/strong&gt;：权限分配给“角色”，用户根据其角色获得权限。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;灵活、集中管理&lt;/strong&gt;：适合组织结构复杂、职责分明的环境。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="举例-2"&gt;&lt;a href="#%e4%b8%be%e4%be%8b-2" class="header-anchor"&gt;&lt;/a&gt;举例：
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;角色“管理员”拥有系统配置权限；角色“用户”只能读写自己的数据。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;用户 A 被分配为“管理员”，系统自动赋予所有“管理员”权限。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="类似系统-2"&gt;&lt;a href="#%e7%b1%bb%e4%bc%bc%e7%b3%bb%e7%bb%9f-2" class="header-anchor"&gt;&lt;/a&gt;类似系统：
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;多数企业应用和身份管理系统（如 Active Directory、Kubernetes、数据库权限管理）使用 RBAC。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="4-tbactask-based-access-control"&gt;&lt;a href="#4-tbactask-based-access-control" class="header-anchor"&gt;&lt;/a&gt;4. TBAC（Task-Based Access Control）
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;基于任务的访问控制&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="核心特点-3"&gt;&lt;a href="#%e6%a0%b8%e5%bf%83%e7%89%b9%e7%82%b9-3" class="header-anchor"&gt;&lt;/a&gt;核心特点：
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;权限与具体任务绑定，而不是与用户或角色绑定&lt;/strong&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;用户只有在执行某个“已授权任务”时，才能获得所需权限。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;强调“动态激活权限”，避免静态分配带来的过度权限问题。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="举例-3"&gt;&lt;a href="#%e4%b8%be%e4%be%8b-3" class="header-anchor"&gt;&lt;/a&gt;举例：
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;某人是“医生”角色，但只有在处理某个病人的病历任务时，才能访问该病历。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;执行完任务后，权限自动撤销。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="应用场景"&gt;&lt;a href="#%e5%ba%94%e7%94%a8%e5%9c%ba%e6%99%af" class="header-anchor"&gt;&lt;/a&gt;应用场景：
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;工作流系统、审批系统、临时授权操作（如 DevOps 自动化脚本）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="5-obacobject-based-access-control"&gt;&lt;a href="#5-obacobject-based-access-control" class="header-anchor"&gt;&lt;/a&gt;5. OBAC（Object-Based Access Control）
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;基于对象的访问控制&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="核心特点-4"&gt;&lt;a href="#%e6%a0%b8%e5%bf%83%e7%89%b9%e7%82%b9-4" class="header-anchor"&gt;&lt;/a&gt;核心特点：
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;访问控制依赖对象本身的属性和策略&lt;/strong&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;不看用户或角色，看“对象是否允许某类用户访问”。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="举例-4"&gt;&lt;a href="#%e4%b8%be%e4%be%8b-4" class="header-anchor"&gt;&lt;/a&gt;举例：
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;一个文件设置了“仅允许创建者和其直属上级访问”，访问控制规则写在对象的元数据或策略中。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;不依赖用户的角色或任务，只要对象规则允许，就能访问。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="应用场景-1"&gt;&lt;a href="#%e5%ba%94%e7%94%a8%e5%9c%ba%e6%99%af-1" class="header-anchor"&gt;&lt;/a&gt;应用场景：
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;微服务架构、面向对象系统、基于资源策略的授权系统（如某些云平台）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="总结对比表"&gt;&lt;a href="#%e6%80%bb%e7%bb%93%e5%af%b9%e6%af%94%e8%a1%a8" class="header-anchor"&gt;&lt;/a&gt;总结对比表：
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;模型&lt;/th&gt;
					&lt;th&gt;控制基础&lt;/th&gt;
					&lt;th&gt;权限分配方式&lt;/th&gt;
					&lt;th&gt;粒度&lt;/th&gt;
					&lt;th&gt;动态性&lt;/th&gt;
					&lt;th&gt;上下文感知&lt;/th&gt;
					&lt;th&gt;安全性&lt;/th&gt;
					&lt;th&gt;灵活性&lt;/th&gt;
					&lt;th&gt;常见场景/系统&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;DAC&lt;/td&gt;
					&lt;td&gt;用户（资源拥有者）&lt;/td&gt;
					&lt;td&gt;手动分配&lt;/td&gt;
					&lt;td&gt;中&lt;/td&gt;
					&lt;td&gt;静态&lt;/td&gt;
					&lt;td&gt;低&lt;/td&gt;
					&lt;td&gt;低&lt;/td&gt;
					&lt;td&gt;高&lt;/td&gt;
					&lt;td&gt;Unix/Linux 文件系统、用户共享&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;MAC&lt;/td&gt;
					&lt;td&gt;系统策略/安全标签&lt;/td&gt;
					&lt;td&gt;统一策略控制&lt;/td&gt;
					&lt;td&gt;高&lt;/td&gt;
					&lt;td&gt;静态&lt;/td&gt;
					&lt;td&gt;中&lt;/td&gt;
					&lt;td&gt;很高&lt;/td&gt;
					&lt;td&gt;低&lt;/td&gt;
					&lt;td&gt;SELinux、军事系统、政府保密系统&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;RBAC&lt;/td&gt;
					&lt;td&gt;用户角色&lt;/td&gt;
					&lt;td&gt;基于角色分配&lt;/td&gt;
					&lt;td&gt;中&lt;/td&gt;
					&lt;td&gt;静态&lt;/td&gt;
					&lt;td&gt;中&lt;/td&gt;
					&lt;td&gt;高&lt;/td&gt;
					&lt;td&gt;中&lt;/td&gt;
					&lt;td&gt;企业权限管理、数据库、Kubernetes&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;TBAC&lt;/td&gt;
					&lt;td&gt;当前执行任务&lt;/td&gt;
					&lt;td&gt;任务自动授权&lt;/td&gt;
					&lt;td&gt;高&lt;/td&gt;
					&lt;td&gt;动态&lt;/td&gt;
					&lt;td&gt;高&lt;/td&gt;
					&lt;td&gt;高&lt;/td&gt;
					&lt;td&gt;中&lt;/td&gt;
					&lt;td&gt;工作流系统、临时任务授权、自动化系统&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;OBAC&lt;/td&gt;
					&lt;td&gt;对象自身策略&lt;/td&gt;
					&lt;td&gt;对象定义控制策略&lt;/td&gt;
					&lt;td&gt;非常高&lt;/td&gt;
					&lt;td&gt;动态或静态&lt;/td&gt;
					&lt;td&gt;高&lt;/td&gt;
					&lt;td&gt;高&lt;/td&gt;
					&lt;td&gt;高&lt;/td&gt;
					&lt;td&gt;云服务（如 AWS IAM）、微服务资源管理&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>三种 FreeRTOS 通信方式</title><link>https://dandansad.com/2025/05/06/%E4%B8%89%E7%A7%8D-freertos-%E9%80%9A%E4%BF%A1%E6%96%B9%E5%BC%8F/</link><pubDate>Tue, 06 May 2025 21:21:12 +0800</pubDate><guid>https://dandansad.com/2025/05/06/%E4%B8%89%E7%A7%8D-freertos-%E9%80%9A%E4%BF%A1%E6%96%B9%E5%BC%8F/</guid><description>&lt;p&gt;在嵌入式系统中，任务之间的通信是实现并发、同步和资源共享的关键。FreeRTOS 提供了多种通信机制，以满足不同的应用场景和性能要求。本文将重点介绍三种常用的通信方式：&lt;strong&gt;消息队列（Queue）&lt;/strong&gt;、&lt;strong&gt;邮箱（Semaphore）和任务通知（Task Notification）&lt;/strong&gt;，并通过代码示例分析其适用场景和使用方法。&lt;/p&gt;
&lt;h2 id="一消息队列queue"&gt;&lt;a href="#%e4%b8%80%e6%b6%88%e6%81%af%e9%98%9f%e5%88%97queue" class="header-anchor"&gt;&lt;/a&gt;一、消息队列（Queue）
&lt;/h2&gt;&lt;h3 id="概述"&gt;&lt;a href="#%e6%a6%82%e8%bf%b0" class="header-anchor"&gt;&lt;/a&gt;概述
&lt;/h3&gt;&lt;p&gt;消息队列用于在任务之间&lt;strong&gt;传递消息或数据&lt;/strong&gt;。它可以存储多个数据项，常用于任务与任务、中断与任务之间的通信，适合需要“带数据”传递的情况。&lt;/p&gt;
&lt;h3 id="使用场景"&gt;&lt;a href="#%e4%bd%bf%e7%94%a8%e5%9c%ba%e6%99%af" class="header-anchor"&gt;&lt;/a&gt;使用场景
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;按钮中断向任务传递事件编号&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;任务间传输传感器值、指令等&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="示例代码"&gt;&lt;a href="#%e7%a4%ba%e4%be%8b%e4%bb%a3%e7%a0%81" class="header-anchor"&gt;&lt;/a&gt;示例代码
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 定义一个整型队列
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;QueueHandle_t my_queue;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 初始化队列，容量为10，每个元素是int类型
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;my_queue &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;xQueueCreate&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 消费者任务：从队列接收数据
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;consumer_task&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;arg) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; received_data;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;xQueueReceive&lt;/span&gt;(my_queue, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;received_data, portMAX_DELAY)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Received value: %d&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;, received_data);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 在此处理数据
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 中断服务程序：向队列发送数据
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EXTI_IRQHandler&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; data &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; BaseType_t xHigherPriorityTaskWoken &lt;span style="color:#f92672"&gt;=&lt;/span&gt; pdFALSE;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;xQueueSendFromISR&lt;/span&gt;(my_queue, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;data, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;xHigherPriorityTaskWoken);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;portYIELD_FROM_ISR&lt;/span&gt;(xHigherPriorityTaskWoken);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="特点"&gt;&lt;a href="#%e7%89%b9%e7%82%b9" class="header-anchor"&gt;&lt;/a&gt;特点
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;✅ 可传递任意数据类型&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;✅ 可用于任务与中断间通信&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;❌ 内存开销略大&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;❌ 比任务通知慢一些&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="二邮箱semaphore"&gt;&lt;a href="#%e4%ba%8c%e9%82%ae%e7%ae%b1semaphore" class="header-anchor"&gt;&lt;/a&gt;二、邮箱（Semaphore）
&lt;/h2&gt;&lt;h3 id="概述-1"&gt;&lt;a href="#%e6%a6%82%e8%bf%b0-1" class="header-anchor"&gt;&lt;/a&gt;概述
&lt;/h3&gt;&lt;p&gt;邮箱本质上是一种&lt;strong&gt;二值信号量&lt;/strong&gt;，主要用于任务同步，不承载数据。它常被用作“任务启动信号”或“事件通知”，而非传输数据。&lt;/p&gt;
&lt;h3 id="使用场景-1"&gt;&lt;a href="#%e4%bd%bf%e7%94%a8%e5%9c%ba%e6%99%af-1" class="header-anchor"&gt;&lt;/a&gt;使用场景
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;通知任务“有事情要做了”，但不传递数据&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;中断触发任务启动&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="示例代码-1"&gt;&lt;a href="#%e7%a4%ba%e4%be%8b%e4%bb%a3%e7%a0%81-1" class="header-anchor"&gt;&lt;/a&gt;示例代码
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 创建一个二值信号量
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SemaphoreHandle_t binary_semaphore;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 初始化
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;binary_semaphore &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;xSemaphoreCreateBinary&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 任务：等待信号量
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;led_task&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;arg) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;xSemaphoreTake&lt;/span&gt;(binary_semaphore, portMAX_DELAY)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Button pressed, toggle LED.&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 翻转 LED 状态
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 中断服务程序：发送信号量
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;button_isr&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; BaseType_t xHigherPriorityTaskWoken &lt;span style="color:#f92672"&gt;=&lt;/span&gt; pdFALSE;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;xSemaphoreGiveFromISR&lt;/span&gt;(binary_semaphore, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;xHigherPriorityTaskWoken);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;portYIELD_FROM_ISR&lt;/span&gt;(xHigherPriorityTaskWoken);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="特点-1"&gt;&lt;a href="#%e7%89%b9%e7%82%b9-1" class="header-anchor"&gt;&lt;/a&gt;特点
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;✅ 简单高效&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;✅ 适合事件同步（不含数据）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;❌ 无法携带数据&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;✅ 支持中断触发&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="三任务通知task-notification"&gt;&lt;a href="#%e4%b8%89%e4%bb%bb%e5%8a%a1%e9%80%9a%e7%9f%a5task-notification" class="header-anchor"&gt;&lt;/a&gt;三、任务通知（Task Notification）
&lt;/h2&gt;&lt;h3 id="概述-2"&gt;&lt;a href="#%e6%a6%82%e8%bf%b0-2" class="header-anchor"&gt;&lt;/a&gt;概述
&lt;/h3&gt;&lt;p&gt;任务通知是 FreeRTOS 中一种&lt;strong&gt;轻量级的任务间通信机制&lt;/strong&gt;，每个任务有一个 32 位的“通知值”，可以在任务之间或中断中更新和读取。它支持传递一个整数值，效率高，是性能最优的通信方式。&lt;/p&gt;
&lt;h3 id="使用场景-2"&gt;&lt;a href="#%e4%bd%bf%e7%94%a8%e5%9c%ba%e6%99%af-2" class="header-anchor"&gt;&lt;/a&gt;使用场景
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;单一任务之间快速通信&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;按钮等中断触发简单事件通知&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;替代低开销信号量和队列&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="示例代码-2"&gt;&lt;a href="#%e7%a4%ba%e4%be%8b%e4%bb%a3%e7%a0%81-2" class="header-anchor"&gt;&lt;/a&gt;示例代码
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 假设我们已经获得任务句柄 task_handle
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 任务：等待通知
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;notify_task&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;arg) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;uint32_t&lt;/span&gt; value;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 阻塞等待通知，并获取通知值
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;xTaskNotifyWait&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;value, portMAX_DELAY)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Received notify value: %lu&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;, value);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 响应事件
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 中断服务程序：发送通知
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;notify_isr&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; BaseType_t xHigherPriorityTaskWoken &lt;span style="color:#f92672"&gt;=&lt;/span&gt; pdFALSE;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;xTaskNotifyFromISR&lt;/span&gt;(task_handle, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, eSetValueWithOverwrite, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;xHigherPriorityTaskWoken);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;portYIELD_FROM_ISR&lt;/span&gt;(xHigherPriorityTaskWoken);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="特点-2"&gt;&lt;a href="#%e7%89%b9%e7%82%b9-2" class="header-anchor"&gt;&lt;/a&gt;特点
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;✅ 传输单个整数值&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;✅ 效率最高、开销最小&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;❌ 每个任务只能有一个通知槽位&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;✅ 适合中断触发事件通知&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="四总结对比"&gt;&lt;a href="#%e5%9b%9b%e6%80%bb%e7%bb%93%e5%af%b9%e6%af%94" class="header-anchor"&gt;&lt;/a&gt;四、总结对比
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;特性&lt;/th&gt;
					&lt;th&gt;消息队列&lt;/th&gt;
					&lt;th&gt;邮箱（信号量）&lt;/th&gt;
					&lt;th&gt;任务通知&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;是否传递数据&lt;/td&gt;
					&lt;td&gt;✅ 是（任意类型）&lt;/td&gt;
					&lt;td&gt;❌ 否（仅通知）&lt;/td&gt;
					&lt;td&gt;✅ 是（单个整数）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;是否支持中断调用&lt;/td&gt;
					&lt;td&gt;✅ 是&lt;/td&gt;
					&lt;td&gt;✅ 是&lt;/td&gt;
					&lt;td&gt;✅ 是&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;通信效率&lt;/td&gt;
					&lt;td&gt;中&lt;/td&gt;
					&lt;td&gt;高&lt;/td&gt;
					&lt;td&gt;最高&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;资源开销&lt;/td&gt;
					&lt;td&gt;较大（占用内存）&lt;/td&gt;
					&lt;td&gt;小&lt;/td&gt;
					&lt;td&gt;最小（无堆内存）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;多对一通信支持&lt;/td&gt;
					&lt;td&gt;✅ 支持（多个任务写入）&lt;/td&gt;
					&lt;td&gt;✅ 支持&lt;/td&gt;
					&lt;td&gt;❌ 单槽位，需注意覆盖&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;典型使用场景&lt;/td&gt;
					&lt;td&gt;传输数据、任务调度&lt;/td&gt;
					&lt;td&gt;同步任务、事件触发&lt;/td&gt;
					&lt;td&gt;快速事件触发、ISR通信&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>算法设计与分析：要点总结-3</title><link>https://dandansad.com/2025/04/28/%E7%AE%97%E6%B3%95%E8%AE%BE%E8%AE%A1%E4%B8%8E%E5%88%86%E6%9E%90%E8%A6%81%E7%82%B9%E6%80%BB%E7%BB%93-3/</link><pubDate>Mon, 28 Apr 2025 10:11:52 +0800</pubDate><guid>https://dandansad.com/2025/04/28/%E7%AE%97%E6%B3%95%E8%AE%BE%E8%AE%A1%E4%B8%8E%E5%88%86%E6%9E%90%E8%A6%81%E7%82%B9%E6%80%BB%E7%BB%93-3/</guid><description>&lt;h3 id="贪婪算法greedy-algorithm"&gt;&lt;a href="#%e8%b4%aa%e5%a9%aa%e7%ae%97%e6%b3%95greedy-algorithm" class="header-anchor"&gt;&lt;/a&gt;贪婪算法（Greedy Algorithm）
&lt;/h3&gt;&lt;h4 id="1-基本思想"&gt;&lt;a href="#1-%e5%9f%ba%e6%9c%ac%e6%80%9d%e6%83%b3" class="header-anchor"&gt;&lt;/a&gt;1. 基本思想
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;每一步&lt;strong&gt;都做当前看来最优的选择&lt;/strong&gt;（即局部最优），希望通过一系列局部最优，&lt;strong&gt;达到整体最优&lt;/strong&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;特点是&lt;strong&gt;只顾眼前&lt;/strong&gt;（每次选择最优），&lt;strong&gt;不回溯&lt;/strong&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="2-贪婪问题分类"&gt;&lt;a href="#2-%e8%b4%aa%e5%a9%aa%e9%97%ae%e9%a2%98%e5%88%86%e7%b1%bb" class="header-anchor"&gt;&lt;/a&gt;2. 贪婪问题分类
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;绝对贪婪问题&lt;/strong&gt;：&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;每一步的局部最优选择，&lt;strong&gt;最终一定得到全局最优解&lt;/strong&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;例子：活动安排问题、最小生成树问题。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;相对贪婪问题&lt;/strong&gt;：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;贪婪算法得到的解&lt;strong&gt;不是全局最优&lt;/strong&gt;，但通常是一个&lt;strong&gt;近似最优&lt;/strong&gt;（有时足够好了）。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;例子：一些NP问题的贪婪近似，比如旅行商问题的贪婪解。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="贪婪算法与问题复杂性"&gt;&lt;a href="#%e8%b4%aa%e5%a9%aa%e7%ae%97%e6%b3%95%e4%b8%8e%e9%97%ae%e9%a2%98%e5%a4%8d%e6%9d%82%e6%80%a7" class="header-anchor"&gt;&lt;/a&gt;贪婪算法与问题复杂性
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;P问题&lt;/strong&gt;：可以在多项式时间内求解的问题（即存在有效算法）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;NP问题&lt;/strong&gt;：能在多项式时间内&lt;strong&gt;验证&lt;/strong&gt;一个解是否正确，但&lt;strong&gt;不一定能快速求解&lt;/strong&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;贪婪算法通常用于P问题或NP问题的&lt;strong&gt;近似解&lt;/strong&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;有效算法&lt;/strong&gt;：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;运行时间是问题规模的多项式函数，比如 O(n^2), O(nlog⁡n)。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;相对的，指数时间 O(2^n)算法就不是有效算法。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="经典例题"&gt;&lt;a href="#%e7%bb%8f%e5%85%b8%e4%be%8b%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;经典例题
&lt;/h3&gt;&lt;h4 id="1-工资分发问题类似找零问题"&gt;&lt;a href="#1-%e5%b7%a5%e8%b5%84%e5%88%86%e5%8f%91%e9%97%ae%e9%a2%98%e7%b1%bb%e4%bc%bc%e6%89%be%e9%9b%b6%e9%97%ae%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;1. 工资分发问题（类似找零问题）
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;题意：用最少数量的钱币发工资。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;解法：每次选&lt;strong&gt;面额最大且不超过剩余金额&lt;/strong&gt;的钱币。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;注意：有些面额组合下贪心策略不一定最优（比如奇怪的硬币系统）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="2-活动安排问题"&gt;&lt;a href="#2-%e6%b4%bb%e5%8a%a8%e5%ae%89%e6%8e%92%e9%97%ae%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;2. 活动安排问题
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;题意：给定若干活动，每个活动有开始、结束时间，要求安排最多不重叠活动。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;贪心策略：&lt;strong&gt;优先选结束时间最早的活动&lt;/strong&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="3-多机调度问题"&gt;&lt;a href="#3-%e5%a4%9a%e6%9c%ba%e8%b0%83%e5%ba%a6%e9%97%ae%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;3. 多机调度问题
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;题意：n个任务分配到k台机器，使得最晚完成时间最早。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;贪心策略：&lt;strong&gt;每次将任务分配到当前负载最轻的机器上&lt;/strong&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="重要贪婪算法"&gt;&lt;a href="#%e9%87%8d%e8%a6%81%e8%b4%aa%e5%a9%aa%e7%ae%97%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;重要贪婪算法
&lt;/h3&gt;&lt;h4 id="1-huffman树构造最优编码问题"&gt;&lt;a href="#1-huffman%e6%a0%91%e6%9e%84%e9%80%a0%e6%9c%80%e4%bc%98%e7%bc%96%e7%a0%81%e9%97%ae%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;1. Huffman树构造（最优编码问题）
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;题意：给定字符及其出现频率，设计编码使总编码长度最短。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;方法：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;每次选取出现频率最小的两个节点合并。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;最后生成哈夫曼树。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="2-单源最短路径dijkstra算法"&gt;&lt;a href="#2-%e5%8d%95%e6%ba%90%e6%9c%80%e7%9f%ad%e8%b7%af%e5%be%84dijkstra%e7%ae%97%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;2. 单源最短路径：Dijkstra算法
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;适用于&lt;strong&gt;边权非负&lt;/strong&gt;的图。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;思路：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;维护一张最短距离表。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每次选取&lt;strong&gt;当前未访问、距离源点最短&lt;/strong&gt;的点，更新它的邻居。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="3-最小生成树"&gt;&lt;a href="#3-%e6%9c%80%e5%b0%8f%e7%94%9f%e6%88%90%e6%a0%91" class="header-anchor"&gt;&lt;/a&gt;3. 最小生成树
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Prim算法&lt;/strong&gt;：&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;从任意点开始，逐步将&lt;strong&gt;最近的点&lt;/strong&gt;连入生成树。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Kruskal算法&lt;/strong&gt;：&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;把边按权值从小到大排序，&lt;strong&gt;逐条选边&lt;/strong&gt;，如果不会成环就加入生成树。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用&lt;strong&gt;并查集&lt;/strong&gt;快速判断成环。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>ActiveMQ-Exercise</title><link>https://dandansad.com/2025/04/21/activemq-exercise/</link><pubDate>Mon, 21 Apr 2025 23:26:38 +0800</pubDate><guid>https://dandansad.com/2025/04/21/activemq-exercise/</guid><description>&lt;h2 id="项目理解"&gt;&lt;a href="#%e9%a1%b9%e7%9b%ae%e7%90%86%e8%a7%a3" class="header-anchor"&gt;&lt;/a&gt;项目理解
&lt;/h2&gt;&lt;p&gt;一个使用了ActiveMQ消息队列的订单-物流系统，两个系统之间通过消息队列来通信，主要有&lt;code&gt;order.created.queue&lt;/code&gt;和&lt;code&gt;logistics.updated.queue&lt;/code&gt;两个消息队列。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;order.created.queue&lt;/strong&gt;是一个订单创建消息队列。当新订单创建时，系统会将订单信息发送到此队列，通知其他系统或者服务去处理与该订单相关的后续操作。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;logistics.updated.queue&lt;/strong&gt;是一个物流更新消息队列。当订单的物流信息发生更新（比如订单发货、配送进度等）时，系统会将物流信息发送到此队列，通知其他系统或者服务更新或处理订单的物流状态。&lt;/p&gt;
&lt;p&gt;消息队列在这个场景中充当了&lt;strong&gt;异步通信机制&lt;/strong&gt;，不是传统意义上的“推送通知”（比如给用户发送消息），而是指在系统内部，&lt;strong&gt;消息队列&lt;/strong&gt;作为一种通信机制，允许服务之间通过异步消息交换来实现解耦。队列本身不会主动“传递”消息给目标服务，而是由目标服务去&lt;strong&gt;监听&lt;/strong&gt;这个队列，然后&lt;strong&gt;被动拉取&lt;/strong&gt;新消息进行处理。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ActiveMQ-Exercise/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── README.md &lt;span style="color:#75715e"&gt;# 项目说明文档，描述项目的目的、使用方法等&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── common &lt;span style="color:#75715e"&gt;# 公共模块，包含多个共享的类、配置、DTO等&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── pom.xml &lt;span style="color:#75715e"&gt;# 公共模块的Maven配置文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── src
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── main
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── example
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── common
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ ├── config
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ │ ├── ActiveMQConfig.java &lt;span style="color:#75715e"&gt;# ActiveMQ配置，连接消息队列&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ │ └── JmsConverterConfig.java &lt;span style="color:#75715e"&gt;# JMS消息转换器配置&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ ├── constants
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ │ └── JmsConstants.java &lt;span style="color:#75715e"&gt;# 定义常量，如消息队列的名称等&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ ├── dto
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ │ ├── LogisticsOrderDTO.java &lt;span style="color:#75715e"&gt;# 物流订单DTO&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ │ ├── LogisticsUpdateDTO.java &lt;span style="color:#75715e"&gt;# 物流更新DTO&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ │ └── OrderDTO.java &lt;span style="color:#75715e"&gt;# 订单DTO&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ ├── model
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ │ └── OrderStatus.java &lt;span style="color:#75715e"&gt;# 订单状态枚举类&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── util
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── EntityDtoConverter.java &lt;span style="color:#75715e"&gt;# 实体类与DTO类的转换工具类&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── logistics-system &lt;span style="color:#75715e"&gt;# 物流系统模块&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── logistics-system.iml &lt;span style="color:#75715e"&gt;# IntelliJ IDEA项目文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── pom.xml &lt;span style="color:#75715e"&gt;# 物流系统模块的Maven配置文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── src
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── main
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── example
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── logistics
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── LogisticsSystemApplication.java &lt;span style="color:#75715e"&gt;# 物流系统启动类&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── config
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── JacksonConfig.java &lt;span style="color:#75715e"&gt;# 配置Jackson，处理JSON序列化和反序列化&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── controller
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── LogisticsController.java &lt;span style="color:#75715e"&gt;# 处理物流订单的控制器&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── entity
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ ├── LogisticsOrder.java &lt;span style="color:#75715e"&gt;# 物流订单实体类&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── LogisticsOrderItem.java &lt;span style="color:#75715e"&gt;# 物流订单项实体类&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── listener
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── OrderCreatedListener.java &lt;span style="color:#75715e"&gt;# 监听新订单创建的事件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── repository
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── LogisticsOrderRepository.java &lt;span style="color:#75715e"&gt;# 物流订单的数据库操作接口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── service
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── LogisticsService.java &lt;span style="color:#75715e"&gt;# 物流服务接口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── impl
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── LogisticsServiceImpl.java &lt;span style="color:#75715e"&gt;# 物流服务实现类&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── resources
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── application-local.properties &lt;span style="color:#75715e"&gt;# 本地配置文件，包含数据库、消息队列等配置&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── application.properties &lt;span style="color:#75715e"&gt;# 默认配置文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── static
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── css
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── apple-style.css &lt;span style="color:#75715e"&gt;# CSS样式文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── templates
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── logistics
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── list.html &lt;span style="color:#75715e"&gt;# 物流订单列表页面&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── shipped.html &lt;span style="color:#75715e"&gt;# 物流订单已发货页面&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── order-system &lt;span style="color:#75715e"&gt;# 订单系统模块&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── pom.xml &lt;span style="color:#75715e"&gt;# 订单系统模块的Maven配置文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── src
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── main
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── example
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── order
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── OrderSystemApplication.java &lt;span style="color:#75715e"&gt;# 订单系统启动类&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── controller
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── OrderController.java &lt;span style="color:#75715e"&gt;# 处理订单的控制器&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── entity
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ ├── Order.java &lt;span style="color:#75715e"&gt;# 订单实体类&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── OrderItem.java &lt;span style="color:#75715e"&gt;# 订单项实体类&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── listener
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── LogisticsUpdateListener.java &lt;span style="color:#75715e"&gt;# 监听物流更新事件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── repository
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── OrderRepository.java &lt;span style="color:#75715e"&gt;# 订单数据库操作接口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── service
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── OrderService.java &lt;span style="color:#75715e"&gt;# 订单服务接口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── impl
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── OrderServiceImpl.java &lt;span style="color:#75715e"&gt;# 订单服务实现类&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── resources
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── application-local.properties &lt;span style="color:#75715e"&gt;# 本地配置文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── application.properties &lt;span style="color:#75715e"&gt;# 默认配置文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── static
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── css
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── apple-style.css &lt;span style="color:#75715e"&gt;# CSS样式文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── templates
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── order
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── create.html &lt;span style="color:#75715e"&gt;# 创建订单页面&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── list.html &lt;span style="color:#75715e"&gt;# 订单列表页面&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└── pom.xml &lt;span style="color:#75715e"&gt;# 根目录的Maven配置文件，管理依赖和构建配置&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在本项目中，消息队列的作用可以概括为：&lt;strong&gt;订单系统在用户创建订单后，通过 Controller 层的业务逻辑将订单信息封装为消息发送到 ActiveMQ 队列中（如 &lt;code&gt;order.created.queue&lt;/code&gt;），而物流系统则通过监听器持续监听该队列，一旦接收到新消息，立即触发对应的处理逻辑（如入库、更新状态等）&lt;/strong&gt;。这一过程实现了服务之间的解耦，使得各模块可以异步通信、独立扩展，提高了系统的可靠性与可维护性。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;订单系统前端&lt;span style="color:#f92672"&gt;]&lt;/span&gt; --&amp;gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;OrderController&lt;span style="color:#f92672"&gt;]&lt;/span&gt; --&amp;gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;JmsTemplate 发送消息到 MQ&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;ActiveMQ 消息队列: order.created.queue&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;物流系统 OrderCreatedListener 自动监听并处理消息&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="接触到的新技术"&gt;&lt;a href="#%e6%8e%a5%e8%a7%a6%e5%88%b0%e7%9a%84%e6%96%b0%e6%8a%80%e6%9c%af" class="header-anchor"&gt;&lt;/a&gt;接触到的新技术
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;技术 / 框架&lt;/th&gt;
					&lt;th&gt;作用说明&lt;/th&gt;
					&lt;th&gt;项目中的使用示例&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Spring Boot&lt;/td&gt;
					&lt;td&gt;简化配置和启动流程，快速构建微服务项目&lt;/td&gt;
					&lt;td&gt;构建订单系统和物流系统两个独立的 Spring Boot 服务&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Spring JPA (Hibernate)&lt;/td&gt;
					&lt;td&gt;简化数据库操作，基于实体类自动生成数据库表及 SQL&lt;/td&gt;
					&lt;td&gt;使用 JpaRepository 快速实现订单、物流数据的增删改查&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;ActiveMQ（JMS）&lt;/td&gt;
					&lt;td&gt;实现系统间异步通信，消息解耦&lt;/td&gt;
					&lt;td&gt;用于订单系统与物流系统之间通过消息队列进行数据传递&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;JmsTemplate / @JmsListener&lt;/td&gt;
					&lt;td&gt;发送和监听消息的核心工具&lt;/td&gt;
					&lt;td&gt;OrderServiceImpl 中发送消息，OrderCreatedListener 中接收并处理&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;H2 内存数据库&lt;/td&gt;
					&lt;td&gt;用于开发测试的轻量级数据库，启动即用&lt;/td&gt;
					&lt;td&gt;默认配置存储订单与物流信息，无需手动创建数据库&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Jackson 配置自定义 ObjectMapper&lt;/td&gt;
					&lt;td&gt;处理 JSON 与对象间的序列化、反序列化，尤其是日期格式等&lt;/td&gt;
					&lt;td&gt;在 JacksonConfig.java 中配置 JavaTimeModule 支持时间类型&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;DTO（数据传输对象）设计&lt;/td&gt;
					&lt;td&gt;实体与传输对象分离，增强系统灵活性与安全性&lt;/td&gt;
					&lt;td&gt;使用 OrderDTO、LogisticsOrderDTO 进行跨系统数据传输&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Thymeleaf 模板引擎&lt;/td&gt;
					&lt;td&gt;用于前端展示，结合 Spring MVC 渲染页面&lt;/td&gt;
					&lt;td&gt;项目中如 order/list.html、logistics/list.html 等模板&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Lombok（@Data、@Slf4j、@RequiredArgsConstructor）&lt;/td&gt;
					&lt;td&gt;简化 Java 代码的开发，自动生成 getter/setter 等&lt;/td&gt;
					&lt;td&gt;提高开发效率，减少模板代码，如实体类、服务类中大量使用&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;多模块 Maven 工程结构&lt;/td&gt;
					&lt;td&gt;实现模块复用和结构清晰，便于维护&lt;/td&gt;
					&lt;td&gt;common 模块抽象公共部分，order-system 和 logistics-system 各自独立&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;@ConditionalOnProperty（Spring Boot）&lt;/td&gt;
					&lt;td&gt;条件注解，只有在配置文件中某个属性满足特定值时，才会启用对应的配置类或Bean。&lt;/td&gt;
					&lt;td&gt;当 application.properties 中 jms.implementation=spring，或者该属性缺失（matchIfMissing=true）时，启用当前Bean或配置。&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="后续新增"&gt;&lt;a href="#%e5%90%8e%e7%bb%ad%e6%96%b0%e5%a2%9e" class="header-anchor"&gt;&lt;/a&gt;后续新增
&lt;/h2&gt;&lt;p&gt;后续新增了底层JMS API的使用方法。&lt;/p&gt;
&lt;h3 id="-点对点模型queue"&gt;&lt;a href="#-%e7%82%b9%e5%af%b9%e7%82%b9%e6%a8%a1%e5%9e%8bqueue" class="header-anchor"&gt;&lt;/a&gt;✅ 点对点模型（Queue）
&lt;/h3&gt;&lt;h4 id="-生产者代码queueproducerjava"&gt;&lt;a href="#-%e7%94%9f%e4%ba%a7%e8%80%85%e4%bb%a3%e7%a0%81queueproducerjava" class="header-anchor"&gt;&lt;/a&gt;📤 生产者代码（QueueProducer.java）
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; javax.jms.*;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; org.apache.activemq.ActiveMQConnectionFactory;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;QueueProducer&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;(String&lt;span style="color:#f92672"&gt;[]&lt;/span&gt; args) &lt;span style="color:#66d9ef"&gt;throws&lt;/span&gt; JMSException {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建连接工厂，连接到ActiveMQ服务器&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ConnectionFactory factory &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; ActiveMQConnectionFactory(&lt;span style="color:#e6db74"&gt;&amp;#34;tcp://localhost:61616&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建连接&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Connection connection &lt;span style="color:#f92672"&gt;=&lt;/span&gt; factory.&lt;span style="color:#a6e22e"&gt;createConnection&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建会话（不使用事务，自动确认消息）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Session session &lt;span style="color:#f92672"&gt;=&lt;/span&gt; connection.&lt;span style="color:#a6e22e"&gt;createSession&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;, Session.&lt;span style="color:#a6e22e"&gt;AUTO_ACKNOWLEDGE&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建一个队列（Queue）目的地&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Queue queue &lt;span style="color:#f92672"&gt;=&lt;/span&gt; session.&lt;span style="color:#a6e22e"&gt;createQueue&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;myQueue&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建生产者，发送到指定队列&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MessageProducer producer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; session.&lt;span style="color:#a6e22e"&gt;createProducer&lt;/span&gt;(queue);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建一条文本消息&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TextMessage message &lt;span style="color:#f92672"&gt;=&lt;/span&gt; session.&lt;span style="color:#a6e22e"&gt;createTextMessage&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Hello from QueueProducer!&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 发送消息&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; producer.&lt;span style="color:#a6e22e"&gt;send&lt;/span&gt;(message);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 输出发送内容&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.&lt;span style="color:#a6e22e"&gt;out&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Sent message: &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; message.&lt;span style="color:#a6e22e"&gt;getText&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 关闭资源&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; session.&lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; connection.&lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="-消费者代码queueconsumerjava"&gt;&lt;a href="#-%e6%b6%88%e8%b4%b9%e8%80%85%e4%bb%a3%e7%a0%81queueconsumerjava" class="header-anchor"&gt;&lt;/a&gt;📥 消费者代码（QueueConsumer.java）
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; javax.jms.*;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; org.apache.activemq.ActiveMQConnectionFactory;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;QueueConsumer&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;(String&lt;span style="color:#f92672"&gt;[]&lt;/span&gt; args) &lt;span style="color:#66d9ef"&gt;throws&lt;/span&gt; JMSException {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建连接工厂&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ConnectionFactory factory &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; ActiveMQConnectionFactory(&lt;span style="color:#e6db74"&gt;&amp;#34;tcp://localhost:61616&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建连接&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Connection connection &lt;span style="color:#f92672"&gt;=&lt;/span&gt; factory.&lt;span style="color:#a6e22e"&gt;createConnection&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; connection.&lt;span style="color:#a6e22e"&gt;start&lt;/span&gt;(); &lt;span style="color:#75715e"&gt;// 启动连接，消费者必须先启动才能接收消息&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建会话（不使用事务，自动确认消息）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Session session &lt;span style="color:#f92672"&gt;=&lt;/span&gt; connection.&lt;span style="color:#a6e22e"&gt;createSession&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;, Session.&lt;span style="color:#a6e22e"&gt;AUTO_ACKNOWLEDGE&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建队列（与生产者的队列名称必须一致）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Queue queue &lt;span style="color:#f92672"&gt;=&lt;/span&gt; session.&lt;span style="color:#a6e22e"&gt;createQueue&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;myQueue&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建消费者，从队列接收消息&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MessageConsumer consumer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; session.&lt;span style="color:#a6e22e"&gt;createConsumer&lt;/span&gt;(queue);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 接收消息（这是一个阻塞方法，直到接收到消息为止）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Message message &lt;span style="color:#f92672"&gt;=&lt;/span&gt; consumer.&lt;span style="color:#a6e22e"&gt;receive&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 判断消息类型并打印内容&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (message &lt;span style="color:#66d9ef"&gt;instanceof&lt;/span&gt; TextMessage) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.&lt;span style="color:#a6e22e"&gt;out&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Received: &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; ((TextMessage) message).&lt;span style="color:#a6e22e"&gt;getText&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 关闭资源&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; session.&lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; connection.&lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="-发布订阅模型topic"&gt;&lt;a href="#-%e5%8f%91%e5%b8%83%e8%ae%a2%e9%98%85%e6%a8%a1%e5%9e%8btopic" class="header-anchor"&gt;&lt;/a&gt;✅ 发布/订阅模型（Topic）
&lt;/h3&gt;&lt;h4 id="-发布者代码topicpublisherjava"&gt;&lt;a href="#-%e5%8f%91%e5%b8%83%e8%80%85%e4%bb%a3%e7%a0%81topicpublisherjava" class="header-anchor"&gt;&lt;/a&gt;📢 发布者代码（TopicPublisher.java）
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; javax.jms.*;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; org.apache.activemq.ActiveMQConnectionFactory;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;TopicPublisher&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;(String&lt;span style="color:#f92672"&gt;[]&lt;/span&gt; args) &lt;span style="color:#66d9ef"&gt;throws&lt;/span&gt; JMSException {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建连接工厂&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ConnectionFactory factory &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; ActiveMQConnectionFactory(&lt;span style="color:#e6db74"&gt;&amp;#34;tcp://localhost:61616&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建连接&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Connection connection &lt;span style="color:#f92672"&gt;=&lt;/span&gt; factory.&lt;span style="color:#a6e22e"&gt;createConnection&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建会话&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Session session &lt;span style="color:#f92672"&gt;=&lt;/span&gt; connection.&lt;span style="color:#a6e22e"&gt;createSession&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;, Session.&lt;span style="color:#a6e22e"&gt;AUTO_ACKNOWLEDGE&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建主题（Topic）目的地&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Topic topic &lt;span style="color:#f92672"&gt;=&lt;/span&gt; session.&lt;span style="color:#a6e22e"&gt;createTopic&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;myTopic&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建消息发布者&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MessageProducer producer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; session.&lt;span style="color:#a6e22e"&gt;createProducer&lt;/span&gt;(topic);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建文本消息&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TextMessage message &lt;span style="color:#f92672"&gt;=&lt;/span&gt; session.&lt;span style="color:#a6e22e"&gt;createTextMessage&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Hello from TopicPublisher!&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 发布消息到主题&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; producer.&lt;span style="color:#a6e22e"&gt;send&lt;/span&gt;(message);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 打印消息内容&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.&lt;span style="color:#a6e22e"&gt;out&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Published message: &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; message.&lt;span style="color:#a6e22e"&gt;getText&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 关闭资源&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; session.&lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; connection.&lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="-订阅者代码topicsubscriberjava"&gt;&lt;a href="#-%e8%ae%a2%e9%98%85%e8%80%85%e4%bb%a3%e7%a0%81topicsubscriberjava" class="header-anchor"&gt;&lt;/a&gt;📡 订阅者代码（TopicSubscriber.java）
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; javax.jms.*;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; org.apache.activemq.ActiveMQConnectionFactory;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;TopicSubscriber&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;(String&lt;span style="color:#f92672"&gt;[]&lt;/span&gt; args) &lt;span style="color:#66d9ef"&gt;throws&lt;/span&gt; JMSException {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建连接工厂&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ConnectionFactory factory &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; ActiveMQConnectionFactory(&lt;span style="color:#e6db74"&gt;&amp;#34;tcp://localhost:61616&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建连接&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Connection connection &lt;span style="color:#f92672"&gt;=&lt;/span&gt; factory.&lt;span style="color:#a6e22e"&gt;createConnection&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 为连接设置客户端 ID（用于持久订阅）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; connection.&lt;span style="color:#a6e22e"&gt;setClientID&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;client1&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 启动连接，必须启动后才能接收消息&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; connection.&lt;span style="color:#a6e22e"&gt;start&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建会话&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Session session &lt;span style="color:#f92672"&gt;=&lt;/span&gt; connection.&lt;span style="color:#a6e22e"&gt;createSession&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;, Session.&lt;span style="color:#a6e22e"&gt;AUTO_ACKNOWLEDGE&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建主题（Topic）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Topic topic &lt;span style="color:#f92672"&gt;=&lt;/span&gt; session.&lt;span style="color:#a6e22e"&gt;createTopic&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;myTopic&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 创建订阅者（普通订阅；如果你想要持久订阅，请使用 `createDurableSubscriber`）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MessageConsumer consumer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; session.&lt;span style="color:#a6e22e"&gt;createConsumer&lt;/span&gt;(topic);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 接收消息&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Message message &lt;span style="color:#f92672"&gt;=&lt;/span&gt; consumer.&lt;span style="color:#a6e22e"&gt;receive&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 打印消息内容&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (message &lt;span style="color:#66d9ef"&gt;instanceof&lt;/span&gt; TextMessage) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.&lt;span style="color:#a6e22e"&gt;out&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Received: &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; ((TextMessage) message).&lt;span style="color:#a6e22e"&gt;getText&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 关闭资源&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; session.&lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; connection.&lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>算法设计与分析：要点总结-2</title><link>https://dandansad.com/2025/04/21/%E7%AE%97%E6%B3%95%E8%AE%BE%E8%AE%A1%E4%B8%8E%E5%88%86%E6%9E%90%E8%A6%81%E7%82%B9%E6%80%BB%E7%BB%93-2/</link><pubDate>Mon, 21 Apr 2025 00:36:48 +0800</pubDate><guid>https://dandansad.com/2025/04/21/%E7%AE%97%E6%B3%95%E8%AE%BE%E8%AE%A1%E4%B8%8E%E5%88%86%E6%9E%90%E8%A6%81%E7%82%B9%E6%80%BB%E7%BB%93-2/</guid><description>&lt;h3 id="分治算法"&gt;&lt;a href="#%e5%88%86%e6%b2%bb%e7%ae%97%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;分治算法
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;分治思想&lt;/strong&gt;： 分治算法是一种将一个复杂问题分解成多个较小的子问题，通过递归解决子问题，再将子问题的解合并起来，得到原问题的解。分治思想的核心是通过将问题规模减小、分解和组合来简化问题的解决。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;分治算法的基本步骤&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;分解&lt;/strong&gt;：将问题划分为多个规模较小、结构与原问题类似的子问题。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：递归地解决这些子问题，当子问题的规模足够小或问题简单时，可以直接求解。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;合并&lt;/strong&gt;：将子问题的解合并成原问题的解。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;减治算法&lt;/strong&gt;： 减治算法是分治算法的一种特殊形式，它也将问题分解成多个子问题，但在减治算法中，通常没有合并步骤。每次递归都是通过缩小问题规模来直接逼近解决方案，典型的例子是 &lt;strong&gt;归纳法&lt;/strong&gt; 和 &lt;strong&gt;动态规划&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id="二分法"&gt;&lt;a href="#%e4%ba%8c%e5%88%86%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;二分法
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;什么是二分法&lt;/strong&gt;： 二分法是一种通过将问题的解空间不断对半分割，逐步缩小搜索范围的算法。通常用来解决有序数据的查找问题。二分法的典型例子是 &lt;strong&gt;二分查找&lt;/strong&gt;，其基本思想是通过比较目标值和中间元素来决定查找区间，逐步缩小查找范围。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;二分法变异&lt;/strong&gt;： 二分法变异是对传统二分法的扩展或修改，常见的变异包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;变异1&lt;/strong&gt;：处理不完全有序的情况（例如，寻找最左或最右的目标元素）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;变异2&lt;/strong&gt;：用于解决更复杂的决策问题，比如 &lt;strong&gt;最小最大值问题&lt;/strong&gt; 或 &lt;strong&gt;区间问题&lt;/strong&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;为什么需要变异二分法&lt;/strong&gt;： 传统二分法只适用于简单的查找问题，但在实际应用中，经常遇到更复杂的情况，如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;查找某个值的最左或最右位置。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;求解某个条件成立的最小/最大值。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;寻找某个阈值条件下的解空间。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些问题需要对标准二分法进行适当变异，以适应更复杂的需求。&lt;/p&gt;
&lt;h3 id="重要例题"&gt;&lt;a href="#%e9%87%8d%e8%a6%81%e4%be%8b%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;重要例题
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;金块问题&lt;/strong&gt;：&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：给定一个二维矩阵，其中每个位置都有金块，如何找到从左上角到右下角的最大金块数？你可以在矩阵中上下左右移动。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;引出结论&lt;/strong&gt;：通过分治，将问题分解成子问题，利用动态规划的思想来求解最大值。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;残缺棋盘问题&lt;/strong&gt;：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：给定一个 &lt;code&gt;2^n x 2^n&lt;/code&gt; 的棋盘，其中一个小方块被去除，如何将其余部分覆盖上 L 型小块？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;引出结论&lt;/strong&gt;：这是一道典型的分治问题，通过递归分割棋盘并覆盖，可以有效地解决。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;循环赛日程表&lt;/strong&gt;：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：有 &lt;code&gt;n&lt;/code&gt; 个队伍，如何安排一个循环赛程，使得每个队伍与其他队伍比赛一次？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;引出结论&lt;/strong&gt;：通过分治，将问题划分为较小的子问题，求解比赛安排。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;最大子段和问题&lt;/strong&gt;：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：给定一个整数数组，求出其中和最大的连续子数组。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;引出结论&lt;/strong&gt;：这道题目可以通过分治的方式进行求解，分解成较小的子问题，最终合并求得最大子段和。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="重要算法"&gt;&lt;a href="#%e9%87%8d%e8%a6%81%e7%ae%97%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;重要算法
&lt;/h3&gt;&lt;h4 id="冒泡排序"&gt;&lt;a href="#%e5%86%92%e6%b3%a1%e6%8e%92%e5%ba%8f" class="header-anchor"&gt;&lt;/a&gt;&lt;strong&gt;冒泡排序&lt;/strong&gt;
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;时间复杂度&lt;/strong&gt;：&lt;code&gt;O(n^2)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;空间复杂度&lt;/strong&gt;：&lt;code&gt;O(1)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：通过多次遍历，将最大（或最小）元素“冒泡”到数组的一端。适合小规模数据。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;bubble_sort&lt;/span&gt;(arr):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; n &lt;span style="color:#f92672"&gt;=&lt;/span&gt; len(arr)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; j &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, n&lt;span style="color:#f92672"&gt;-&lt;/span&gt;i&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; arr[j] &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; arr[j&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; arr[j], arr[j&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; arr[j&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;], arr[j]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; arr
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 示例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;arr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;90&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(&lt;span style="color:#e6db74"&gt;&amp;#34;冒泡排序结果:&amp;#34;&lt;/span&gt;, bubble_sort(arr))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="插入排序"&gt;&lt;a href="#%e6%8f%92%e5%85%a5%e6%8e%92%e5%ba%8f" class="header-anchor"&gt;&lt;/a&gt;&lt;strong&gt;插入排序&lt;/strong&gt;
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;时间复杂度&lt;/strong&gt;：&lt;code&gt;O(n^2)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;空间复杂度&lt;/strong&gt;：&lt;code&gt;O(1)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：通过从未排序的部分插入元素到已排序部分，逐步扩大已排序部分。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;insertion_sort&lt;/span&gt;(arr):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, len(arr)):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; key &lt;span style="color:#f92672"&gt;=&lt;/span&gt; arr[i]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; j &lt;span style="color:#f92672"&gt;=&lt;/span&gt; i &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; j &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;and&lt;/span&gt; arr[j] &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; key:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; arr[j &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; arr[j]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; j &lt;span style="color:#f92672"&gt;-=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; arr[j &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; key
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; arr
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 示例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;arr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;90&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(&lt;span style="color:#e6db74"&gt;&amp;#34;插入排序结果:&amp;#34;&lt;/span&gt;, insertion_sort(arr))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="快速排序"&gt;&lt;a href="#%e5%bf%ab%e9%80%9f%e6%8e%92%e5%ba%8f" class="header-anchor"&gt;&lt;/a&gt;&lt;strong&gt;快速排序&lt;/strong&gt;
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;时间复杂度&lt;/strong&gt;：&lt;code&gt;O(n log n)&lt;/code&gt;（平均），&lt;code&gt;O(n^2)&lt;/code&gt;（最坏）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;空间复杂度&lt;/strong&gt;：&lt;code&gt;O(log n)&lt;/code&gt;（平均）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：通过选择一个基准元素，将数组分为两个部分，递归地对每个部分进行排序。效率较高。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;quick_sort&lt;/span&gt;(arr):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; len(arr) pivot]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; quick_sort(left) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; middle &lt;span style="color:#f92672"&gt;+&lt;/span&gt; quick_sort(right)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 示例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;arr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;90&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(&lt;span style="color:#e6db74"&gt;&amp;#34;快速排序结果:&amp;#34;&lt;/span&gt;, quick_sort(arr))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="归并排序"&gt;&lt;a href="#%e5%bd%92%e5%b9%b6%e6%8e%92%e5%ba%8f" class="header-anchor"&gt;&lt;/a&gt;&lt;strong&gt;归并排序&lt;/strong&gt;
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;时间复杂度&lt;/strong&gt;：&lt;code&gt;O(n log n)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;空间复杂度&lt;/strong&gt;：&lt;code&gt;O(n)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：通过递归地将数组分成两个子数组，然后合并排序。稳定且适用于大规模数据。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;merge_sort&lt;/span&gt;(arr):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; len(arr) &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mid &lt;span style="color:#f92672"&gt;=&lt;/span&gt; len(arr) &lt;span style="color:#f92672"&gt;//&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; left_half &lt;span style="color:#f92672"&gt;=&lt;/span&gt; arr[:mid]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; right_half &lt;span style="color:#f92672"&gt;=&lt;/span&gt; arr[mid:]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; merge_sort(left_half)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; merge_sort(right_half)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; i &lt;span style="color:#f92672"&gt;=&lt;/span&gt; j &lt;span style="color:#f92672"&gt;=&lt;/span&gt; k &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; i &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; len(left_half) &lt;span style="color:#f92672"&gt;and&lt;/span&gt; j &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; len(right_half):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; left_half[i] &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; right_half[j]:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; arr[k] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; left_half[i]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; i &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; arr[k] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; right_half[j]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; j &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; k &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; i &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; len(left_half):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; arr[k] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; left_half[i]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; i &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; k &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; j &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; len(right_half):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; arr[k] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; right_half[j]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; j &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; k &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; arr
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 示例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;arr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;90&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(&lt;span style="color:#e6db74"&gt;&amp;#34;归并排序结果:&amp;#34;&lt;/span&gt;, merge_sort(arr))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>spring-demo</title><link>https://dandansad.com/2025/04/11/spring-demo/</link><pubDate>Fri, 11 Apr 2025 00:46:25 +0800</pubDate><guid>https://dandansad.com/2025/04/11/spring-demo/</guid><description>&lt;p&gt;一个Spring的AOP练习程序。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;&lt;span style="color:#f92672"&gt;---&lt;/span&gt;springdemo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; SpringDemoApplication.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├─&lt;/span&gt;aop
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; MyAspect.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├─&lt;/span&gt;controller
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; Test.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;└─&lt;/span&gt;service
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Another.java
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;对于Spring来说，其AOP的实现十分简单。只需要在导入相关依赖之后在注解类上使用@Aspect和@Component注解，然后使用@Pointcut定义切点，在相关方法上用你需要的AOP通知类型注解即可。&lt;/p&gt;</description></item><item><title>RMI-Exercise</title><link>https://dandansad.com/2025/04/11/rmi-exercise/</link><pubDate>Fri, 11 Apr 2025 00:37:35 +0800</pubDate><guid>https://dandansad.com/2025/04/11/rmi-exercise/</guid><description>&lt;p&gt;&lt;strong&gt;Java RMI&lt;/strong&gt;，即 &lt;strong&gt;远程方法调用&lt;/strong&gt;（Remote Method Invocation），它的实现依赖于Java虚拟机(JVM)，RMI允许在一个Java虚拟机中运行的对象调用在另一个Java虚拟机中运行的对象上的方法。RMI是Java的一组拥护开发分布式应用程序的API，RMI使用Java语言接口定义了远程对象，它集合了Java序列化和Java远程方法协议(Java Remote Method Protocol)，RMI能直接传输序列化后的Java对象和分布式垃圾收集，因此它仅支持从一个JVM到另一个JVM的调用。RMI提供了用Java编程语言编写的程序之间的远程通信。&lt;/p&gt;
&lt;p&gt;这是一个RMI（Remote Method Invocation）远程方法调用的练习程序。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;&lt;span style="color:#f92672"&gt;--&lt;/span&gt;rmi
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RemoteService.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RMIClient.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RMIServer.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RMIService.java
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="remoteservicejava"&gt;&lt;a href="#remoteservicejava" class="header-anchor"&gt;&lt;/a&gt;RemoteService.java
&lt;/h2&gt;&lt;p&gt;一个远程接口文件，它定义了可以被远程调用的方法。&lt;/p&gt;
&lt;h2 id="rmiservicejava"&gt;&lt;a href="#rmiservicejava" class="header-anchor"&gt;&lt;/a&gt;RMIService.java
&lt;/h2&gt;&lt;p&gt;远程服务的实现类。继承了UnicastRemoteObject类，这是RMI中实现远程对象的基类。实现了RemoteService接口，提供了run()方法的具体实现&lt;/p&gt;
&lt;h2 id="rmiclientjava"&gt;&lt;a href="#rmiclientjava" class="header-anchor"&gt;&lt;/a&gt;RMIClient.java
&lt;/h2&gt;&lt;p&gt;RMI客户端程序。定义了与服务器相同的注册表端口(9999)、主机(localhost)和服务URL。在main方法中使用Naming.lookup查找远程服务对象，将返回的对象强制转换为RemoteService接口类型，然后调用远程服务的run()方法。&lt;/p&gt;
&lt;h2 id="rmiserverjava"&gt;&lt;a href="#rmiserverjava" class="header-anchor"&gt;&lt;/a&gt;RMIServer.java
&lt;/h2&gt;&lt;p&gt;RMI服务器程序。定义了RMI注册表端口(9999)、主机(localhost)和服务URL。在main方法中创建RMIService实例作为远程服务实现，然后使用LocateRegistry.createRegistry创建RMI注册表，并使用Naming.rebind将远程服务绑定到命名服务。&lt;/p&gt;
&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;p&gt;RMI的实现较为简单便捷，只需要在服务端创建实例、创建注册表、绑定远程服务到命名服务即可。在客户端使用Naming.lookup查找远程服务对象，将返回的对象强制转换为RemoteService接口类型即可直接调用。&lt;/p&gt;
&lt;p&gt;RMI本质上只传输方法调用的参数和返回值。当你在远程对象的方法中执行&lt;code&gt;System.out.println()&lt;/code&gt;时，这些输出会打印在&lt;strong&gt;远程JVM的终端/日志&lt;/strong&gt;中，而不是调用方的控制台。这是因为&lt;code&gt;System.out&lt;/code&gt;是本地进程的标准输出流，与RMI调用无关。&lt;/p&gt;</description></item><item><title>AOP-Exercise</title><link>https://dandansad.com/2025/04/10/aop-exercise/</link><pubDate>Thu, 10 Apr 2025 22:19:28 +0800</pubDate><guid>https://dandansad.com/2025/04/10/aop-exercise/</guid><description>&lt;p&gt;一个面向切面编程的练习程序。其中面向切面编程采用的是配置文件的做法，支持多个前置方法和后置方法，按照配置文件中的优先级区分执行顺序。食物类通过注解获取食物名称和价格。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;&lt;span style="color:#f92672"&gt;--&lt;/span&gt;aop
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; FoodInfo.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; Kitchen.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; MyAspect.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; Proxyhandler.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; Restaurant.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; RestaurantInterface.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; TestRestaurant.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;└─&lt;/span&gt;foods
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Beef.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Broccoli.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Chicken.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Food.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Newfood.java
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="foods包下的类"&gt;&lt;a href="#foods%e5%8c%85%e4%b8%8b%e7%9a%84%e7%b1%bb" class="header-anchor"&gt;&lt;/a&gt;foods包下的类
&lt;/h2&gt;&lt;p&gt;食物类，其中食物名称和价格用注解标注。&lt;/p&gt;
&lt;h2 id="foodinfojava"&gt;&lt;a href="#foodinfojava" class="header-anchor"&gt;&lt;/a&gt;FoodInfo.java
&lt;/h2&gt;&lt;p&gt;注解，食物名称和价格。&lt;/p&gt;
&lt;h2 id="kitchenjava"&gt;&lt;a href="#kitchenjava" class="header-anchor"&gt;&lt;/a&gt;Kitchen.java
&lt;/h2&gt;&lt;p&gt;工厂类，主要负责根据名称创建食物实例、获取食物价格。&lt;/p&gt;
&lt;h2 id="myaspectjava"&gt;&lt;a href="#myaspectjava" class="header-anchor"&gt;&lt;/a&gt;MyAspect.java
&lt;/h2&gt;&lt;p&gt;切面方法。&lt;/p&gt;
&lt;h2 id="proxyhandlerjava"&gt;&lt;a href="#proxyhandlerjava" class="header-anchor"&gt;&lt;/a&gt;Proxyhandler.java
&lt;/h2&gt;&lt;p&gt;调用处理器类，在其中实现面向切面编程，在需要切入的方法前后分别按照优先级执行前置方法和后置方法。&lt;/p&gt;
&lt;h2 id="restaurantjava"&gt;&lt;a href="#restaurantjava" class="header-anchor"&gt;&lt;/a&gt;Restaurant.java
&lt;/h2&gt;&lt;p&gt;RestaurantInterface的实现类，实现餐厅的方法。&lt;/p&gt;
&lt;h2 id="restaurantinterfacejava"&gt;&lt;a href="#restaurantinterfacejava" class="header-anchor"&gt;&lt;/a&gt;RestaurantInterface.java
&lt;/h2&gt;&lt;p&gt;接口，定义餐厅的方法。&lt;/p&gt;
&lt;h2 id="testrestaurantjava"&gt;&lt;a href="#testrestaurantjava" class="header-anchor"&gt;&lt;/a&gt;TestRestaurant.java
&lt;/h2&gt;&lt;p&gt;主类，完成点餐功能。在开始时读入并加载配置文件，创建动态代理对象，之后执行正常的点餐流程，当用户点餐时调用Kitchen创建食物类，下单并享用食物。&lt;/p&gt;
&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;p&gt;这个程序主要使用动态代理实现了AOP，从配置文件中读取前置方法和后置方法。&lt;/p&gt;</description></item><item><title>RPC-Exercise</title><link>https://dandansad.com/2025/04/10/rpc-exercise/</link><pubDate>Thu, 10 Apr 2025 20:24:07 +0800</pubDate><guid>https://dandansad.com/2025/04/10/rpc-exercise/</guid><description>&lt;p&gt;一个RPC（Remote Procedure Call）远程过程调用的练习程序。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;&lt;span style="color:#f92672"&gt;---&lt;/span&gt;client
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Client.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Connector.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; DynamicProxyFactory.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RemoteCall.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RPCService.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RPCServiceImpl.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Server.java
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="remotecalljava"&gt;&lt;a href="#remotecalljava" class="header-anchor"&gt;&lt;/a&gt;RemoteCall.java
&lt;/h2&gt;&lt;p&gt;是一个用于传输的对象。它是RPC（远程过程调用）系统中非常关键的一个组件，负责封装远程方法调用的所有必要信息。&lt;/p&gt;
&lt;h2 id="rpcservicejava"&gt;&lt;a href="#rpcservicejava" class="header-anchor"&gt;&lt;/a&gt;RPCService.java
&lt;/h2&gt;&lt;p&gt;一个接口，定义request方法。&lt;/p&gt;
&lt;h2 id="rpcserviceimpljava"&gt;&lt;a href="#rpcserviceimpljava" class="header-anchor"&gt;&lt;/a&gt;RPCServiceImpl.java
&lt;/h2&gt;&lt;p&gt;RPCService的实现类，实现request方法。&lt;/p&gt;
&lt;h2 id="clientjava"&gt;&lt;a href="#clientjava" class="header-anchor"&gt;&lt;/a&gt;Client.java
&lt;/h2&gt;&lt;p&gt;客户端，调用DynamicProxyFactory.getProxy返回动态代理对象，从而进行远程调用。&lt;/p&gt;
&lt;h2 id="connectorjava"&gt;&lt;a href="#connectorjava" class="header-anchor"&gt;&lt;/a&gt;Connector.java
&lt;/h2&gt;&lt;p&gt;协助客户端与服务器之间通信的通信工具类，主要包括建立网络连接、数据传输、连接管理。&lt;/p&gt;
&lt;h2 id="dynamicproxyfactoryjava"&gt;&lt;a href="#dynamicproxyfactoryjava" class="header-anchor"&gt;&lt;/a&gt;DynamicProxyFactory.java
&lt;/h2&gt;&lt;p&gt;用于创建客户端的动态代理对象。主要功能就是隐藏了网络通信细节，将方法调用转换为网络请求。返回进行远程调用的动态代理。&lt;/p&gt;
&lt;h2 id="serverjava"&gt;&lt;a href="#serverjava" class="header-anchor"&gt;&lt;/a&gt;Server.java
&lt;/h2&gt;&lt;p&gt;服务端，用于接收客户端请求、执行本地服务实现的方法并返回结果。首先监听指定端口，然后注册服务，再启动服务。在服务运行的过程中不断接到连接请求，接到连接请求后便开启新线程处理请求。&lt;/p&gt;
&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;p&gt;实现远程过程调用主要就是使用动态代理对象，让其看起来像切切实实的本地方法，但实际是隐藏了网络通信细节，将方法调用转换为网络请求，从而获取到远程调用的结果。服务端只需要不断地监听端口，处理请求并返回RemoteCall对象即可。&lt;/p&gt;</description></item><item><title>Proxy-Exercise</title><link>https://dandansad.com/2025/04/10/proxy-exercise/</link><pubDate>Thu, 10 Apr 2025 10:33:01 +0800</pubDate><guid>https://dandansad.com/2025/04/10/proxy-exercise/</guid><description>&lt;p&gt;在代理模式中，我们使用代理对象来代替对真实对象(real object)的访问，这样就可以在不修改原目标对象的前提下，提供额外的功能操作，扩展目标对象的功能。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;&lt;span style="color:#f92672"&gt;---&lt;/span&gt;demo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; DynamicProxyDemo.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; OneService.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Service.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; StaticProxyDemo.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TwoService.java
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="servicejava"&gt;&lt;a href="#servicejava" class="header-anchor"&gt;&lt;/a&gt;Service.java
&lt;/h2&gt;&lt;p&gt;接口，提供perform()方法。&lt;/p&gt;
&lt;h2 id="oneservicejava"&gt;&lt;a href="#oneservicejava" class="header-anchor"&gt;&lt;/a&gt;OneService.java
&lt;/h2&gt;&lt;p&gt;实现类，实现perform()方法。&lt;/p&gt;
&lt;h2 id="twoservicejava"&gt;&lt;a href="#twoservicejava" class="header-anchor"&gt;&lt;/a&gt;TwoService.java
&lt;/h2&gt;&lt;p&gt;实现类，实现perform()方法。&lt;/p&gt;
&lt;h2 id="staticproxydemojava静态代理"&gt;&lt;a href="#staticproxydemojava%e9%9d%99%e6%80%81%e4%bb%a3%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;StaticProxyDemo.java（静态代理）
&lt;/h2&gt;&lt;p&gt;静态代理，里面有一个ServiceProxy类，在该类中也重写了perform()方法。在perform()方法中，调用了真实对象的perform()方法，同时新增了一些操作。&lt;/p&gt;
&lt;p&gt;但是静态代理有个缺点：一个真实对象要对应一个静态代理对象，代码编写十分繁琐。&lt;/p&gt;
&lt;h2 id="dynamicproxydemojava动态代理"&gt;&lt;a href="#dynamicproxydemojava%e5%8a%a8%e6%80%81%e4%bb%a3%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;DynamicProxyDemo.java（动态代理）
&lt;/h2&gt;&lt;p&gt;动态代理，创建实现InvocationHandler接口的类，再通过Proxy.newProxyInstance方法创建代理对象，之后便可以通过代理对象调用perform方法。&lt;/p&gt;
&lt;h2 id="区别"&gt;&lt;a href="#%e5%8c%ba%e5%88%ab" class="header-anchor"&gt;&lt;/a&gt;区别
&lt;/h2&gt;&lt;p&gt;静态代理需要为每个接口创建代理类，并为每个方法编写代理逻辑，这会导致大量的重复代码。在实际开发中，当涉及到多个类和方法需要类似的代理逻辑时，通过动态代理来实现通常是更好的选择。动态代理通过创建调用处理器（InvocationHandler）、创建代理实例（Proxy.newProxyInstance），然后便可以直接调用代理方法。&lt;/p&gt;</description></item><item><title>算法设计与分析：要点总结-1</title><link>https://dandansad.com/2025/03/31/%E7%AE%97%E6%B3%95%E8%AE%BE%E8%AE%A1%E4%B8%8E%E5%88%86%E6%9E%90%E8%A6%81%E7%82%B9%E6%80%BB%E7%BB%93-1/</link><pubDate>Mon, 31 Mar 2025 01:48:48 +0800</pubDate><guid>https://dandansad.com/2025/03/31/%E7%AE%97%E6%B3%95%E8%AE%BE%E8%AE%A1%E4%B8%8E%E5%88%86%E6%9E%90%E8%A6%81%E7%82%B9%E6%80%BB%E7%BB%93-1/</guid><description>&lt;h2 id="算法概述"&gt;&lt;a href="#%e7%ae%97%e6%b3%95%e6%a6%82%e8%bf%b0" class="header-anchor"&gt;&lt;/a&gt;算法概述
&lt;/h2&gt;&lt;h3 id="算法的5大特性"&gt;&lt;a href="#%e7%ae%97%e6%b3%95%e7%9a%845%e5%a4%a7%e7%89%b9%e6%80%a7" class="header-anchor"&gt;&lt;/a&gt;算法的5大特性
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;确定性:算法的每一步骤必须有明确的定义，无二义性。即在相同输入下，每次执行都应得到相同的结果。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;能行性:算法的每一步都必须是可实现的，即在有限时间内能用有限资源完成。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;输入：算法可以有零个或多个输入，输入是算法处理的初始数据。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;输出：算法必须有一个或多个输出，输出是算法处理的结果。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;有穷性/有限性：算法必须在执行有限步骤后终止，不能无限循环。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="算法与计算过程的区别"&gt;&lt;a href="#%e7%ae%97%e6%b3%95%e4%b8%8e%e8%ae%a1%e7%ae%97%e8%bf%87%e7%a8%8b%e7%9a%84%e5%8c%ba%e5%88%ab" class="header-anchor"&gt;&lt;/a&gt;算法与计算过程的区别
&lt;/h3&gt;&lt;p&gt;计算过程可能无限执行（如操作系统），而算法必须是有穷的。&lt;/p&gt;
&lt;h3 id="算法描述的主要语言"&gt;&lt;a href="#%e7%ae%97%e6%b3%95%e6%8f%8f%e8%bf%b0%e7%9a%84%e4%b8%bb%e8%a6%81%e8%af%ad%e8%a8%80" class="header-anchor"&gt;&lt;/a&gt;算法描述的主要语言
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;自然语言：直观但容易歧义。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;伪代码：介于自然语言和编程语言之间，结构清晰，无语法限制。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;流程图：图形化表示，直观展示控制流。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;编程语言：直接实现，但需关注语法细节。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="渐进表示"&gt;&lt;a href="#%e6%b8%90%e8%bf%9b%e8%a1%a8%e7%a4%ba" class="header-anchor"&gt;&lt;/a&gt;渐进表示
&lt;/h3&gt;&lt;h4 id="定义"&gt;&lt;a href="#%e5%ae%9a%e4%b9%89" class="header-anchor"&gt;&lt;/a&gt;定义
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;O（大O符号，上界）&lt;/strong&gt;：
f(n)=O(g(n)) 表示存在常数 c&amp;gt;0 和 &lt;em&gt;n&lt;/em&gt;0​，使得对所有 &lt;em&gt;n&lt;/em&gt;≥&lt;em&gt;n&lt;/em&gt;0​，有 &lt;em&gt;f&lt;/em&gt;(&lt;em&gt;n&lt;/em&gt;)≤&lt;em&gt;c&lt;/em&gt;⋅&lt;em&gt;g&lt;/em&gt;(&lt;em&gt;n&lt;/em&gt;)。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;表示算法的最坏情况时间复杂度。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ω（Omega，下界）&lt;/strong&gt;：
f(n)=Ω(g(n)) 表示存在常数 c&amp;gt;0 和 &lt;em&gt;n&lt;/em&gt;0​，使得对所有 &lt;em&gt;n&lt;/em&gt;≥&lt;em&gt;n&lt;/em&gt;0​，有 &lt;em&gt;f&lt;/em&gt;(&lt;em&gt;n&lt;/em&gt;)≥&lt;em&gt;c&lt;/em&gt;⋅&lt;em&gt;g&lt;/em&gt;(&lt;em&gt;n&lt;/em&gt;)。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;表示算法的最好情况时间复杂度。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Θ（Theta，紧确界）&lt;/strong&gt;：
f(n)=Θ(g(n)) 当且仅当 f(n)=O(g(n)) 且 f(n)=Ω(g(n))。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;表示算法的平均情况时间复杂度。&lt;/p&gt;
&lt;h4 id="多项式定理"&gt;&lt;a href="#%e5%a4%9a%e9%a1%b9%e5%bc%8f%e5%ae%9a%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;多项式定理
&lt;/h4&gt;&lt;p&gt;若 f(n) 是 d 次多项式，则 &lt;em&gt;f&lt;/em&gt;(&lt;em&gt;n&lt;/em&gt;)=Θ(&lt;em&gt;n**d&lt;/em&gt;)。&lt;/p&gt;
&lt;h4 id="常见的多项式指数限界函数"&gt;&lt;a href="#%e5%b8%b8%e8%a7%81%e7%9a%84%e5%a4%9a%e9%a1%b9%e5%bc%8f%e6%8c%87%e6%95%b0%e9%99%90%e7%95%8c%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;常见的多项式/指数限界函数
&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;O(1) &amp;lt; O(logn) &amp;lt; O(n) &amp;lt; O(nlogn) &amp;lt; O(n2) &amp;lt; O(n3) &amp;lt; O(2n) &amp;lt; O(n!) &amp;lt; O(nn)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/03/image-12-1024x682.png"&gt;&lt;/p&gt;
&lt;h3 id="渐进符号o运算性质"&gt;&lt;a href="#%e6%b8%90%e8%bf%9b%e7%ac%a6%e5%8f%b7o%e8%bf%90%e7%ae%97%e6%80%a7%e8%b4%a8" class="header-anchor"&gt;&lt;/a&gt;渐进符号O运算性质
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;传递性：若 f(n)=O(g(n)) 且 g(n)=O(h(n))，则 f(n)=O(h(n))。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;加法规则：O(f(n))+O(g(n))=O(max⁡(f(n),g(n)))。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;乘法规则：O(f(n))⋅O(g(n))=O(f(n)⋅g(n))。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="重要例题"&gt;&lt;a href="#%e9%87%8d%e8%a6%81%e4%be%8b%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;重要例题
&lt;/h3&gt;&lt;h4 id="冒泡排序"&gt;&lt;a href="#%e5%86%92%e6%b3%a1%e6%8e%92%e5%ba%8f" class="header-anchor"&gt;&lt;/a&gt;冒泡排序
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;bubble_sort&lt;/span&gt;(arr):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; n &lt;span style="color:#f92672"&gt;=&lt;/span&gt; len(arr)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; j &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, n&lt;span style="color:#f92672"&gt;-&lt;/span&gt;i&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; arr[j] &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; arr[j&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; arr[j], arr[j&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; arr[j&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;], arr[j]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; arr
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 示例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(bubble_sort([&lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;90&lt;/span&gt;])) &lt;span style="color:#75715e"&gt;# 输出: [11, 12, 22, 25, 34, 64, 90]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="警察抓小偷"&gt;&lt;a href="#%e8%ad%a6%e5%af%9f%e6%8a%93%e5%b0%8f%e5%81%b7" class="header-anchor"&gt;&lt;/a&gt;警察抓小偷
&lt;/h4&gt;&lt;p&gt;信息数字化。&lt;/p&gt;
&lt;h4 id="竞赛预测"&gt;&lt;a href="#%e7%ab%9e%e8%b5%9b%e9%a2%84%e6%b5%8b" class="header-anchor"&gt;&lt;/a&gt;竞赛预测
&lt;/h4&gt;&lt;p&gt;信息数字化。将逻辑问题转化为代码，遍历求解。&lt;/p&gt;
&lt;h4 id="楼梯台阶问题"&gt;&lt;a href="#%e6%a5%bc%e6%a2%af%e5%8f%b0%e9%98%b6%e9%97%ae%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;楼梯台阶问题
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;climb_stairs&lt;/span&gt;(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; n 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#f92672"&gt;**&lt;/span&gt;基准情形&lt;span style="color:#f92672"&gt;**&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;：&lt;/span&gt;明确递归终止条件&lt;span style="color:#960050;background-color:#1e0010"&gt;（&lt;/span&gt;如 n&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 或 n&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;）。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#f92672"&gt;**&lt;/span&gt;递归调用&lt;span style="color:#f92672"&gt;**&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;：&lt;/span&gt;将问题分解为更小的同类子问题&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#f92672"&gt;**&lt;/span&gt;正确性证明&lt;span style="color:#f92672"&gt;**&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;：&lt;/span&gt;通常用数学归纳法验证&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### 循环与递归的比较&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; 比较维度 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 循环&lt;span style="color:#960050;background-color:#1e0010"&gt;（&lt;/span&gt;迭代&lt;span style="color:#960050;background-color:#1e0010"&gt;）&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 递归 &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;---&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;---&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;---&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; 程序可读性 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 通常更直观&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;适合线性逻辑&lt;span style="color:#960050;background-color:#1e0010"&gt;（&lt;/span&gt;如遍历数组&lt;span style="color:#960050;background-color:#1e0010"&gt;）。&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 更符合数学思维&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;适合分治&lt;span style="color:#960050;background-color:#1e0010"&gt;、&lt;/span&gt;树&lt;span style="color:#f92672"&gt;/&lt;/span&gt;图遍历等问题&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;但嵌套过深时难理解&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; 代码量 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 通常较短&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;尤其是简单循环&lt;span style="color:#960050;background-color:#1e0010"&gt;（&lt;/span&gt;如 &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;、&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;）。&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 可能更简洁&lt;span style="color:#960050;background-color:#1e0010"&gt;（&lt;/span&gt;如阶乘&lt;span style="color:#960050;background-color:#1e0010"&gt;、&lt;/span&gt;斐波那契数列&lt;span style="color:#960050;background-color:#1e0010"&gt;），&lt;/span&gt;但需要额外递归终止条件&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; 时间效率 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 无函数调用开销&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;执行更快&lt;span style="color:#960050;background-color:#1e0010"&gt;（&lt;/span&gt;适合大规模数据&lt;span style="color:#960050;background-color:#1e0010"&gt;）。&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 每次递归调用需保存栈帧&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;函数调用开销大&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;可能更慢&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; 占用空间 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 仅需固定内存&lt;span style="color:#960050;background-color:#1e0010"&gt;（&lt;/span&gt;如几个变量&lt;span style="color:#960050;background-color:#1e0010"&gt;），&lt;/span&gt;空间复杂度通常为 O(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 需保存每一层调用的栈帧&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;空间复杂度取决于递归深度&lt;span style="color:#960050;background-color:#1e0010"&gt;（&lt;/span&gt;如 O(n) 或 O(log&lt;span style="color:#960050;background-color:#1e0010"&gt;⁡&lt;/span&gt;n)&lt;span style="color:#960050;background-color:#1e0010"&gt;），&lt;/span&gt;可能栈溢出&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; 适用范围 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 所有可迭代问题&lt;span style="color:#960050;background-color:#1e0010"&gt;（&lt;/span&gt;如数组遍历&lt;span style="color:#960050;background-color:#1e0010"&gt;、&lt;/span&gt;数值计算&lt;span style="color:#960050;background-color:#1e0010"&gt;）。&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 适合分治&lt;span style="color:#960050;background-color:#1e0010"&gt;（&lt;/span&gt;如归并排序&lt;span style="color:#960050;background-color:#1e0010"&gt;）、&lt;/span&gt;回溯&lt;span style="color:#960050;background-color:#1e0010"&gt;（&lt;/span&gt;如八皇后&lt;span style="color:#960050;background-color:#1e0010"&gt;）、&lt;/span&gt;树&lt;span style="color:#f92672"&gt;/&lt;/span&gt;图遍历&lt;span style="color:#960050;background-color:#1e0010"&gt;（&lt;/span&gt;如DFS&lt;span style="color:#960050;background-color:#1e0010"&gt;）&lt;/span&gt;等递归定义的问题&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; 设计难度 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 较直观&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;适合顺序逻辑&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 需找到子问题分解方式&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;设计递归终止条件&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;对思维抽象能力要求更高&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 一般的&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;理论上&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;循环&lt;span style="color:#960050;background-color:#1e0010"&gt;（&lt;/span&gt;迭代&lt;span style="color:#960050;background-color:#1e0010"&gt;）&lt;/span&gt;都可以改写成递归&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;反之不然&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### 常用数据结构的比较&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#f92672"&gt;**&lt;/span&gt;数组&lt;span style="color:#f92672"&gt;**&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;：&lt;/span&gt;随机访问快&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;插入&lt;span style="color:#f92672"&gt;/&lt;/span&gt;删除慢&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#f92672"&gt;**&lt;/span&gt;链表&lt;span style="color:#f92672"&gt;**&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;：&lt;/span&gt;插入&lt;span style="color:#f92672"&gt;/&lt;/span&gt;删除快&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;访问需遍历&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#f92672"&gt;**&lt;/span&gt;栈&lt;span style="color:#f92672"&gt;/&lt;/span&gt;队列&lt;span style="color:#f92672"&gt;**&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;：&lt;/span&gt;特定顺序操作&lt;span style="color:#960050;background-color:#1e0010"&gt;（&lt;/span&gt;LIFO&lt;span style="color:#f92672"&gt;/&lt;/span&gt;FIFO&lt;span style="color:#960050;background-color:#1e0010"&gt;）。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#f92672"&gt;**&lt;/span&gt;哈希表&lt;span style="color:#f92672"&gt;**&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;：&lt;/span&gt;快速查找&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;但需处理冲突&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### 重要例题&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#### 欧几里得算法&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;```&lt;/span&gt;python
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;gcd&lt;/span&gt;(a, b):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; b:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; a, b &lt;span style="color:#f92672"&gt;=&lt;/span&gt; b, a &lt;span style="color:#f92672"&gt;%&lt;/span&gt; b
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; a
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 示例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(gcd(&lt;span style="color:#ae81ff"&gt;48&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;# 输出: 6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="hanoi塔"&gt;&lt;a href="#hanoi%e5%a1%94" class="header-anchor"&gt;&lt;/a&gt;Hanoi塔
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;hanoi&lt;/span&gt;(n, source, target, auxiliary):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 汉诺塔递归解法
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param n: 盘子数量
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param source: 起始柱子（如 &amp;#39;A&amp;#39;）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param target: 目标柱子（如 &amp;#39;C&amp;#39;）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param auxiliary: 辅助柱子（如 &amp;#39;B&amp;#39;）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; n &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 基准情形：只有一个盘子时，直接移动到目标柱子&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Move disk 1 from &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;source&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; to &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;target&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 递归步骤：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 1. 将前 n-1 个盘子从 source 移到 auxiliary（借助 target）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; hanoi(n&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, source, auxiliary, target)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 2. 将第 n 个盘子（最大的）从 source 移到 target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Move disk &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;n&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; from &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;source&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; to &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;target&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 3. 将前 n-1 个盘子从 auxiliary 移到 target（借助 source）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; hanoi(n&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, auxiliary, target, source)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 示例：移动 3 个盘子从 A 到 C，借助 B&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hanoi(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;C&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;B&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="整数的划分"&gt;&lt;a href="#%e6%95%b4%e6%95%b0%e7%9a%84%e5%88%92%e5%88%86" class="header-anchor"&gt;&lt;/a&gt;整数的划分
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;integer_partition&lt;/span&gt;(n, m):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 计算将整数 n 划分为最大部分不超过 m 的划分数。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param n: 待划分的整数。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param m: 划分中允许的最大部分。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; n &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 空划分算一种&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; m &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 只能划分为 1+1+...+1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; n 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#f92672"&gt;**&lt;/span&gt;初始化&lt;span style="color:#f92672"&gt;**&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;：&lt;/span&gt;设定初始状态&lt;span style="color:#960050;background-color:#1e0010"&gt;（&lt;/span&gt;如变量初值&lt;span style="color:#960050;background-color:#1e0010"&gt;）。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#f92672"&gt;**&lt;/span&gt;迭代过程&lt;span style="color:#f92672"&gt;**&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;：&lt;/span&gt;通过循环逐步更新状态&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#f92672"&gt;**&lt;/span&gt;终止条件&lt;span style="color:#f92672"&gt;**&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;：&lt;/span&gt;达到目标时退出循环&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### 递推法vs倒推法&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#f92672"&gt;**&lt;/span&gt;递推法&lt;span style="color:#f92672"&gt;**&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;：&lt;/span&gt;从已知条件逐步推导到目标&lt;span style="color:#960050;background-color:#1e0010"&gt;（&lt;/span&gt;如斐波那契数列&lt;span style="color:#960050;background-color:#1e0010"&gt;）。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#f92672"&gt;**&lt;/span&gt;倒推法&lt;span style="color:#f92672"&gt;**&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;：&lt;/span&gt;从目标反向推导初始条件&lt;span style="color:#960050;background-color:#1e0010"&gt;（&lt;/span&gt;如猴子吃桃问题&lt;span style="color:#960050;background-color:#1e0010"&gt;）。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### 重要例题&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#### 兔子繁衍问题&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;```&lt;/span&gt;python
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fibonacci&lt;/span&gt;(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; a, b &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; _ &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; a, b &lt;span style="color:#f92672"&gt;=&lt;/span&gt; b, a &lt;span style="color:#f92672"&gt;+&lt;/span&gt; b
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; a
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 示例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(fibonacci(&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;# 输出: 8（第6个月有8对兔子）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="猴子吃桃问题"&gt;&lt;a href="#%e7%8c%b4%e5%ad%90%e5%90%83%e6%a1%83%e9%97%ae%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;猴子吃桃问题
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;peach_count&lt;/span&gt;(days):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; peaches &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 最后一天剩1个&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; _ &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(days&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; peaches &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (peaches &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; peaches
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 示例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(peach_count(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;# 输出: 46（第1天有46个桃子）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="杨辉三角形"&gt;&lt;a href="#%e6%9d%a8%e8%be%89%e4%b8%89%e8%a7%92%e5%bd%a2" class="header-anchor"&gt;&lt;/a&gt;杨辉三角形
&lt;/h4&gt;&lt;p&gt;递推关系：C(n,k)=C(n−1,k−1)+C(n−1,k)。&lt;/p&gt;
&lt;h4 id="穿越沙漠问题重点在于如何理解其思想"&gt;&lt;a href="#%e7%a9%bf%e8%b6%8a%e6%b2%99%e6%bc%a0%e9%97%ae%e9%a2%98%e9%87%8d%e7%82%b9%e5%9c%a8%e4%ba%8e%e5%a6%82%e4%bd%95%e7%90%86%e8%a7%a3%e5%85%b6%e6%80%9d%e6%83%b3" class="header-anchor"&gt;&lt;/a&gt;穿越沙漠问题（重点在于如何理解其思想）
&lt;/h4&gt;&lt;p&gt;核心思想：分段设立补给站，逆向计算资源消耗。&lt;/p&gt;
&lt;h4 id="牛顿迭代法"&gt;&lt;a href="#%e7%89%9b%e9%a1%bf%e8%bf%ad%e4%bb%a3%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;牛顿迭代法
&lt;/h4&gt;&lt;p&gt;求方程根：xn+1=xn−f(xn)/f′(xn)​。&lt;/p&gt;
&lt;h2 id="蛮力法"&gt;&lt;a href="#%e8%9b%ae%e5%8a%9b%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;蛮力法
&lt;/h2&gt;&lt;h3 id="重要例题-1"&gt;&lt;a href="#%e9%87%8d%e8%a6%81%e4%be%8b%e9%a2%98-1" class="header-anchor"&gt;&lt;/a&gt;重要例题
&lt;/h3&gt;&lt;h4 id="百钱百鸡问题"&gt;&lt;a href="#%e7%99%be%e9%92%b1%e7%99%be%e9%b8%a1%e9%97%ae%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;百钱百鸡问题
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;hundred_chickens&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; x &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;): &lt;span style="color:#75715e"&gt;# 公鸡最多20只&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; y &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;34&lt;/span&gt;): &lt;span style="color:#75715e"&gt;# 母鸡最多33只&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; z &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; x &lt;span style="color:#f92672"&gt;-&lt;/span&gt; y
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;x &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;y &lt;span style="color:#f92672"&gt;+&lt;/span&gt; z&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;公鸡: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;x&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;, 母鸡: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;y&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;, 小鸡: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;z&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 示例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hundred_chickens() &lt;span style="color:#75715e"&gt;# 输出所有解&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="解数字迷abcab-x-a--dddddd"&gt;&lt;a href="#%e8%a7%a3%e6%95%b0%e5%ad%97%e8%bf%b7abcab-x-a--dddddd" class="header-anchor"&gt;&lt;/a&gt;解数字迷（ABCAB X A = DDDDDD）
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;solve_abcab&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; a &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; b &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; c &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; abcab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10000&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;a &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;b &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;c &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;a &lt;span style="color:#f92672"&gt;+&lt;/span&gt; b
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; d &lt;span style="color:#f92672"&gt;=&lt;/span&gt; abcab &lt;span style="color:#f92672"&gt;*&lt;/span&gt; a
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; len(str(d)) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; &lt;span style="color:#f92672"&gt;and&lt;/span&gt; len(set(str(d))) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ABCAB = &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;abcab&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;, A = &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;a&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;, D = &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;d&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 示例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;solve_abcab() &lt;span style="color:#75715e"&gt;# 输出: ABCAB = 37037, A = 3, D = 111111&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="狱吏问题蛮力-数学技巧-深入挖掘数学规律"&gt;&lt;a href="#%e7%8b%b1%e5%90%8f%e9%97%ae%e9%a2%98%e8%9b%ae%e5%8a%9b-%e6%95%b0%e5%ad%a6%e6%8a%80%e5%b7%a7-%e6%b7%b1%e5%85%a5%e6%8c%96%e6%8e%98%e6%95%b0%e5%ad%a6%e8%a7%84%e5%be%8b" class="header-anchor"&gt;&lt;/a&gt;狱吏问题（蛮力-&amp;gt;数学技巧-&amp;gt;深入挖掘数学规律）
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;prison_doors&lt;/span&gt;(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; doors &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;] &lt;span style="color:#f92672"&gt;*&lt;/span&gt; n &lt;span style="color:#75715e"&gt;# False表示门关闭&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, n&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; j &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(i&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, n, i):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; doors[j] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;not&lt;/span&gt; doors[j]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; [i&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i, door &lt;span style="color:#f92672"&gt;in&lt;/span&gt; enumerate(doors) &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; door]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 示例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(prison_doors(&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;# 输出: [1, 4, 9]（完全平方数编号的门开着）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>IOC-Exercise</title><link>https://dandansad.com/2025/03/18/ioc-exercise/</link><pubDate>Tue, 18 Mar 2025 13:31:24 +0800</pubDate><guid>https://dandansad.com/2025/03/18/ioc-exercise/</guid><description>
 &lt;blockquote&gt;
 &lt;p&gt;严格地说，这个不算IOC，详见：&lt;a class="link" href="https://dandansad.com/2025/04/10/ioc-ioc%e4%b8%8edi%ef%bc%9f/" target="_blank" rel="noopener"
 &gt;IOC? IOC与DI？&lt;/a&gt;。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;一个IOC（控制反转）和DI（依赖注入）的练习程序，实际上和&lt;a class="link" href="https://dandansad.com/2025/03/11/highway-toll-framework/" target="_blank" rel="noopener"
 &gt;Highway-Toll-Framework&lt;/a&gt;的实现基本类似。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;&lt;span style="color:#f92672"&gt;---&lt;/span&gt;IOC&lt;span style="color:#f92672"&gt;-&lt;/span&gt;Exercise
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Agent.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Person.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Vehicle.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; VehicleType.java
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="agentjava"&gt;&lt;a href="#agentjava" class="header-anchor"&gt;&lt;/a&gt;Agent.java
&lt;/h2&gt;&lt;p&gt;提供findVehicleClasses方法，扫描包中的类，返回class列表。提供getVehicle方法，创建所给名称对应的车辆类，返回相应实例。&lt;/p&gt;
&lt;h2 id="personjava"&gt;&lt;a href="#personjava" class="header-anchor"&gt;&lt;/a&gt;Person.java
&lt;/h2&gt;&lt;p&gt;这个程序的主类，在里面通过Agent类来获取所需的具体对象，在通过setVehicle方法注入到Person类中，从而调用不同类的同名方法。&lt;/p&gt;
&lt;h2 id="vehiclejava"&gt;&lt;a href="#vehiclejava" class="header-anchor"&gt;&lt;/a&gt;Vehicle.java
&lt;/h2&gt;&lt;p&gt;接口，所有车辆类实现该接口，再在车辆类上打注解便可以不侵入原有代码增加新类。&lt;/p&gt;
&lt;h2 id="vehicletypejava"&gt;&lt;a href="#vehicletypejava" class="header-anchor"&gt;&lt;/a&gt;VehicleType.java
&lt;/h2&gt;&lt;p&gt;注解类，存储了类的名称值，一个类对应多个名称。&lt;/p&gt;</description></item><item><title>E2_AES</title><link>https://dandansad.com/2025/03/18/e2_aes/</link><pubDate>Tue, 18 Mar 2025 13:09:22 +0800</pubDate><guid>https://dandansad.com/2025/03/18/e2_aes/</guid><description>&lt;h2 id="算法主要原理"&gt;&lt;a href="#%e7%ae%97%e6%b3%95%e4%b8%bb%e8%a6%81%e5%8e%9f%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;算法主要原理
&lt;/h2&gt;&lt;p&gt;算法流程如下：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/03/image-10-1024x949.png"&gt;&lt;/p&gt;
&lt;h2 id="算法步骤"&gt;&lt;a href="#%e7%ae%97%e6%b3%95%e6%ad%a5%e9%aa%a4" class="header-anchor"&gt;&lt;/a&gt;算法步骤
&lt;/h2&gt;&lt;p&gt;AES算法是一种对称分组密码算法，采用代换-置换网络（SPN）结构，通过多轮迭代的加密过程对数据进行混淆和扩散，确保其安全性。该算法将明文分成固定长度的128位数据块（实际上分组长度也有128位、192位或256位三种选择），并支持128位、192位或256位的密钥，分别对应10轮、12轮或14轮的加密轮次。每一轮加密过程包括四个核心操作：&lt;strong&gt;字节代换&lt;/strong&gt;、&lt;strong&gt;行移位&lt;/strong&gt;、&lt;strong&gt;列混淆&lt;/strong&gt;和&lt;strong&gt;轮密钥加&lt;/strong&gt;，其中最后一轮省略列混淆步骤。通过&lt;strong&gt;密钥扩展算法&lt;/strong&gt;，初始密钥被扩展为多组轮密钥，供每一轮加密使用。AES算法的安全性依赖于其非线性的S盒变换、扩散层操作以及密钥的复杂性，使其能够有效抵抗线性攻击和差分攻击，成为当前最广泛使用的对称加密标准之一。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/03/image-18.png"&gt;&lt;/p&gt;
&lt;h3 id="1字节代换"&gt;&lt;a href="#1%e5%ad%97%e8%8a%82%e4%bb%a3%e6%8d%a2" class="header-anchor"&gt;&lt;/a&gt;1.字节代换
&lt;/h3&gt;&lt;p&gt;字节代换是AES加密的核心非线性变换，它通过一个被称为S盒的查找表对状态矩阵中的每个字节进行独立替换。其中，S盒是经过精心设计的，它基于有限域GF(2⁸)上的乘法逆运算，再加上一个仿射变换，使得输出与输入之间不存在明显的数学关系。具体来说，每个字节先被看作GF(2⁸)中的元素，计算其乘法逆元（0x00映射到自身），然后经过一个固定的仿射变换。这种设计让S盒具备极强的非线性特性，有效抵抗线性密码分析。而解密过程则使用逆S盒进行反向替换，但这两个S盒并不是简单的互逆关系，而是各自独立构造的。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/03/image-19-810x1024.png"&gt;&lt;/p&gt;
&lt;h3 id="2行移位"&gt;&lt;a href="#2%e8%a1%8c%e7%a7%bb%e4%bd%8d" class="header-anchor"&gt;&lt;/a&gt;2.行移位
&lt;/h3&gt;&lt;p&gt;行移位步骤是对状态矩阵的行进行循环移位操作。具体来说，状态矩阵是一个4行4列的字节数组。第一行保持不变，第二行循环左移1个字节，第三行循环左移2个字节，第四行循环左移3个字节。这个操作使得原本在同一列中的字节被分散到不同列中。在解密时，需要进行相反方向的循环右移操作。行移位的目的是实现字节在状态矩阵中的扩散，使得后续的列混淆操作能更有效地传播变化。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/03/image-20.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/03/image-22.png"&gt;&lt;/p&gt;
&lt;h3 id="3列混淆"&gt;&lt;a href="#3%e5%88%97%e6%b7%b7%e6%b7%86" class="header-anchor"&gt;&lt;/a&gt;3.列混淆
&lt;/h3&gt;&lt;p&gt;列混淆步骤对状态矩阵的每一列进行线性变换。该操作将每一列视为GF(2^8)上的多项式，与固定多项式进行有限域上的乘法。这个运算可以表示为矩阵乘法，其中每个字节的变换都是与固定系数的乘法和异或组合。&lt;/p&gt;
&lt;p&gt;在实际实现中，这个步骤可以使用xtime进行化简。xtime定义为这样的一个函数，其输入是一个 8 位字节（即 GF(2⁸) 的元素），输出是该字节与 {02}（即多项式 x）相乘的结果，并在必要时进行模 x⁸ + x⁴ + x³ + x + 1（AES 使用的不可约多项式）的约简，也即异或0x1B。&lt;/p&gt;
&lt;p&gt;在解密时，只需要变换固定系数矩阵即可。值得注意的是，最后一轮加密不包含列混淆操作。这个步骤增强了AES的扩散特性，使得单个字节的变化会影响整个列。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/03/image-23.png"&gt;&lt;/p&gt;
&lt;h3 id="4轮密钥加"&gt;&lt;a href="#4%e8%bd%ae%e5%af%86%e9%92%a5%e5%8a%a0" class="header-anchor"&gt;&lt;/a&gt;4.轮密钥加
&lt;/h3&gt;&lt;p&gt;轮密钥加步骤将当前轮的扩展密钥与状态矩阵进行简单的按位异或操作。每一轮都使用不同的轮密钥，这些密钥是通过密钥扩展算法从初始密钥派生出来的。这个操作是AES中唯一直接使用密钥的步骤。由于异或操作的可逆性，解密时只需使用相同的轮密钥再次异或即可恢复原始数据。这个步骤为算法提供了基于密钥的安全性。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/03/image-24.png"&gt;&lt;/p&gt;
&lt;h3 id="5密钥扩展算法"&gt;&lt;a href="#5%e5%af%86%e9%92%a5%e6%89%a9%e5%b1%95%e7%ae%97%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;5.密钥扩展算法
&lt;/h3&gt;&lt;p&gt;密钥扩展算法负责从初始密钥生成各轮所需的轮密钥。对于128位密钥，需要生成10个轮密钥（共44个32位字）。算法首先将初始密钥分成4个字（w[0]-w[3]），然后递归生成后续的字。我们这里只讨论128位密钥的扩展，其他位数的扩展步骤大致相同。&lt;/p&gt;
&lt;p&gt;对于非4k个字，计算方式为前一个字w[i-1]与w[i-4]的简单异或（XOR）。每第4k个字（如w[4],w[8]等）需要特殊处理，计算方式为先对前一个字w[i-1]进行字节代换、循环移位，再与w[i-4]、轮常数异或。轮常数是一个与轮次相关的固定值，用于打破对称性。对于192位和256位密钥，扩展过程类似但细节略有不同。这个算法确保每个轮密钥都与前一个不同，且整个密钥调度具有足够的随机性。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/03/image-25.png"&gt;&lt;/p&gt;
&lt;h3 id="6des与aes的对比"&gt;&lt;a href="#6des%e4%b8%8eaes%e7%9a%84%e5%af%b9%e6%af%94" class="header-anchor"&gt;&lt;/a&gt;6.DES与AES的对比
&lt;/h3&gt;&lt;p&gt;DES和AES在结构设计上采用了不同的密码学架构，体现了对称加密算法演进的思路。DES基于Feistel网络结构，这种结构将输入分组分为左右两部分，每轮只对其中一半进行加密变换，再通过交换左右部分实现数据混淆。Feistel结构的特点是加密解密过程对称，只需调整子密钥顺序即可实现逆向运算，这使得硬件实现相对简单。然而DES的56位密钥长度在计算能力提升后显得不足，且固定的S盒设计存在潜在的分析风险。&lt;/p&gt;
&lt;p&gt;AES则采用了更为现代的SPN（Substitution-Permutation Network）结构，这种结构通过多轮重复的代换和置换操作实现数据加密。与Feistel网络不同，SPN结构在每一轮都对整个数据块进行完整的非线性变换和线性扩散。具体来说，AES的每轮加密都包含字节代换、行移位、列混淆和轮密钥加四个步骤，其中前三步分别实现非线性代换和线性扩散，最后一步引入密钥相关变换。这种设计使得AES在相同轮数下能实现更强的混淆和扩散效果。&lt;/p&gt;
&lt;p&gt;从安全性角度来看，AES的SPN结构具有明显优势。其更大的分组长度（128位起）和可变的密钥长度（128/192/256位）能更好抵抗穷举攻击。每一轮对整个数据块的处理方式使得差分和线性分析更加困难，而DES的Feistel结构由于每轮只处理半块数据，需要更多轮数才能达到相似的混淆效果。此外，AES的S盒设计基于严密的数学理论，相比DES的固定S盒具有更强的抗分析能力。&lt;/p&gt;
&lt;p&gt;在性能表现上，AES的SPN结构更适合现代计算环境。其算法设计充分考虑了软硬件实现的效率，在各类平台上都能展现出优异的性能。而DES由于其初始设计年代较早，在软件实现效率上相对较低，特别是在处理大数据量时更为明显。AES的轮数可以根据密钥长度灵活调整（10/12/14轮），在安全性和效率之间取得了更好的平衡。&lt;/p&gt;
&lt;p&gt;NIST提出AES标准的主要原因在于DES已不能满足现代安全需求。随着计算能力的提升，DES的56位密钥面临被暴力破解的风险。1997年DES挑战赛被成功攻破，加速了新标准的制定进程。AES的选拔过程公开透明，最终Rijndael算法因其在安全性、性能和实现灵活性上的综合优势胜出。相比DES，AES提供了更高的安全强度、更优的执行效率以及更好的算法透明度，这些特点使其成为21世纪最重要的对称加密标准。&lt;/p&gt;
&lt;h2 id="程序运行截图"&gt;&lt;a href="#%e7%a8%8b%e5%ba%8f%e8%bf%90%e8%a1%8c%e6%88%aa%e5%9b%be" class="header-anchor"&gt;&lt;/a&gt;程序运行截图
&lt;/h2&gt;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/03/image-26.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/03/image-27.png"&gt;&lt;/p&gt;
&lt;h2 id="参考代码"&gt;&lt;a href="#%e5%8f%82%e8%80%83%e4%bb%a3%e7%a0%81" class="header-anchor"&gt;&lt;/a&gt;参考代码
&lt;/h2&gt;&lt;h3 id="aespy"&gt;&lt;a href="#aespy" class="header-anchor"&gt;&lt;/a&gt;aes.py
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# AES 128 bit encryption and decryption&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 128 bit 密钥 == 16 bytes == 32位十六进制&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 192 bit 密钥 == 24 bytes == 48位十六进制&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 256 bit 密钥 == 32 bytes == 64位十六进制&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Sbox &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x63&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x7C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x77&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x7B&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x6B&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x6F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x30&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x01&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x67&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x2B&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xFE&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xD7&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xAB&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x76&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0xCA&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x82&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC9&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x7D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xFA&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x59&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x47&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xAD&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xD4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xAF&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x9C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x72&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0xB7&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xFD&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x93&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x26&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x36&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x3F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF7&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xCC&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x34&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xE5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x71&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xD8&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x31&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x15&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x04&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC7&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x23&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x18&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x96&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x05&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x9A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x07&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x12&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x80&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xE2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xEB&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x27&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x75&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x09&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x83&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x2C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x1A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x1B&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x6E&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x5A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x52&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x3B&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xD6&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x29&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xE3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x2F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x84&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x53&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xD1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x00&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xED&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x20&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xFC&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x5B&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x6A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xCB&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xBE&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x39&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x4A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x4C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x58&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xCF&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0xD0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xEF&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xAA&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xFB&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x43&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x4D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x33&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x85&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x45&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF9&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x02&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x7F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x50&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x3C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x9F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA8&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x51&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x40&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x8F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x92&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x9D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x38&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xBC&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB6&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xDA&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x21&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x10&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xFF&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xD2&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0xCD&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x0C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x13&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xEC&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x5F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x97&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x44&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x17&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA7&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x7E&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x3D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x64&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x5D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x19&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x73&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x60&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x81&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x4F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xDC&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x22&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x2A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x90&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x88&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x46&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xEE&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB8&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x14&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xDE&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x5E&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x0B&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xDB&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0xE0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x32&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x3A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x0A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x49&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x06&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x24&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x5C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xD3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xAC&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x62&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x91&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x95&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xE4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x79&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0xE7&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC8&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x37&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x6D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x8D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xD5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x4E&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA9&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x6C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x56&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xEA&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x65&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x7A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xAE&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x08&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0xBA&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x78&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x25&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x2E&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x1C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA6&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC6&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xE8&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xDD&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x74&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x1F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x4B&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xBD&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x8B&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x8A&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x70&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x3E&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x66&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x48&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x03&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF6&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x0E&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x61&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x35&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x57&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB9&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x86&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x1D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x9E&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0xE1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF8&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x98&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x11&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x69&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xD9&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x8E&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x94&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x9B&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x1E&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x87&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xE9&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xCE&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x55&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x28&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xDF&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x8C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x89&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x0D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xBF&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xE6&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x42&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x68&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x41&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x99&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x2D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x0F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x54&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xBB&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x16&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;InvSbox &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x52&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x09&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x6A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xD5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x30&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x36&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x38&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xBF&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x40&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x9E&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x81&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xD7&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xFB&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x7C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xE3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x39&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x82&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x9B&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x2F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xFF&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x87&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x34&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x8E&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x43&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x44&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xDE&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xE9&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xCB&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x54&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x7B&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x94&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x32&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA6&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x23&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x3D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xEE&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x4C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x95&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x0B&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x42&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xFA&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x4E&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x08&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x2E&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x66&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x28&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xD9&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x24&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x76&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x5B&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x49&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x6D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x8B&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xD1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x25&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x72&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF8&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF6&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x64&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x86&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x68&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x98&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x16&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xD4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x5C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xCC&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x5D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x65&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB6&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x92&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x6C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x70&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x48&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x50&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xFD&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xED&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB9&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xDA&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x5E&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x15&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x46&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x57&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA7&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x8D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x9D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x84&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x90&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xD8&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xAB&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x00&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x8C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xBC&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xD3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x0A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF7&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xE4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x58&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x05&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB8&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x45&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x06&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0xD0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x2C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x1E&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x8F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xCA&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x3F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x0F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x02&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xAF&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xBD&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x03&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x01&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x13&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x8A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x6B&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x3A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x91&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x11&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x41&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x4F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x67&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xDC&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xEA&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x97&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xCF&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xCE&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xE6&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x73&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x96&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xAC&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x74&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x22&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xE7&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xAD&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x35&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x85&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xE2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF9&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x37&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xE8&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x1C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x75&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xDF&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x6E&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x47&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x1A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x71&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x1D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x29&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x89&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x6F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB7&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x62&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x0E&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xAA&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x18&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xBE&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x1B&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0xFC&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x56&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x3E&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x4B&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC6&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xD2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x79&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x20&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x9A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xDB&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xFE&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x78&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xCD&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x5A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF4&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x1F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xDD&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA8&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x33&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x88&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x07&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC7&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x31&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x12&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x10&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x59&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x27&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x80&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xEC&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x5F&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x60&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x51&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x7F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xA9&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x19&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x4A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x0D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x2D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xE5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x7A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x9F&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x93&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC9&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x9C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xEF&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0xA0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xE0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x3B&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x4D&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xAE&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x2A&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xF5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xC8&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xEB&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xBB&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x3C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x83&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x53&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x99&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x61&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0x17&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x2B&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x04&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x7E&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xBA&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x77&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xD6&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x26&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xE1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x69&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x14&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x63&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x55&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x21&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x0C&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x7D&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# xtime函数，用于有限域上的乘法运算&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 如果a的最高位为1，则左移1位后与0x1B异或，否则直接左移1位&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 0x1B 是 0001 1011 的十六进制表示，&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 0xFF 是 1111 1111 的十六进制表示，&amp;amp; 0xFF 运算只保留最低8位，其余位为0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 0x80 是 1000 0000 的十六进制表示，&amp;amp; 0x80 运算只保留最高位，其余位为0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xtime &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;lambda&lt;/span&gt; a: (((a &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; i))) &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0xFF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; i &lt;span style="color:#f92672"&gt;%&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 每4个字节开始一个新行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; matrix&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([byte])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 将字节添加到当前行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; matrix[int(i &lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;)]&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(byte)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; matrix
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;matrix2text&lt;/span&gt;(matrix):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 将矩阵转换为文本&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; j &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 将每个字节移动到正确的位置并组合&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; text &lt;span style="color:#f92672"&gt;|=&lt;/span&gt; (matrix[i][j] &lt;span style="color:#960050;background-color:#1e0010"&gt;!&lt;/span&gt;[](&lt;span style="color:#f92672"&gt;/&lt;/span&gt;images&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2025&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;03&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;image&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;x429&lt;span style="color:#f92672"&gt;.&lt;/span&gt;png)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## 参考资料&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[bozhu&lt;span style="color:#f92672"&gt;/&lt;/span&gt;AES&lt;span style="color:#f92672"&gt;-&lt;/span&gt;Python: A pure Python implementation of AES](https:&lt;span style="color:#f92672"&gt;//&lt;/span&gt;github&lt;span style="color:#f92672"&gt;.&lt;/span&gt;com&lt;span style="color:#f92672"&gt;/&lt;/span&gt;bozhu&lt;span style="color:#f92672"&gt;/&lt;/span&gt;AES&lt;span style="color:#f92672"&gt;-&lt;/span&gt;Python)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[AES &lt;span style="color:#f92672"&gt;-&lt;/span&gt; CTF Wiki](https:&lt;span style="color:#f92672"&gt;//&lt;/span&gt;ctf&lt;span style="color:#f92672"&gt;-&lt;/span&gt;wiki&lt;span style="color:#f92672"&gt;.&lt;/span&gt;org&lt;span style="color:#f92672"&gt;/&lt;/span&gt;crypto&lt;span style="color:#f92672"&gt;/&lt;/span&gt;blockcipher&lt;span style="color:#f92672"&gt;/&lt;/span&gt;aes)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[密码学基础&lt;span style="color:#960050;background-color:#1e0010"&gt;：&lt;/span&gt;AES加密算法 &lt;span style="color:#f92672"&gt;-&lt;/span&gt; 知乎](https:&lt;span style="color:#f92672"&gt;//&lt;/span&gt;zhuanlan&lt;span style="color:#f92672"&gt;.&lt;/span&gt;zhihu&lt;span style="color:#f92672"&gt;.&lt;/span&gt;com&lt;span style="color:#f92672"&gt;/&lt;/span&gt;p&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;78913397&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>E1_Vigenere</title><link>https://dandansad.com/2025/03/18/e1_vigenere/</link><pubDate>Tue, 18 Mar 2025 12:32:52 +0800</pubDate><guid>https://dandansad.com/2025/03/18/e1_vigenere/</guid><description>&lt;h2 id="算法主要原理"&gt;&lt;a href="#%e7%ae%97%e6%b3%95%e4%b8%bb%e8%a6%81%e5%8e%9f%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;算法主要原理
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;加密公式：C = (P + K)%26&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;C：密文&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;P：原文&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;K：第几套加密方式&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;解密公式：P = (C - K)%26&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;C：密文&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;P：原文&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;K：第几套加密方式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;如果P&amp;lt;0,P+26取得正序&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;简单来说，Vigenere密码实际上就是分组的凯撒密码。而分组的方法就是重复密钥，密钥相同的明文为同一组。每一组都可以看作是由不同的密钥所加密的凯撒密码。&lt;/p&gt;
&lt;h2 id="算法步骤"&gt;&lt;a href="#%e7%ae%97%e6%b3%95%e6%ad%a5%e9%aa%a4" class="header-anchor"&gt;&lt;/a&gt;算法步骤
&lt;/h2&gt;&lt;h3 id="加解密"&gt;&lt;a href="#%e5%8a%a0%e8%a7%a3%e5%af%86" class="header-anchor"&gt;&lt;/a&gt;加/解密
&lt;/h3&gt;&lt;p&gt;维吉尼亚密码是一种经典的多表替换加密算法，其改进了凯撒密码单表替换的弱点，通过使用不同的字母移位规则，使得频率分析攻击更加困难。&lt;/p&gt;
&lt;p&gt;实际上可以将维吉尼亚密码理解为多个凯撒密码的加密，它的核心思想是用一个关键词来控制加密过程，使得同样的字母在明文的不同位置可能会被加密成不同的密文字母，这样就比简单的凯撒密码安全得多。&lt;/p&gt;
&lt;p&gt;加密的时候就是把明文的每个字母按照密钥字母对应的数值进行移位，比如密钥字母A代表移0位（相当于不变），B移1位，一直到Z移25位。例如，当加密&amp;quot;HELLO&amp;quot;这个单词，选择的密钥是&amp;quot;KEY&amp;quot;，首先要把密钥重复到和明文一样长变成&amp;quot;KEYKE&amp;quot;，然后每个明文字母都对应一个密钥字母。然后每个字母加密时，H（在字母表里排第7位）对应K（排第10位），就往后移10位变成R（第17位）；E（第4位）对应E（第4位），移4位变成I（第8位）；第一个L（第11位）对应Y（第24位），11加24等于35，因为字母表只有26个字母，所以35减26得到9，对应J；第二个L（第11位）对应K（第10位），11加10等于21，对应V；O（第14位）对应E（第4位），14加4等于18，对应S。这样最终&amp;quot;HELLO&amp;quot;就被加密成了&amp;quot;RIJVS&amp;quot;。但要注意的是字母表是循环的，超过Z就要回到A继续算，所以计算时要取模26。&lt;/p&gt;
&lt;p&gt;解密过程与加密过程相反，用密文字母和密钥字母相减，比如R（17位）减去K（10位）得到7对应H，I（8位）减E（4位）得到4对应E，以此类推。如果遇到字母相减得到负数的情况，把负数加上26就能得到正确的结果。&lt;/p&gt;
&lt;h3 id="破解"&gt;&lt;a href="#%e7%a0%b4%e8%a7%a3" class="header-anchor"&gt;&lt;/a&gt;破解
&lt;/h3&gt;&lt;p&gt;维吉尼亚密码的核心安全特性来自于它的多表代换机制，但这也恰恰成为它被破解的突破口。要理解破解原理，我们需要先认清一个关键事实：&lt;strong&gt;维吉尼亚密码本质上是多个凯撒密码的交替使用。&lt;/strong&gt;****&lt;/p&gt;
&lt;p&gt;具体说来则是密钥长度决定了位移序列的长度，也即维吉尼亚密码是在循环应用一组固定的凯撒密码。若是我们确定了其密钥长度，则分组后的密码实际上呈现出单表特性，每组内部都是纯粹的凯撒密码，完全保留自然语言的统计特征。&lt;/p&gt;
&lt;p&gt;因此破解维吉尼亚密码的重中之重是要破解出密钥长度，确定了密钥长度后就和破解凯撒密码无异了。所以说我们的破解步骤就分为&lt;strong&gt;确定密钥长度&lt;/strong&gt;和&lt;strong&gt;确定密钥内容&lt;/strong&gt;两步。&lt;/p&gt;
&lt;h4 id="一确定密钥长度重合指数法确定密钥长度"&gt;&lt;a href="#%e4%b8%80%e7%a1%ae%e5%ae%9a%e5%af%86%e9%92%a5%e9%95%bf%e5%ba%a6%e9%87%8d%e5%90%88%e6%8c%87%e6%95%b0%e6%b3%95%e7%a1%ae%e5%ae%9a%e5%af%86%e9%92%a5%e9%95%bf%e5%ba%a6" class="header-anchor"&gt;&lt;/a&gt;（一）&lt;strong&gt;确定密钥长度&lt;/strong&gt;——重合指数法确定密钥长度
&lt;/h4&gt;&lt;p&gt;确定密钥长度这一步，我们采用重合指数法来确定。&lt;/p&gt;
&lt;p&gt;因为对于正常的英语分布来说，从正常英语句子中随机取两个元素相同的概率是0.065，而如果是完全随机的字符串概率则是0.038。0.038~0.065之间的差距，让我们可以检验某一段文字是否符合正常的英语分布。&lt;/p&gt;
&lt;p&gt;所以说，我们先假定密钥长度，便可以分出多组密文。每组密文内都是用相同的密钥加密的，因此只要是正常的、有意义的英文句子便符合0.065的概率。我们遍历可能的密钥长度，计算出接近0.065的值后取最小值就可以得到密钥长度。（当遍历的密钥长度稍长时，可能会出现真正密钥长度的倍数的IC会更接近0.065的情况，因此最好选容许的误差范围中的最小值）&lt;/p&gt;
&lt;p&gt;以下是详细的数学证明过程：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/03/image-9-862x1024.png"&gt;&lt;/p&gt;
&lt;h4 id="二确定密钥内容使用卡方检验确定密钥的内容"&gt;&lt;a href="#%e4%ba%8c%e7%a1%ae%e5%ae%9a%e5%af%86%e9%92%a5%e5%86%85%e5%ae%b9%e4%bd%bf%e7%94%a8%e5%8d%a1%e6%96%b9%e6%a3%80%e9%aa%8c%e7%a1%ae%e5%ae%9a%e5%af%86%e9%92%a5%e7%9a%84%e5%86%85%e5%ae%b9" class="header-anchor"&gt;&lt;/a&gt;（二）&lt;strong&gt;确定密钥内容&lt;/strong&gt;——使用卡方检验确定密钥的内容
&lt;/h4&gt;&lt;p&gt;在确定密钥内容这一步，我们使用卡方检验来确定。&lt;/p&gt;
&lt;p&gt;之前的步骤中我们已经将维吉尼亚密码转换为了多组凯撒密码。而对于凯撒密码来说，因为所有自然语言都存在特定的字母出现频率规律，单表替换加密虽然改变了字母的表象，但完整保留了这种统计特征。以英语为例，字母E的出现频率高达12.7%，T约9.1%，A约8.2%，这种分布特征就像语言的&amp;quot;指纹&amp;quot;一样稳定。当我们将明文通过凯撒密码加密时，整个字母表只是被整体平移了一定位数，比如位移3的情况下，原本高频的E会被统一替换成H，T变成W，A变成D，此时密文中H、W、D就会成为新的高频字母，它们与原始高频字母的对应关系完全由位移量决定。&lt;/p&gt;
&lt;p&gt;那我们首先需要统计密文中各字母的出现频率，制作频率分布表，然后将这个统计结果与目标语言的标准字母频率进行对比匹配，这一步我们使用卡方检验。卡方检验可以通过量化比较两个字母频率分布的差异程度，来找出最可能使用的位移量。这个卡方值的计算公式是：将每个字母在解密文本中的观察频次与标准英语中的期望频次之差的平方除以期望频次后求和。卡方值越小，说明解密后的字母频率分布与标准英语越接近，也就意味着这个位移量越有可能是正确的密钥。求出密钥后，我们便可以轻松解密维吉尼亚密码了。&lt;/p&gt;
&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;p&gt;破解Vigenere算法最主要就是两个步骤——&lt;strong&gt;确定密钥长度&lt;/strong&gt;和&lt;strong&gt;确定密钥内容&lt;/strong&gt;，而这两个步骤实际上都是利用了英语字母的分布规律来破解的，一个是通过&lt;strong&gt;重合指数&lt;/strong&gt;，一个是通过&lt;strong&gt;卡方检验&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id="程序运行截图"&gt;&lt;a href="#%e7%a8%8b%e5%ba%8f%e8%bf%90%e8%a1%8c%e6%88%aa%e5%9b%be" class="header-anchor"&gt;&lt;/a&gt;程序运行截图
&lt;/h2&gt;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/03/image-13.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/03/image-14.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/03/image-15.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/03/image-16.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2025/03/image-17.png"&gt;&lt;/p&gt;
&lt;h2 id="参考代码"&gt;&lt;a href="#%e5%8f%82%e8%80%83%e4%bb%a3%e7%a0%81" class="header-anchor"&gt;&lt;/a&gt;参考代码
&lt;/h2&gt;&lt;h3 id="endecryptpy"&gt;&lt;a href="#endecryptpy" class="header-anchor"&gt;&lt;/a&gt;&lt;strong&gt;endecrypt.py&lt;/strong&gt;
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Vigenere Cipher Encrypt/Decrypt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 字母转数字&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;L2N&lt;/span&gt;(L):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; ord(L&lt;span style="color:#f92672"&gt;.&lt;/span&gt;upper()) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; ord(&lt;span style="color:#e6db74"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 数字转字母&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;N2L&lt;/span&gt;(N):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; chr(N &lt;span style="color:#f92672"&gt;+&lt;/span&gt; ord(&lt;span style="color:#e6db74"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 加密&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;encrypt&lt;/span&gt;(text, key):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypted_text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; j&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(len(text)):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(text[i]&lt;span style="color:#f92672"&gt;.&lt;/span&gt;isalpha()):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypted_text &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; N2L((L2N(text[i]) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; L2N(key[j&lt;span style="color:#f92672"&gt;%&lt;/span&gt;len(key)])) &lt;span style="color:#f92672"&gt;%&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; j&lt;span style="color:#f92672"&gt;+=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; encrypted_text
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 解密&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;decrypt&lt;/span&gt;(text, key):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; decrypted_text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; j&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(len(text)):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; decrypted_text &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; N2L((L2N(text[i]) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; L2N(key[j&lt;span style="color:#f92672"&gt;%&lt;/span&gt;len(key)])) &lt;span style="color:#f92672"&gt;%&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; j&lt;span style="color:#f92672"&gt;+=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; decrypted_text
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; __name__ &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;I am alive here, my beloved, for the reason to adore you. Oh!How anxious I have been for you and how sorry I am about all you must have suffered in having no news from us. May heaven grant that this letter reaches you. Do not write to me, this would compromise all of us and above all,do not return under any circumstances. It is known that it was you who helped us to get away from here and all would be lost if you should show yourself.We are guarded day and night. I do not care you are not here. Do not be troubled on my account. Nothing will happen to me. The national assemble will show leniency. Farewell the most loved of men. Be quiet if you can take care of yourself.For myself I cannot write any more, but nothing in the world could stop me to adore you up to the death.&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; key &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;crypt&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(encrypt(text, key)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;lower())
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="crackpy"&gt;&lt;a href="#crackpy" class="header-anchor"&gt;&lt;/a&gt;&lt;strong&gt;crack.py&lt;/strong&gt;
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Vigenere Cipher Crack&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; math
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; numpy &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; np
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; typing &lt;span style="color:#f92672"&gt;import&lt;/span&gt; List, Tuple
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;alpha&lt;/span&gt;(cipher: str) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; str:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 预处理函数：去掉密文中的非字母字符（如空格、回车、标点符号等）。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param cipher: 密文字符串
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return: 只包含字母的密文字符串
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; c &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; char &lt;span style="color:#f92672"&gt;in&lt;/span&gt; cipher:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; char&lt;span style="color:#f92672"&gt;.&lt;/span&gt;isalpha():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; c &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; char
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; c
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;count_IC&lt;/span&gt;(cipher: str) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; float:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 计算字符串的重合指数（IC）。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param cipher: 密文字符串
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return: 重合指数值
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; count &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; L &lt;span style="color:#f92672"&gt;=&lt;/span&gt; len(cipher)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IC &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; char &lt;span style="color:#f92672"&gt;in&lt;/span&gt; cipher:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; char&lt;span style="color:#f92672"&gt;.&lt;/span&gt;isupper():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; count[ord(char) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; ord(&lt;span style="color:#e6db74"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;)] &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;elif&lt;/span&gt; char&lt;span style="color:#f92672"&gt;.&lt;/span&gt;islower():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; count[ord(char) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; ord(&lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;)] &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;26&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IC &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; (count[i] &lt;span style="color:#f92672"&gt;*&lt;/span&gt; (count[i] &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)) &lt;span style="color:#f92672"&gt;/&lt;/span&gt; (L &lt;span style="color:#f92672"&gt;*&lt;/span&gt; (L &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; IC
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;count_key_len&lt;/span&gt;(cipher: str, key_len: int) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; float:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 对密文按密钥长度分组，并计算每组的平均重合指数。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param cipher: 密文字符串
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param key_len: 密钥长度
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return: 平均重合指数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; groups &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;] &lt;span style="color:#f92672"&gt;*&lt;/span&gt; key_len
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IC &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] &lt;span style="color:#f92672"&gt;*&lt;/span&gt; key_len
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(len(cipher)):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; m &lt;span style="color:#f92672"&gt;=&lt;/span&gt; i &lt;span style="color:#f92672"&gt;%&lt;/span&gt; key_len
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; groups[m] &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; cipher[i]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(key_len):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IC[i] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; count_IC(groups[i])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;长度为&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;key_len&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;时, 平均重合指数为&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;np&lt;span style="color:#f92672"&gt;.&lt;/span&gt;mean(IC)&lt;span style="color:#e6db74"&gt;:&lt;/span&gt;&lt;span style="color:#e6db74"&gt;.5f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; np&lt;span style="color:#f92672"&gt;.&lt;/span&gt;mean(IC)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;determine_key_length&lt;/span&gt;(cipher: str, tolerance: float &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.01&lt;/span&gt;) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; int:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 确定最可能的密钥长度。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param cipher: 密文字符串
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param tolerance: 允许的重合指数误差范围
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return: 最可能的密钥长度
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; possible_lengths &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [] &lt;span style="color:#75715e"&gt;# 存储可能的密钥长度&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; key_len &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;): &lt;span style="color:#75715e"&gt;# 尝试密钥长度从1到100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; avg_IC &lt;span style="color:#f92672"&gt;=&lt;/span&gt; count_key_len(cipher, key_len)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; abs(avg_IC &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.065&lt;/span&gt;) int:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 确定最可能的密钥长度。(老旧版本)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param cipher: 密文字符串
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return: 最可能的密钥长度
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; key_len &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; min_diff &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; avg_IC &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; current_IC &lt;span style="color:#f92672"&gt;=&lt;/span&gt; count_key_len(cipher, i)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; abs(current_IC &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.065&lt;/span&gt;) float:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 计算卡方统计量，用于评估解密后的文本是否符合英文字母频率分布。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param vec: 密文的子串（按密钥长度分组后的某一组）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param key: 尝试的密钥偏移量
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return: 卡方统计量
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; freq &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 统计字母频率&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; c &lt;span style="color:#f92672"&gt;in&lt;/span&gt; vec:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; c&lt;span style="color:#f92672"&gt;.&lt;/span&gt;isalpha():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; c &lt;span style="color:#f92672"&gt;=&lt;/span&gt; c&lt;span style="color:#f92672"&gt;.&lt;/span&gt;lower()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; c &lt;span style="color:#f92672"&gt;=&lt;/span&gt; chr((ord(c) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; ord(&lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; key)) &lt;span style="color:#f92672"&gt;%&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; ord(&lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; freq[ord(c) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; ord(&lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;)] &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 英文字母的期望频率&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; expected_freq &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.08167&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.01492&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.02782&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.04253&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.12702&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.02228&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.02015&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.06094&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.06966&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.00153&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.00772&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.04025&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.02406&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.06749&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.07507&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.01929&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.00095&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.05987&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.06327&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.09056&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.02758&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.00978&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.02360&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.00150&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.01974&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.00074&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 确保期望频率的总和为1.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;assert&lt;/span&gt; abs(&lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; sum(expected_freq)) List[int]:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 使用卡方检验确定每组最可能的相对偏移量。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param cipher: 密文字符串
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param key_len: 密钥长度
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return: 相对偏移量列表
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; possible_key &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [] &lt;span style="color:#75715e"&gt;# 存储可能的密钥&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(key_len):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 生成当前分组的子串&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; vec &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [cipher[j] &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; j &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(i, len(cipher), key_len)]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 尝试所有可能的偏移量（0-25）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; possibility_array &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; j &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;26&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; curr_chi_square &lt;span style="color:#f92672"&gt;=&lt;/span&gt; chi_square(vec, j)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; possibility_array&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append((chr(ord(&lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; j), curr_chi_square))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 按卡方值从小到大排序（卡方值越小，可能性越大）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; possibility_array&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sort(key&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;lambda&lt;/span&gt; x: x[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 选择卡方值最小的偏移量作为当前分组的密钥字母&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; possible_key&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(ord(possibility_array[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;][&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; ord(&lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; possible_key
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;decrypt&lt;/span&gt;(cipher: str, key_len: int, shifts: List[int]) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; str:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 使用密钥对密文进行解密。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param cipher: 密文字符串
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param key_len: 密钥长度
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param shifts: 密钥字母的下标列表
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return: 解密后的明文字符串
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plain &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; i &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; i str:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 预处理函数：去掉密文中的非字母字符（如空格、回车、标点符号等）。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param cipher: 密文字符串
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return: 只包含字母的密文字符串
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; c &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; char &lt;span style="color:#f92672"&gt;in&lt;/span&gt; cipher:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; char&lt;span style="color:#f92672"&gt;.&lt;/span&gt;isalpha():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; c &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; char
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; c
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;count_IC&lt;/span&gt;(cipher: str) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; float:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 计算字符串的重合指数（IC）。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param cipher: 密文字符串
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return: 重合指数值
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; count &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; L &lt;span style="color:#f92672"&gt;=&lt;/span&gt; len(cipher)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IC &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; char &lt;span style="color:#f92672"&gt;in&lt;/span&gt; cipher:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; char&lt;span style="color:#f92672"&gt;.&lt;/span&gt;isupper():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; count[ord(char) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; ord(&lt;span style="color:#e6db74"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;)] &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;elif&lt;/span&gt; char&lt;span style="color:#f92672"&gt;.&lt;/span&gt;islower():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; count[ord(char) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; ord(&lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;)] &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;26&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IC &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; (count[i] &lt;span style="color:#f92672"&gt;*&lt;/span&gt; (count[i] &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)) &lt;span style="color:#f92672"&gt;/&lt;/span&gt; (L &lt;span style="color:#f92672"&gt;*&lt;/span&gt; (L &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; IC
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;count_key_len&lt;/span&gt;(cipher: str, key_len: int) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; float:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 对密文按密钥长度分组，并计算每组的平均重合指数。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param cipher: 密文字符串
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param key_len: 密钥长度
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return: 平均重合指数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; groups &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;] &lt;span style="color:#f92672"&gt;*&lt;/span&gt; key_len
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IC &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] &lt;span style="color:#f92672"&gt;*&lt;/span&gt; key_len
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(len(cipher)):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; m &lt;span style="color:#f92672"&gt;=&lt;/span&gt; i &lt;span style="color:#f92672"&gt;%&lt;/span&gt; key_len
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; groups[m] &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; cipher[i]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(key_len):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IC[i] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; count_IC(groups[i])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; np&lt;span style="color:#f92672"&gt;.&lt;/span&gt;mean(IC)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;determine_key_length&lt;/span&gt;(cipher: str, tolerance: float &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.01&lt;/span&gt;) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; int:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 确定最可能的密钥长度。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param cipher: 密文字符串
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param tolerance: 允许的重合指数误差范围
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return: 最可能的密钥长度
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; possible_lengths &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [] &lt;span style="color:#75715e"&gt;# 存储可能的密钥长度&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IC_values &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [] &lt;span style="color:#75715e"&gt;# 存储每个密钥长度对应的重合指数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; key_len &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;): &lt;span style="color:#75715e"&gt;# 尝试密钥长度从1到100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; avg_IC &lt;span style="color:#f92672"&gt;=&lt;/span&gt; count_key_len(cipher, key_len)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IC_values&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(avg_IC)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; abs(avg_IC &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.065&lt;/span&gt;) float:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 计算卡方统计量，用于评估解密后的文本是否符合英文字母频率分布。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param vec: 密文的子串（按密钥长度分组后的某一组）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param key: 尝试的密钥偏移量
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return: 卡方统计量
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; freq &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 统计字母频率&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; c &lt;span style="color:#f92672"&gt;in&lt;/span&gt; vec:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; c&lt;span style="color:#f92672"&gt;.&lt;/span&gt;isalpha():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; c &lt;span style="color:#f92672"&gt;=&lt;/span&gt; c&lt;span style="color:#f92672"&gt;.&lt;/span&gt;lower()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; c &lt;span style="color:#f92672"&gt;=&lt;/span&gt; chr((ord(c) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; ord(&lt;span style="color:#e6db74"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; key)) &lt;span style="color:#f92672"&gt;%&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; ord(&lt;span style="color:#e6db74"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; freq[ord(c) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; ord(&lt;span style="color:#e6db74"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;)] &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 英文字母的期望频率&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; expected_freq &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.08167&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.01492&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.02782&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.04253&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.12702&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.02228&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.02015&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.06094&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.06966&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.00153&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.00772&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.04025&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.02406&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.06749&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.07507&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.01929&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.00095&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.05987&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.06327&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.09056&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0.02758&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.00978&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.02360&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.00150&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.01974&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.00074&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 确保期望频率的总和为1.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;assert&lt;/span&gt; abs(&lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; sum(expected_freq)) Tuple[List[int], List[List[float]]]:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 使用卡方检验确定每组与第一组之间的相对偏移量。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param cipher: 密文字符串
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param key_len: 密钥长度
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return: 相对偏移量列表和每一组的卡方值列表（未排序）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; possible_key &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [] &lt;span style="color:#75715e"&gt;# 存储可能的密钥&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; chi_square_values &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [] &lt;span style="color:#75715e"&gt;# 存储每一组的卡方值（未排序）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(key_len):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 生成当前分组的子串&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; vec &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [cipher[j] &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; j &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(i, len(cipher), key_len)]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 尝试所有可能的偏移量（0-25）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; chi_values &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [] &lt;span style="color:#75715e"&gt;# 存储当前分组的卡方值（未排序）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; j &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;26&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; curr_chi_square &lt;span style="color:#f92672"&gt;=&lt;/span&gt; chi_square(vec, j)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; chi_values&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(curr_chi_square)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 按卡方值从小到大排序（卡方值越小，可能性越大）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sorted_indices &lt;span style="color:#f92672"&gt;=&lt;/span&gt; np&lt;span style="color:#f92672"&gt;.&lt;/span&gt;argsort(chi_values) &lt;span style="color:#75715e"&gt;# 获取排序后的索引&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; best_shift &lt;span style="color:#f92672"&gt;=&lt;/span&gt; sorted_indices[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] &lt;span style="color:#75715e"&gt;# 选择卡方值最小的偏移量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 存储结果&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; possible_key&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(best_shift)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; chi_square_values&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(chi_values) &lt;span style="color:#75715e"&gt;# 存储未排序的卡方值&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; possible_key, chi_square_values
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;decrypt&lt;/span&gt;(cipher: str, key_len: int, shifts: List[int]) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; str:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 使用密钥对密文进行解密。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param cipher: 密文字符串
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param key_len: 密钥长度
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param shifts: 密钥字母的下标列表
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return: 解密后的明文字符串
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plain &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; i &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; i &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; len(cipher):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; j &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(key_len):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; cipher[i]&lt;span style="color:#f92672"&gt;.&lt;/span&gt;isupper():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plain &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; chr(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (ord(cipher[i]) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; ord(&lt;span style="color:#e6db74"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; shifts[j] &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt;) &lt;span style="color:#f92672"&gt;%&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; ord(&lt;span style="color:#e6db74"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plain &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; chr(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (ord(cipher[i]) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; ord(&lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; shifts[j] &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt;) &lt;span style="color:#f92672"&gt;%&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; ord(&lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; i &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; i &lt;span style="color:#f92672"&gt;==&lt;/span&gt; len(cipher):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; plain
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# GUI 界面&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;VigenereCrackerApp&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;__init__&lt;/span&gt;(self, root):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;root &lt;span style="color:#f92672"&gt;=&lt;/span&gt; root
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;root&lt;span style="color:#f92672"&gt;.&lt;/span&gt;title(&lt;span style="color:#e6db74"&gt;&amp;#34;维吉尼亚密码工具&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;cipher &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;key_len &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;shifts &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;plain &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;show_plots &lt;span style="color:#f92672"&gt;=&lt;/span&gt; tk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;BooleanVar(value&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# 是否展示柱状图&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 创建选项卡&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;notebook &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ttk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Notebook(root)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;notebook&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack(fill&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;both&amp;#34;&lt;/span&gt;, expand&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 添加“加/解密”选项卡&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;add_encrypt_decrypt_tab()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 添加“破解”选项卡&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;add_crack_tab()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;add_encrypt_decrypt_tab&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;添加加/解密选项卡&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ttk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Frame(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;notebook)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;notebook&lt;span style="color:#f92672"&gt;.&lt;/span&gt;add(tab, text&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;加/解密&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 输入框&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; input_label &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ttk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Label(tab, text&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;原文：&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; input_label&lt;span style="color:#f92672"&gt;.&lt;/span&gt;grid(row&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, column&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, padx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, pady&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, sticky&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;w&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;input_text_encrypt &lt;span style="color:#f92672"&gt;=&lt;/span&gt; tk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Text(tab, height&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;, width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;input_text_encrypt&lt;span style="color:#f92672"&gt;.&lt;/span&gt;grid(row&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, column&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, padx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, pady&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 密钥输入框&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; key_label &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ttk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Label(tab, text&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;密钥：&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; key_label&lt;span style="color:#f92672"&gt;.&lt;/span&gt;grid(row&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, column&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, padx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, pady&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, sticky&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;w&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;key_entry &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ttk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Entry(tab, width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;key_entry&lt;span style="color:#f92672"&gt;.&lt;/span&gt;grid(row&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, column&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, padx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, pady&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, sticky&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;w&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 创建一个 Frame 来放置按钮&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; button_frame &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ttk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Frame(tab)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; button_frame&lt;span style="color:#f92672"&gt;.&lt;/span&gt;grid(row&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, column&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, columnspan&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, padx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, pady&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 加密按钮&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypt_button &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ttk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Button(button_frame, text&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;👇加密👇&amp;#34;&lt;/span&gt;, command&lt;span style="color:#f92672"&gt;=&lt;/span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;encrypt_text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypt_button&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack(side&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;left&amp;#34;&lt;/span&gt;, padx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 解密按钮&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; decrypt_button &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ttk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Button(button_frame, text&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;👆解密👆&amp;#34;&lt;/span&gt;, command&lt;span style="color:#f92672"&gt;=&lt;/span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;decrypt_text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; decrypt_button&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack(side&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;left&amp;#34;&lt;/span&gt;, padx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 输出框&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; output_label &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ttk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Label(tab, text&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;密文：&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; output_label&lt;span style="color:#f92672"&gt;.&lt;/span&gt;grid(row&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, column&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, padx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, pady&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, sticky&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;w&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;output_text_encrypt &lt;span style="color:#f92672"&gt;=&lt;/span&gt; tk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Text(tab, height&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;, width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;output_text_encrypt&lt;span style="color:#f92672"&gt;.&lt;/span&gt;grid(row&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, column&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, padx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, pady&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;add_crack_tab&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;添加破解选项卡&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ttk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Frame(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;notebook)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;notebook&lt;span style="color:#f92672"&gt;.&lt;/span&gt;add(tab, text&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;破解&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 输入框&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; input_label &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ttk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Label(tab, text&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;输入密文：&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; input_label&lt;span style="color:#f92672"&gt;.&lt;/span&gt;grid(row&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, column&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, padx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, pady&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, sticky&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;w&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;input_text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; tk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Text(tab, height&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;, width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;input_text&lt;span style="color:#f92672"&gt;.&lt;/span&gt;grid(row&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, column&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, padx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, pady&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 输出框&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; output_label &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ttk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Label(tab, text&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;输出结果：&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; output_label&lt;span style="color:#f92672"&gt;.&lt;/span&gt;grid(row&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, column&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, padx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, pady&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, sticky&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;w&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;output_text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; tk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Text(tab, height&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;, width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;output_text&lt;span style="color:#f92672"&gt;.&lt;/span&gt;grid(row&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, column&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, padx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, pady&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 按钮&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;step1_button &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ttk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Button(tab, text&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;1. 确定密钥长度&amp;#34;&lt;/span&gt;, command&lt;span style="color:#f92672"&gt;=&lt;/span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;step1)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;step1_button&lt;span style="color:#f92672"&gt;.&lt;/span&gt;grid(row&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, column&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, padx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, pady&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;step2_button &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ttk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Button(tab, text&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;2. 确定密钥&amp;#34;&lt;/span&gt;, command&lt;span style="color:#f92672"&gt;=&lt;/span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;step2)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;step2_button&lt;span style="color:#f92672"&gt;.&lt;/span&gt;grid(row&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, column&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, padx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, pady&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;step3_button &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ttk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Button(tab, text&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;3. 解密&amp;#34;&lt;/span&gt;, command&lt;span style="color:#f92672"&gt;=&lt;/span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;step3)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;step3_button&lt;span style="color:#f92672"&gt;.&lt;/span&gt;grid(row&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, column&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, padx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, pady&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 是否展示柱状图&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;plot_check &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ttk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Checkbutton(tab, text&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;展示柱状图&amp;#34;&lt;/span&gt;, variable&lt;span style="color:#f92672"&gt;=&lt;/span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;show_plots)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;plot_check&lt;span style="color:#f92672"&gt;.&lt;/span&gt;grid(row&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, column&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, padx&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, pady&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;encrypt_text&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;加密文本&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;input_text_encrypt&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;, tk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;END)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;strip() &lt;span style="color:#75715e"&gt;# 获取明文&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; key &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;key_entry&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get()&lt;span style="color:#f92672"&gt;.&lt;/span&gt;strip() &lt;span style="color:#75715e"&gt;# 获取密钥&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;not&lt;/span&gt; text &lt;span style="color:#f92672"&gt;or&lt;/span&gt; &lt;span style="color:#f92672"&gt;not&lt;/span&gt; key:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; messagebox&lt;span style="color:#f92672"&gt;.&lt;/span&gt;showerror(&lt;span style="color:#e6db74"&gt;&amp;#34;错误&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;请输入明文和密钥！&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypted_text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; encrypt(text, key) &lt;span style="color:#75715e"&gt;# 调用加密函数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;output_text_encrypt&lt;span style="color:#f92672"&gt;.&lt;/span&gt;delete(&lt;span style="color:#e6db74"&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;, tk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;END) &lt;span style="color:#75715e"&gt;# 清空输出框&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;output_text_encrypt&lt;span style="color:#f92672"&gt;.&lt;/span&gt;insert(tk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;END, encrypted_text) &lt;span style="color:#75715e"&gt;# 显示密文&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;decrypt_text&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;解密文本&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;output_text_encrypt&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;, tk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;END)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;strip() &lt;span style="color:#75715e"&gt;# 获取密文&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; key &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;key_entry&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get()&lt;span style="color:#f92672"&gt;.&lt;/span&gt;strip() &lt;span style="color:#75715e"&gt;# 获取密钥&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;not&lt;/span&gt; text &lt;span style="color:#f92672"&gt;or&lt;/span&gt; &lt;span style="color:#f92672"&gt;not&lt;/span&gt; key:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; messagebox&lt;span style="color:#f92672"&gt;.&lt;/span&gt;showerror(&lt;span style="color:#e6db74"&gt;&amp;#34;错误&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;请输入密文和密钥！&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; decrypted_text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; decrypt_vigenere(text, key) &lt;span style="color:#75715e"&gt;# 调用解密函数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;input_text_encrypt&lt;span style="color:#f92672"&gt;.&lt;/span&gt;delete(&lt;span style="color:#e6db74"&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;, tk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;END) &lt;span style="color:#75715e"&gt;# 清空输入框&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;input_text_encrypt&lt;span style="color:#f92672"&gt;.&lt;/span&gt;insert(tk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;END, decrypted_text) &lt;span style="color:#75715e"&gt;# 显示明文&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;step1&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;第一步：确定密钥长度&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;cipher &lt;span style="color:#f92672"&gt;=&lt;/span&gt; alpha(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;input_text&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;, tk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;END)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;strip())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;key_len, IC_values &lt;span style="color:#f92672"&gt;=&lt;/span&gt; determine_key_length(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;cipher)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;output_text&lt;span style="color:#f92672"&gt;.&lt;/span&gt;delete(&lt;span style="color:#e6db74"&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;, tk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;END)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;output_text&lt;span style="color:#f92672"&gt;.&lt;/span&gt;insert(tk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;END, &lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;密钥长度为: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;key_len&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 展示重合指数与密钥长度的图&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;show_plots&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;plot_IC_vs_keylen(IC_values)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;except&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ValueError&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; e:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; messagebox&lt;span style="color:#f92672"&gt;.&lt;/span&gt;showerror(&lt;span style="color:#e6db74"&gt;&amp;#34;错误&amp;#34;&lt;/span&gt;, str(e))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;step2&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;第二步：确定密钥&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;not&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;key_len:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; messagebox&lt;span style="color:#f92672"&gt;.&lt;/span&gt;showerror(&lt;span style="color:#e6db74"&gt;&amp;#34;错误&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;请先确定密钥长度！&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 调用 determine_relative_shifts 获取密钥和卡方值&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;shifts, chi_square_values &lt;span style="color:#f92672"&gt;=&lt;/span&gt; determine_relative_shifts(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;cipher, self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;key_len)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;output_text&lt;span style="color:#f92672"&gt;.&lt;/span&gt;insert(tk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;END, &lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;相对偏移量: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;shifts&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 展示每一组的卡方与偏移量的图&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;show_plots&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;plot_chi_square_vs_shift(chi_square_values)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;step3&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;第三步：解密&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;not&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;shifts:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; messagebox&lt;span style="color:#f92672"&gt;.&lt;/span&gt;showerror(&lt;span style="color:#e6db74"&gt;&amp;#34;错误&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;请先确定密钥！&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;plain &lt;span style="color:#f92672"&gt;=&lt;/span&gt; decrypt(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;cipher, self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;key_len, self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;shifts)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;output_text&lt;span style="color:#f92672"&gt;.&lt;/span&gt;insert(tk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;END, &lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;解密后的明文: &lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;plain&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;plot_IC_vs_keylen&lt;/span&gt;(self, IC_values):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;绘制重合指数与密钥长度的柱状图&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fig, ax &lt;span style="color:#f92672"&gt;=&lt;/span&gt; plt&lt;span style="color:#f92672"&gt;.&lt;/span&gt;subplots()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, len(IC_values) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# 横轴：密钥长度&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ax&lt;span style="color:#f92672"&gt;.&lt;/span&gt;bar(x, IC_values) &lt;span style="color:#75715e"&gt;# 绘制柱状图&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ax&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_xlabel(&lt;span style="color:#e6db74"&gt;&amp;#34;密钥长度&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ax&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_ylabel(&lt;span style="color:#e6db74"&gt;&amp;#34;重合指数&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ax&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_title(&lt;span style="color:#e6db74"&gt;&amp;#34;重合指数与密钥长度的关系&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plt&lt;span style="color:#f92672"&gt;.&lt;/span&gt;show()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;plot_chi_square_vs_shift&lt;/span&gt;(self, chi_square_values):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 绘制每一组的卡方与偏移量的图。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param chi_square_values: 每一组的卡方值列表（未排序）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i, chi_values &lt;span style="color:#f92672"&gt;in&lt;/span&gt; enumerate(chi_square_values):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fig, ax &lt;span style="color:#f92672"&gt;=&lt;/span&gt; plt&lt;span style="color:#f92672"&gt;.&lt;/span&gt;subplots()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;26&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# 横轴：偏移量（0-25）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ax&lt;span style="color:#f92672"&gt;.&lt;/span&gt;bar(x, chi_values) &lt;span style="color:#75715e"&gt;# 绘制柱状图&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ax&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_xlabel(&lt;span style="color:#e6db74"&gt;&amp;#34;偏移量&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ax&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_ylabel(&lt;span style="color:#e6db74"&gt;&amp;#34;卡方值&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ax&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_title(&lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;分组 &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;i&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; 的偏移量与卡方值&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plt&lt;span style="color:#f92672"&gt;.&lt;/span&gt;show()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 运行 GUI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; __name__ &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; root &lt;span style="color:#f92672"&gt;=&lt;/span&gt; tk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Tk()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; app &lt;span style="color:#f92672"&gt;=&lt;/span&gt; VigenereCrackerApp(root)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; root&lt;span style="color:#f92672"&gt;.&lt;/span&gt;mainloop()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考资料"&gt;&lt;a href="#%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99" class="header-anchor"&gt;&lt;/a&gt;参考资料
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://blog.csdn.net/qq_47912072/article/details/112684665" target="_blank" rel="noopener"
 &gt;维吉尼亚密码的破解算法及python代码实现_维吉尼亚密码解密代码-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.zhihu.com/question/494708265/answer/3630012436" target="_blank" rel="noopener"
 &gt;维吉尼亚密码产生密文，和密钥，如何得到明文? - 知乎&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Highway-Toll-Framework</title><link>https://dandansad.com/2025/03/11/highway-toll-framework/</link><pubDate>Tue, 11 Mar 2025 01:59:54 +0800</pubDate><guid>https://dandansad.com/2025/03/11/highway-toll-framework/</guid><description>&lt;p&gt;一个高速收费站框架，新增车辆类型（包括是真的新增车辆类型或者同一类型车辆叫法不同）不用修改原有代码，只需要在类上加注解（或注解配合properties配置文件）即可。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;&lt;span style="color:#f92672"&gt;---&lt;/span&gt;highway
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Main.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; MainV2.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; MainV3.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; MainV4.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;+---&lt;/span&gt;annotation
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; VehicleType.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; VehicleTypeV2.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;+---&lt;/span&gt;config
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; VehicleConfig.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;+---&lt;/span&gt;toll
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; TollManager.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; TollManagerV2.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; TollManagerV3.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; TollManagerV4.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;&lt;span style="color:#f92672"&gt;---&lt;/span&gt;vehicle
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Bus.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Car.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; NewElectricCar.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; NewEmergencyVehicle.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; NewMotorcycle.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Truck.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Vehicle.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;+---&lt;/span&gt;v2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Bus.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Car.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; ElectricCar.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; EmergencyVehicle.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Motorcycle.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Truck.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Vehicle.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;+---&lt;/span&gt;v3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; BaseVehicle.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Bus.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Car.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; ElectricCar.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; EmergencyVehicle.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Motorcycle.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Truck.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Vehicle.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;&lt;span style="color:#f92672"&gt;---&lt;/span&gt;v4
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; BaseVehicle.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Bus.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Car.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ElectricCar.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; EmergencyVehicle.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Motorcycle.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Truck.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Vehicle.java
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="1-单纯使用注解信息"&gt;&lt;a href="#1-%e5%8d%95%e7%ba%af%e4%bd%bf%e7%94%a8%e6%b3%a8%e8%a7%a3%e4%bf%a1%e6%81%af" class="header-anchor"&gt;&lt;/a&gt;1. 单纯使用注解信息
&lt;/h2&gt;&lt;h3 id="注解类"&gt;&lt;a href="#%e6%b3%a8%e8%a7%a3%e7%b1%bb" class="header-anchor"&gt;&lt;/a&gt;注解类
&lt;/h3&gt;&lt;p&gt;在注解类中定义所需要的元素，这里是一个名称列表和每公里收费。&lt;/p&gt;
&lt;h3 id="收费管理器类"&gt;&lt;a href="#%e6%94%b6%e8%b4%b9%e7%ae%a1%e7%90%86%e5%99%a8%e7%b1%bb" class="header-anchor"&gt;&lt;/a&gt;收费管理器类
&lt;/h3&gt;&lt;p&gt;在收费管理器类中扫描和加载所有带有@VehicleType注解的车辆类，并提供计算收费的方法。在这里获取信息是直接通过注解进行的。&lt;/p&gt;
&lt;h3 id="车辆接口"&gt;&lt;a href="#%e8%bd%a6%e8%be%86%e6%8e%a5%e5%8f%a3" class="header-anchor"&gt;&lt;/a&gt;车辆接口
&lt;/h3&gt;&lt;p&gt;车辆接口，用于提供一个默认方法计算车辆收费。&lt;/p&gt;
&lt;h3 id="各种车辆类"&gt;&lt;a href="#%e5%90%84%e7%a7%8d%e8%bd%a6%e8%be%86%e7%b1%bb" class="header-anchor"&gt;&lt;/a&gt;各种车辆类
&lt;/h3&gt;&lt;p&gt;只需要在类前加上@VehicleType注解，指定相应值即可，不用侵入原有代码。&lt;/p&gt;
&lt;h3 id="主函数"&gt;&lt;a href="#%e4%b8%bb%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;主函数
&lt;/h3&gt;&lt;p&gt;创建TollManager实例进行业务逻辑。&lt;/p&gt;
&lt;h2 id="2-配合properties配置文件"&gt;&lt;a href="#2-%e9%85%8d%e5%90%88properties%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;2. 配合properties配置文件
&lt;/h2&gt;&lt;h3 id="注解类-1"&gt;&lt;a href="#%e6%b3%a8%e8%a7%a3%e7%b1%bb-1" class="header-anchor"&gt;&lt;/a&gt;注解类
&lt;/h3&gt;&lt;p&gt;在注解类中定义所需要的元素，在配合properties配置文件的情况下只需要一个配置文件中的键名。&lt;/p&gt;
&lt;h3 id="车辆配置管理类"&gt;&lt;a href="#%e8%bd%a6%e8%be%86%e9%85%8d%e7%bd%ae%e7%ae%a1%e7%90%86%e7%b1%bb" class="header-anchor"&gt;&lt;/a&gt;车辆配置管理类
&lt;/h3&gt;&lt;p&gt;从配置文件（vehicles.properties）中读取和管理车辆相关的配置信息。&lt;/p&gt;
&lt;h3 id="收费管理器类-1"&gt;&lt;a href="#%e6%94%b6%e8%b4%b9%e7%ae%a1%e7%90%86%e5%99%a8%e7%b1%bb-1" class="header-anchor"&gt;&lt;/a&gt;收费管理器类
&lt;/h3&gt;&lt;p&gt;在收费管理器类中扫描和加载所有带有@VehicleType注解的车辆类，并提供计算收费的方法。在这里获取信息是先拿到注解中的配置文件中的键名，再通过车辆配置管理类提供的方法从配置文件中获取相应的数据。&lt;/p&gt;
&lt;h3 id="车辆接口-1"&gt;&lt;a href="#%e8%bd%a6%e8%be%86%e6%8e%a5%e5%8f%a3-1" class="header-anchor"&gt;&lt;/a&gt;车辆接口
&lt;/h3&gt;&lt;p&gt;车辆接口，用于提供一个默认方法计算车辆收费。&lt;/p&gt;
&lt;h3 id="各种车辆类-1"&gt;&lt;a href="#%e5%90%84%e7%a7%8d%e8%bd%a6%e8%be%86%e7%b1%bb-1" class="header-anchor"&gt;&lt;/a&gt;各种车辆类
&lt;/h3&gt;&lt;p&gt;只需要在类前加上@VehicleType注解，指定相应值即可，不用侵入原有代码。&lt;/p&gt;
&lt;h3 id="主函数-1"&gt;&lt;a href="#%e4%b8%bb%e5%87%bd%e6%95%b0-1" class="header-anchor"&gt;&lt;/a&gt;主函数
&lt;/h3&gt;&lt;p&gt;创建TollManager实例进行业务逻辑。&lt;/p&gt;
&lt;h2 id="3-只用properties配置文件不用注解"&gt;&lt;a href="#3-%e5%8f%aa%e7%94%a8properties%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6%e4%b8%8d%e7%94%a8%e6%b3%a8%e8%a7%a3" class="header-anchor"&gt;&lt;/a&gt;3. 只用properties配置文件，不用注解
&lt;/h2&gt;&lt;p&gt;只用properties配置文件唯一的不同就在于，将类的所有信息都放在配置文件中，包括类名，名称，价格等等，只需要从配置文件中读取即可。&lt;/p&gt;
&lt;h2 id="4-使用-reflections-库"&gt;&lt;a href="#4-%e4%bd%bf%e7%94%a8-reflections-%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;4. 使用 Reflections 库
&lt;/h2&gt;&lt;p&gt;使用reflections库，信息读取的方式变成了使用 Reflections 扫描指定包下的所有 Vehicle 实现类，从实现类中读取信息。&lt;/p&gt;
&lt;h2 id="5-主要区别"&gt;&lt;a href="#5-%e4%b8%bb%e8%a6%81%e5%8c%ba%e5%88%ab" class="header-anchor"&gt;&lt;/a&gt;5. 主要区别
&lt;/h2&gt;&lt;p&gt;用不用配置文件的主要区别就在于&lt;strong&gt;注解中信息的多少&lt;/strong&gt;，你可以把全部信息都放到注解中，也可以只放一个配置文件中的键名。在之后的获取信息步骤，要么通过注解拿到所有信息，要么通过注解中的键名用车辆配置管理类从配置文件（vehicles.properties）中读取和管理车辆相关的配置信息。&lt;/p&gt;
&lt;p&gt;使用不同的方法的主要区别就是读取信息方式的不同，单纯用注解就是到注解中获取所需的信息；注解加配置文件就是先从注解中读取键名，再到配置文件中读取其他信息；只用properties配置文件，不用注解就只从配置文件中读取信息；使用 Reflections 库就是使用 Reflections 扫描指定包下的所有 Vehicle 实现类，从实现类中读取信息。&lt;/p&gt;</description></item><item><title>Three-terminal-communication</title><link>https://dandansad.com/2025/03/11/three-terminal-communication/</link><pubDate>Tue, 11 Mar 2025 01:37:05 +0800</pubDate><guid>https://dandansad.com/2025/03/11/three-terminal-communication/</guid><description>&lt;p&gt;一个socket应用程序，有服务端、消费端和充值端。不同端通过对象处理流用一个MyTransaction类来进行信息传输。服务端监听端口，并开一个新线程对发来的信息执行相应操作。消费端向服务端发送消费请求，充值端向服务端发送充值请求。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;&lt;span style="color:#f92672"&gt;---&lt;/span&gt;v2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ConsumeClient.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MyTransaction.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RechargeClient.java
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Server.java
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="mytransactionjava"&gt;&lt;a href="#mytransactionjava" class="header-anchor"&gt;&lt;/a&gt;MyTransaction.java
&lt;/h2&gt;&lt;p&gt;交易类，用于传输交易信息，实现了java.io.Serializable接口用于序列化。除了该有的账户名、金额、交易信息、是否成功外，还用了一个枚举类型来区分是消费请求还是充值请求。此外，还有应有的构造函数和GetSet方法。&lt;/p&gt;
&lt;h2 id="serverjava"&gt;&lt;a href="#serverjava" class="header-anchor"&gt;&lt;/a&gt;Server.java
&lt;/h2&gt;&lt;p&gt;主函数中使用ServerSocket不断对指定端口进行监听是否有连接请求，通过 accept() 方法接受连接后创建一个实际的网络连接Socket。然后新开一个实现了Runnable接口的ClientHandler方法的线程，在线程中从客户端 Socket 获取输入输出流，并将输入输出流包装成ObjectInputStream/ObjectOutputStream。之后从流中读取MyTransaction对象，执行相应逻辑后修改MyTransaction对象信息重新发回客户端。同时由于涉及到多线程，于是使用Collections.synchronizedMap将Map变成线程安全的Map。&lt;/p&gt;
&lt;h2 id="rechargeclientjava"&gt;&lt;a href="#rechargeclientjava" class="header-anchor"&gt;&lt;/a&gt;RechargeClient.java
&lt;/h2&gt;&lt;p&gt;循环读入用户输入，创建Socket连接向服务端发送信息，之后等待接收回复信息，输出结果。Socket连接不保持，每个请求都重新创建。&lt;/p&gt;
&lt;h2 id="consumeclientjava"&gt;&lt;a href="#consumeclientjava" class="header-anchor"&gt;&lt;/a&gt;ConsumeClient.java
&lt;/h2&gt;
 &lt;blockquote&gt;
 &lt;p&gt;用户事件调度线程EDT：负责对GUI组件的渲染和刷新，它只有一个，一定要注意这个问题，它处理的就是事件队列里的事情，他通过调用事件处理器来响应用户交互。所有的事件处理都是在EDT上进行的。&lt;/p&gt;

 &lt;/blockquote&gt;

 &lt;blockquote&gt;
 &lt;ul&gt;
&lt;li&gt;&lt;strong&gt;不能在主线程更新UI操作&lt;/strong&gt;或执行耗时操作&lt;/li&gt;
&lt;/ul&gt;

 &lt;/blockquote&gt;

 &lt;blockquote&gt;
 &lt;ul&gt;
&lt;li&gt;&lt;strong&gt;所有的耗时操作应在非EDT中执行&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

 &lt;/blockquote&gt;

 &lt;blockquote&gt;
 &lt;ul&gt;
&lt;li&gt;&lt;strong&gt;所有的更新UI操作应该在EDT中执行&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

 &lt;/blockquote&gt;

 &lt;blockquote&gt;
 
 &lt;/blockquote&gt;
&lt;p&gt;在主函数中调用&lt;code&gt;SwingUtilities.invokeLater()&lt;/code&gt;在EDT队列尾部插入GUI界面生成事件，并等待异步执行。GUI绘制省略不说。输入信息点击按钮后执行handleTransaction()函数校验输入，通过后调用sendTransaction()方法发送交易信息。在sendTransaction()函数中，也是同充值端一样创建Socket连接向服务端发送信息，之后等待接收回复信息，输出结果。&lt;/p&gt;</description></item><item><title>软件工程课堂讨论二</title><link>https://dandansad.com/2024/11/01/%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B%E8%AF%BE%E5%A0%82%E8%AE%A8%E8%AE%BA%E4%BA%8C/</link><pubDate>Fri, 01 Nov 2024 02:59:46 +0800</pubDate><guid>https://dandansad.com/2024/11/01/%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B%E8%AF%BE%E5%A0%82%E8%AE%A8%E8%AE%BA%E4%BA%8C/</guid><description>&lt;h2 id="计算器实现"&gt;&lt;a href="#%e8%ae%a1%e7%ae%97%e5%99%a8%e5%ae%9e%e7%8e%b0" class="header-anchor"&gt;&lt;/a&gt;计算器实现
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Calculator&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;__init__&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [] &lt;span style="color:#75715e"&gt;# 用于存储输入的计算表达式&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;press_key&lt;/span&gt;(self, key):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;is_valid_key(key):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; key &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;=&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;calculate()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; result &lt;span style="color:#f92672"&gt;is&lt;/span&gt; &lt;span style="color:#f92672"&gt;not&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;just_clear()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# for ch in str(result):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# self.add_to_queue(ch) # 将结果添加到队列中&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(result)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;elif&lt;/span&gt; key &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;AC&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;clear()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;elif&lt;/span&gt; key &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;+/-&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;toggle_sign()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;elif&lt;/span&gt; key &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;%&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;percent()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;add_to_queue(key)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;is_valid_key&lt;/span&gt;(self, key):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; valid_keys &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#39;AC&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;+/-&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;%&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;*&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;-&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;+&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;=&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;2&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;3&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;4&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;5&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;6&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;7&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;8&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;9&amp;#39;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; key &lt;span style="color:#f92672"&gt;in&lt;/span&gt; valid_keys
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;add_to_queue&lt;/span&gt;(self, key):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; key&lt;span style="color:#f92672"&gt;.&lt;/span&gt;isdigit():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 处理数字输入&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; len(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;and&lt;/span&gt; key &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 避免添加无意义的0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; len(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue) &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;and&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue[&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]&lt;span style="color:#f92672"&gt;.&lt;/span&gt;isdigit() &lt;span style="color:#f92672"&gt;and&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue[&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;] &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pop() &lt;span style="color:#75715e"&gt;# 删除之前的无意义0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(key)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;elif&lt;/span&gt; key &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 检查队列中是否已有小数点，确保只能在数字后添加小数点&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; len(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue) &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;and&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue[&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]&lt;span style="color:#f92672"&gt;.&lt;/span&gt;isdigit():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 遍历队列，确保在最近的运算符前没有小数点&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(len(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue[i] &lt;span style="color:#f92672"&gt;in&lt;/span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#39;+&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;-&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;*&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;}:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 遇到运算符停止&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;in&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue[i]:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 如果在数字中已经有小数点，忽略输入&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue[&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;] &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 将小数点添加到最后的数字&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; len(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;: &lt;span style="color:#75715e"&gt;# 如果队列为空，不允许直接输入运算符&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; last_key &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue[&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 不允许连续运算符&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; last_key &lt;span style="color:#f92672"&gt;in&lt;/span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#39;+&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;-&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;*&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;} &lt;span style="color:#f92672"&gt;and&lt;/span&gt; key &lt;span style="color:#f92672"&gt;in&lt;/span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#39;+&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;-&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;*&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;}:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(key)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;clear&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#34;Calculator cleared.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;just_clear&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;toggle_sign&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; len(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue) &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;and&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue[&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]&lt;span style="color:#f92672"&gt;.&lt;/span&gt;replace(&lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;isdigit(): &lt;span style="color:#75715e"&gt;# 处理数字或小数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; number &lt;span style="color:#f92672"&gt;=&lt;/span&gt; str(&lt;span style="color:#f92672"&gt;-&lt;/span&gt;float(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue[&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue[&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; number
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Toggled sign: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;number&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;percent&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; len(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue) &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;and&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue[&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]&lt;span style="color:#f92672"&gt;.&lt;/span&gt;replace(&lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;isdigit(): &lt;span style="color:#75715e"&gt;# 处理数字或小数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; number &lt;span style="color:#f92672"&gt;=&lt;/span&gt; str(float(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue[&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]) &lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue[&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; number
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Percent: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;number&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;calculate&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; expression &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;join(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;queue)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(expression,end&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;=&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; eval(expression)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; result
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;except&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Exception&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; e:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Error&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;e&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;clear()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 示例用法&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Calculator()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;+&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;5&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;=&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;AC&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;2&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;*&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;5&amp;#39;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# 形成小数0.5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;=&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;3&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;3&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;+&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;2&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;=&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;3&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;3&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;+&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;2&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;5&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;=&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;3&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;+&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;2&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;=&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;3&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;+&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;2&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;=&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;3&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;+&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;2&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;calculator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;press_key(&lt;span style="color:#e6db74"&gt;&amp;#39;=&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>软件工程课堂讨论一</title><link>https://dandansad.com/2024/10/11/%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B%E8%AF%BE%E5%A0%82%E8%AE%A8%E8%AE%BA%E4%B8%80/</link><pubDate>Fri, 11 Oct 2024 03:01:25 +0800</pubDate><guid>https://dandansad.com/2024/10/11/%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B%E8%AF%BE%E5%A0%82%E8%AE%A8%E8%AE%BA%E4%B8%80/</guid><description>&lt;h2 id="从运行状态到阻塞状态有等待锁的情况吗"&gt;&lt;a href="#%e4%bb%8e%e8%bf%90%e8%a1%8c%e7%8a%b6%e6%80%81%e5%88%b0%e9%98%bb%e5%a1%9e%e7%8a%b6%e6%80%81%e6%9c%89%e7%ad%89%e5%be%85%e9%94%81%e7%9a%84%e6%83%85%e5%86%b5%e5%90%97" class="header-anchor"&gt;&lt;/a&gt;从运行状态到阻塞状态有等待锁的情况吗？
&lt;/h2&gt;&lt;p&gt;当一个线程试图获取一个锁（如 &lt;code&gt;synchronized&lt;/code&gt; 块或 &lt;code&gt;ReentrantLock&lt;/code&gt;），如果该锁已经被其他线程持有，当前线程无法立即获取锁时，就会从运行状态（&lt;code&gt;Running&lt;/code&gt;）转换为阻塞状态（&lt;code&gt;Blocked&lt;/code&gt;），直到锁被释放。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="../../images/2024/10/image.png"&gt;&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;文章最后部分有两个讨论：&lt;/p&gt;

 &lt;/blockquote&gt;

 &lt;blockquote&gt;
 &lt;ul&gt;
&lt;li&gt;获取到锁的线程为什么不直接执行到结束，这样就不会占用锁了？&lt;/li&gt;
&lt;/ul&gt;

 &lt;/blockquote&gt;

 &lt;blockquote&gt;
 &lt;ul&gt;
&lt;li&gt;为什么不在调度线程前检测这个线程要用到的锁有没有被占用从而判断要不要调度该线程？&lt;/li&gt;
&lt;/ul&gt;

 &lt;/blockquote&gt;

 &lt;blockquote&gt;
 
 &lt;/blockquote&gt;
&lt;h2 id="yield的使用场景"&gt;&lt;a href="#yield%e7%9a%84%e4%bd%bf%e7%94%a8%e5%9c%ba%e6%99%af" class="header-anchor"&gt;&lt;/a&gt;&lt;code&gt;yield&lt;/code&gt;的使用场景？
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;yield&lt;/code&gt;在Python和Java中的作用完全不同。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python中的 &lt;code&gt;yield&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在 Python 中，&lt;code&gt;yield&lt;/code&gt; 是一种用于定义&lt;strong&gt;生成器&lt;/strong&gt;（Generator）的关键字，它的作用是将函数变成一个生成器函数。生成器函数在调用时不会一次性执行完毕，而是返回一个生成器对象，可以在迭代过程中多次暂停并继续。&lt;/p&gt;
&lt;p&gt;使用场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;迭代大数据集合&lt;/strong&gt;：当处理的数据量非常大时，如果使用普通的 &lt;code&gt;return&lt;/code&gt; 返回整个集合，会导致内存占用过高。使用 &lt;code&gt;yield&lt;/code&gt; 可以让函数每次返回一个数据，迭代时才真正计算或生成下一个数据。例如，从文件中逐行读取数据，或生成一个无限序列时，&lt;code&gt;yield&lt;/code&gt; 可以显著减少内存使用。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;简化迭代器实现&lt;/strong&gt;：Python 中可以通过 &lt;code&gt;yield&lt;/code&gt; 简单地创建一个自定义的迭代器，而不需要实现 &lt;code&gt;__iter__&lt;/code&gt; 和 &lt;code&gt;__next__&lt;/code&gt; 方法。生成器函数使用 &lt;code&gt;yield&lt;/code&gt; 暂停并返回一个值，下次迭代时从上次暂停的地方继续执行。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;流水线数据处理&lt;/strong&gt;：在数据流处理的场景中，例如从某个源头获取数据，逐步处理并将结果传递给下游，&lt;code&gt;yield&lt;/code&gt; 可以用于构建数据管道。这种方式能够按需生成数据，节省内存和处理时间。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Java 中的 &lt;code&gt;yield&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在 Java 中，&lt;code&gt;yield&lt;/code&gt; 这个关键字是 &lt;code&gt;Thread&lt;/code&gt; 类的一个静态方法，用于线程调度。Java 的 &lt;code&gt;Thread.yield()&lt;/code&gt; 方法使当前线程将 CPU 的执行权暂时让给其他同样处于可运行状态的线程。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;ul&gt;
&lt;li&gt;&lt;code&gt;sleep&lt;/code&gt;执行后线程进入&lt;strong&gt;阻塞状态&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

 &lt;/blockquote&gt;

 &lt;blockquote&gt;
 &lt;ul&gt;
&lt;li&gt;&lt;code&gt;yield&lt;/code&gt;执行后线程进入&lt;strong&gt;就绪状态&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

 &lt;/blockquote&gt;

 &lt;blockquote&gt;
 &lt;ul&gt;
&lt;li&gt;&lt;code&gt;join&lt;/code&gt;执行后线程进入&lt;strong&gt;阻塞状态&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

 &lt;/blockquote&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;code&gt;yield()&lt;/code&gt;应该做的是让当前运行线程回到可运行状态，以允许具有相同优先级的其他线程获得运行机会。因此，使用&lt;code&gt;yield()&lt;/code&gt;的目的是让相同优先级的线程之间能适当的&lt;strong&gt;轮转执行&lt;/strong&gt;。但是，实际中无法保证&lt;code&gt;yield()&lt;/code&gt;达到让步目的，因为让步的线程还有可能被线程调度程序再次选中。&lt;/p&gt;

 &lt;/blockquote&gt;

 &lt;blockquote&gt;
 &lt;p&gt;所以说&lt;code&gt;yield()&lt;/code&gt;从未导致线程转到等待/睡眠/阻塞状态。在大多数情况下，&lt;code&gt;yield()&lt;/code&gt;将导致线程从运行状态转到可运行状态，但有可能没有效果。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;使用场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;让步 CPU 时间片&lt;/strong&gt;：当当前线程执行到某个位置，可以适当让出 CPU，给其他优先级相同的线程执行的机会时，可以调用 &lt;code&gt;Thread.yield()&lt;/code&gt;。这并不意味着当前线程会立刻进入阻塞状态，只是让操作系统重新调度当前线程和其他可运行线程。使用 &lt;code&gt;yield&lt;/code&gt; 通常是为了优化多线程的执行效率，在某些高并发环境中，有助于避免一个线程独占 CPU 资源。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;测试和调试目的&lt;/strong&gt;：在调试多线程代码时，有时为了观察线程调度的行为，可以插入 &lt;code&gt;yield()&lt;/code&gt;，以便更清晰地观察不同线程的执行顺序。在这种情况下，&lt;code&gt;yield()&lt;/code&gt; 可以帮助程序员更好地理解多线程程序的行为。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;配合轻量级任务&lt;/strong&gt;：在编写一些不需要长时间运行的轻量级任务时，可以使用 &lt;code&gt;yield()&lt;/code&gt; 来避免某个线程在循环或任务中长时间占用 CPU，从而提高系统资源的利用率。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="不使用yield发生io操作远程调用会自动进入阻塞状态吗"&gt;&lt;a href="#%e4%b8%8d%e4%bd%bf%e7%94%a8yield%e5%8f%91%e7%94%9fio%e6%93%8d%e4%bd%9c%e8%bf%9c%e7%a8%8b%e8%b0%83%e7%94%a8%e4%bc%9a%e8%87%aa%e5%8a%a8%e8%bf%9b%e5%85%a5%e9%98%bb%e5%a1%9e%e7%8a%b6%e6%80%81%e5%90%97" class="header-anchor"&gt;&lt;/a&gt;不使用&lt;code&gt;yield&lt;/code&gt;发生IO操作/远程调用会自动进入阻塞状态吗？
&lt;/h2&gt;&lt;p&gt;其实这个问题问出来是有问题的。&lt;/p&gt;
&lt;p&gt;首先，&lt;code&gt;yield&lt;/code&gt;在Python和Java中的作用完全不同，我们这里并没有明确指出我们讨论的是哪一个。当然了，依照问题提出的场景，我们可以确定这个问题更准确的版本是——在用Python写的爬虫中，如果我不使用&lt;code&gt;yield&lt;/code&gt;，当发生IO操作/远程调用会自动进入阻塞状态吗？&lt;/p&gt;
&lt;p&gt;当然，这样问的话又引出了第二个问题。那就是在Python中&lt;code&gt;yield&lt;/code&gt;是一种用于定义生成器的关键字，是实现&lt;strong&gt;异步操作&lt;/strong&gt;的，与&lt;strong&gt;线程调度&lt;/strong&gt;完完全全没有关系。所以对于这个问题，不管你使用还是不使用&lt;code&gt;yield&lt;/code&gt;，都不能回答发生IO操作/远程调用是否会自动进入阻塞状态。&lt;/p&gt;
&lt;p&gt;那对于发生IO操作/远程调用是否会自动进入阻塞状态这个问题来说，答案是只要你使用了线程，就会在该线程发生IO操作/远程调用时自动进入阻塞状态，也即会自动进行线程调度。&lt;/p&gt;
&lt;p&gt;对于提出错误问题的原因有二：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;一是把Python和Java中的&lt;code&gt;yield&lt;/code&gt;搞混淆了。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;二是把异步编程与线程调度的概念搞混淆了。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

 &lt;blockquote&gt;
 &lt;p&gt;文章最后部分有两个讨论：&lt;/p&gt;

 &lt;/blockquote&gt;

 &lt;blockquote&gt;
 &lt;ul&gt;
&lt;li&gt;在Python写的爬虫里面会用到&lt;code&gt;yield&lt;/code&gt;吗?&lt;/li&gt;
&lt;/ul&gt;

 &lt;/blockquote&gt;

 &lt;blockquote&gt;
 &lt;ul&gt;
&lt;li&gt;异步操作和线程调度的区别&lt;/li&gt;
&lt;/ul&gt;

 &lt;/blockquote&gt;

 &lt;blockquote&gt;
 
 &lt;/blockquote&gt;
&lt;h2 id="一些讨论"&gt;&lt;a href="#%e4%b8%80%e4%ba%9b%e8%ae%a8%e8%ae%ba" class="header-anchor"&gt;&lt;/a&gt;一些讨论
&lt;/h2&gt;&lt;h3 id="1-获取到锁的线程为什么不直接执行到结束这样就不会占用锁了"&gt;&lt;a href="#1-%e8%8e%b7%e5%8f%96%e5%88%b0%e9%94%81%e7%9a%84%e7%ba%bf%e7%a8%8b%e4%b8%ba%e4%bb%80%e4%b9%88%e4%b8%8d%e7%9b%b4%e6%8e%a5%e6%89%a7%e8%a1%8c%e5%88%b0%e7%bb%93%e6%9d%9f%e8%bf%99%e6%a0%b7%e5%b0%b1%e4%b8%8d%e4%bc%9a%e5%8d%a0%e7%94%a8%e9%94%81%e4%ba%86" class="header-anchor"&gt;&lt;/a&gt;1. 获取到锁的线程为什么不直接执行到结束，这样就不会占用锁了？
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;线程执行过程中被操作系统挂起：&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;线程的执行并不是连续的，它受限于操作系统的线程调度机制。在多任务操作系统中，CPU 会在多个线程之间进行时间片轮转调度。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;假设 &lt;code&gt;Thread A&lt;/code&gt; 获得了锁并开始执行，但在执行过程中，操作系统把它的时间片分配给了其他线程，此时 &lt;code&gt;Thread A&lt;/code&gt; 被挂起。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;尽管 &lt;code&gt;Thread A&lt;/code&gt; 还没有完成对锁的操作，但它的执行被暂停了，锁依然被它持有，其他线程如 &lt;code&gt;Thread B&lt;/code&gt; 只能等待，直到操作系统再次调度 &lt;code&gt;Thread A&lt;/code&gt; 执行并完成释放锁的操作。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;锁保护的代码块执行时间过长：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果 &lt;code&gt;Thread A&lt;/code&gt; 在持有锁时，执行的受保护的代码块非常耗时，例如需要进行复杂的计算、文件读写操作、数据库访问等，就会导致它占用锁的时间变长。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;这种情况下，其他线程在 &lt;code&gt;Thread A&lt;/code&gt; 完成这些耗时操作之前，都无法获取到锁，只能进入阻塞状态等待。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;线程在持有锁期间发生阻塞操作：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果 &lt;code&gt;Thread A&lt;/code&gt; 在持有锁时，执行了可能会阻塞的操作，比如：&lt;/p&gt;
&lt;p&gt;等待 I/O 操作完成（如读取文件、网络请求）。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;调用了 &lt;code&gt;sleep()&lt;/code&gt; 方法或其他可能导致线程暂停的操作。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;这会导致 &lt;code&gt;Thread A&lt;/code&gt; 在持有锁的情况下等待外部资源，而此时锁不能被释放，其他线程就只能等待。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;代码设计不合理：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;有时候，程序设计者可能没有合理地设计锁的粒度，即锁住的代码块过大，导致持有锁的时间变长。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;比如，某个方法中的很多操作其实不需要加锁，但是由于整个方法都被 &lt;code&gt;synchronized&lt;/code&gt; 关键字修饰，导致所有操作都必须等到锁释放后才能执行。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;更好的做法是&lt;strong&gt;缩小锁的粒度&lt;/strong&gt;，只在必要的地方使用锁，这样可以减少锁的持有时间，从而提高并发性能。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;死锁问题：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在某些情况下，可能出现&lt;strong&gt;死锁&lt;/strong&gt;，即多个线程相互等待对方释放锁，导致所有线程都被阻塞，无法继续执行。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;例如，&lt;code&gt;Thread A&lt;/code&gt; 持有锁 &lt;code&gt;Lock1&lt;/code&gt;，等待 &lt;code&gt;Lock2&lt;/code&gt;，而 &lt;code&gt;Thread B&lt;/code&gt; 持有 &lt;code&gt;Lock2&lt;/code&gt;，等待 &lt;code&gt;Lock1&lt;/code&gt;。这就会导致两者相互等待，永远无法完成。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如何优化锁的使用：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;缩小锁的粒度&lt;/strong&gt;：只对真正需要保护的代码段加锁，尽量减少锁的使用范围。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;使用更高效的锁机制&lt;/strong&gt;：如 &lt;code&gt;ReentrantLock&lt;/code&gt; 提供了更多的灵活性，还可以用 &lt;code&gt;tryLock()&lt;/code&gt; 方法来避免无限制等待。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;避免持有锁时进行耗时操作&lt;/strong&gt;：例如，尽量不要在持有锁的代码段中进行 I/O 操作。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;使用读写锁&lt;/strong&gt;（如 &lt;code&gt;ReadWriteLock&lt;/code&gt;）：如果有大量的读操作，可以使用读写锁来提高性能，让多个读线程并发访问，而写线程会独占。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-为什么不在调度线程前检测这个线程要用到的锁有没有被占用从而判断要不要调度该线程"&gt;&lt;a href="#2-%e4%b8%ba%e4%bb%80%e4%b9%88%e4%b8%8d%e5%9c%a8%e8%b0%83%e5%ba%a6%e7%ba%bf%e7%a8%8b%e5%89%8d%e6%a3%80%e6%b5%8b%e8%bf%99%e4%b8%aa%e7%ba%bf%e7%a8%8b%e8%a6%81%e7%94%a8%e5%88%b0%e7%9a%84%e9%94%81%e6%9c%89%e6%b2%a1%e6%9c%89%e8%a2%ab%e5%8d%a0%e7%94%a8%e4%bb%8e%e8%80%8c%e5%88%a4%e6%96%ad%e8%a6%81%e4%b8%8d%e8%a6%81%e8%b0%83%e5%ba%a6%e8%af%a5%e7%ba%bf%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;2. 为什么不在调度线程前检测这个线程要用到的锁有没有被占用从而判断要不要调度该线程？
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;锁的持有状态是动态的：&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;锁的状态会随着线程执行过程中的操作而不断变化&lt;/strong&gt;。一个锁可能在某一时刻被占用，但在另一个时刻就释放了。操作系统在调度线程时，如果预先检测锁状态，就可能在做出调度决定时，锁的状态已经改变了。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;举例来说，如果操作系统在某个瞬间检测到 &lt;code&gt;Thread A&lt;/code&gt; 想要使用的锁 &lt;code&gt;Lock1&lt;/code&gt; 被 &lt;code&gt;Thread B&lt;/code&gt; 占用，因此不调度 &lt;code&gt;Thread A&lt;/code&gt;，但这时 &lt;code&gt;Thread B&lt;/code&gt; 可能正好释放了 &lt;code&gt;Lock1&lt;/code&gt;。如果再重新调度 &lt;code&gt;Thread A&lt;/code&gt;，就会引入额外的延迟。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;线程的调度和锁管理分属不同层次：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;线程调度&lt;/strong&gt;是由操作系统的内核负责的，而&lt;strong&gt;锁的管理&lt;/strong&gt;则往往由用户级的程序或线程库（如 Java 的 &lt;code&gt;synchronized&lt;/code&gt; 或 &lt;code&gt;ReentrantLock&lt;/code&gt;）来实现。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;调度器不直接知道一个线程将要访问哪些具体资源，它只是基于线程的优先级、状态（如就绪、运行）等进行调度。而锁的管理发生在更高层次的应用逻辑中，操作系统不会对应用层的锁状态进行管理。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;为了让调度器了解每一个线程在未来会访问哪些锁，并在调度前进行检查，需要建立复杂的机制，这会大大增加操作系统的复杂性和调度开销。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;预判锁的使用并不总是可靠：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在多线程环境中，线程的执行顺序和锁的请求顺序是不可预知的。提前检测一个线程是否需要使用某个锁，实际上是对未来执行路径的预测。这个预测不仅复杂，而且可能并不准确。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;线程的逻辑中，锁的使用通常是由程序执行路径决定的，例如只有在满足某个条件时，才会去获取某个锁。操作系统很难提前判断某个线程在执行过程中一定会请求某个锁。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;效率问题：调度开销和频繁检测：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;假设操作系统在每次调度前都要检查一个线程要使用的锁是否被占用，那么对于大量的线程和锁，这种检查操作会极大地增加调度的开销。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;频繁的锁状态检查会消耗更多的系统资源，尤其是当有大量线程频繁竞争少数几个锁时，这种机制可能会导致更多的系统开销，而不是提升整体的效率。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;现代调度器的设计已经优化了线程的等待：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;现代操作系统的调度器已经优化了线程在等待状态下的调度。例如，当一个线程因为等待锁进入阻塞状态时，调度器会将它放入等待队列中，而不会浪费 CPU 资源反复检查。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;当锁释放时，调度器会及时唤醒等待的线程，并尽快让其获取锁继续执行。这样做的好处是，可以让其他不需要该锁的线程在这段时间内利用 CPU 资源，提升系统的整体效率。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;锁的竞争是正常的并发现象：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;锁竞争&lt;/strong&gt;是多线程编程中的一种正常现象，操作系统通过调度算法和锁管理机制，尽量让锁的竞争对系统性能的影响降到最低。提前预判并不总是最佳选择，因为在多数情况下，线程在获取锁后能够快速完成操作。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;通过设计更高效的并发程序，例如减少临界区的代码量、合理使用锁的粒度、避免不必要的锁定操作，往往可以更有效地解决锁竞争问题。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3-在python写的爬虫里面会用到yield吗"&gt;&lt;a href="#3-%e5%9c%a8python%e5%86%99%e7%9a%84%e7%88%ac%e8%99%ab%e9%87%8c%e9%9d%a2%e4%bc%9a%e7%94%a8%e5%88%b0yield%e5%90%97" class="header-anchor"&gt;&lt;/a&gt;3. 在Python写的爬虫里面会用到&lt;code&gt;yield&lt;/code&gt;吗?
&lt;/h3&gt;&lt;p&gt;答案是是的，但是在 Python 写的爬虫中，&lt;code&gt;yield&lt;/code&gt; 是被用来进行异步操作和作为生成器的。下面是 Python 爬虫中使用 &lt;code&gt;yield&lt;/code&gt; 的一些常见场景及其优势：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 逐步获取网页数据&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;在爬取大量网页时，如果一次性将所有数据加载到内存中，会占用大量内存。使用 &lt;code&gt;yield&lt;/code&gt; 可以在每次请求到数据时返回一部分，允许逐步处理数据，而不是一次性获取所有内容。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;这在处理分页数据时尤为常见，比如爬取多页列表数据时，通过生成器逐页获取。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例：逐页爬取网页数据&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; requests
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fetch_pages&lt;/span&gt;(url, max_pages&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; page &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; page 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; 爬虫抓取到大量数据时&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;可以使用生成器逐个解析和处理每条记录&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt;通过 &lt;span style="color:#960050;background-color:#1e0010"&gt;`&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;yield&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;`，&lt;/span&gt;你可以在读取数据的同时进行解析&lt;span style="color:#960050;background-color:#1e0010"&gt;，&lt;/span&gt;避免一次性处理所有数据&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; 这对于解析 JSON 格式的 API 数据或 HTML 页面中的条目非常有用&lt;span style="color:#960050;background-color:#1e0010"&gt;。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;**&lt;/span&gt;示例&lt;span style="color:#960050;background-color:#1e0010"&gt;：&lt;/span&gt;逐条解析 JSON 数据&lt;span style="color:#f92672"&gt;**&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;```&lt;/span&gt;python
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; requests
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; json
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fetch_items&lt;/span&gt;(api_url):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; response &lt;span style="color:#f92672"&gt;=&lt;/span&gt; requests&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(api_url)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; data &lt;span style="color:#f92672"&gt;=&lt;/span&gt; json&lt;span style="color:#f92672"&gt;.&lt;/span&gt;loads(response&lt;span style="color:#f92672"&gt;.&lt;/span&gt;content)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; item &lt;span style="color:#f92672"&gt;in&lt;/span&gt; data&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#39;results&amp;#39;&lt;/span&gt;, []):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;yield&lt;/span&gt; item &lt;span style="color:#75715e"&gt;# 使用 yield 返回每一条记录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 逐条处理数据&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; item &lt;span style="color:#f92672"&gt;in&lt;/span&gt; fetch_items(&lt;span style="color:#e6db74"&gt;&amp;#34;https://example.com/api/data&amp;#34;&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(item)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这个例子中，&lt;code&gt;fetch_items&lt;/code&gt; 函数使用 &lt;code&gt;yield&lt;/code&gt; 将解析后的每条记录逐条返回。调用方可以一条条处理数据，适合处理数据量大的场景。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. 实现异步爬取与处理&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;在协程和异步编程中，&lt;code&gt;yield&lt;/code&gt; 可以配合 &lt;code&gt;asyncio&lt;/code&gt; 和 &lt;code&gt;aiohttp&lt;/code&gt; 等库使用，构建异步生成器。这种方式可以同时爬取多个网页，而不必等待每一个网页的响应，从而提高爬取速度。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;虽然在 Python 3.5 以后，&lt;code&gt;async&lt;/code&gt; 和 &lt;code&gt;await&lt;/code&gt; 更为常用，但 &lt;code&gt;yield&lt;/code&gt; 仍然可以在某些特定场景中与异步生成器结合使用。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例：异步爬虫中的生成器&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; aiohttp
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; asyncio
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fetch&lt;/span&gt;(url):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; aiohttp&lt;span style="color:#f92672"&gt;.&lt;/span&gt;ClientSession() &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; session:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; session&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(url) &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; response:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;yield&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; response&lt;span style="color:#f92672"&gt;.&lt;/span&gt;text() &lt;span style="color:#75715e"&gt;# 使用 yield 返回网页内容&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;(urls):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; url &lt;span style="color:#f92672"&gt;in&lt;/span&gt; urls:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; page_content &lt;span style="color:#f92672"&gt;in&lt;/span&gt; fetch(url):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Page content: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;page_content[:&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;]&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# 打印前100个字符&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;urls &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#34;https://example.com/page1&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;https://example.com/page2&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;asyncio&lt;span style="color:#f92672"&gt;.&lt;/span&gt;run(main(urls))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在这个例子中，&lt;code&gt;fetch&lt;/code&gt; 是一个异步生成器函数，它使用 &lt;code&gt;yield&lt;/code&gt; 返回每个请求到的网页内容。这种方式能够更高效地爬取多个网页。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. 数据管道与流水线处理&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;爬虫的数据处理往往需要多个步骤，比如下载页面、解析内容、提取信息等。使用 &lt;code&gt;yield&lt;/code&gt; 可以在这些步骤之间构建数据管道，使得数据在各个步骤之间流动。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;这种方式让爬虫的逻辑更加清晰，并且可以按需生成和处理数据。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例：构建数据管道&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;download_pages&lt;/span&gt;(urls):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; url &lt;span style="color:#f92672"&gt;in&lt;/span&gt; urls:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; response &lt;span style="color:#f92672"&gt;=&lt;/span&gt; requests&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(url)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; response&lt;span style="color:#f92672"&gt;.&lt;/span&gt;status_code &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;yield&lt;/span&gt; response&lt;span style="color:#f92672"&gt;.&lt;/span&gt;content
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;parse_pages&lt;/span&gt;(pages):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; page &lt;span style="color:#f92672"&gt;in&lt;/span&gt; pages:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 假设这里使用 BeautifulSoup 解析 HTML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;yield&lt;/span&gt; page[:&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;] &lt;span style="color:#75715e"&gt;# 简单返回前100个字符作为示例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 组合生成器&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;urls &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#34;https://example.com/page1&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;https://example.com/page2&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pages &lt;span style="color:#f92672"&gt;=&lt;/span&gt; download_pages(urls)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;parsed_data &lt;span style="color:#f92672"&gt;=&lt;/span&gt; parse_pages(pages)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 逐步处理数据&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; data &lt;span style="color:#f92672"&gt;in&lt;/span&gt; parsed_data:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Parsed data: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;data&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在这个例子中，&lt;code&gt;download_pages&lt;/code&gt; 和 &lt;code&gt;parse_pages&lt;/code&gt; 都是生成器，使用 &lt;code&gt;yield&lt;/code&gt; 形成数据管道。这使得每个步骤都能逐步处理数据，避免一次性占用大量内存。&lt;/p&gt;
&lt;h3 id="4-异步操作和线程调度的区别"&gt;&lt;a href="#4-%e5%bc%82%e6%ad%a5%e6%93%8d%e4%bd%9c%e5%92%8c%e7%ba%bf%e7%a8%8b%e8%b0%83%e5%ba%a6%e7%9a%84%e5%8c%ba%e5%88%ab" class="header-anchor"&gt;&lt;/a&gt;4. 异步操作和线程调度的区别
&lt;/h3&gt;&lt;p&gt;简单来说，&lt;strong&gt;异步操作&lt;/strong&gt;和&lt;strong&gt;线程调度&lt;/strong&gt;会在某种程度上有一些表现相似，但它们在设计理念、工作方式和适用场景上仍然存在显著的区别。&lt;/p&gt;
&lt;p&gt;由于这是一个比较复杂的问题，而且撰写这篇文章的时候也比较晚了（2024年10月11日星期五02:59），所以这部分是待补充状态。&lt;/p&gt;
&lt;p&gt;以下文章中讨论了&lt;strong&gt;异步操作&lt;/strong&gt;和&lt;strong&gt;线程调度&lt;/strong&gt;的区别：&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://dandansad.com/2025/04/26/%e5%90%8c%e6%ad%a5%e4%b8%8e%e5%bc%82%e6%ad%a5%ef%bc%9f/" target="_blank" rel="noopener"
 &gt;https://dandansad.com/2025/04/26/%e5%90%8c%e6%ad%a5%e4%b8%8e%e5%bc%82%e6%ad%a5%ef%bc%9f/&lt;/a&gt;&lt;/p&gt;</description></item><item><title>当AI成熟之后，老板会选择AI还是真人？</title><link>https://dandansad.com/2024/10/08/%E5%BD%93ai%E6%88%90%E7%86%9F%E4%B9%8B%E5%90%8E%E8%80%81%E6%9D%BF%E4%BC%9A%E9%80%89%E6%8B%A9ai%E8%BF%98%E6%98%AF%E7%9C%9F%E4%BA%BA/</link><pubDate>Tue, 08 Oct 2024 12:08:51 +0800</pubDate><guid>https://dandansad.com/2024/10/08/%E5%BD%93ai%E6%88%90%E7%86%9F%E4%B9%8B%E5%90%8E%E8%80%81%E6%9D%BF%E4%BC%9A%E9%80%89%E6%8B%A9ai%E8%BF%98%E6%98%AF%E7%9C%9F%E4%BA%BA/</guid><description>&lt;p&gt;自ChatGPT在2022年11月上线后，一路开挂，5天时间便突破百万用户，仅2个月时间月活用户就突破1亿，成为史上增速最快的消费级应用，远超TikTok、Facebook、Google等全球应用。也因此，ChatGPT掀起了一场全民AI热潮。&lt;/p&gt;
&lt;p&gt;在当前科技迅猛发展的背景下，各种AI工具如雨后春笋般涌现，并迅速渗透到各行各业。从ChatGPT、Midjourney到自动驾驶技术，这些AI工具在数据分析、图像生成、自然语言处理等领域展现出了强大的能力。企业也纷纷引入AI技术来提升工作效率、降低运营成本。这种趋势使得AI逐渐从辅助工具演变为工作中的重要角色，企业管理者们也面临一个关键选择：当未来AI完全成熟时，是选择AI作为员工，还是保留真人作为员工？&lt;/p&gt;
&lt;p&gt;要讨论这个问题，我认为最重要的前提应该要先行设置好，那就是AI的成熟程度。接下来的讨论将依照AI的成熟程度分为三个阶段进行讨论。&lt;/p&gt;
&lt;h2 id="阶段一ai只作为工作中的辅助工具"&gt;&lt;a href="#%e9%98%b6%e6%ae%b5%e4%b8%80ai%e5%8f%aa%e4%bd%9c%e4%b8%ba%e5%b7%a5%e4%bd%9c%e4%b8%ad%e7%9a%84%e8%be%85%e5%8a%a9%e5%b7%a5%e5%85%b7" class="header-anchor"&gt;&lt;/a&gt;阶段一：AI只作为工作中的辅助工具
&lt;/h2&gt;&lt;p&gt;当AI只是作为工作中的辅助工具时，AI主要作为人类员工的“助手”，帮助他们提高工作效率。例如，在客服行业，AI可以通过自动化回答常见问题，减轻客服人员的负担；在金融领域，AI可以进行数据筛选和风险初步评估，为分析师提供辅助数据。在这一阶段，AI的作用更多是减少重复性劳动和优化流程，而对创造性和复杂决策的工作仍依赖于人类。此时，企业管理者通常会选择将AI与人类员工结合使用，以提高工作效率，为企业赚取更多利益。&lt;/p&gt;
&lt;h2 id="阶段二ai作为工作中的一大主力"&gt;&lt;a href="#%e9%98%b6%e6%ae%b5%e4%ba%8cai%e4%bd%9c%e4%b8%ba%e5%b7%a5%e4%bd%9c%e4%b8%ad%e7%9a%84%e4%b8%80%e5%a4%a7%e4%b8%bb%e5%8a%9b" class="header-anchor"&gt;&lt;/a&gt;阶段二：AI作为工作中的一大主力
&lt;/h2&gt;&lt;p&gt;随着AI技术的进一步发展，当AI作为工作中的一大主力时。在这个阶段，AI能够处理大多数门槛较低的工作，但仍需要人类的共同工作。在此时，管理者会倾向于减少人类员工的雇用，并且雇用的员工也会被要求能够与AI协同工作，以此进一步降低成本，提高工作效率，为企业赚取更多利益。&lt;/p&gt;
&lt;h2 id="阶段三ai成为合格员工"&gt;&lt;a href="#%e9%98%b6%e6%ae%b5%e4%b8%89ai%e6%88%90%e4%b8%ba%e5%90%88%e6%a0%bc%e5%91%98%e5%b7%a5" class="header-anchor"&gt;&lt;/a&gt;阶段三：AI成为合格员工
&lt;/h2&gt;&lt;p&gt;在这个阶段，AI已经发展得非常成熟，几乎可以替代大部分人类员工，甚至在某些方面超越了普通水平的员工。AI不仅能够处理复杂的任务，还具备高度的自主学习和适应能力，可以根据环境和需求不断优化自身的工作方式。AI只需要听从企业管理者的命令，自行迭代地完成相应工作。&lt;/p&gt;
&lt;p&gt;而在这个阶段，企业管理者需要考虑的问题就是：是否要全面用AI替代人类员工，或是保留部分人类岗位。此时企业管理者最主要考虑的问题应该是成本问题。因为一个合格的AI员工各方面的开销也不一定会小于人类员工，所以一些简单的工作，出于成本考虑可能仍然会选择雇用人类员工。&lt;/p&gt;
&lt;h2 id="一些遗漏"&gt;&lt;a href="#%e4%b8%80%e4%ba%9b%e9%81%97%e6%bc%8f" class="header-anchor"&gt;&lt;/a&gt;一些遗漏
&lt;/h2&gt;&lt;p&gt;刚刚的讨论部分并没有提到一些头部的工作，在这里我是默认一些头部的工作是无法被替代的。因为拘于AI的原理特性，AI并不能进行自主的创新，因此一些头部的工作（复杂的、创新型的）是无法被替代的。&lt;/p&gt;
&lt;p&gt;同时，我们的讨论还忽略掉了现实的一些法律法规、社会责任、企业形象等更广泛的考量。我们只是简单从盈利角度讨论这个问题，并不是对现实生活的完美预测。&lt;/p&gt;
&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;p&gt;总的来说，一些不会被AI替代的职位一定会有以下几个特质：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;成本比AI还要低的工作&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;行业里的顶尖工作&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;需要与人类有情感共鸣的工作&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;需要参杂人类道德判断的工作以及一些需要找到责任人的工作&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;剩余一些没有单独罗列的AI无法承担的工作&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;总结下来，老板会选择AI的情况就是AI能够胜任该工作并且当使用AI的费用会低于一个人类员工的情况。所以说，当AI成熟之后，老板会在大部分岗位都选择使用AI，然而仍会保留部分真人的岗位。&lt;/p&gt;</description></item></channel></rss>