<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>大橙子</title>
  
  
  <link href="https://log.660066.xyz/atom.xml" rel="self"/>
  
  <link href="https://log.660066.xyz/"/>
  <updated>2026-05-06T16:10:18.429Z</updated>
  <id>https://log.660066.xyz/</id>
  
  <author>
    <name>BigOrange</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>世界这么大我想去看看-3</title>
    <link href="https://log.660066.xyz/2026/05/06/worldGoToSee4/"/>
    <id>https://log.660066.xyz/2026/05/06/worldGoToSee4/</id>
    <published>2026-05-06T02:56:59.000Z</published>
    <updated>2026-05-06T16:10:18.429Z</updated>
    
    <content type="html"><![CDATA[<h1 id="一-第一次出国"><a class="markdownIt-Anchor" href="#一-第一次出国"></a> 一、第一次出国</h1><p>第一走出国门，说不激动不兴奋是不可能的。当天早早的到了遥墙机场，是晚上9点飞仁川的山航航班。</p><p>到了机场后，先去办值机，工作人员会帮你确认行李箱需不需要托运，当时去的时候，行李箱就是点衣服和一次性浴巾，很轻，就直接带着上机了。（可以快点出机场，所以能不托运就不托运）</p><p>然后就是安检，把带电池的都掏出来得，液体不能带进去（空水瓶可以带进去），外套也需要脱下来放入安检的盒子。</p><p>安检完成后，过海关，查护照、机票、签证（提前打印出来）。最后移民局的警察同志，还会帮你检查一下护照是否破损（破损的别有侥幸心理，移民局警察放你走，到了韩国也不一定让你入境！）还会告诉你注意安全，按时回来哈哈哈哈。</p><p>当晚到了仁川后，还是先见韩国海关，查护照和签证（电子的不用你出示）。采集双手食指指纹（我按的有点重），韩国海关的工作人员跟我说，轻轻的哈哈哈哈哈。到了机场的到达层的外围，办理流量卡。</p><p>流量卡有点说道，可以在携程买、或者韩游网也可以（二维码提前打印出来，到时候给工作人员看）。我办的SKT，我朋友办的LGU。从服务态度上，LGU的更好，会帮你换好卡，出信号了再让你离柜。SKT的就正常的给你卡，你自己去换，并且SKT要去设置里删除一个描述文件，才能出信号（幸亏我提醒做攻略了）。</p><p>我建议还是SKT好一点，一个是无高速流量限制，二是信号好像要比LGU好一点。他们两家都送TMoney卡（后续全部简称TM卡），所以选谁家的都无所谓。</p><p><img src="passp.png" alt="logo" /></p><h1 id="二-首尔所见所闻"><a class="markdownIt-Anchor" href="#二-首尔所见所闻"></a> 二、首尔所见所闻</h1><p>第二天，我们坐机场快线，从仁川机场地铁站先到金浦机场地铁站（用的手机卡送的TM卡），出站找黑色的柜机，办气候卡（建议提前在小红书找好路线，我跟我朋友和无头苍蝇了，找了很久才找到）。</p><p>气候卡，自己算好用几天，天数越多越优惠，但是也没必要多买。</p><p>有了气候卡，从金浦机场地铁站，再去明洞附近（我们定的明洞附近的酒店，钟舍L-Hotel，推荐！有免费泡面哈哈哈哈，味道还是很不错的。前台的美女会一点点中文，他们可以寄存行李，然后6楼能自助办理入住）。</p><p>当天中午，在楼下吃了个猪骨汤？好像是猪骨汤，反正就是韩国辣酱味的大骨头，肉很多，我俩点的中锅，没吃了。味道还可以，价格不便宜，200+。</p><p><img src="pigsoup.jpg" alt="logo" /></p><p>后面就去了明洞的OliveYoung，帮各位朋友带面膜、洗面奶等等，二楼最里面，可以薅小样包哈哈哈哈哈，感觉旁边的工作人员都快认识我了哈哈哈哈哈哈。</p><p><img src="smallbag.jpg" alt="logo" /></p><p>OliveYoung，朋友让帮忙带的绿豆洗面奶、神经酰胺的小棒、补水面膜、碱水面包圈。我自己额外买了个OliveYoung的大袋子（3000韩元，质感还是很不错的，基本回来的时候人手一个哈哈哈哈）</p><p>没找到明洞的OliveYoung的照片，凑合用个别的地方的吧。</p><p><img src="oy.jpg" alt="logo" /></p><p>后面去了乐天、新世界的免税店，虽有的柜台工作人员，都会说中文，你甚至感觉不出来他们是不是中国人哈哈哈哈哈。</p><p>记得在淘宝找挂团的，或者问问不挂团有啥优惠，那个便宜用那个方式去买！</p><p>乐天可以办一个金卡，它能当TM卡用，记得去办一下哈哈哈哈哈。</p><p>图-乐天TM卡</p><p>第一天基本就结束了，在OliveYoung和免税店来回的穿梭。</p><p>第二天去了景福宫、青瓦台、国会、汉江。</p><p>景福宫好像就类似中国的故宫吧？但是明显不如中国故宫的档次高哈哈哈哈，有部分路面还是土路。、</p><p><img src="jfg1.jpg" alt="logo" /></p><p>到景福宫，刚好碰上换防仪式，挺有意思的。</p><p><img src="jfg2.jpg" alt="logo" /></p><p>景福宫的大树，真的挺大的。</p><p><img src="jfg3.jpg" alt="logo" /></p><p>韩国大统领的官邸，不知道现在有没有人，反正是不让游客进去参观。</p><p><img src="qtt.jpg" alt="logo" /></p><p>韩国的国会，当年李大统领，在这直播翻墙，撤销戒严令的地方。</p><p><img src="gh1.jpg" alt="logo" /></p><p><img src="gh2.jpg" alt="logo" /></p><p>国会大门，据说当地人可以申请参观，外国游客可以提前发邮件申请参观。不过我们没进去，时间比较紧张，打卡即结束。</p><p><img src="gh3.jpg" alt="logo" /></p><p>汉江奇迹，汉江的人很多，商业区泡面也很多哈哈哈哈哈，很多人都在吃泡面。</p><p><img src="hanRiver.jpg" alt="logo" /></p><p>附上两张街景图，韩国人的设计还是很在线的，不一样的韩国韵味。</p><p><img src="street1.jpg" alt="logo" /></p><p><img src="street2.jpg" alt="logo" /></p><p>忘记哪天中午吃的炸猪排饭了，叫首尔套餐，有炸猪排、炸鱼排、炸牛肉饼。很好吃，套餐价格15万韩元。老板和工作人员也很热情，人不多，可以去尝尝哈哈哈哈哈。</p><p>那个绿色的小辣椒，蘸酱吃，很好吃。一点都不辣，可以试试。</p><p><img src="lunch.jpg" alt="logo" /></p><p><img src="lunch2.jpg" alt="logo" /></p><p>兔子周边布艺商店？反正卖布艺的工艺品的商店。我去买了几个兔子的收纳包。环境和设计都很在线，就是有点小贵。</p><p><img src="rabbitshop.jpg" alt="logo" /></p><p><img src="rabbit1.jpg" alt="logo" /></p><p><img src="rabbit2.jpg" alt="logo" /></p><p>不懂这是在干啥，行为艺术？反正在街头奏乐，颠到了我无法理解的程度哈哈哈哈。只有这俩奏乐，周围没人接着舞。</p><p><img src="streetArt.jpg" alt="logo" /></p><p>韩国的街景</p><p><img src="street3.jpg" alt="logo" /></p><p>远处的那个最大的塔，好像是首尔塔，我还以为跟上海的东方明珠一样，很大。</p><p><img src="seoulTower.jpg" alt="logo" /></p><p>KTX首尔站候车厅，来回飞的鸽鸽。估计跟我一样，也在候车准备去釜山。韩国的鸽子和乌鸦是真多，鸽鸽遍地走，行走的脆皮乳鸽，乌鸦满天叫。接下来，就要到釜山行了，没僵尸，但是景色很不错。</p><p><img src="seoulstation.jpg" alt="logo" /></p><h1 id="三-釜山所见所闻"><a class="markdownIt-Anchor" href="#三-釜山所见所闻"></a> 三、釜山所见所闻</h1><p>釜山的这段行程，一言难尽。去的时候刚好下雨，到了釜山吃顿饭，雨停了，在海边逛了一会，等到下午三点，才去办理的入住。</p><p>在KTX上拍的，外面在下雨，前几天天天满街跑，累趴了，路上睡了一路。</p><p><img src="ktx.jpg" alt="ktx" /></p><p>下了KTX，在出站口拍的釜山站门口。</p><p><img src="entranceBusanStation.jpg" alt="entranceBusanStation" /></p><p>到酒店后，寄存完行李拍的，雨中的海边。</p><p><img src="rainInBusan.jpg" alt="rainInBusan" /></p><p>酒店的大浴缸，第一次住带浴缸的。但是没用，怕不干净。不过韩国的酒店，即使是那种小旅馆，收拾的也很干净。感觉比起国内的一些连锁酒店，干净多了。</p><p><img src="bathtub.jpg" alt="bathtub" /></p><p>韩国的60炸鸡，这个60好像是说，每炸60次，会换新油。一进门，老板上来就问Chinese？然后拿菜单指着说，“一般一般一般”。我当时还心思，老板这么谦虚嘛，原来是一半一半哈哈哈哈哈哈哈。</p><p>味道呢，是甜口的，送的玉米酱和辣酱，还有酸萝卜。还有一大瓶百事可乐，我们买了啤酒，可乐一点都没喝。</p><p><img src="friedChicken.jpg" alt="friedChicken" /></p><p>韩国到处都是鸽鸽，说不定有一个是鸽鸽跟我一样，坐KTX过来的。</p><p><img src="gege.jpg" alt="gege" /></p><p>夜景，为啥拍夜景能，是因为酒店不让带外卖进去。我俩吃完的炸鸡，得偷偷的把垃圾处理了，要不罚款10W韩元。真无语了，为啥不让带外卖进酒店。</p><p><img src="nightView.jpg" alt="nightView" /></p><p><img src="nightView2.jpg" alt="nightView" /></p><p><img src="nightView3.jpg" alt="nightView" /></p><p>第二天早上，Check Out后。拍的酒店门口，雨过天晴的海边，还是很好看的。是个度假旅游的好去处。</p><p><img src="sunnyAfterRain.jpg" alt="sunnyAfterRain" /></p><p>又到釜山站了，在釜山站附近的大裤衩子建筑。看了全世界都有这种，大裤衩风格的建筑。</p><p><img src="busanBigUnderpants.jpg" alt="busanBigUnderpants" /></p><p>站前广场</p><p><img src="stationSquare.jpg" alt="stationSquare" /></p><p>釜山站附近的一个码头，大游轮，我搜了搜，好像母港在上海。船东是皇家加勒比，美国的船，专门跑中日韩路线。</p><p><img src="cruiseShip.jpg" alt="cruiseShip" /></p><p>我跟我朋友，最开始说，你看看，兰州拉面的图标都开到韩国了。最后到了仁川机场，才知道，原来是韩国的一个银行哈哈哈哈哈哈。</p><p><img src="bank.jpg" alt="bank" /></p><h1 id="四-下次还去韩国吗"><a class="markdownIt-Anchor" href="#四-下次还去韩国吗"></a> 四、下次还去韩国吗</h1><p>我觉的还是要去的，有几个地方我还没逛。三八线、蔚山的文在寅书店。</p><p>有机会再去看看西冰库大酒店哈哈哈哈哈哈，多的不说了，懂得都懂。</p><h1 id="五-遥墙入境"><a class="markdownIt-Anchor" href="#五-遥墙入境"></a> 五、遥墙入境</h1><p>到了遥墙，还是有点小插曲。海关、安检都没啥问题。</p><p>然后上了地铁后，发现行李箱有个裂纹，托运给我摔坏了。联系客服在线登记了一下，第二天给我打电话，说可以赔付200元。登记完成了，现在还没赔付，不知道啥情况反正。实在不行，这周五就要打电话问问了。</p><h1 id="六-the-end"><a class="markdownIt-Anchor" href="#六-the-end"></a> 六、The End</h1><p>4天的韩国自由行，是第一次出国玩。韩国给我的感受很奇怪，我发现大街上的车大多数都是现代和起亚，极少情况下看到过几辆宝马、特斯拉，很不多见。</p><p>消费水平不低，不知道是不是因为去的首尔和釜山是因为大城市的原因？吃上价格比较高。烟比我想象的要便宜，之前在香港买了一盒万宝路，竟然要100港币。在韩国买的红万，才折合人民币20元。（抽烟的地方真难找哈哈哈哈，网上说，地上烟头超过三个就能吸，但是一抬头就是禁止吸烟的标识）</p><p>交通比较方便吧，还有气候卡，对外国游客来说，比较合算。有一说一，坐地铁公交的时候，看到的韩国妹子真的很白很漂亮哈哈哈哈哈哈。</p>]]></content>
    
    
    <summary type="html">2026年5月1日韩国自由行</summary>
    
    
    
    
    <category term="生活" scheme="https://log.660066.xyz/tags/%E7%94%9F%E6%B4%BB/"/>
    
  </entry>
  
  <entry>
    <title>拉链表（SlowlyChangingDimensions）</title>
    <link href="https://log.660066.xyz/2026/03/26/SlowlyChangingDimensions/"/>
    <id>https://log.660066.xyz/2026/03/26/SlowlyChangingDimensions/</id>
    <published>2026-03-26T07:14:31.000Z</published>
    <updated>2026-03-26T08:27:31.607Z</updated>
    
    <content type="html"><![CDATA[<h1 id="一-前言"><a class="markdownIt-Anchor" href="#一-前言"></a> 一、前言</h1><p>这几天刷抖音，看到了个新的玩意儿。拉链表，所以打算学习一下。</p><h1 id="二-什么是拉链表及其实现"><a class="markdownIt-Anchor" href="#二-什么是拉链表及其实现"></a> 二、什么是拉链表及其实现</h1><ol><li>一个带历史数据的信息表。</li><li>表里要有两个字段，startTime、endTime、status(可选)。</li><li>startTime：记录数据的生成时间，这里完全可以在数据库设置上默认值，插值时间就是startTime。</li><li>endTime：记录数据的失效时间，默认应该是一个无限大的时间，例如9999-12-31。当数据失效，作为历史记录时，应该改为当前时间。</li><li>status：记录该行数据是否为历史数据，但是我觉得这个字段可有可无，用endTime的9999-12-31值作为判断也可以。</li></ol><h1 id="三-应用场景"><a class="markdownIt-Anchor" href="#三-应用场景"></a> 三、应用场景</h1><ol><li><strong>用户信息变更</strong>：城市、等级、手机号</li><li><strong>商品价格变更</strong>：不同时期价格</li><li><strong>员工组织关系变更</strong>：部门、岗位</li><li><strong>风控/审计</strong>：需要追踪某时点数据</li><li><strong>数仓维度表（SCD2）</strong>：最常见</li></ol><p>大多数情况下，这个思想应用在数仓和数据分析的场景，一般业务的情况下使用较少。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查询当前生效数据</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> A <span class="keyword">where</span> endTime <span class="operator">=</span> <span class="string">&#x27;9999-12-31&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- 查询历史数据</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> A <span class="keyword">where</span> startTime <span class="operator">&gt;=</span> <span class="string">&#x27;#&#123;开始时间&#125;&#x27;</span> <span class="keyword">and</span> endTime <span class="operator">&lt;=</span> <span class="string">&#x27;#&#123;结束时间&#125;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- 修改操作</span></span><br><span class="line"><span class="comment">-- 先关闭数据</span></span><br><span class="line"><span class="keyword">UPDATE</span> A <span class="keyword">SET</span> endTime <span class="operator">=</span> <span class="string">&#x27;2026-6-6&#x27;</span> <span class="keyword">WHERE</span> user_id <span class="operator">=</span> <span class="number">1001</span> <span class="keyword">AND</span> endTime <span class="operator">=</span> <span class="string">&#x27;9999-12-31&#x27;</span>;</span><br><span class="line"><span class="comment">-- 插入新数据</span></span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> A (……) <span class="keyword">VALUES</span> ( ……, <span class="type">DATE</span> <span class="string">&#x27;2024-03-01&#x27;</span>, <span class="type">DATE</span> <span class="string">&#x27;9999-12-31&#x27;</span>);</span><br></pre></td></tr></table></figure><h1 id="四-扩展"><a class="markdownIt-Anchor" href="#四-扩展"></a> 四、扩展</h1><p>Slowly Changing Dimensions即缓慢变化维（SCD）</p><p>维度表中的属性会随着时间慢慢变化，但这种变化不是高频实时的，需要考虑是否保留历史。</p><p>SCD解决了当维度属性变化时，如何管理旧值、新值和历史版本。</p><p>SCD的三种类型：</p><ul><li>Type 1：直接覆盖，新值直接覆盖旧值，不保留历史。</li><li>Type 2：新增版本，不覆盖旧记录，而是保留旧版本，再插入一条新版本。【拉链表属于这个类型】</li><li>Type 3：保留有限历史，保留当前值和上一个值，但不保留完整历史。</li></ul><p><strong>缓慢变化维，就是“维度数据会变，而我们要设计一种方式处理这种变化”。</strong></p><p><strong>拉链表不用代理键，最大的问题不是“不能做”，而是“很难做对、很难长期稳定地做对”。</strong></p>]]></content>
    
    
    <summary type="html">文章描述了拉链表的实现、应用场景、扩展</summary>
    
    
    
    
    <category term="开发纪实" scheme="https://log.660066.xyz/tags/%E5%BC%80%E5%8F%91%E7%BA%AA%E5%AE%9E/"/>
    
  </entry>
  
  <entry>
    <title>2025年终总结</title>
    <link href="https://log.660066.xyz/2026/02/13/2025-summary/"/>
    <id>https://log.660066.xyz/2026/02/13/2025-summary/</id>
    <published>2026-02-13T15:59:18.000Z</published>
    <updated>2026-02-13T16:59:43.581Z</updated>
    
    <content type="html"><![CDATA[<h1 id="前言"><a class="markdownIt-Anchor" href="#前言"></a> 前言</h1><p>现在是北京时间2026年2月14日，凌晨0点0分，很久没更新博客了，倒不是没有什么新的东西去更新。是真的太忙，忙着换工作，忙着改BUG。</p><p>25年年底，我下定决心，回济南，回到老东家，再续我的前缘……</p><h1 id="世界很大我要去看看"><a class="markdownIt-Anchor" href="#世界很大我要去看看"></a> 世界很大，我要去看看！</h1><p>2025年，我去了深圳、香港、嘉兴、杭州、舟山。</p><p>去深圳和香港，是早就计划好的，是我每年旅游计划的一部分。说实话，真的没感觉出香港到底好在了哪里，感觉跟大陆的一线城市，基本上是一样，不同点就是消费高，金融环境比较宽松。</p><p>嘉兴、杭州、舟山，是计划外，因为5月跳槽到了苏州。在苏州的时候，顺便跟同事去这些地方转了转，待的时间都不是很久，所以也没啥可说的，附几张照片把。</p><style>.pnvlugaewvdn{zoom:50%;}</style><img src="/2026/02/13/2025-summary/nanhuhongchuan.jpg" class="pnvlugaewvdn" alt="南湖红船"><p>我党一大的会议进行处，嘉兴南湖的一条游船。很有纪念意义！共产主义万岁！</p><style>.shammfmlfjtp{zoom:50%;}</style><img src="/2026/02/13/2025-summary/xilingyinshe.jpg" class="shammfmlfjtp" alt="西泠印社"><p>杭州西湖附近的西泠印社，我对篆刻印章特别喜欢，虽然自己不会篆刻，但是在博物馆，必看的东西就是各种印章哈哈哈哈哈。</p><p>突然想起一句话，写这吧：使我有洛阳二顷田，安能佩六国相印。</p><style>.romjxpmqaoha{zoom: 50%;}</style><img src="/2026/02/13/2025-summary/xihu.jpg" class="romjxpmqaoha" alt="西湖1"><p>这也是西湖附近的一个塔，好像是雷峰塔？记不清了，只拍了个照片，没上去，记得当时需要门票来着。</p><style>.wwdbpvsnxrpm{zoom:50%;}</style><img src="/2026/02/13/2025-summary/nanhugeming.jpg" class="wwdbpvsnxrpm" alt="南湖革命纪念"><p>南湖革命纪念馆，我党历史展览，学到了很多。大家有机会也可以去参观参观。</p><style>.oarpjkmhannu{zoom:50%;}</style><img src="/2026/02/13/2025-summary/haiyan.jpg" class="oarpjkmhannu" alt="海盐县"><p>海盐县，当时想去海边玩，同事开车带着一块去了海盐县。临走之前，发现这个地方很不错，就拍了张照片留念。</p><h1 id="运动"><a class="markdownIt-Anchor" href="#运动"></a> 运动</h1><p>今年找到了自己喜欢的运动，羽毛球！</p><p>你打吧，一打一个不吱声。嘎嘎累，嘎嘎爽。体重降没降不知道，累是真的累。</p><p>在苏州跟同事，经常下班去打一小时的球，买了入门级球拍，的幸的均衡之刃（回济南的时候，可能落在了火车上，自己坐火车去兰州了哈哈哈哈）。</p><p>回济南又买了一把均衡之刃，真是很好用。第三把均衡之刃了。</p><p>千幸万幸不如的幸，跟我的杀球去说吧。🐶</p><style>.gukchsgyodin{zoom:50%;}</style><img src="/2026/02/13/2025-summary/5361fc71ebf866cb0aea0f044854ed81.jpg" class="gukchsgyodin" alt="5361fc71ebf866cb0aea0f044854ed81"><p>回济南打的第一场球，认识了一个老哥，实力不凡（对我来说）。三个人，一口气打了俩小时，到了第二天，依旧没缓过来，累的半死。</p><h1 id="投资"><a class="markdownIt-Anchor" href="#投资"></a> 投资</h1><p>今年没怎么操作股票和基金，贵金属也没买。主要是换了两次工作，导致自己很忙，没时间去搞这个，也就放下了一段时间。</p><h1 id="技术进步"><a class="markdownIt-Anchor" href="#技术进步"></a> 技术进步</h1><p>技术进步，有，但是不多。</p><p>主要是在苏州，第一次接触到了微服务架构，对这东西彻底祛魅了。小公司、小体量软件，纯粹自找难受。</p><p>对于互联网巨头来说，确实可以提高开发速度，解耦等等的好处。但是对于一般体量的公司或者软件，纯粹是脱了裤子放屁，不管是维护还是开发，都搞得人很难受。</p><p>在苏州，也接触了项目管理，这东西倒不是很难搞，纯粹的操心哈哈哈哈哈。跟进展、协调部门资源、跟客户沟通等等，都得操心，得举一反三，多思考才行。</p><p>回到济南，依旧是微服务项目，但是软件体量大，明显能感觉出来，对开发速度等方面，有不小的提升。</p><p>再就是AI方面，多少的了解了一些机器学习的东西，接触到了一个很神奇的技术，三维重建。就是对一个物体拍几个不同方向的照片（需要标定板），通过机器学习的模型，把他重建成3d模型。</p><p>大语言模型方面，自己搞了个文档提取的Demo，用的Qwen系列的模型，向量转换、基座模型都是Qwen3。其实我一直不看的小参数量的大语言模型，但是这次用了8B的超乎我的想象，只要是提示词做好了，指哪打哪！</p><h1 id="人生的坎"><a class="markdownIt-Anchor" href="#人生的坎"></a> 人生的坎</h1><p>2025年，这一年就是在折腾，不停的折腾。换工作、分手、又回老东家。</p><p>一开始，满怀希望的去了苏州，但实际到了以后，发现。</p><p>一个组6个人（包含我），10W个心眼子，各怀鬼胎，难搞的一批。大部分时间不是在做技术，而是扯皮，处理背后捅的刀子。人心隔肚皮，真的是吃一堑长一智，也算是在苏州这半年没白待。再就是真的很闲，我才20多岁啊，正式闯的年纪，再不跑，就被时代的车轮碾压了。</p><p>到了苏州，因为长时间异地，又不能月月去找对象，所以被分手了，也算是和平分手。大路朝边，各走一边。每个人都有自己的路要走，祝福！我也有我的新生活要开始。（各位读者，感觉给我推姐姐，我要跟姐姐谈恋爱。哈哈哈哈哈哈哈哈哈。）</p><p>后面，跟之前的同事交流，找了老东家的领导，确定要回济南，然后再续前缘哈哈哈哈。但是跟苏州这边，提离职，真的给我搞懵了。先是苏州的领导，对我一顿贬低，再就是想卡我离职，说是交接不好，就要让董事长的影响力，让我无法入职下家哈哈哈哈哈哈。开玩笑，哥们最不怕威胁，大不了鱼死网破，都别好🐶。最后交接也算顺利，顺利离职，开启我的新职业生涯哈哈哈哈哈哈。</p><p>总的来说，都是小砍，轻轻松松迈过去哈哈哈哈。</p><h1 id="明年展望"><a class="markdownIt-Anchor" href="#明年展望"></a> 明年展望</h1><p>今年，技术要继续提升，务必把Vue拾起来，全方位发展，把全干工程师的门槛迈过去。再就是公司的低代码框架，尽快把知识库建立起来，为后续开发打下良好的基础。</p><p>投资也要有进展！缠论要看，债基要学！钱这个东西，你不理他，他不理你。做好投资，也是资产自己产仔的一个好路线。</p><p>婚恋方面，先缓缓吧，一切随缘（我再提一下，我想跟姐姐谈恋爱哈哈哈哈）</p><p>运动也不能停，羽毛球向天王丹哥看齐，多学学练，菜就多练哈哈哈哈哈。</p><h1 id="最后"><a class="markdownIt-Anchor" href="#最后"></a> 最后</h1><p>最后，放一句，教员的金句，镇镇文章！</p><p>“在危险环境中表示绝望的人，在黑暗环境中看不见光明的人，只是<strong>懦夫和机会主义者</strong>。”</p><p>放一张作者的帅照，哈哈哈哈哈哈哈哈。</p><style>.czcfgrrlhkrn{zoom: 25%;}</style><img src="/2026/02/13/2025-summary/me.jpg" class="czcfgrrlhkrn" alt="作者帅照"><p>2026年2月14日，出租房记。</p>]]></content>
    
    
    <summary type="html">2025年终总结</summary>
    
    
    
    
    <category term="生活" scheme="https://log.660066.xyz/tags/%E7%94%9F%E6%B4%BB/"/>
    
  </entry>
  
  <entry>
    <title>【大厂思维】缓存一致性问题解决方案</title>
    <link href="https://log.660066.xyz/2025/11/06/big-factory-think-cache-consistency/"/>
    <id>https://log.660066.xyz/2025/11/06/big-factory-think-cache-consistency/</id>
    <published>2025-11-06T05:52:22.000Z</published>
    <updated>2025-11-20T01:37:57.966Z</updated>
    
    <content type="html"><![CDATA[<h1 id="一-三种方案"><a class="markdownIt-Anchor" href="#一-三种方案"></a> 一、三种方案</h1><ol><li>延迟双删：缓存与数据库一致性问题的公认解决方案，也是面试高频考点，在各类技术八股文中均有重点提及。</li><li>租约机制：多见于分布式场景的大厂方案，更适配高并发、大规模架构。对于流量较小的内部 ERP 等系统，通常无需缓存设计，因此极少采用。</li><li>版本号对比机制：同样是大厂常用方案，核心通过数据自带的版本号标识，直观判断数据新旧，进而保障数据一致性。</li></ol><h1 id="二-延迟双删"><a class="markdownIt-Anchor" href="#二-延迟双删"></a> 二、延迟双删</h1><h2 id="21-什么是延迟双删"><a class="markdownIt-Anchor" href="#21-什么是延迟双删"></a> 2.1 什么是延迟双删</h2><p>通过两次缓存删除操作，最大限度降低缓存与数据库的数据不一致风险</p><ol><li><p><strong>首次删除</strong>：更新数据库前，先删除缓存数据。</p><p>作用：避免更新时，请求命中缓存，读取到旧数据</p></li><li><p><strong>数据库更新</strong>：更新数据库中的数据。</p></li><li><p><strong>延迟后第二次删除</strong>：等待几秒(具体时间，根据业务需要调整)后，将缓存中的数据再次删除。</p><p>作用：解决首次删除后，数据库更新完成前的并发问题。即有并发请求，旧数据被重新写入缓存的问题</p></li></ol><h2 id="22-优缺点"><a class="markdownIt-Anchor" href="#22-优缺点"></a> 2.2 优缺点</h2><p><strong>优点：</strong></p><ol><li>实现成本低。</li><li>兼容性强，支持常见的缓存、数据库。</li><li>覆盖并发窗口，降低缓存与数据库的不一致性概率。</li></ol><p><strong>缺点：</strong></p><ol><li>可能存在缓存击穿的问题。</li><li>延迟删除时间难以把控。</li><li>依赖异步任务的可靠性。（一般情况下，延迟删除通过定时任务、消息队列实现，如发生故障，难以保证第二次删除）</li><li>无法满足强一致性的要求。</li></ol><h2 id="23-适用"><a class="markdownIt-Anchor" href="#23-适用"></a> 2.3 适用</h2><ol><li>中小型规模</li><li>并发量较小，数据库能承受短时的缓存击穿。</li><li>无复杂的分布式架构</li></ol><h1 id="三-租约机制"><a class="markdownIt-Anchor" href="#三-租约机制"></a> 三、租约机制</h1><h2 id="31-什么是租约机制"><a class="markdownIt-Anchor" href="#31-什么是租约机制"></a> 3.1 什么是租约机制</h2><p>简单的说，就是多个请求查询缓存，只有第一个请求可以获取到令牌后写入缓存。</p><ol><li>缓存中不存在查询的数据时，多个并发请求中，只给第一个颁发“令牌”。</li><li>拿到令牌后，才允许其查询数据库，写入缓存。其他请求，要么等待，要么放弃。</li></ol><h2 id="32-有缺点"><a class="markdownIt-Anchor" href="#32-有缺点"></a> 3.2 有缺点</h2><p><strong>优点：</strong></p><ol><li>防止并发出现混乱，不会出现旧数据覆盖新数据的问题。</li><li>轻量化，依靠Redis Lua脚本实现。</li><li>令牌过期时间可灵活设置。</li></ol><p><strong>缺点：</strong></p><ol><li>实现比延迟双删复杂，需要用Lua脚本实现令牌的生成、验证、删除，令牌过期、请求排队也需要考虑。</li><li>存在等待期，未获取到令牌的请求，要么等现有令牌过期，要么放弃，极端情况下部分用户可能需要等待。</li><li>缓存服务依赖度高，令牌的实现在缓存中，缓存一旦宕机，就可能出现租约机制失效的问题。</li></ol><h2 id="33-适用"><a class="markdownIt-Anchor" href="#33-适用"></a> 3.3 适用</h2><ol><li>大流量分布式系统</li><li>并发写多的业务</li><li>可接受等待的业务</li></ol><h1 id="四-版本号对比机制"><a class="markdownIt-Anchor" href="#四-版本号对比机制"></a> 四、版本号对比机制</h1><h2 id="41-什么是版本号对比机制"><a class="markdownIt-Anchor" href="#41-什么是版本号对比机制"></a> 4.1 什么是版本号对比机制</h2><p>给每条数据，添加一个时间戳字段或版本号字段。</p><p>写缓存是，先判断版本号的新旧，新版本存入，旧版本丢弃。</p><h2 id="42-优缺点"><a class="markdownIt-Anchor" href="#42-优缺点"></a> 4.2 优缺点</h2><p><strong>优点：</strong></p><ol><li>性能好，直接对比版本号，无需排队等待。</li><li>数据一致性，根据版本号，可防止旧数据覆盖新数据的问题。</li><li>实现较简单，无需考虑令牌的生成、过期等逻辑。</li><li>无锁设计，不会出现锁竞争、死锁等问题。</li></ol><p><strong>缺点：</strong></p><ol><li>版本号生成逻辑出现问题，会导致数据更新异常。</li><li>无法解决缓存击穿问题。</li><li>版本号存储占用空间。</li></ol><h2 id="43-适用"><a class="markdownIt-Anchor" href="#43-适用"></a> 4.3 适用</h2><ol><li>超大规模的高并发系统。</li><li>读多写少、数据更新频繁的业务。</li><li>需要“强一致性”优先级高于“防止缓存击穿”</li></ol><h1 id="五-总结"><a class="markdownIt-Anchor" href="#五-总结"></a> 五、总结</h1><table><thead><tr><th>方案</th><th>适用</th><th>核心逻辑</th><th>优点</th></tr></thead><tbody><tr><td>延迟双删</td><td>中小系统</td><td>删除缓存、延迟删除</td><td>简单</td></tr><tr><td>租约机制</td><td>大型系统</td><td>令牌的控制逻辑</td><td>防缓存击穿</td></tr><tr><td>版本号对比机制</td><td>超大型系统</td><td>版本号对比</td><td>无锁，性能好</td></tr></tbody></table>]]></content>
    
    
    <summary type="html">本文叙述的是学习大厂开发思维，如何解决缓存一致性问题，以及每种方案的优缺点。</summary>
    
    
    
    
    <category term="开发纪实" scheme="https://log.660066.xyz/tags/%E5%BC%80%E5%8F%91%E7%BA%AA%E5%AE%9E/"/>
    
  </entry>
  
  <entry>
    <title>【软考zst2001专辑笔记】005知识产权</title>
    <link href="https://log.660066.xyz/2025/09/29/zst-intellectual-property-right/"/>
    <id>https://log.660066.xyz/2025/09/29/zst-intellectual-property-right/</id>
    <published>2025-09-29T05:38:11.000Z</published>
    <updated>2025-09-29T05:44:30.945Z</updated>
    
    <content type="html"><![CDATA[<h1 id="一-著作权"><a class="markdownIt-Anchor" href="#一-著作权"></a> 一、著作权</h1><p>作者对作品享有人身权和财产权</p><p>人身权：发表权、署名权、修改权、保护作品完整权</p><p>财产权：使用权、获得报酬权</p><p>知识产权具有法定的保护期：</p><p>发明专利20年、新型实用专利和外观专利10年。</p><p>作品发表权：作者终生及其死后50年。</p><p>商标：有效期10年，可以无限续。</p><h1 id="二-专利地域性"><a class="markdownIt-Anchor" href="#二-专利地域性"></a> 二、专利地域性</h1><p>外国人在我国领域外使用中国专利局授权的发明专利，不侵犯我国专利权。</p><p>参加国际公约的国家和我国保护相关国家的专利。</p><h1 id="三-计算机软件著作权"><a class="markdownIt-Anchor" href="#三-计算机软件著作权"></a> 三、计算机软件著作权</h1><p>著作权法（中华人民共和国著作权法）、计算机软件保护条例</p><p>计算机软件著作权的客体：计算机程序、有关文档。</p><p>计算机程序包括：源程序、目标程序</p><p>计算机文档包括：程序设计说明书、流程图、用户手册等。</p><p>著作权法规定，软件作品享有两类权益：人身权（精神权利）、财产权（经济权利）。计算机软件保护条例规定，著作权人享受发表权、开发者身份权（署名权，不受开发者的消失而丧失，无时间限制）。</p><p>财产权包括：使用权、复制权、修改权、发行权、<strong>翻译权（从一种编程语言翻译成另一种编程语言）、注释权、信息网络传播权、出租权、使用许可权、获得报酬权、转让权。</strong></p><p>**软件著作权的保护期：自开发完成之日起50年。**保护期满后除开发者身份权以外，其他权利终止，软件进入公有领域。</p><p>计算机软件著作权人，单位终止或公民死亡，无合法继承人时，除开发者身份权外，其他权利进入公有领域。</p><h1 id="四-职务作品"><a class="markdownIt-Anchor" href="#四-职务作品"></a> 四、职务作品</h1><p>公民在单位任职期间，为执行本单位工作任务开发的计算机软件作品。</p><p>公民单位任职期间所开发的软件，如果是执行本质工作的结果，即针对本质工作中明确制定的开发名表所开发的，或者是从事本质工作活动所遇见的结果或自然的结果，则软件的著作权归属该单位。</p><p>如果雇员<strong>主要使用了单位的设备</strong>，按照保护条例，<strong>不能属于雇员个人享有</strong>。</p><p>归属原则（计算机软件保护条例）：<strong>符合以下三个，才算非职务作品</strong></p><ul><li>所开发的软件作品不是执行起本职工作的结果。</li><li>开发的软件作品与开发者单位中从事的工作内容无直接联系。</li><li>开发的软件作品未使用单位的物质技术条件。</li></ul><h1 id="五-委托开发"><a class="markdownIt-Anchor" href="#五-委托开发"></a> 五、委托开发</h1><p>接受他人委托开发的软件，其著作权的归属由委托者和受委托者签订书面合同约定，<strong>无书面合同或者合同未明确约定的，其著作权由受托人享有。</strong></p><h1 id="六-商业秘密权"><a class="markdownIt-Anchor" href="#六-商业秘密权"></a> 六、商业秘密权</h1><p>不为公众所知悉的、能为权利人带来经济利益、具有实用性并经权利人采取保密措施的<strong>技术信息、经营信息</strong></p><h1 id="七-专利申请"><a class="markdownIt-Anchor" href="#七-专利申请"></a> 七、专利申请</h1><p>一份专利申请文件只能就一项发明创造提出专利申请，即“一份申请一项发明”</p><p>两个或两个以上的人分别就同样的发明创造申请专利的，专利权授给最先申请人。</p><h1 id="八-商标权"><a class="markdownIt-Anchor" href="#八-商标权"></a> 八、商标权</h1><p>商标保护期10年，可以无限续期。</p><p>在期限满6个月内，提出续期申请，每次续期10年，续期次数不限。</p><h1 id="九-商标注册"><a class="markdownIt-Anchor" href="#九-商标注册"></a> 九、商标注册</h1><p>同时申请，先调解两个申请人谁让步，不让步，抽签决定。</p><h1 id="十-其他"><a class="markdownIt-Anchor" href="#十-其他"></a> 十、其他</h1><p>游戏规则和方法、计算机算法，不能申请专利。</p><p>合理使用指可以不经著作权人许可，不需支付报酬，使用其作品。</p><p>为说明某一问题，在学术论文中需要引用某些资料必须是已发表的作品，但只能限于介绍、评论作品，只要不构成自己作品的主要部分，可适当引用资料，而不必征得原作者的同意，不需要向他支付报酬。</p><p>国务院颁布的《计算机软件保护条例》，不适用或不受著作权法保护的是(14)。(2013 年下半年)</p><p>我国法律法规的规定必须使用注册商标的是烟草类商品，</p>]]></content>
    
    
    <summary type="html">【软考zst2001专辑笔记】005知识产权</summary>
    
    
    
    
    <category term="软考" scheme="https://log.660066.xyz/tags/%E8%BD%AF%E8%80%83/"/>
    
  </entry>
  
  <entry>
    <title>【薛定谔的字段】XXL-JOB执行器不受事务管理</title>
    <link href="https://log.660066.xyz/2025/09/02/schrodinger-of-field-transaction-management-issues/"/>
    <id>https://log.660066.xyz/2025/09/02/schrodinger-of-field-transaction-management-issues/</id>
    <published>2025-09-02T03:00:22.000Z</published>
    <updated>2025-09-02T03:10:48.623Z</updated>
    
    <content type="html"><![CDATA[<h1 id="一-问题"><a class="markdownIt-Anchor" href="#一-问题"></a> 一、问题</h1><p>近期在开发过程中发现，设备相关数据的某个字段偶尔出现 <code>null</code> 值，并非每次必现。该问题主要发生在任务刚执行完成，设备立即调用接口获取数据时。初步判断与数据写入和读取的时序有关，存在一定的竞争条件。</p><h1 id="二-排查"><a class="markdownIt-Anchor" href="#二-排查"></a> 二、排查</h1><h2 id="21-初步怀疑异常回滚"><a class="markdownIt-Anchor" href="#21-初步怀疑异常回滚"></a> 2.1 初步怀疑异常回滚</h2><p>最初怀疑是任务执行过程中发生异常并触发事务回滚，导致字段未能正确写入而为 <code>null</code>。但通过查阅近期 ELK 日志，未发现相关异常记录，排除了因异常回滚导致数据缺失的可能性。</p><h2 id="22-字段填充"><a class="markdownIt-Anchor" href="#22-字段填充"></a> 2.2 字段填充</h2><p>随后将排查重点转向该字段的填充方法。考虑到数据写入时机问题，怀疑是否存在事务传播机制不当，导致部分数据在事务未完成前就被提前写入数据库，后续流程继续执行，从而引发字段为null的异常。</p><h2 id="23-检查事务注解与调用方式"><a class="markdownIt-Anchor" href="#23-检查事务注解与调用方式"></a> 2.3 检查事务注解与调用方式</h2><p>在相关方法中发现其使用了 <code>@Transactional(rollbackFor = Exception.class)</code> 注解，该注解仅用于异常时回滚，并未强制开启新事务（即 <code>propagation = REQUIRES_NEW</code>），因此不会导致数据提前提交。</p><p>进一步检查发现，该方法内部存在 <code>this.</code> 方式的自调用，可能因为 Spring AOP 代理机制导致事务失效？尝试改为通过 <code>service</code> Bean 引用进行外部调用后，问题依然存在。</p><h2 id="24-xxl-job-反射调用与事务管理"><a class="markdownIt-Anchor" href="#24-xxl-job-反射调用与事务管理"></a> 2.4 XXL-JOB 反射调用与事务管理</h2><p>这里就猛的想起，XXL-JOB好像是通过反射进行定时调用的。立马Google确认， 确定是通过反射进行调用的。那么就基本确定，很有可能是XXL-JOB执行器反射，导致方法不受Springboot的事务管理。</p><p><img src="1756776777447-f0a032e4-d164-4cc9-8961-f36e20757cf8.png" alt="" /></p><p>上图原文链接：<a href="https://www.cnblogs.com/yejg1212/p/14794098.html">https://www.cnblogs.com/yejg1212/p/14794098.html</a></p><h1 id="三-解决"><a class="markdownIt-Anchor" href="#三-解决"></a> 三、解决：</h1><p>在定时任务类和方法上加上@Transactional注解，经过多轮测试，null值不再出现。</p><h1 id="四-问题点"><a class="markdownIt-Anchor" href="#四-问题点"></a> 四、问题点：</h1><h2 id="41-为啥事务失效"><a class="markdownIt-Anchor" href="#41-为啥事务失效"></a> 4.1 为啥事务失效？</h2><p><code>@Transactional</code> 是通过 <strong>Spring AOP</strong> 来实现的。只有方法是通过 <strong>Spring 容器生成的代理对象</strong> 调用时，事务切面才会生效。如果方法不是通过代理调用（比如直接 new 出来的对象，或者直接在同一个类里this自调用），事务就不会生效。</p><p>XXL-JOB 调度任务时，是通过 <strong>反射调用你标注的方法</strong>。  所以说，它并不是通过 Spring AOP 代理对象去调用的，而是直接调用你 <code>@Component</code> 类里的那个方法。</p><h2 id="42-为啥加了-transactional-就生效了"><a class="markdownIt-Anchor" href="#42-为啥加了-transactional-就生效了"></a> 4.2 为啥加了 <code>@Transactional</code> 就生效了？</h2><p>当给方法加上 <code>@Transactional</code>，Spring 在启动时会发现这个方法需要事务切面，会为整个类生成一个<strong>代理对象</strong>。</p><p>XXL-JOB 在执行任务时，仍然是通过 Spring 容器中的 bean 去拿这个类，但此时拿到的已经是代理对象。当 XXL-JOB 通过反射调用这个代理对象的方法时，Spring AOP 的事务切面就会拦截到，事务开始生效。</p><h2 id="43-正确的解决方式"><a class="markdownIt-Anchor" href="#43-正确的解决方式"></a> 4.3 正确的解决方式</h2><p>因为项目上存在重构分支和开发分支，后期打算将重构分支切为生产，所以目前临时添加<code>@Transactional</code>解决掉问题。</p><p>实际上， 执行器方法应该只做参数校验、任务调度、开始结束日志等。实际的业务逻辑，应当放入service中，使用@Transactional管理事务。</p>]]></content>
    
    
    <summary type="html">【薛定谔的字段】XXL-JOB执行器不受事务管理</summary>
    
    
    
    
    <category term="开发纪实" scheme="https://log.660066.xyz/tags/%E5%BC%80%E5%8F%91%E7%BA%AA%E5%AE%9E/"/>
    
  </entry>
  
  <entry>
    <title>【软考zst2001专辑笔记】004数据结构-下卷</title>
    <link href="https://log.660066.xyz/2025/08/27/zst-data-structure-volume-roll-down-notes/"/>
    <id>https://log.660066.xyz/2025/08/27/zst-data-structure-volume-roll-down-notes/</id>
    <published>2025-08-27T02:05:07.000Z</published>
    <updated>2025-08-27T08:37:27.818Z</updated>
    
    <content type="html"><![CDATA[<h1 id="一-查找"><a class="markdownIt-Anchor" href="#一-查找"></a> 一、查找</h1><h2 id="11-基本概念"><a class="markdownIt-Anchor" href="#11-基本概念"></a> 1.1 基本概念</h2><p>静态查找表：顺序查找、折半（二分）查找、分块查找</p><p>动态查找表：二叉排序树、平衡二叉树、B树、哈希表</p><p>静态查找表：</p><ul><li>查找某个特定的数据元素是否在查找表中。</li><li>检索某个特定的数据元素的各个属性。</li></ul><p>动态查找表：</p><ul><li>在查找表中插入一个数据元素</li><li>在查找表中删除一个数据元素</li></ul><h2 id="12-顺序查找"><a class="markdownIt-Anchor" href="#12-顺序查找"></a> 1.2 顺序查找</h2><p>适用于顺序存储和链式存储。</p><p>平均查找长度：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><mn>2</mn></mfrac></mrow><annotation encoding="application/x-tex"> \frac{n+1}{2} </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></p><h2 id="13-折半查找"><a class="markdownIt-Anchor" href="#13-折半查找"></a> 1.3 折半查找</h2><p>折半查找的必要条件：顺序存储，有序。</p><p>最坏的比较次数：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">⌊</mo><msub><mrow><mi>log</mi><mo>⁡</mo></mrow><mn>2</mn></msub><mi>n</mi><mo stretchy="false">⌋</mo><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex"> \lfloor \log_2 n \rfloor + 1 </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⌊</span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mclose">⌋</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></p><p>平均查找长度：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mrow><mi>log</mi><mo>⁡</mo></mrow><mn>2</mn></msub><mo stretchy="false">(</mo><mi>n</mi><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex"> \log_2(n+1) - 1 </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></p><p>折半查找过程与关键字比较的次数即为被查找结点在树中的层数。</p><p>我自己在这提一下，如果不考虑查找的元素不存在的问题，斐波那契查找更快（基于Java8开发过程中发现的）。</p><p>折半查找的比对顺序有以下几种可能：</p><ol><li>大大大大大……（越来越大）</li><li>小小小小小……（越大越小）</li><li>大小大小大……（大小间隔）</li><li>小大小大小……（小大间隔）</li></ol><h1 id="二-哈希表"><a class="markdownIt-Anchor" href="#二-哈希表"></a> 二、哈希表</h1><h2 id="21-定义"><a class="markdownIt-Anchor" href="#21-定义"></a> 2.1 定义</h2><p>核心思想是：<strong>把查找关键字的值，通过一个函数计算，直接得到它应该存放在哪里。</strong></p><p>具有相同哈希数值的关键字，对于该哈西函数来说称为同义词。</p><h2 id="22-哈希函数构造与处理冲突"><a class="markdownIt-Anchor" href="#22-哈希函数构造与处理冲突"></a> 2.2 哈希函数构造与处理冲突</h2><p>哈希函数构造方法：直接定址法、数字分析法、平方取中法、折叠法、随机数法、<strong>除留余数法</strong></p><p>H(Key) = Key % m = 地址</p><p>m取接近n(元素个数)但是大于n的质数。</p><p>开放定址法：</p><ol><li><strong>线性探测法</strong>：如果该位置已被占用（无论是因为另一个键值对还是之前因冲突而移动至此的键值对），则<strong>按顺序检查下一个位置</strong>（即 (h(key) + 1) % table_size`）</li><li><strong>二次探测再散列</strong>：如果该位置已被占用，则按照二次函数的规律，探测 (h(key) + 1²) % m<code>, (h(key) + 2²) % m</code>, (h(key) + 3²) % m`, …，直到找到一个空位置为止。</li><li>随机探测再散列：如果位置被占用，则使用一个<strong>伪随机数生成器</strong>（PRNG）来决定下一个探测的位置。这个生成器的种子通常与当前的 key<code> 相关，以确保对于同一个 key</code>，探测序列是确定且可重现的。</li></ol><h2 id="23-处理冲突拓展和装填因子"><a class="markdownIt-Anchor" href="#23-处理冲突拓展和装填因子"></a> 2.3 处理冲突拓展和装填因子</h2><p>链地址法：</p><p><img src="1755831156335-2f01f55d-6af6-41f2-b23b-cc8d45923d57.png" alt="" /></p><p>哈希表的填装因子定义为：α = <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mtext>表中装入的记录数</mtext><mtext>哈希表的长度</mtext></mfrac></mrow><annotation encoding="application/x-tex"> \frac{表中装入的记录数}{哈希表的长度} </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.2173em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8723em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord cjk_fallback mtight">哈希表的长度</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord cjk_fallback mtight">表中装入的记录数</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></p><p>α越小，发生冲突的可能性越小。</p><h1 id="三-排序"><a class="markdownIt-Anchor" href="#三-排序"></a> 三、排序</h1><table><thead><tr><th style="text-align:center">排序算法</th><th style="text-align:center">平均时间复杂度</th><th style="text-align:center">最坏时间复杂度</th><th style="text-align:center">最好时间复杂度</th><th style="text-align:center">空间复杂度</th><th style="text-align:center">稳定性</th></tr></thead><tbody><tr><td style="text-align:center">快速排序</td><td style="text-align:center">O(<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mi>lg</mi><mo>⁡</mo><mi>n</mi></mrow><annotation encoding="application/x-tex"> n \lg n </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">l<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span>)</td><td style="text-align:center">O(n<sup>2</sup>)</td><td style="text-align:center">O(<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mi>lg</mi><mo>⁡</mo><mi>n</mi></mrow><annotation encoding="application/x-tex"> n \lg n </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">l<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span>)</td><td style="text-align:center">O(<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mi>lg</mi><mo>⁡</mo><mi>n</mi></mrow><annotation encoding="application/x-tex"> n\lg n </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">l<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span>)</td><td style="text-align:center">不稳定</td></tr><tr><td style="text-align:center">归并排序</td><td style="text-align:center">O(<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><msub><mrow><mi>log</mi><mo>⁡</mo></mrow><mn>2</mn></msub><mi>n</mi></mrow><annotation encoding="application/x-tex"> n \log_2 n </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9386em;vertical-align:-0.2441em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span>)</td><td style="text-align:center">O(<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><msub><mrow><mi>log</mi><mo>⁡</mo></mrow><mn>2</mn></msub><mi>n</mi></mrow><annotation encoding="application/x-tex"> n \log_2 n </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9386em;vertical-align:-0.2441em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span>)</td><td style="text-align:center">O(<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><msub><mrow><mi>log</mi><mo>⁡</mo></mrow><mn>2</mn></msub><mi>n</mi></mrow><annotation encoding="application/x-tex"> n \log_2 n </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9386em;vertical-align:-0.2441em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span>)</td><td style="text-align:center">O(n)</td><td style="text-align:center">稳定</td></tr><tr><td style="text-align:center">直接插入排序</td><td style="text-align:center">O(n<sup>2</sup>)</td><td style="text-align:center">O(n<sup>2</sup>)</td><td style="text-align:center">O(n)</td><td style="text-align:center">O(1)</td><td style="text-align:center">稳定</td></tr><tr><td style="text-align:center">简单选择排序</td><td style="text-align:center">O(n<sup>2</sup>)</td><td style="text-align:center">O(n<sup>2</sup>)</td><td style="text-align:center">O(n<sup>2</sup>)</td><td style="text-align:center">O(1)</td><td style="text-align:center">不稳定</td></tr><tr><td style="text-align:center">冒泡排序</td><td style="text-align:center">O(n<sup>2</sup>)</td><td style="text-align:center">O(n<sup>2</sup>)</td><td style="text-align:center">O(n)</td><td style="text-align:center">O(1)</td><td style="text-align:center">稳定</td></tr><tr><td style="text-align:center">堆排序</td><td style="text-align:center">O(<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><msub><mrow><mi>log</mi><mo>⁡</mo></mrow><mn>2</mn></msub><mi>n</mi></mrow><annotation encoding="application/x-tex"> n \log_2 n </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9386em;vertical-align:-0.2441em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span>)</td><td style="text-align:center">O(<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><msub><mrow><mi>log</mi><mo>⁡</mo></mrow><mn>2</mn></msub><mi>n</mi></mrow><annotation encoding="application/x-tex"> n \log_2 n </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9386em;vertical-align:-0.2441em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span>)</td><td style="text-align:center">O(<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><msub><mrow><mi>log</mi><mo>⁡</mo></mrow><mn>2</mn></msub><mi>n</mi></mrow><annotation encoding="application/x-tex"> n \log_2 n </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9386em;vertical-align:-0.2441em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span>)</td><td style="text-align:center">O(1)</td><td style="text-align:center">不稳定</td></tr><tr><td style="text-align:center">希尔排序</td><td style="text-align:center">O(n<sup>1.3</sup>)</td><td style="text-align:center">O(n<sup>2</sup>)</td><td style="text-align:center">O(n)</td><td style="text-align:center">O(1)</td><td style="text-align:center">不稳定</td></tr></tbody></table><h2 id="31-直接插入排序"><a class="markdownIt-Anchor" href="#31-直接插入排序"></a> 3.1 直接插入排序</h2><p>🌰：你手里有一副乱序的牌，现在你要把它们从小到大排好。你从左到右一张一张看：</p><ol><li>第一张牌，不用排，自己就是“有序”的。</li><li>拿第二张牌，跟第一张比一下，小就插到前面，大就放后面。现在前两张是有序的。</li><li>拿第三张牌，从右往左一个个比，把它<strong>插到正确的位置</strong>，让前三张有序。</li><li>继续这样，每拿一张新牌，都把它<strong>插入到前面已排序部分的正确位置</strong>。</li></ol><p><img src="1756178038456-5afd7275-0dac-4584-8d19-da16e110a602.gif" alt="" /></p><h2 id="32-希尔排序"><a class="markdownIt-Anchor" href="#32-希尔排序"></a> 3.2 希尔排序</h2><p>🌰：整理书架上的书（按高度排序）：</p><ol><li>先每隔几本排一次（大间隔）比如每隔 4 本书为一组</li><li>缩小间隔，比如每隔 2 本一组</li><li>最后，间隔为1，做一次普通插入排序</li></ol><p><img src="1756177887931-3bcdfb4d-0df2-49ca-8e56-1e2a6decd255.gif" alt="" /></p><h2 id="33-计数排序"><a class="markdownIt-Anchor" href="#33-计数排序"></a> 3.3 计数排序</h2><p>假设你有一堆小朋友的年龄，范围是 0 到 5 岁，想把他们按年龄从小到大排序。</p><ol><li>数一数每个年龄有多少人，拿一个表格（数组），从 0 开始，数每个年龄出现的次数：</li><li>按顺序把年龄写出来。从年龄 0 开始，写 1 个 0，写 2 个 1，写 1 个 2，写 2 个 3……以此类推。</li></ol><p><img src="1756178393350-f677791b-1d75-4408-aa49-323481ab5a0c.gif" alt="" /></p><h2 id="34-简单选择排序"><a class="markdownIt-Anchor" href="#34-简单选择排序"></a> 3.4 简单选择排序</h2><p>每次从剩下的数里，挑出最小的那个，放到前面。</p><ol><li>在所有数  [5, 2, 4, 1, 3]  中找最小的</li><li>在剩下的 [2, 4, 5, 3]` 中找最小的</li><li>在剩下的 [4, 5, 3]` 中找最小的</li><li>在剩下的 [5, 4]` 中找最小的</li></ol><p><img src="1756189664935-7d6ddfc6-2d75-430c-a12f-bf314cdafc13.gif" alt="" /></p><h2 id="35-堆排序"><a class="markdownIt-Anchor" href="#35-堆排序"></a> 3.5 堆排序</h2><ol><li>建立大顶堆</li><li>将大的权值向后排（重复此步骤）</li></ol><p><img src="1756189702353-6589fc11-c8d4-4145-8ef4-61006983259a.gif" alt="" /></p><h2 id="36-冒泡排序"><a class="markdownIt-Anchor" href="#36-冒泡排序"></a> 3.6 冒泡排序</h2><p>一排站在一起的高矮不一的学生（比如5个人），把他们按照从矮到高的顺序重新排列。</p><ol><li>从最左边开始：让第1个和第2个学生比身高。 如果左边（第1个）比右边（第2个）高，就让他们交换位置（让高的去右边）。</li><li>向右移动：接着让第2个和第3个学生比身高，同样，如果左边的比右边高就交换。</li><li>一直比到最后：继续这个过程，一直比到最后一对（第4个和第5个学生），最高的那个学生一定会被排到最右边</li><li>重复这个过程：现在，最高的学生已经就位了。我们忽略最后一个位置（因为他已经排好了）。</li></ol><p><img src="849589-20171015223238449-2146169197.gif" alt="img" /></p><h2 id="37-快速排序"><a class="markdownIt-Anchor" href="#37-快速排序"></a> 3.7 快速排序</h2><p>想象你有一堆杂乱无章的书，你需要把它们按照高度从矮到高排列。</p><ol><li><p>挑一本“标杆”书：从书堆里随便拿起一本书（比如正中间那本），这本书的高度就是我们的“标杆”。</p></li><li><p>分区操作（核心！）：现在，你开始整理剩下的书：</p><ul><li><p>创建一个 “矮个子区”（左边），创建一个 “高个子区”（右边）</p></li><li><p>然后，你一本一本地拿起剩下的书，和手里的“标杆”书比身高：如果比“标杆”矮，就扔到 “矮个子区”。如果比“标杆”高，就扔到 “高个子区”。</p></li></ul></li><li><p>递归排序：现在你有了三堆书：</p><ul><li>左边的一堆 “矮个子”（它们都比标杆矮，但内部顺序是乱的）</li><li>中间的一本“标杆”（它现在已经在了最终正确的位置上！）</li><li>右边的一堆 “高个子”（它们都比标杆高，但内部顺序也是乱的）右边的一堆 “高个子”（它们都比标杆高，但内部顺序也是乱的）</li></ul></li><li><p>对左右两堆重复：对左边的“矮个子区”和右边的“高个子区”分别重复步骤1-3（再为它们选新的“标杆”，再分区）。</p></li><li><p>合并：当每一堆小书堆都只剩下0本或1本书时（0或1本书本身就有序，不需要再排），把所有排好序的小书堆从左到右（矮区 + 标杆 + 高区）合并起来，整个序列就有序了。</p></li></ol><p><img src="1756259399527-48b04dfc-882d-4130-aaba-0f9d265179c6.gif" alt="" /></p><h2 id="38-归并排序"><a class="markdownIt-Anchor" href="#38-归并排序"></a> 3.8 归并排序</h2><p>有两叠已经按从小到大排好序的扑克牌（比如一叠是[3, 8, Q]，另一叠是[5, 9, K]），合并成一叠新的有序牌。</p><ol><li>总是比较最上面的牌：你看两叠牌最上面的一张，左边是3，右边是5。</li><li>拿出小的那张：3比5小，所以你拿出左边的3，放到新牌堆里。</li><li>继续比较：现在左边最上面是8，右边还是5。5比8小，所以你拿出右边的5，放到新牌堆（现在是[3, 5]）。</li><li>重复直到完：继续这个过程（比较8和9，拿8；比较Q和9，拿9；最后把Q和K依次拿出）。</li><li>最终：你得到了一个全新的、有序的牌堆：[3, 5, 8, 9, Q, K]。</li></ol><p><img src="1756259439615-6a92c3b1-20a3-42ac-b286-10e494bd35eb.gif" alt="" /></p><h2 id="39-排序算法总结"><a class="markdownIt-Anchor" href="#39-排序算法总结"></a> 3.9 排序算法总结</h2><table><thead><tr><th><strong>排序算法</strong></th><th><strong>核心思想</strong></th><th><strong>关键字</strong></th><th><strong>大概的逻辑</strong></th></tr></thead><tbody><tr><td><strong>快速排序</strong></td><td>分区、递归</td><td><strong>基准、分区</strong></td><td>一分为二，递归下去。</td></tr><tr><td><strong>归并排序</strong></td><td>先分后合、递归</td><td><strong>分治、合并</strong></td><td>先分后合，分治典范。</td></tr><tr><td><strong>堆排序</strong></td><td>利用堆结构</td><td><strong>建堆、取顶</strong></td><td>建堆取顶，反复调整。</td></tr><tr><td><strong>希尔排序</strong></td><td>分组插入</td><td><strong>间隔、分组</strong></td><td>分组插入，由粗到细。</td></tr><tr><td><strong>直接插入排序</strong></td><td>插牌</td><td><strong>插入、有序序列</strong></td><td>摸牌插牌，步步为营。</td></tr><tr><td><strong>冒泡排序</strong></td><td>两两交换</td><td><strong>相邻比较、交换</strong></td><td>两两比较，大的下沉。</td></tr><tr><td><strong>简单选择排序</strong></td><td>选择最值</td><td><strong>选择、最值</strong></td><td>每次选最小，放到最前面。</td></tr></tbody></table><ul><li>带“递归/分治”的：快排、归并。</li><li>带“插入”的：直接插入（基础）、希尔（改进版）。</li><li>名字即方法：选择、冒泡。</li><li>用数据结构的：堆排序。</li></ul>]]></content>
    
    
    <summary type="html">【软考zst2001专辑笔记】004数据结构-下卷</summary>
    
    
    
    
    <category term="软考" scheme="https://log.660066.xyz/tags/%E8%BD%AF%E8%80%83/"/>
    
  </entry>
  
  <entry>
    <title>【软考zst2001专辑笔记】003数据结构-上卷</title>
    <link href="https://log.660066.xyz/2025/08/21/zst-data-structure-volume-roll-up-notes/"/>
    <id>https://log.660066.xyz/2025/08/21/zst-data-structure-volume-roll-up-notes/</id>
    <published>2025-08-21T00:48:43.000Z</published>
    <updated>2025-08-21T01:36:45.825Z</updated>
    
    <content type="html"><![CDATA[<h1 id="一-大o表示法"><a class="markdownIt-Anchor" href="#一-大o表示法"></a> 一、大O表示法</h1><p>算法时间复杂度：以算法中基本操作重复执行的次数（简称频度）作为算法的时间度量。</p><style>.xrjphymrjaxx{zoom:50%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1754407027244-e35e7d76-407a-495a-b986-bb60737733f8.png" class="xrjphymrjaxx"><p>加法规则：多项相加，保留最高阶项，并将系数化为1</p><p>乘法法则：多项相乘都保留，系数化为1</p><p>加法乘法混合规则：先小括号 再乘法规则 最后加法规则</p><h1 id="二-时间复杂度"><a class="markdownIt-Anchor" href="#二-时间复杂度"></a> 二、时间复杂度</h1><p>例子：</p><ul><li>O(1)：<style>.rictibrtcvex{zoom:50%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1754407237453-2fd1fc9d-ab49-4175-9721-c3bb8b5c6133.png" class="rictibrtcvex"></li><li>O(log<sub>2</sub>n)：<style>.ljuwwjwuuhyu{zoom:50%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1754407255524-7712c8e1-dac6-4c57-8cd9-8ec311bef9c9.png" class="ljuwwjwuuhyu"></li><li>O(n)：<style>.jemobggxyotl{zoom:50%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1754407272409-768f1f0d-a3bf-417d-9608-0d32649ceb3d.png" class="jemobggxyotl"></li><li>O(nlog<sub>2</sub>n)：<style>.nkglqzqwbqbo{zoom:50%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1754407287442-6c82abe6-3351-4f18-8525-d200f7af6bf5.png" class="nkglqzqwbqbo"></li><li>O(n<sup>2</sup>)：<style>.sffcwpoubbsi{zoom:50%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1754407304859-edb98d84-c4cf-4738-8e1e-c6121cafe5c0.png" class="sffcwpoubbsi"></li><li>O(n<sup>3</sup>)：<style>.lpvfffrcxuty{zoom:50%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1754407320826-78134547-5ea4-4189-b4a2-742bd8ae15e5.png" class="lpvfffrcxuty"></li></ul><h1 id="三-空间复杂度"><a class="markdownIt-Anchor" href="#三-空间复杂度"></a> 三、空间复杂度</h1><style>.xrsnxtsibnke{zoom:50%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1754407573375-da4895d9-a10e-4b3c-9465-faab32fccbd1.png" class="xrsnxtsibnke"><p>T(n) = n<sup>2</sup> = O(n<sup>2</sup>)</p><h1 id="四-渐进符号"><a class="markdownIt-Anchor" href="#四-渐进符号"></a> 四、渐进符号</h1><ol><li><strong>渐进上界</strong><ul><li><strong>符号</strong>: <code>O</code></li><li><strong>含义</strong>: <code>f(n)</code> 的增长速度<strong>至多</strong>与 <code>g(n)</code> 一样快（或更慢）。它给出了函数 <code>f(n)</code> 的一个<strong>上界</strong>。常用于描述算法的<strong>最坏情况</strong>时间复杂度。</li><li><strong>类比</strong>: <code>f(n) ≤ g(n)</code> (在渐进意义上)。</li></ul></li><li><strong>渐进下界</strong><ul><li><strong>符号</strong>: <code>Ω</code></li><li><strong>含义</strong>: <code>f(n)</code> 的增长速度<strong>至少</strong>与 <code>g(n)</code> 一样快（或更快）。它给出了函数 <code>f(n)</code> 的一个<strong>下界</strong>。常用于描述算法的<strong>最好情况</strong>时间复杂度。</li><li><strong>类比</strong>: <code>f(n) ≥ g(n)</code> (在渐进意义上)。</li></ul></li><li>**渐进紧致界 **<ul><li><strong>符号</strong>: <code>Θ</code></li><li><strong>含义</strong>: <code>f(n)</code> 的增长速度<strong>精确地</strong>与 <code>g(n)</code> 一样快。它同时是 <code>f(n)</code> 的上界和下界，因此是一个<strong>紧致界</strong>。当算法的最好情况和最坏情况复杂度相同时，常用 <code>Θ</code> 来描述其<strong>平均情况</strong>或<strong>精确</strong>的时间复杂度。</li><li><strong>类比</strong>: <code>f(n) = g(n)</code> (在渐进意义上)。</li></ul></li></ol><style>.iuxqlnpzdmlw{zoom:50%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1754408011939-49169003-b7e5-43ca-9792-0d2c9e673556.png" class="iuxqlnpzdmlw"><h1 id="五-递归式时间-空间复杂度"><a class="markdownIt-Anchor" href="#五-递归式时间-空间复杂度"></a> 五、递归式时间、空间复杂度</h1><p>时间复杂度 = 递归的次数 x 每次的时间复杂度 <strong>(每次递归时间复杂度不变的情况下)</strong></p><p>空间复杂度 = ？？？？</p><p><strong>这一章讲的不是很清晰，学的也不是很透彻，待定吧</strong></p><h1 id="六-递归式主方法"><a class="markdownIt-Anchor" href="#六-递归式主方法"></a> 六、递归式主方法</h1><p>T(n) = aT(n/b) + f(n)</p><p>例子：</p><style>.zjjvcapcafem{zoom:50%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1754408464435-b8d50b81-f757-4282-8515-a86d9a5cadc2.png" class="zjjvcapcafem"><style>.lrerbmsexvth{zoom:50%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1754408445279-b6b85a49-cdf5-433e-a275-80512ea7af34.png" class="lrerbmsexvth"><h1 id="七-线性结构与线性表定义"><a class="markdownIt-Anchor" href="#七-线性结构与线性表定义"></a> 七、线性结构与线性表定义</h1><p>特点：数据元素之间呈现一种线性关系，即元素“一个接一个排列”。</p><p>线性表：顺序存储、链式存储。</p><p>非空线性表特点：</p><ul><li>存在唯一的一个称为“第一个”的元素。</li><li>存在唯一的一个称为“最后一个”的元素。</li><li>除第一个元素外，序列中的每个元素均只有一个直接前驱</li><li>除最后一个元素外，序列中的每个元素均只有一个直接后继。</li></ul><h2 id="71-线性表的顺序存储"><a class="markdownIt-Anchor" href="#71-线性表的顺序存储"></a> 7.1 线性表的顺序存储</h2><p>顺序存储是指，一组地址连续的存储单元依次存储线性表中的数据元素。</p><p>优点：可以随机存取表中元素。</p><p>缺点：插入、删除都需要移动元素。</p><p>插入一个新元素需要移动的元素个数期望值为：n/2</p><p>删除元素时需要移动的元素个数期望值为：(n-1)/2</p><h2 id="72-顺序表的插入-删除-查找时间复杂度"><a class="markdownIt-Anchor" href="#72-顺序表的插入-删除-查找时间复杂度"></a> 7.2 顺序表的插入、删除、查找时间复杂度</h2><table><thead><tr><th><strong>插入</strong>时间复杂度</th><th></th></tr></thead><tbody><tr><td>最好</td><td>O(1)</td></tr><tr><td>最坏</td><td>O(n)</td></tr><tr><td>平均</td><td>O(n)</td></tr></tbody></table><table><thead><tr><th><strong>删除</strong>时间复杂度</th><th></th></tr></thead><tbody><tr><td>最好</td><td>O(1)</td></tr><tr><td>最坏</td><td>O(n)</td></tr><tr><td>平均</td><td>O(n)</td></tr></tbody></table><table><thead><tr><th><strong>查找</strong>时间复杂度</th><th></th></tr></thead><tbody><tr><td>最好</td><td>O(1)</td></tr><tr><td>最坏</td><td></td></tr><tr><td>平均</td><td></td></tr></tbody></table><h2 id="73-顺序表的链式存储"><a class="markdownIt-Anchor" href="#73-顺序表的链式存储"></a> 7.3 顺序表的链式存储</h2><p><img src="1754986403014-82d01c6e-66ac-4391-9c9a-429a920cd14d.png" alt="" /></p><p>数据域用于存储元素的值，指针域用于存储元素的直接前驱或直接后继的位置信息。</p><p>各个数据元素的节点的地址并<strong>不要求是连续</strong>，因此存储数据元素的同时，必须存储元素的逻辑关系。</p><p>若元素的结点只有一个指针域，称为线性链表（单链表）</p><p><img src="1754986569650-e2ee665b-c1ef-454b-a16c-96418c5daf7d.png" alt="" /></p><h2 id="74-单链表的插入-删除-查找时间复杂度"><a class="markdownIt-Anchor" href="#74-单链表的插入-删除-查找时间复杂度"></a> 7.4 单链表的插入、删除、查找时间复杂度</h2><table><thead><tr><th style="text-align:center"><strong>插入</strong>时间复杂度</th><th></th></tr></thead><tbody><tr><td style="text-align:center">最好</td><td>O(1)</td></tr><tr><td style="text-align:center">最坏</td><td>O(n)</td></tr><tr><td style="text-align:center">平均</td><td>O(n)</td></tr></tbody></table><table><thead><tr><th style="text-align:center"><strong>删除</strong>时间复杂度</th><th></th></tr></thead><tbody><tr><td style="text-align:center">最好</td><td>O(1)</td></tr><tr><td style="text-align:center">最坏</td><td>O(n)</td></tr><tr><td style="text-align:center">平均</td><td>O(n)</td></tr></tbody></table><table><thead><tr><th style="text-align:center"><strong>查找</strong>时间复杂度</th><th></th></tr></thead><tbody><tr><td style="text-align:center">最好</td><td>O(1)</td></tr><tr><td style="text-align:center">最坏</td><td>O(n)</td></tr><tr><td style="text-align:center">平均</td><td>O(n)</td></tr></tbody></table><h2 id="75-循环单链表-双链表"><a class="markdownIt-Anchor" href="#75-循环单链表-双链表"></a> 7.5 循环单链表、双链表</h2><p>循环单链表：尾结点的指针域指向头结点。</p><p>双链表：两个指针域，分别指向前驱和后继。</p><h1 id="八-栈相关"><a class="markdownIt-Anchor" href="#八-栈相关"></a> 八、栈相关</h1><h2 id="81-栈的顺序存储"><a class="markdownIt-Anchor" href="#81-栈的顺序存储"></a> 8.1 栈的顺序存储</h2><p>先进后出</p><p>基本运算：</p><ol><li>初始化栈：创建一个空栈</li><li>判栈空：当栈为空时返回真，否则返回假</li><li>入栈：将元素x加入栈顶，并更新栈顶指针</li><li>出栈：将元素从栈中删除，并更新栈顶指针。</li><li>读站定元素：返回栈顶元素的值，但不修改栈顶指针</li></ol><h2 id="82-栈的链式存储"><a class="markdownIt-Anchor" href="#82-栈的链式存储"></a> 8.2 栈的链式存储</h2><p><img src="1754987160860-793b2d92-4482-4b92-aa7c-1572654efbc1.png" alt="" /></p><h1 id="九-队列相关"><a class="markdownIt-Anchor" href="#九-队列相关"></a> 九、队列相关</h1><h2 id="91-队列的顺序存储与循环队列"><a class="markdownIt-Anchor" href="#91-队列的顺序存储与循环队列"></a> 9.1 队列的顺序存储与循环队列</h2><p>先进先出。允许插入元素的一端为队尾，允许删除元素的一段为队头。</p><p>由于队列的元素插入和删除分别再两端进行，因此设置队头指针和队尾指针。</p><p>运算：</p><ol><li>初始化队列：创建一个空的队列。</li><li>判队空：当队列为空时返回真，否则返回假。</li><li>入队：将元素加入到队列的队尾，并更新队尾指针。</li><li>出队：将队头元素从队列中删除，并更新队头指针。</li><li>读队头元素：返回队头元素的值，但不修改队头指针。</li></ol><p><img src="1754987493922-98346a78-e075-4241-932f-1aa51a387dc0.png" alt="" />循环队列</p><h2 id="92-队列的链式存储与双端队列"><a class="markdownIt-Anchor" href="#92-队列的链式存储与双端队列"></a> 9.2 队列的链式存储与双端队列</h2><p><img src="1754987966760-8c5e0fca-5311-4ea5-9db4-905737ed5e96.png" alt="" />队列的链式存储</p><p><img src="1754988025073-1a2f5c14-97a2-405e-b6b6-db51e8b69bd0.png" alt="" /><img src="1754987987595-22350516-73ed-4927-a777-84191eb17691.png" alt="" /></p><h1 id="十-串相关"><a class="markdownIt-Anchor" href="#十-串相关"></a> 十、串相关</h1><p>特殊的线性表，元素为字符。</p><p>基本概念：</p><ol><li><strong>空串</strong>：长度为零称为空串，空串不包含任何字符。</li><li><strong>空格串</strong>：由一个或多个空格组成的串。空格在计算长度是也要将其计算在内。</li><li><strong>子串</strong>：串中任意长度的连续字符构成的序列称为子串。空串是任意串的子串。</li><li>串相等：两个串长度相等，且对应序号的字符相同。</li><li>串比较：比较两个串大小时，以字符的ASCII码作为依据。</li></ol><h2 id="101-串的模式匹配与朴素模式匹配"><a class="markdownIt-Anchor" href="#101-串的模式匹配与朴素模式匹配"></a> 10.1 串的模式匹配与朴素模式匹配</h2><p>最好：O(m)</p><p>最坏：O(nm)</p><p>平均：O(n+m)</p><h2 id="102-手算next数组值"><a class="markdownIt-Anchor" href="#102-手算next数组值"></a> 10.2 手算next数组值</h2><p>串的前缀：包含第一个字符并且不包含最后一个字符的子串</p><p>串的后缀：包含最后一个字符并且不包含第一个字符的子串</p><p>第i个字符的next值 = 从1 ~ i-1 串中最长相等前后缀长度 + 1</p><p>特殊情况：next[1] = 0</p><p>**手算步骤（以模式串 **<code>ABABC</code> <strong>为例）</strong></p><p>模式串：<code>P = &quot;ABABC&quot;</code></p><p>我们逐位计算 <code>next[i]</code>：</p><hr /><ol><li><strong>i = 0: 子串<code>A</code></strong></li></ol><ul><li>没有真前后缀 → <code>next[0] = 0</code></li></ul><ol start="2"><li><strong>i = 1: 子串<code>AB</code></strong></li></ol><ul><li>前缀：<code>A</code></li><li>后缀：<code>&quot;B&quot;</code></li><li>无相等前后缀 → <code>next[1] = 0</code></li></ul><ol start="3"><li><strong>i = 2: 子串 <code>ABA</code></strong></li></ol><ul><li>前缀：<code>&quot;A&quot;</code>, <code>&quot;AB&quot;</code></li><li>后缀：<code>&quot;A&quot;</code>, <code>&quot;BA&quot;</code></li><li>相等的有：<code>&quot;A&quot;</code>（长度1）</li><li>最长相等真前后缀长度 = 1 → <code>next[2] = 1</code></li></ul><ol start="4"><li><strong>i = 3: 子串 <code>ABAB</code></strong></li></ol><ul><li>前缀：<code>&quot;A&quot;</code>, <code>&quot;AB&quot;</code>, <code>&quot;ABA&quot;</code></li><li>后缀：<code>&quot;B&quot;</code>, <code>&quot;AB&quot;</code>, <code>&quot;BAB&quot;</code></li><li>相等的有：<code>&quot;AB&quot;</code>（长度2）</li><li>最长 = 2 → <code>next[3] = 2</code></li></ul><ol start="5"><li><strong>i = 4: 子串 <code>ABABC</code></strong></li></ol><ul><li>前缀：<code>&quot;A&quot;</code>, <code>&quot;AB&quot;</code>, <code>&quot;ABA&quot;</code>, <code>&quot;ABAB&quot;</code></li><li>后缀：<code>&quot;C&quot;</code>, <code>&quot;BC&quot;</code>, <code>&quot;ABC&quot;</code>, <code>&quot;BABC&quot;</code></li><li>没有相等的前后缀 → <code>next[4] = 0</code></li></ul><hr /><p>✅ 最终next数组：</p><table><thead><tr><th><strong>i</strong></th><th><strong>P[i]</strong></th><th><strong>子串</strong></th><th><strong>next[i]</strong></th></tr></thead><tbody><tr><td>0</td><td>A</td><td>A</td><td>0</td></tr><tr><td>1</td><td>B</td><td>AB</td><td>0</td></tr><tr><td>2</td><td>A</td><td>ABA</td><td>1</td></tr><tr><td>3</td><td>B</td><td>ABAB</td><td>2</td></tr><tr><td>4</td><td>C</td><td>ABABC</td><td>0</td></tr></tbody></table><p>👉 所以：<code>next = [0, 0, 1, 2, 0]</code></p><p>✅总结：手算next数组口诀</p><p>逐位看子串，拆分前和后，</p><p>找最长相等，记长度为next。</p><p>单字符为0，无匹配也为0，</p><p>前后缀不重叠，才是“真”前后。</p><h1 id="十一-数组相关"><a class="markdownIt-Anchor" href="#十一-数组相关"></a> 十一、数组相关</h1><h2 id="111-一维数组"><a class="markdownIt-Anchor" href="#111-一维数组"></a> 11.1 一维数组</h2><p>L：元素大小</p><p>LOC：数组首地址</p><p>内存中：a[0] a[1] a[2] a[3] a[4] a[5]</p><p><strong>某个元素在内存中实际地址的公式：</strong></p><p>下标从<strong>0</strong>开始： a<sub>i</sub> = LOC + i x L</p><p>下标从<strong>1</strong>开始： a<sub>i</sub> = LOC + (i-1) x L</p><h2 id="112-二维数组"><a class="markdownIt-Anchor" href="#112-二维数组"></a> 11.2 二维数组</h2><p>N：行 M：列</p><p>L：元素大小</p><p>LOC：数组首地址</p><p>a[0][0] a[0][1] a[0][2]</p><p>a[1][0] a[1][1] a[1][2]</p><p>按行优先：a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2]</p><p>按列优先：a[0][0] a[1][0] a[0][1] a[1][1] a[0][2] a[1][2]</p><p><strong>某个元素在内存中实际地址的公式：</strong></p><p>按<strong>行</strong>优先存储，下标从<strong>0</strong>开始：a<sub>i,j</sub> =LOC + (i x M + j) x L</p><p>按<strong>行</strong>优先存储，下标从<strong>1</strong>开始：a<sub>i,j</sub> =LOC + [(i - 1) x M + (j - 1)] x L</p><p>按<strong>列</strong>优先存储，下标从<strong>0</strong>开始：a<sub>i,j</sub> =LOC + (j x N + i) x L</p><p>按<strong>列</strong>优先存储，下标从<strong>1</strong>开始：a<sub>i,j</sub> =LOC + [(j - 1) x M + (i - 1)] x L</p><h1 id="十二-矩阵相关"><a class="markdownIt-Anchor" href="#十二-矩阵相关"></a> 十二、矩阵相关</h1><h2 id="121-对称矩阵"><a class="markdownIt-Anchor" href="#121-对称矩阵"></a> 12.1 对称矩阵</h2><p>123A<sub>0,0</sub>A<sub>0,1</sub>A<sub>0,3</sub></p><p>234A<sub>1,0</sub>A<sub>1,1</sub>A<sub>1,3</sub></p><p>345A<sub>2,0</sub>A<sub>2,1</sub>A<sub>2,3</sub></p><p><img src="1755497915439-c5ef434c-d352-4e62-ab24-39ca78b15b50.png" alt="" />A<sub>i,j</sub> = A<sub>j,i</sub></p><p>左下三角区 + 主对角线</p><p>对称矩阵按<strong>行</strong>存储<strong>下三角</strong>区和<strong>主对角</strong>线并且下标从<strong>0</strong>(A0.0)开始</p><p>当(i ≥ j)时：A<sub>i,j</sub> = <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mrow><mi>i</mi><mo stretchy="false">(</mo><mi>i</mi><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><mn>2</mn></mfrac><mo>+</mo><mi>j</mi><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex"> \frac{i(i+1)}{2}+j+1 </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.355em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.01em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.485em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mbin mtight">+</span><span class="mord mtight">1</span><span class="mclose mtight">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.854em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></p><p>当(i ≤ j)时：A<sub>i,j</sub> = <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mrow><mi>i</mi><mo stretchy="false">(</mo><mi>j</mi><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><mn>2</mn></mfrac><mo>+</mo><mi>i</mi><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex"> \frac{i(j+1)}{2}+i+1 </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.355em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.01em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.485em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mbin mtight">+</span><span class="mord mtight">1</span><span class="mclose mtight">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7429em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></p><p>对称矩阵按<strong>行</strong>存储<strong>下三角区</strong>和<strong>主对角</strong>线并且下标从<strong>1</strong>(A1.1)开始</p><p>当(i ≥ j)时：A<sub>i,j</sub> =  <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mrow><mi>i</mi><mo stretchy="false">(</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><mn>2</mn></mfrac><mo>+</mo><mi>j</mi></mrow><annotation encoding="application/x-tex"> \frac{i(i-1)}{2}+j </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.355em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.01em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.485em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span><span class="mclose mtight">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.854em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span></span></span></span></p><p>当(i ≤ j)时：A<sub>i,j</sub> =  <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mrow><mi>j</mi><mo stretchy="false">(</mo><mi>j</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><mn>2</mn></mfrac><mo>+</mo><mi>i</mi></mrow><annotation encoding="application/x-tex"> \frac{j(j-1)}{2}+i </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.355em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.01em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.485em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mbin mtight">−</span><span class="mord mtight">1</span><span class="mclose mtight">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span></span></span></span></p><h2 id="122-三对角矩阵"><a class="markdownIt-Anchor" href="#122-三对角矩阵"></a> 12.2 三对角矩阵</h2><p><img src="1755501050170-6184df72-4c8d-4d9c-9a4a-3d8eca9714e1.png" alt="" /></p><p>三对角矩阵按<strong>行</strong>存储并且下标从<strong>0</strong>(A<sub>0,0</sub>)开始：A<sub>i,j</sub> = 2i + j + 1</p><p>三对角矩阵按<strong>列</strong>存储并且下标从<strong>1</strong>(A<sub>1,1</sub>)开始：A<sub>i,j</sub> = 2i + j - 2</p><h2 id="123-稀疏矩阵"><a class="markdownIt-Anchor" href="#123-稀疏矩阵"></a> 12.3 稀疏矩阵</h2><p>顺序存储：三元组顺序表</p><p>链式存储：十字链表</p><p><img src="1755504250266-ed4f1bd1-40ce-4674-a8a9-dbcfa58d2639.png" alt="" /></p><table><thead><tr><th>行</th><th>列</th><th>值</th></tr></thead><tbody><tr><td>同行的下一个元素</td><td></td><td>同列的下一个元素</td></tr></tbody></table><h1 id="十三-树相关"><a class="markdownIt-Anchor" href="#十三-树相关"></a> 十三、树相关</h1><h2 id="131属性结构与树的定义"><a class="markdownIt-Anchor" href="#131属性结构与树的定义"></a> 13.1属性结构与树的定义</h2><p>非线性结构</p><p>树是n(n≥0)个结点的有限集合，n=0时称为空树。</p><p>有且仅有一个结点称为根。</p><p>树的定义是递归的，由若干颗子树构成，子树又由更小的子树构成。</p><p><img src="1755504447152-90f38e7d-6432-48b9-bab0-ebca8ef59d04.png" alt="" /></p><h2 id="132-树的基本概念"><a class="markdownIt-Anchor" href="#132-树的基本概念"></a> 13.2 树的基本概念</h2><ul><li>双亲、孩子：结点的子树称为该节点的孩子，该节点是子结点的双亲。</li><li>兄弟：具有相同双亲的结点互为兄弟。</li><li><strong>结点的度</strong>：<strong>结点的子树的个数。</strong></li><li>叶子结点：终端结点，度为0的结点。</li><li>内部结点：也称为分支节点或非终端结点。度不为0，除了根节点外，分支结点也称为内部结点。</li><li>结点的层次：根为第一层，根的孩子为第二层，以此类推。</li><li><strong>树的高度（深度）</strong>：<strong>树的最大层次。</strong></li></ul><h2 id="133-树的性质"><a class="markdownIt-Anchor" href="#133-树的性质"></a> 13.3 树的性质</h2><hr /><ol><li>树的结点总数 = 树所有结点的度数之和 + 1</li><li>度为m的树中第i层，最多有m<sup>i-1</sup>个结点（i ≥ 1）</li><li>高度为h的m次树，最多有<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mrow><msup><mi>m</mi><mi>h</mi></msup><mo>−</mo><mn>1</mn></mrow><mrow><mi>m</mi><mo>−</mo><mn>1</mn></mrow></mfrac></mrow><annotation encoding="application/x-tex"> \frac{m^h - 1}{m - 1} </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.4463em;vertical-align:-0.4033em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.0429em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.927em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">h</span></span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4033em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></li><li>具有n个结点、度为m的树，最小高度为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo fence="true">⌈</mo><msub><mrow><mi>log</mi><mo>⁡</mo></mrow><mi>m</mi></msub><mrow><mo fence="true">(</mo><mi>n</mi><mo stretchy="false">(</mo><mi>m</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mo>+</mo><mn>1</mn><mo fence="true">)</mo></mrow><mo fence="true">⌉</mo></mrow><annotation encoding="application/x-tex"> \left\lceil \log_m \left( n(m-1) + 1 \right) \right\rceil </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">⌈</span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0573em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">n</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mclose delimcenter" style="top:0em;">⌉</span></span></span></span></span>（上取整）</li></ol><h2 id="134-二叉树的定义"><a class="markdownIt-Anchor" href="#134-二叉树的定义"></a> 13.4 二叉树的定义</h2><p><img src="1755505362893-60f07965-ff56-4a48-b817-16076aefc81c.png" alt="" /></p><p>二叉树结点的子树，要<strong>区分左子树和右子树</strong>。（即使结点只有一棵树的时候也要明确指出）</p><p>二叉树的结点<strong>最大的度为2</strong></p><h2 id="135-二叉树的性质"><a class="markdownIt-Anchor" href="#135-二叉树的性质"></a> 13.5 二叉树的性质</h2><ol><li>二叉树<strong>第i层(i ≥ 1)<strong>上</strong>最多有2</strong><sup><strong>i-1</strong></sup><strong>个结点</strong></li><li><strong>高度为h</strong>的二叉树<strong>最多有2</strong><sup><strong>h</strong></sup><strong>-1个结点</strong></li><li>对于任何一棵二叉树，<strong>度为0</strong>的结点数等于<strong>度为2的结点数+1</strong></li><li>具有<strong>n个结点</strong>的<strong>完全二叉树</strong>的高度为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mo fence="true">⌊</mo><msub><mrow><mi>log</mi><mo>⁡</mo></mrow><mn>2</mn></msub><mi>n</mi><mo fence="true">⌋</mo></mrow><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex"> \left\lfloor \log_2 n \right\rfloor + 1 </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">⌊</span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mclose delimcenter" style="top:0em;">⌋</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span>或<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo fence="true">⌈</mo><msub><mrow><mi>log</mi><mo>⁡</mo></mrow><mn>2</mn></msub><mo stretchy="false">(</mo><mi>n</mi><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo><mo fence="true">⌉</mo></mrow><annotation encoding="application/x-tex"> \left\lceil \log_2 (n+1) \right\rceil </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">⌈</span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mclose delimcenter" style="top:0em;">⌉</span></span></span></span></span></li></ol><h2 id="136-满二叉树与完全二叉树"><a class="markdownIt-Anchor" href="#136-满二叉树与完全二叉树"></a> 13.6 满二叉树与完全二叉树</h2><p>满二叉树：深度为k的二叉树，有2<sup>k</sup>-1个结点。叶结点只能出现在最底层，且非叶结点的度都为2</p><p>完全二叉树：<strong>从根到最后一层从左到右依次填满</strong>的结构。</p><p><strong>满二叉树是完全二叉树的一个特例</strong>。</p><p><img src="1755505854018-c7893107-08d3-49e4-b502-1b28040838b4.png" alt="" /></p><h2 id="137-二叉树顺序存储"><a class="markdownIt-Anchor" href="#137-二叉树顺序存储"></a> 13.7 二叉树顺序存储</h2><p><img src="1755508385541-0591fad8-63d3-4eb0-a656-30e6ffb5d6b9.png" alt="" /></p><p>编号为i的结点：i=1，该节点为根节点，无双亲；i&gt;1，则该结点的双亲结点为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo fence="true">⌊</mo><mfrac><mi>i</mi><mn>2</mn></mfrac><mo fence="true">⌋</mo></mrow><annotation encoding="application/x-tex"> \left\lfloor \frac{i}{2} \right\rfloor </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.2057em;vertical-align:-0.35em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size1">⌊</span></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8557em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size1">⌋</span></span></span></span></span></span></p><p>完全二叉树适合使用顺序存储，一般二叉树不宜采用顺序存储。</p><p><strong>最坏</strong>的情况下，一个深<strong>度为k且只有k个结点的二叉树</strong>（单支树）<strong>需要2</strong><sup><strong>k</strong></sup><strong>-1个存储单元</strong></p><h2 id="138-二叉树链式存储"><a class="markdownIt-Anchor" href="#138-二叉树链式存储"></a> 13.8 二叉树链式存储</h2><p><img src="1755509318055-51303399-8ffe-4f0f-8c68-e795ef26d2f7.png" alt="" /></p><p>二叉链表：n个节点，有n+1个空指针域</p><p>三叉链表：n个节点，有n+2个空指针域</p><h2 id="139-二叉树遍历"><a class="markdownIt-Anchor" href="#139-二叉树遍历"></a> 13.9 二叉树遍历</h2><ol><li>先序遍历：<strong>根左右</strong></li></ol><style>.ejwpiynisxez{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510059838-08e0b68d-7008-47ba-9a62-5272f977117f.png" class="ejwpiynisxez"> ===>  遍历结果：ABDGCEF<ol start="2"><li>中序遍历：左根右</li></ol><style>.mhwfaapkyiyb{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510059838-08e0b68d-7008-47ba-9a62-5272f977117f-20250821085653936.png" class="mhwfaapkyiyb"> ===>  遍历结果：BDGAECF<ol start="3"><li>后续遍历：左右根</li></ol><style>.gqsrbkcnxkou{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510059838-08e0b68d-7008-47ba-9a62-5272f977117f-20250821085656564.png" class="gqsrbkcnxkou"> ===>  遍历结果：GDBEFCA<ol start="4"><li>层序遍历：一层一层，从左到右</li></ol><style>.llfptuxupzxc{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510059838-08e0b68d-7008-47ba-9a62-5272f977117f-20250821085658683.png" class="llfptuxupzxc"> ===>  遍历结果：ABCDEFG<h2 id="1310-根据遍历构造二叉树"><a class="markdownIt-Anchor" href="#1310-根据遍历构造二叉树"></a> 13.10 根据遍历构造二叉树</h2><p>先序遍历：<strong>A</strong>BDGCEF</p><p>中序遍历：BDGAECF</p><p>后续遍历：GDBEFC<strong>A</strong></p><p>层次遍历：<strong>A</strong>BCDEFG</p><p>以上加粗的为根节点，可以从<strong>先序、后序、层次</strong>中找到。</p><p><strong>先序、后序是确定根的位置，中序确定根的子结点。</strong></p><p><strong>🌰****例子1：</strong></p><ul><li><strong>先序</strong>：<strong>A</strong>BDGCEF</li><li><strong>中序</strong>：BDGAECF</li><li><style>.mcfxzybdqrvn{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510513643-c6fc5932-1331-4b32-b5ea-ad6bb26ef977.png" class="mcfxzybdqrvn"><style>.ttlekgcyrtry{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510520200-f052d738-6828-43c4-bdca-90efaa856b14.png" class="ttlekgcyrtry"><style>.hqlvxjlxodkd{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510530829-aeeca3f5-396f-4184-9299-c4b34ee3614e.png" class="hqlvxjlxodkd"><style>.pzpwunahlrgf{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510538283-46f9afb4-1eff-4ff1-bb55-86e868e21c91.png" class="pzpwunahlrgf"><style>.vnqnflcbjwrz{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510547102-86faef93-f97f-4cde-adbe-431cd782a552.png" class="vnqnflcbjwrz"><style>.vbiphjddxcuk{zoom: 67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510568546-5198eb83-3a9c-4442-92a2-efe7695c0c73.png" class="vbiphjddxcuk"><style>.jpywuiysrocd{zoom: 67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510578175-f71c7f83-f037-4d75-9227-a2322c40e8c9.png" class="jpywuiysrocd"></li></ul><p><strong>🌰****例子2：</strong></p><ul><li><strong>后序</strong>：GDBEFC<strong>A</strong></li><li><strong>中序</strong>：BDGAECF</li><li><style>.npzjabvrpkkq{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510513643-c6fc5932-1331-4b32-b5ea-ad6bb26ef977-20250821085927805.png" class="npzjabvrpkkq"><style>.qikukydlwopd{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510649890-76fcaa86-dd61-4b43-9d24-b5602da91202.png" class="qikukydlwopd"><style>.gwsgbjdnuoug{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510658277-2284e9e8-5b9b-466c-a903-75eabe1a6109.png" class="gwsgbjdnuoug"><style>.qkvkvqwjvobp{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510675469-10a70e27-b76e-46e5-8b30-7d09a947d32f.png" class="qkvkvqwjvobp"><style>.uywcpyuvbvtm{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510684434-ed9a3ea7-827d-4bcc-98f7-b60060e340a4.png" class="uywcpyuvbvtm"><style>.odhfzfoqemyd{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510691650-7fcb96b4-940f-483b-ac3e-e8cfd4387e02.png" class="odhfzfoqemyd"></li></ul><p>🌰<strong>例子3：</strong></p><ul><li><strong>层次遍历：A</strong>BCDEFG</li><li>**中序：**BDGAECF</li><li><style>.aiwcmqrplpia{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510760318-7bf27db6-f88b-4b1e-9bb3-171069ff84c4.png" class="aiwcmqrplpia"><style>.qhhwlmhthhwh{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510771398-22d72035-9a0c-4766-9d4f-caeb9d1b6924.png" class="qhhwlmhthhwh"><style>.lvtnrokraian{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510781348-f7be26e7-c29d-40a7-b5aa-adfa0fb304ee.png" class="lvtnrokraian"><style>.rvyrwfwmkwqc{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510797455-b5b9d84b-6835-4463-bfeb-e202b7026eff.png" class="rvyrwfwmkwqc"><style>.weiprzedmwrm{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510810083-ad8990c1-f652-4a9c-a19c-7c7b62e898c8.png" class="weiprzedmwrm"><style>.niaejllesdgl{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510819992-4345c2c9-a591-4c91-84fe-8aa5a7e774fa.png" class="niaejllesdgl"><style>.tcerhnpdlphp{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755510828320-1bdab794-108c-43ab-b94a-2a8da22491ee.png" class="tcerhnpdlphp"></li></ul><table><thead><tr><th>组合</th><th>是否可构造</th><th>关键技巧</th></tr></thead><tbody><tr><td>先序 + 中序</td><td>✅</td><td>先序定根，中序分左右，递归</td></tr><tr><td>后序 + 中序</td><td>✅</td><td>后序定根，中序分左右，递归</td></tr><tr><td>层序 + 中序</td><td>✅（较难）</td><td>层序取根，中序分左右，筛选子序列</td></tr><tr><td>其他组合</td><td>❌ 或不唯一</td><td>缺少左右子树划分依据</td></tr></tbody></table><h2 id="1311-平衡二叉树"><a class="markdownIt-Anchor" href="#1311-平衡二叉树"></a> 13.11 平衡二叉树</h2><p>二叉树中的<strong>任意一个结点的左右子树高度之差的绝对值不超过1</strong></p><p><strong>叶子结点满足平衡二叉树的条件要求</strong></p><p><strong>完全二叉树是平衡二叉树</strong></p><h2 id="1312-二叉排序树的定义"><a class="markdownIt-Anchor" href="#1312-二叉排序树的定义"></a> 13.12 二叉排序树的定义</h2><p>根节点的关键字 <strong>&gt;</strong> 左子树所有结点的关键字，</p><p>根节点的关键字 **&lt; **右子树所有结点的关键字，</p><p>左右子树也是一颗二叉排序树</p><p>中序遍历得到的序列是有序序列。</p><p><img src="1755511339211-a6902725-c190-4e9d-8896-0f23690831a8.png" alt="" /></p><h2 id="1313-二叉排序树的构造"><a class="markdownIt-Anchor" href="#1313-二叉排序树的构造"></a> 13.13 二叉排序树的构造</h2><p>例子：</p><p>23 31 17 19 11 27 13 90 61</p><style>.eowvtsrvsrve{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755511464058-a511ab6c-49f9-4e74-8faf-13d895aaecdb.png" class="eowvtsrvsrve"><style>.dzyhuxipzuvy{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755511472091-db70a3b0-29bd-41dc-9d0f-156ddc236600.png" class="dzyhuxipzuvy"><style>.oyqwultkoupu{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755511478656-243c0b57-6f87-47f4-89c4-2e14056e7047.png" class="oyqwultkoupu"><style>.sejwbdekcorm{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755511486008-d9bef579-bb37-431c-9883-0bed24ec13a6.png" class="sejwbdekcorm"><style>.xdedhntnwqrm{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755511498278-5c8b50ef-8af4-4c93-9ce0-35f2e6e260c6.png" class="xdedhntnwqrm"><style>.gnejfigofmeu{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755511508085-4f7c5749-5d4d-4310-abf5-7fc7ee93ecfe.png" class="gnejfigofmeu"><style>.iflxtkasbtee{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755511519367-99d4c293-a10c-45da-8234-1c08c9637374.png" class="iflxtkasbtee"><style>.detrtsxlhjuy{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755511529570-13665ce7-7d62-4cb1-9b59-5ab70aac96bc.png" class="detrtsxlhjuy"><style>.hxcnfjfzmghf{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755511541056-fc825ca0-a1bd-4d4a-a21b-e4efa78d6169.png" class="hxcnfjfzmghf"><h2 id="1314-最优二叉树哈夫曼树定义和概念"><a class="markdownIt-Anchor" href="#1314-最优二叉树哈夫曼树定义和概念"></a> 13.14 最优二叉树（哈夫曼树）定义和概念</h2><p>带权路径长度最短的树。</p><p>路径：一个结点到另一个结点之间的通路。</p><p>路径上的分支数目称为路径长度。</p><p><strong>树的带权路径长度</strong>：所有叶子结点的带权路径长度之和，计为<strong>WPL</strong></p><p><img src="1755512061342-f4c4027a-9a4b-40c7-8fd0-c1ac3bb6480b.png" alt="" />WPL = 2x2 + 4x2 + 5x2 + 7x2 = 36</p><p>被乘数：是叶子结点的关键字</p><p>乘数：是根结点到该叶子结点的路径长度。<strong>这里从图中可以看出全是2</strong></p><p><strong>最优二叉树（哈夫曼树）的三个核心性质：</strong></p><ol><li>给定一组具有确定权值的叶子结点，构造出的二叉树中带权路径长度（WPL）最小。</li><li>只有度为0或2，没有度为1</li><li>总结点数为：2n-1</li></ol><h2 id="1315-最优二叉树构造"><a class="markdownIt-Anchor" href="#1315-最优二叉树构造"></a> 13.15 最优二叉树构造</h2><p><strong>最优二叉树不唯一，但是WPL是唯一的。</strong></p><p><strong>构造规则：</strong></p><ol><li>从前往后找2个权值最小</li><li>小的在左边，大的在右边</li><li>计算出权值，放入数组末尾</li><li>权值相同时从前往后</li><li>回调第一步。</li></ol><p>🌰例子：{18、32、4、8、12、26}</p><ol><li>选4和8。<style>.jhqddjxpdfxn{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755512797386-cf1220e7-fc09-4a19-82b0-d6359821cad7.png" class="jhqddjxpdfxn"></li><li>选12和12。<style>.unbnqgjkudgq{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755512867611-72a3d06c-323e-4e13-a956-a750cea0e560.png" class="unbnqgjkudgq"></li><li>选18和24。<style>.smyrkrztetjn{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755512899194-b2f76c19-53a1-410e-b046-dec6c26821da.png" class="smyrkrztetjn"></li><li>选32和26。<style>.fegtinahthpe{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755512957705-899c4605-d2f7-4478-8b75-014b7965b069.png" class="fegtinahthpe"></li><li>合并<style>.jhvfkksrtacx{zoom: 67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755512985382-621b6ba0-9ef3-4f8e-b355-78051209808a.png" class="jhvfkksrtacx"></li></ol><h2 id="1316-哈夫曼编码定义"><a class="markdownIt-Anchor" href="#1316-哈夫曼编码定义"></a> 13.16 哈夫曼编码定义</h2><p>等长编码：对每个字符编值相同长度的二进制编码。</p><p>哈夫曼编码：一种根据字符出现频率构建最优前缀码的变长编码技术，用于数据压缩。</p><table><thead><tr><th>a：45<br/>b：13<br/>c：12<br/>d：16<br/>e：9<br/>f：5</th><th><style>.zmwfixwwivfn{zoom:67%;}</style><img src="/2025/08/21/zst-data-structure-volume-roll-up-notes/1755586218753-23212104-196c-4c07-911a-21de8ad92bbf.png" class="zmwfixwwivfn"></th><th>a：0<br/>b：101<br/>c：100<br/>d：111<br/>e：1101<br/>f：1100</th></tr></thead></table><h2 id="1317-哈夫曼编码压缩比"><a class="markdownIt-Anchor" href="#1317-哈夫曼编码压缩比"></a> 13.17 哈夫曼编码压缩比.</h2><table><thead><tr><th>字符</th><th>a</th><th>b</th><th>c</th><th>d</th><th>e</th></tr></thead><tbody><tr><td>频率(%)</td><td>40</td><td>10</td><td>20</td><td>16</td><td>14</td></tr></tbody></table><hr /><p><img src="1755586562108-8abf4665-2d32-4cac-9a81-ae4908da27c7.png" alt="" /></p><table><thead><tr><th>a</th><th>b</th><th>c</th><th>d</th><th>e</th></tr></thead><tbody><tr><td>0</td><td>100</td><td>111</td><td>110</td><td>101</td></tr></tbody></table><ul><li>哈夫曼编码所需长度：1x40 + 3x10 + 3x20 + 3x16 + 3x14 = 220</li><li>等长编码所需长度：3x(40+10+20+16+14) = 300 （<strong>五个字符，等长编码，就需要3个二进制位代表一个值。</strong>）</li></ul><p>压缩比：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>−</mo><mfrac><mtext>哈夫曼编码所需长度</mtext><mtext>等长编码所需长度</mtext></mfrac></mrow><annotation encoding="application/x-tex"> 1 - \frac{\text{哈夫曼编码所需长度}}{\text{等长编码所需长度}} </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.2173em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8723em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord cjk_fallback mtight">等长编码所需长度</span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord cjk_fallback mtight">哈夫曼编码所需长度</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span> =<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>−</mo><mfrac><mn>220</mn><mn>300</mn></mfrac></mrow><annotation encoding="application/x-tex"> 1 - \frac{220}{300} </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">300</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">220</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span> ≈ 0.27</p><h2 id="1318-线索二叉树定义应该是了解即可"><a class="markdownIt-Anchor" href="#1318-线索二叉树定义应该是了解即可"></a> 13.18 线索二叉树定义【应该是了解即可】</h2><p><img src="1755587188334-eacd9845-d03c-4819-8706-3f6f9a2ab6f2.png" alt="" /></p><h2 id="1319-二叉树类别"><a class="markdownIt-Anchor" href="#1319-二叉树类别"></a> 13.19 二叉树类别</h2><ol><li>满二叉树</li><li>完全二叉树</li><li>平衡二叉树</li><li>排序二叉树</li><li>最优二叉树</li></ol><h1 id="十四-图相关"><a class="markdownIt-Anchor" href="#十四-图相关"></a> 十四、图相关</h1><h2 id="141-图形结构与图的定义"><a class="markdownIt-Anchor" href="#141-图形结构与图的定义"></a> 14.1 图形结构与图的定义</h2><p>图中，任意两个结点之间都可能存在直接关系。所以，图中一个结点的前驱结点和后继结点的数目是没有限制的。</p><p>图G是有集合V和E狗策划给你的二元组，记作G=(V，E)。</p><p>V是图中顶点的非空有限集合，E是图中边的有限集合。</p><p><img src="1755587456653-b4b007da-b73c-417f-942c-146b1c4d3005.png" alt="" /></p><h2 id="142-有向图和无向图"><a class="markdownIt-Anchor" href="#142-有向图和无向图"></a> 14.2 有向图和无向图</h2><p>有向图：图中每条边都是有方向的，顶点的关系用&lt;V<sub>i</sub>，V<sub>j</sub>&gt;表示，V<sub>i</sub>到V<sub>j</sub>有一条有向边，V<sub>i</sub>是起点称为弧尾，V<sub>j</sub>是终点称为弧头</p><p><img src="1755587539524-2abb70da-1a2e-4f90-9029-f8c565bcc7a0.png" alt="" /></p><p>无向图：每条边都是没方向的。顶点的关系用&lt;V<sub>i</sub>，V<sub>j</sub>&gt;表示，但是没有方向上的区别。</p><p><img src="1755587681964-974f2d48-aef7-466e-bd01-461f953e73ec.png" alt="" /></p><h2 id="143-完全图"><a class="markdownIt-Anchor" href="#143-完全图"></a> 14.3 完全图</h2><p><strong>无向</strong>完全图：无向图若有n个顶点，每个顶点与其他n-1个顶点之间都有边。<strong>共有</strong><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mrow><mi>n</mi><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><mn>2</mn></mfrac></mrow><annotation encoding="application/x-tex"> \frac{n(n-1)}{2} </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.355em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.01em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.485em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span><span class="mclose mtight">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span><strong>条边</strong>。</p><p><strong>有向</strong>完全图：有向图中，任意来个那个不同的顶点，都有方向相反的两条弧存在。<strong>共有n(n-1)条边。</strong></p><h2 id="144-顶点的度"><a class="markdownIt-Anchor" href="#144-顶点的度"></a> 14.4 顶点的度</h2><p>度：<strong>仅无向图存在</strong>。当前结点存在的弧的个数。</p><p>出度：<strong>仅有向图存在</strong>。从当前结点指向其他结点的弧的个数</p><p>入度：<strong>仅有向图存在</strong>。从其他结点指向当前结点的弧的个数</p><p><img src="1755596915715-5597e6ee-4bbf-4c09-b94d-55698d525011.png" alt="" /></p><h2 id="145-路径"><a class="markdownIt-Anchor" href="#145-路径"></a> 14.5 路径</h2><p>回路（环）：第一个顶点和最后一个顶点相同的路径</p><p>简单路径：路径中不包含重复的顶点。若一条路径上除了Vp和Vq可以相同外，其余顶点均不相同。</p><table><thead><tr><th>特性</th><th>简单路径</th><th>回路（特别是简单回路）</th></tr></thead><tbody><tr><td>起点与终点</td><td>可以不同</td><td>必须相同</td></tr><tr><td>顶点是否重复</td><td>所有顶点都不重复</td><td>仅起点和终点相同，其余不重复</td></tr><tr><td>是否闭合</td><td>不闭合</td><td>闭合</td></tr></tbody></table><p><strong>🌰****例子：</strong></p><ul><li>简单路径：A → B → C → D（无重复顶点，起点 ≠ 终点）</li><li>简单回路：A → B → C → A（起点 = 终点，其余顶点不重复）</li></ul><h2 id="146-连通图与强连通图"><a class="markdownIt-Anchor" href="#146-连通图与强连通图"></a> 14.6 连通图与强连通图</h2><p>连通图：无向图中任意两个顶点都是联通的。</p><p>最少：n-1</p><p>最多：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mrow><mi>n</mi><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><mn>2</mn></mfrac></mrow><annotation encoding="application/x-tex"> \frac{n(n-1)}{2} </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.355em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.01em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.485em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span><span class="mclose mtight">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></p><p>强连通图：有向图中任意两个顶点都有互相联通的路径。</p><p>最少：n</p><p>最多：n(n-1)</p><h2 id="147-邻接矩阵"><a class="markdownIt-Anchor" href="#147-邻接矩阵"></a> 14.7 邻接矩阵</h2><p><img src="1755657471426-fa6741fe-9189-47a4-9d7a-93e414a18955.png" alt="" /></p><p>无向图的邻接矩阵是对称的。</p><p>无向图：</p><ul><li>非零元素个数 = e 个</li><li>顶点V<sub>i</sub>的度是邻接矩阵第i行（或列）中值不为0的元素个数</li></ul><p>有向图：</p><ul><li>非零元素个数 = 2e 个</li><li>第i行（或列）中值不为0的元素个数是顶点V<sub>i</sub>的出度</li><li>第j列中值不为0的元素个数是顶点V<sub>j</sub>的入度</li></ul><h2 id="148-邻接表"><a class="markdownIt-Anchor" href="#148-邻接表"></a> 14.8 邻接表</h2><p><img src="1755658086248-893067fc-c557-47e6-9017-2560028902ce.png" alt="" /></p><p>无向图：表节点个数 = e = 邻接矩阵非零元素个数</p><h2 id="149-稠密图和稀疏图"><a class="markdownIt-Anchor" href="#149-稠密图和稀疏图"></a> 14.9 稠密图和稀疏图</h2><p>稀疏图：边的数量 <strong>远少于</strong> 顶点可能连接的最大边数。（可能图中大部分顶点之间没有直接连接。）</p><p>稠密图：边的数量 <strong>接近</strong> 顶点可能连接的最大边数。（可能图中大部分顶点之间都有边相连。）</p><table><thead><tr><th>特性</th><th>稀疏图</th><th>稠密图</th></tr></thead><tbody><tr><td>边的数量</td><td>少</td><td>多</td></tr><tr><td>连接程度</td><td>连接稀疏，很多点不相连</td><td>大部分点都有边相连</td></tr><tr><td>存储方式建议</td><td>常用<strong>邻接表</strong></td><td>常用<strong>邻接矩阵</strong></td></tr></tbody></table><h2 id="1410-网"><a class="markdownIt-Anchor" href="#1410-网"></a> 14.10 网</h2><p>边（或弧）带权值的图称为网。</p><p><img src="1755659633619-a3a53d4d-75ec-4c57-a132-8e5abe58d49e.png" alt="" /></p><h2 id="1411-图的遍历"><a class="markdownIt-Anchor" href="#1411-图的遍历"></a> 14.11 图的遍历</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">    A</span><br><span class="line">   / \</span><br><span class="line">  B   C</span><br><span class="line"> /   / \</span><br><span class="line">D   E   F</span><br></pre></td></tr></table></figure><p>深度优先算法：</p><ul><li>定义：从一个起点出发，<strong>沿着一条路径尽可能深入地走到底</strong>，直到无法继续为止，然后<strong>回溯</strong>，再尝试其他分支。</li><li>遍历顺序可能是：<strong>A → B → D → C → E → F</strong></li></ul><p>广度优先算法：</p><ul><li>定义：从起点开始，<strong>先访问所有距离为1的邻居</strong>，再访问距离为2的邻居，<strong>逐层向外扩散</strong>。</li><li>遍历顺序可能是：<strong>A → B → C → D → E → F</strong></li></ul><h2 id="1412-深度优先遍历"><a class="markdownIt-Anchor" href="#1412-深度优先遍历"></a> 14.12 深度优先遍历</h2><p><img src="1755674210642-9769d059-aea4-414e-8824-4634750c6433.png" alt="" /></p><p>遍历顺序： V1、V2、V5、V4、V3 或 V1、V3、V2、V4、V5</p><h2 id="1413-深度遍历-广度遍历的时间复杂度"><a class="markdownIt-Anchor" href="#1413-深度遍历-广度遍历的时间复杂度"></a> 14.13 深度遍历、广度遍历的时间复杂度</h2><p>深度优先搜索DFS：</p><ul><li>使用<strong>递归</strong>的思想进行遍历</li><li><strong>邻接矩阵</strong>时间复杂度：<strong>O(n</strong><sup><strong>2</strong></sup><strong>)</strong></li><li><strong>邻接表</strong>时间复杂度：<strong>O(n+e)</strong></li></ul><p>广度优先搜索BFS：</p><ul><li>使用<strong>队列</strong>的思想进行遍历</li><li><strong>邻接矩阵</strong>时间复杂度：<strong>O(n</strong><sup><strong>2</strong></sup><strong>)</strong></li><li><strong>邻接表</strong>时间复杂度：<strong>O(n+e)</strong></li></ul><h2 id="1414-拓扑排序"><a class="markdownIt-Anchor" href="#1414-拓扑排序"></a> 14.14 拓扑排序</h2><p><img src="1755679556062-50345f03-e279-4b99-9847-a6cbbbb3ab9c.png" alt="" /></p><p><strong>AOV网的特点：</strong></p><ul><li><strong>顶点</strong>：每个顶点代表一个活动。</li><li><strong>有向边</strong>：有向边(A,B)(<em>A</em>,<em>B</em>)表示活动A需要在活动B开始前完成，即A是B的前提条件。</li><li><strong>无环</strong>：为了确保所有活动可以被合理排序并最终完成，AOV网不能包含有向环。如果AOV网中存在环，则意味着某些活动之间存在循环依赖，导致无法进行有效的调度和执行。</li></ul><p><strong>AOV网进行拓扑排序：</strong></p><ol><li>在AOV网选择一个入度为0的顶点，输出它。</li><li>在网中删除该顶点，以及该顶点有关的所有弧。</li><li>重复上述步骤，知道网中不存在入度为0的顶点为止。</li></ol><p><img src="1755736551834-5f091605-c2ee-4569-911f-5b2c01460bdf.png" alt="" /></p>]]></content>
    
    
    <summary type="html">【软考zst2001专辑笔记】003数据结构-上卷</summary>
    
    
    
    
    <category term="软考" scheme="https://log.660066.xyz/tags/%E8%BD%AF%E8%80%83/"/>
    
  </entry>
  
  <entry>
    <title>【软考zst2001专辑笔记】002程序设计语言</title>
    <link href="https://log.660066.xyz/2025/08/05/zst-programming-language-notes/"/>
    <id>https://log.660066.xyz/2025/08/05/zst-programming-language-notes/</id>
    <published>2025-08-05T15:04:36.000Z</published>
    <updated>2025-08-05T15:11:41.756Z</updated>
    
    <content type="html"><![CDATA[<h1 id="一-编译程序与解释程序"><a class="markdownIt-Anchor" href="#一-编译程序与解释程序"></a> 一、编译程序与解释程序</h1><p>低级语言：机器语言、汇编语言</p><p>高级语言：Java、C、C++、PHP、Python、Delphi、PASCAL</p><p>语言之间的翻译形式：汇编、解释、编译</p><p><strong>高级语言</strong>编写的<strong>源程序</strong>，需要对应的<strong>解释程序或编译程序</strong>对其<strong>进行翻译</strong>。</p><p>解释程序（解释器）：</p><ul><li>翻译程序是<strong>不产</strong>成<strong>独立的目标程序</strong>。</li><li>解释程序和源程序<strong>都要参与到程序的运行过程</strong>中。</li></ul><p>编译程序（编译器）：</p><ul><li>翻译时将源程序<strong>翻译成独立</strong>保存的<strong>目标程序</strong>。</li><li>机器上运行的是与<strong>源程序等价的目标程序</strong>。</li><li>源程序和编译程序<strong>都不参与目标程序的运行</strong>过程。</li></ul><h1 id="二-程序设计语言基本成分"><a class="markdownIt-Anchor" href="#二-程序设计语言基本成分"></a> 二、程序设计语言基本成分</h1><p>基本控制结构：顺序、选择、重复（循环）</p><p>数据类型的作用：</p><ul><li>便于合理分配存储单元</li><li>便于对参与表达式计算的对象进行检查</li><li>便于规定数据对象的取值范围以及能进行的运算</li></ul><p>变量有对应的存储单元，常量没有。</p><h1 id="三-传值调用与传地址调用"><a class="markdownIt-Anchor" href="#三-传值调用与传地址调用"></a> 三、传值调用与传地址调用</h1><p>函数定义的基本形式：<style>.xmuukmbwbscg{zoom: 50%;}</style><img src="/2025/08/05/zst-programming-language-notes/1754399793757-105f4f16-1bbd-4795-ae88-27ad49e69e60.png" class="xmuukmbwbscg" alt="img"></p><p>函数调用：<style>.uhifxycgcvtn{zoom:50%;}</style><img src="/2025/08/05/zst-programming-language-notes/1754399822944-bbae9c48-d17d-425b-9bcb-994111dba728.png" class="uhifxycgcvtn" alt="img"></p><p>值调用：</p><ul><li>将实参的值传递给形参，实参可以是<strong>变量、常量、表达式</strong></li><li><strong>不可以实现</strong>形参和传参<strong>双向传递数据</strong>的效果。</li></ul><p>引用调用：</p><ul><li>将实参的地址传递给形参，<strong>形参必须有地址</strong>，实参<strong>不能是常量、表达式</strong>。</li><li>可以实现形参和实参间的双向传递数据的效果，即<strong>改变形参的值同时也改变实参的值</strong></li></ul><h1 id="四-编译-解释程序翻译阶段"><a class="markdownIt-Anchor" href="#四-编译-解释程序翻译阶段"></a> 四、编译、解释程序翻译阶段</h1><p>编译方式：</p><ul><li>词法分析、语法分析、语义分析、中间代码生成、代码优化、目标代码生成</li><li>中间代码生成和代码优化不是必要，即前三步完成后可直接生成目标代码</li></ul><p>解释方式：</p><ul><li>词法分析、语法分析、语义分析</li></ul><p><strong>编译器和解释器</strong>都<strong>不可省略词法分析、语法分析、语义分析</strong>，且<strong>顺序不可变</strong></p><style>.oyjtivngihpz{zoom:33%;}</style><img src="/2025/08/05/zst-programming-language-notes/1754400483239-812aa23e-4eef-4bad-85fc-5b1effec936a.png" class="oyjtivngihpz" alt="img"><h1 id="五-符号表"><a class="markdownIt-Anchor" href="#五-符号表"></a> 五、符号表</h1><p>不断收集、记录和使用源程序中一些相关符号的类型和特征等信息，并将其存入符号表。</p><p>记录源程序中各个字符的必要信息，以辅助语义的正确性检查和代码生成。</p><h1 id="六-词法分析"><a class="markdownIt-Anchor" href="#六-词法分析"></a> 六、词法分析</h1><p>输入：<strong>源程序</strong></p><p>输出：<strong>记号流</strong></p><p>主要作用：<strong>分析</strong>构成程序的<strong>字符</strong>，以及字符<strong>按照构造规则构成的符号是否符合</strong>程序语言的规定。</p><h1 id="七-语法分析"><a class="markdownIt-Anchor" href="#七-语法分析"></a> 七、语法分析</h1><p>输入：<strong>记号流</strong></p><p>输出：<strong>语法树（分析树）</strong></p><p>主要作用：对各条语句的结构进行合法性分析，分析程序中的句子结构是否正确。</p><h1 id="八-语义分析"><a class="markdownIt-Anchor" href="#八-语义分析"></a> 八、语义分析</h1><p>输入：<strong>语法树（分析树）</strong></p><p>主要作用：进行<strong>类型分析和检查</strong>。</p><p>不能发现程序中所有的语义错误，<strong>只能发现静态语义错误</strong>。动态语义错误只能在运行是发现。</p><h1 id="九-目标代码生成"><a class="markdownIt-Anchor" href="#九-目标代码生成"></a> 九、目标代码生成</h1><p>该阶段的<strong>工作与机器密切相关</strong>。</p><p><strong>寄存器的分配</strong>处于目标代码生成阶段。</p><h1 id="十-中间代码生成"><a class="markdownIt-Anchor" href="#十-中间代码生成"></a> 十、中间代码生成</h1><p>常见的中间代码：后缀式、三地址码、三元式、四元式和树（图）等形式</p><p>特征：</p><ul><li>与具体机器无关（不依赖于具体机器）</li><li>可以将不用的高级程序语言翻译成同一种中间代码。</li><li>中间代码可跨平台</li></ul><p>因为与机器无关，使用中间代码有利于进行与机器无关的优化处理和提高编译程序的可执行性。</p><h1 id="十一-正规式"><a class="markdownIt-Anchor" href="#十一-正规式"></a> 十一、正规式</h1><p>词法分析的工具</p><table><thead><tr><th>正规式</th><th>正规集</th></tr></thead><tbody><tr><td>Ab</td><td>字符串ab构成的集合</td></tr><tr><td>a|b</td><td>字符串a、b构成的集合</td></tr><tr><td>a*</td><td>由0个或多个a构成的字符串集合</td></tr><tr><td>(a|b)*</td><td>所有字符a和b构成的串的集合</td></tr><tr><td>a(a|b)*</td><td>以a为首字符的a、b字符串的集合</td></tr><tr><td>(a|b)*abb</td><td>以abb结尾的a、b字符串的集合</td></tr></tbody></table><h1 id="十二-有限自动机"><a class="markdownIt-Anchor" href="#十二-有限自动机"></a> 十二、有限自动机</h1><p>词法分析的工具，能正确识别正规集</p><p>确定的有限自动机（DFA）：对每个状态来说识别字符后转移的状态是唯一的</p><p>不确定的有限自动机（NFA）：对每个状态来说识别字符后转移的状态是不唯一的</p><p>判断依据：看看每个状态（就是哪个小圆圈）是不是存在多个指向别的状态的箭头（指向自己的不算）。</p><h1 id="十三-上下文无关文法"><a class="markdownIt-Anchor" href="#十三-上下文无关文法"></a> 十三、上下文无关文法</h1><p>广泛用于各种程序设计语言的语法规则。</p><p>大写字母为非终结符，小写字母为终结符。</p><h1 id="十四-中缀-后缀表达式装换"><a class="markdownIt-Anchor" href="#十四-中缀-后缀表达式装换"></a> 十四、中缀、后缀表达式装换</h1><p>中缀式转后缀式，优先级相同，从左向右。</p><style>.uvoawgxbrfnz{zoom:33%;}</style><img src="/2025/08/05/zst-programming-language-notes/1754403748749-a83ae4b0-c97b-4bcb-a8f7-0ccf5a7162df.png" class="uvoawgxbrfnz" alt="img"><h1 id="十五-语法树中序-后续遍历"><a class="markdownIt-Anchor" href="#十五-语法树中序-后续遍历"></a> 十五、语法树中序、后续遍历</h1><p>中序遍历-&gt;中缀式</p><p>后序遍历-&gt;后缀式</p><p>中序：左根右</p><p>后序：左右根</p><ul><li>例：1-2x(3+4)/5</li><li><style>.ydwpjsbnepgu{zoom:33%;}</style><img src="/2025/08/05/zst-programming-language-notes/1754404195351-dabdf89f-7095-4d98-ba99-5abd54e6bcc4.png" class="ydwpjsbnepgu" alt="img"></li></ul><h1 id="十六-杂题"><a class="markdownIt-Anchor" href="#十六-杂题"></a> 十六、杂题</h1><ol><li><p>反编译是编译的逆过程，<strong>不能</strong>把可执行文件<strong>还原成高级语言源代码</strong>，只能转换成<strong>功能上等价的汇编程序</strong>。</p></li><li><p>脚本语言是动态语言，动态语言都是解释型语言。</p></li><li><p>变量存储的是内存单元地址时，成为指针变量。对指针变量进行算术运算，可以使其指向其他元素。</p></li><li><p><strong>链表中的结点空间</strong>需要程序员根据<strong>需要申请和释放</strong>，因此数据空间应该<strong>采用堆存储分配策略</strong>。</p></li><li><p>可视化程序设计是以“所见即所得”的编程思想为原则</p></li><li><p><strong>编译时变量</strong>分配存储单元所用<strong>地址是逻辑地址</strong>，<strong>运行时映射成物理地址</strong>。</p></li><li><p>程序运行时，用户内存空间分为<strong>代码区、静态数据区、栈区、堆区</strong>。栈区、堆区属于动态数据区，<strong>常量在静态数据区。</strong></p></li><li><p>语法分析方法，根据产生语法树的方向：</p></li><li><p><strong>自顶向下分析法：递归下降分析法、预测分析法。</strong></p></li><li><p><strong>自底向上分析法：算符优先分析法、LR分析法、移进-规约分析法。</strong></p></li><li><p>用户可命名的对象：变量、函数、数据类型</p></li><li><p>编程语言分类</p></li><li><p>函数式编程语言：Lisp</p></li><li><p>逻辑式编程语言：Prolog</p></li><li><p>过程式、面向对象：Python</p></li><li><p>面向对象：Java、C++</p></li><li><p>语法制导翻译是静态语义分析方法。</p></li><li><p><strong>栈区由系统</strong>进行管理，<strong>堆区由程序员</strong>进行管理。</p></li><li><p>C或C++代码生成可执行文件的过程：<strong>预处理-&gt;编译-&gt;汇编-&gt;链接</strong></p></li><li><p>Java特征：<strong>采用即时编译。对象在堆空间分配。自动垃圾回收</strong>。</p></li><li><p>Python中：</p></li><li><p>列表（list）是<strong>可变、有序、可重复</strong>的序列结构</p></li><li><p>元组（tuptle）、字符串（str）是<strong>不可变</strong>的</p></li><li><p>集合（set）<strong>去重</strong>的</p></li><li><p>Python<strong>深度学习</strong>模型：TensorFlow、PyTorch、Keras</p></li><li><p>Python <strong>绘图</strong>库：Matplotlib</p></li></ol>]]></content>
    
    
    <summary type="html">【软考zst2001专辑笔记】002程序设计语言</summary>
    
    
    
    
    <category term="软考" scheme="https://log.660066.xyz/tags/%E8%BD%AF%E8%80%83/"/>
    
  </entry>
  
  <entry>
    <title>【软考zst2001专辑笔记】001计算机系统</title>
    <link href="https://log.660066.xyz/2025/07/15/zst-computer-system-notes/"/>
    <id>https://log.660066.xyz/2025/07/15/zst-computer-system-notes/</id>
    <published>2025-07-15T01:15:01.000Z</published>
    <updated>2025-07-15T01:29:22.419Z</updated>
    
    <content type="html"><![CDATA[<h1 id="一-cpu"><a class="markdownIt-Anchor" href="#一-cpu"></a> 一、CPU</h1><ul><li>计算机基本硬件系统：运算器、控制器、存储器、输入设备、输出设备</li><li>运算器、控制器等部件集成后成为中央处理器，是硬件系统的核心。</li><li>CPU的功能：<ul><li>控制器：程序控制、操作控制、时间控制</li><li>运算器：数据处理</li></ul></li></ul><h1 id="二-运算器"><a class="markdownIt-Anchor" href="#二-运算器"></a> 二、运算器</h1><ul><li>运算器：由算数逻辑单元（ALU）、累加寄存器、数据缓冲寄存器、状态条件寄存器组成。</li><li>运算器的主要功能：<ul><li>算数运算：加、减、乘、除、附加运算。</li><li>逻辑运算、逻辑测试：与、或、非、零值测试、两个值的比较。</li></ul></li><li><strong>算数逻辑单元（ALU）</strong>：重要组成部件，负责处理数据（算数运算、逻辑运算）。</li><li><strong>累加寄存器（AC）</strong>：通用寄存器，为ALU提供一个工作区。运算结果存储在累加器中。</li><li>数据缓冲寄存器（DR）：CPU和内存、外部设备之间数据传送的中转站。</li><li>状态条件寄存器（PSW）:标志，进位、溢出、0标志、负标志、中断、方向。</li></ul><h1 id="三-控制器"><a class="markdownIt-Anchor" href="#三-控制器"></a> 三、控制器</h1><p>要保证程序的正确执行，还要能处理异常事件。</p><ul><li>指令寄存器（IR）：执行指令先从内存取到缓冲寄存器，再送入IR暂存。</li><li>程序计数器（PC）：具有寄存信息、计数两种功能。存储CPU要执行的下一条指令的地址。大多数情况都是顺序执行，所以修改过程只是简单的加1。</li><li>地址寄存器（AR）：保持当前CPU所访问的内存地址。</li><li>指令译码器（ID）：指令包含操作码和地址码。对指令中的操作码进行分析解释。</li></ul><h1 id="四-计算机基本单位"><a class="markdownIt-Anchor" href="#四-计算机基本单位"></a> 四、计算机基本单位</h1><table><thead><tr><th>名称</th><th>英文</th><th>简写</th><th>换算</th></tr></thead><tbody><tr><td>位（比特）</td><td>bit</td><td>b</td><td></td></tr><tr><td>字节</td><td>byte</td><td>B</td><td>1B = 8b</td></tr><tr><td>千字节</td><td></td><td>KB</td><td>1KB = 1024B</td></tr><tr><td>兆字节</td><td></td><td>MB</td><td>1MB = 1024KB</td></tr><tr><td>吉字节</td><td></td><td>GB</td><td>1GB = 1024MB</td></tr><tr><td>钛字节</td><td></td><td>TB</td><td>1TB = 1024GB</td></tr></tbody></table><p>最小的数据单位：b</p><p>最小的存储单位：byte</p><h1 id="五-十进制-二进制"><a class="markdownIt-Anchor" href="#五-十进制-二进制"></a> 五、十进制、二进制</h1><ul><li>十进制：0—9</li><li>二进制：0—1</li><li>八进制：0—7</li><li>十六进制：0—9 + A—F</li></ul><p>按位展开求和：<strong>n</strong>进制—&gt;<strong>十</strong>进制</p><ul><li>将二进制 <code>1011</code> 转换为十进制  为🌰</li><li><img src="1751592658972-4bfdf271-99f6-4785-94cd-6201c1a7b962.png" alt="" /></li><li></li></ul><p>除n取余法：<strong>十</strong>进制—&gt;<strong>n</strong>进制</p><ul><li>将十进制 <code>23</code> 转换为二进制  为🌰</li><li><img src="1751592618535-bc2db6b9-13de-4a0a-a4f8-8d3738128333.png" alt="" /></li><li><img src="1751593020878-865c5972-9f9c-4b3b-8934-333148cdd128.png" alt="" /></li></ul><h1 id="六-八进制-十六进制"><a class="markdownIt-Anchor" href="#六-八进制-十六进制"></a> 六、八进制、十六进制</h1><p>1位十六进制数 = 4位二进制数</p><p>1位八进制数 = 3位二进制数</p><h1 id="七-进制加减法"><a class="markdownIt-Anchor" href="#七-进制加减法"></a> 七、进制加减法</h1><p>n进制加法：逢n进1</p><p>n进制减法：借1当n</p><h1 id="八-原码-反码-补码-移码"><a class="markdownIt-Anchor" href="#八-原码-反码-补码-移码"></a> 八、原码、反码、补码、移码</h1><p>原码：最高位是符号位，0表示正号，1表示负号，其余的n-1位表示数值的绝对值。</p><ul><li>0有两种表示形式：[+0] = 0 0000000，[-0] = 1 0000000</li></ul><p>反码：最高位是符号位，0表示正号，1表示负号。正数的反码与原码相同，负数的反码是负原码绝对值求反。</p><ul><li>0有两种表示形式：[+0] = 0 0000000，[-0] = 1 1111111</li></ul><p>补码：最高位是符号位，0表示正号，1表示负号。正数的补码与反码、原码相同，负数的补码是负反码末位加1。</p><ul><li>0有唯一值：[+0] = 0 0000000</li></ul><p>移码：补码的符号位取反。</p><p>特性：[[X]<sub>补</sub>]<sub>补</sub> = [X]<sub>原</sub></p><table><thead><tr><th>码制</th><th>定点整数</th><th>定点小数</th></tr></thead><tbody><tr><td>原码</td><td>-(2<sup>n-1</sup>-1)~+(2<sup>n-1</sup>-1)</td><td>-(1-2<sup>-(n-1)</sup>)~+(1-2<sup>-(n-1)</sup>)</td></tr><tr><td>反码</td><td>-(2<sup>n-1</sup>-1)~+(2<sup>n-1</sup>-1)</td><td>-(1-2<sup>-(n-1)</sup>)~+(1-2<sup>-(n-1)</sup>)</td></tr><tr><td>补码</td><td>-2<sup>n-1</sup>~+(2<sup>n-1</sup>-1)</td><td>-1~+(1-2<sup>-(n-1)</sup>)</td></tr><tr><td>移码</td><td>-2<sup>n-1</sup>~+(2<sup>n-1</sup>-1)</td><td>-1~+(1-2<sup>-(n-1)</sup>)</td></tr></tbody></table><h1 id="九-浮点数"><a class="markdownIt-Anchor" href="#九-浮点数"></a> 九、浮点数</h1><p>当机器字长为n时，定点数的补码和移码可表示2<sup>n</sup>个数，而原码和反码只能表示2<sup>n</sup>-1个数（0的表示占用了两个编码）。</p><p>一个二进制数N的<strong>浮点表示法</strong>为N = 2<sup>E</sup> ✕ F，E为阶码，F为尾数。用阶码和尾数表示的数成为浮点数。</p><p>对阶：小阶向大阶对其，浮点数向右移。</p><p><img src="1751595391793-04419973-0fde-4b9a-9a50-9e12248f6a07.png" alt="" /></p><p>浮点数中，数值范围由阶码决定，数值精确度由尾数决定。格式化就是将尾数限定在区间[0.5,1]</p><p>浮点数的阶码（包括1位阶符）用R位的移码表示，尾数（包括1位数符）用M位的补码表示，则这种浮点数能表示的数值范围：最大正数<img src="1751595659539-8a88c2bf-343a-401a-9bee-97abed75c7c4.png" alt="" />  最小负数<img src="1751595678251-edfedd62-85db-4571-8d1c-4c8fbc87c340.png" alt="" /></p><h1 id="十-寻址"><a class="markdownIt-Anchor" href="#十-寻址"></a> 十、寻址</h1><p>立即寻址：操作数包含在指令中。</p><p>直接寻址：操作数存在内存单元中，指令直接给出操作数所在存储单元的地址。</p><p>寄存器寻址：操作数放在寄存器中，指令给出存放操作数寄存器名。</p><p>寄存器间接寻址：操作数存放在内存单元中，操作数所在的存储单元的地址在某个寄存器中。</p><p>间接寻址：指令中直接给出操作数地址的地址。</p><p>速度(由快到慢)：立即寻址&gt;寄存器寻址&gt;直接寻址&gt;寄存器间接寻址&gt;间接寻址</p><p>以下两个无需掌握</p><p><font style="color:#8A8F8D;">相对寻址：指令地址码给出一个偏移量，操作数地址等于本条指令的地址加上偏移量。</font></p><p><font style="color:#8A8F8D;">变址寻址：操作数地址等于变址寄存器的内容加偏移量。</font></p><h1 id="十一-奇偶校验码"><a class="markdownIt-Anchor" href="#十一-奇偶校验码"></a> 十一、奇偶校验码</h1><p>在编码中增加一位校验位，使编码中1的个数位奇数（奇校验）或偶数（偶校验），从而使码距变为2。</p><p>对于奇校验，可以检测出奇数个出错的编码。偶校验是偶数个出错的编码。<strong>无法纠错。</strong></p><p>常用奇偶校验码：水平奇偶校验码、垂直奇偶校验码、水平垂直校验码。</p><h1 id="十二-海明码"><a class="markdownIt-Anchor" href="#十二-海明码"></a> 十二、海明码</h1><p>码距等于2具有检索能力，码距大于等于3具有纠错能力。</p><p>利用奇偶性来检测和纠错的校验方法。</p><p>在数据位之间的特定位置插入k个校验位，扩大码距来实现检错、纠错。</p><p>公式：2<sup>k</sup>-1 ≥ n+k （数据位是n位，校验位是k位）</p><h1 id="十三-crc循环冗余校验码"><a class="markdownIt-Anchor" href="#十三-crc循环冗余校验码"></a> 十三、CRC循环冗余校验码</h1><p>可以检错，但不能纠错。</p><p>利用生成多项式，为k个数据位产生r个校验位来进行编码，编码长度为k+r</p><style>.gspivsuojhkf{zoom:50%;}</style><img src="/2025/07/15/zst-computer-system-notes/1751597009509-6a056d78-34a7-4457-af3f-bd0d4e3aefd6.png" class="gspivsuojhkf"><p>求CRC编码时，采用的是模2运算。</p><h1 id="十四-risc和cisc"><a class="markdownIt-Anchor" href="#十四-risc和cisc"></a> 十四、RISC和CISC</h1><table><thead><tr><th></th><th>RISC（简单指令集计算机）</th><th>CISC（复杂指令集计算机）</th></tr></thead><tbody><tr><td>指令种类</td><td>少、精简</td><td>多、丰富</td></tr><tr><td>指令复杂度</td><td>低（简单）</td><td>高（复杂）</td></tr><tr><td>指令长度</td><td>固定</td><td>变化</td></tr><tr><td>寻址方式</td><td>少</td><td>复杂多样</td></tr><tr><td>实现（译码）方式</td><td>硬布线控制逻辑<br/>（组合逻辑控制器）</td><td>微程序控制技术</td></tr><tr><td>通用寄存器数量</td><td>多、大量</td><td>一般</td></tr><tr><td>流水线技术</td><td>支持</td><td>不支持<br/></td></tr></tbody></table><h1 id="十五-流水线"><a class="markdownIt-Anchor" href="#十五-流水线"></a> 十五、流水线</h1><p>总用时：第一条指令的执行时间 + (n-1) ✕ 最长段的时间</p><p>加速比：不用流水线的时间/采用流水线的时间</p><p>操作周期：最长时间段</p><p>吞吐率：最长时间段的倒数</p><h1 id="十六-存储器"><a class="markdownIt-Anchor" href="#十六-存储器"></a> 十六、存储器</h1><p>按位置分类：</p><ul><li>内存（主存）：<strong>SRAM（静态随机存储器）</strong></li><li>外存（辅存）：磁盘、磁带、光盘等。<strong>DRAM（动态随机存储器）需周期性刷新。</strong></li><li><style>.ehospsrnfscq{zoom: 50%;}</style><img src="/2025/07/15/zst-computer-system-notes/1752506193037-ee4e9a05-5778-4d08-b791-1623fe41b624.png" class="ehospsrnfscq"></li></ul><p>工作方式分类：</p><ul><li>读写存储器（RAM）：既能读取又能写入。</li><li>只读存储器：ROM(固定只读存储器)、PROM(可编程的只读存储器)、EPROM(可擦除可编程的只读存储器)、EEPROM(电擦除可编程的只读存储器)、闪速存储器(介于EPROM、EEPROM之间，以块为单位存储，取代ROM，不能代替主存)</li></ul><p>访问方式分类：</p><ul><li>按地址访问存储器</li><li><strong>按内容访问存储器</strong></li></ul><p>按寻址方式分类：</p><ul><li>随机存储器(RAM)</li><li>顺序存储器(SAM)</li><li>直接存储器(DAM)</li></ul><p><strong>级联存储器</strong>是一种<strong>按内容访问</strong>的存储器</p><p><strong>虚拟存储器</strong>由<strong>主存、辅存</strong>构成。</p><h1 id="十七-cache"><a class="markdownIt-Anchor" href="#十七-cache"></a> 十七、Cache</h1><p>高速缓存主要是存放最活跃的程序和数据。</p><p>位于CPU和主存之间。</p><p><strong>对于程序员来说是透明的。</strong></p><p>部分用来存放<strong>主存的部分拷贝（副本）信息。</strong></p><style>.hoipbshqbvbw{zoom: 50%;}</style><img src="/2025/07/15/zst-computer-system-notes/1752506416223-6d2636ff-ec31-4bce-8070-5fb5be8c1caf.png" class="hoipbshqbvbw"><p><strong>Cache与主存的映射是由硬件自动完成的。</strong></p><p>替换算法：（目标是使Cache尽可能提高命中率，Cache越大，命中率越高）</p><ul><li>随机替换算法：</li><li>先进先出算法：</li><li>近期最少使用算法：</li><li>优化替换算法：</li></ul><p>地址映像方法：</p><ul><li>直接映像：主存的块和Cache的块对应关系是固定的。</li><li>全相联映像：允许主存中的任意块放入Cache的任意块中。</li><li>组相联映像：主存和Cache都分组，组是一一对应的，但是组内的数据是任意存放的。</li><li>冲突：直接映像 &gt; 组相联映像 &gt; 全相联映像</li></ul><h1 id="十八-中断"><a class="markdownIt-Anchor" href="#十八-中断"></a> 十八、中断</h1><style>.nzpyhzdjpmfm{zoom:33%;}</style><img src="/2025/07/15/zst-computer-system-notes/1752507009624-15023c61-b6e1-4f5c-b18e-9a43cd985c25.png" class="nzpyhzdjpmfm"><p>中断向量：提供中断服务程序的入口地址。</p><p>中断响应时间：从中断发出开始 到 进入中断服务程序 的时间</p><p>保存现场：用于中断处理完，返回执行源程序。</p><h1 id="十九-输入输出io控制方式"><a class="markdownIt-Anchor" href="#十九-输入输出io控制方式"></a> 十九、输入输出（IO）控制方式</h1><ol><li>程序查询方式<ol><li><strong>CPU和IO只能串行工作</strong>。CPU需要一直轮询。CPU利用率低</li><li>一次只能读写一个字</li><li>由CPU将数据放入内存</li><li>图例：<style>.pxxlxvkoyvcw{zoom: 33%;}</style><img src="/2025/07/15/zst-computer-system-notes/1752507339839-47a0ac4b-556b-4fe5-bdc7-4842ab6286d0.png" class="pxxlxvkoyvcw"></li></ol></li><li>中断驱动方式：<ol><li>IO由中断信号猪肚报告IO操作已完成。</li><li><strong>CPU和IO可并行工作。CPU利用率高。</strong></li><li>由CPU将数据放入内存。</li><li>图例：<style>.ubtqhwfaykbm{zoom:33%;}</style><img src="/2025/07/15/zst-computer-system-notes/1752507462379-57cb7499-6eb7-4e37-9fda-409f59b6e4ea.png" class="ubtqhwfaykbm"></li></ol></li><li>直接存储器方式（DMA）：<ol><li><strong>CPU和IO可并行工作。</strong></li><li><strong>仅在传送数据块的开始结束时，才需要CPU干预。</strong></li><li><strong>由外设直接将数据放入内存。</strong></li><li>一次读写的单位为“块”。</li><li>图例：<style>.zvudwmipmtep{zoom:33%;}</style><img src="/2025/07/15/zst-computer-system-notes/1752507609623-4ca63fc8-7dda-4791-ac60-5a2683b6e5e9.png" class="zvudwmipmtep"></li></ol></li></ol><h1 id="二十-总线"><a class="markdownIt-Anchor" href="#二十-总线"></a> 二十、总线</h1><p>总线分类：数据总线、地址总线、控制总线（口令：数地控）</p><p>常见总线：</p><ul><li>ISA总线：</li><li>EISA总线：</li><li>PCI总线：内总线，并行传输</li><li>PCI-E总线：点对点串行链接</li><li>前端总线：</li><li>RS-232C:</li><li>SCSI总线：并行外总线</li><li>SATA：</li><li>USB：</li><li>IEEE-1394：高速串行外总线</li><li>IEEE-488:</li></ul><h1 id="二十一-加密技术与认证技术"><a class="markdownIt-Anchor" href="#二十一-加密技术与认证技术"></a> 二十一、加密技术与认证技术</h1><p>窃听——加密</p><p>篡改——摘要</p><p>假冒、否认——数字签名、数字证书</p><ol><li><p>对称加密：加解密只有一把密钥（<strong>私钥用于加密</strong>）</p><ol><li>特点：密钥分发<strong>存在缺陷</strong>。加密解密<strong>速度快</strong>。适合加密大量明文。</li></ol></li><li><p>非对称加密：加密、解密分别有自己的密钥（<strong>公钥用于加密</strong>）</p><ol><li>公钥加密只能私钥解密，私钥加密只能公钥解密。</li><li>使用接收方公钥加密明文，可实现防窃听效果。</li><li>密钥分发<strong>无缺陷</strong>。加解密<strong>速度慢</strong>。</li></ol></li><li><p>混合加密：</p></li><li><p>摘要：把明文进行hash算法，得到的摘要同密文一块发送。接收方解密后的明文，进行Hash得要摘要对比。</p></li><li><p>数字签名：</p><ol><li>发送方用私钥对摘要进行签名（加密）。得到的数字签名放入密文，一同发送。</li><li>接收方用发送方的公钥对数字签名验证（解密）。</li></ol></li></ol><p>数字证书：</p><ul><li>用户向CA（权威）机构申请数字证书。</li><li>将个人信息和公钥发送给CA机构。</li><li>CA机构颁发数字证书给用户。</li><li>数字证书用CA的私钥进行签名（加密）。</li><li>用CA的公钥验证（解密）数字证书，得要用户的公钥。</li></ul><h1 id="二十二-加密算法"><a class="markdownIt-Anchor" href="#二十二-加密算法"></a> 二十二、加密算法</h1><p>对称加密（私钥、私有密钥加密）（共享密钥加密算法）：</p><ul><li>DES</li><li>3DES</li><li>RC-5</li><li>IDEA</li><li>AES</li><li>RC4</li></ul><p>非对称加密：</p><ul><li>RSA</li><li>ECC</li><li>DSA</li></ul><p>摘要算法：</p><ul><li>Hash算法</li><li>MD5</li><li>SHA-1安全散列算法</li></ul><h1 id="二十三-可靠性公式"><a class="markdownIt-Anchor" href="#二十三-可靠性公式"></a> 二十三、可靠性公式</h1><p>串联：</p><ul><li><style>.saiexueppzwi{zoom:33%;}</style><img src="/2025/07/15/zst-computer-system-notes/1752508894111-b79c6215-73c0-4e74-8d28-6e1f4071905e.png" class="saiexueppzwi"></li><li>R = R<sub>1 </sub>R<sub>2 </sub>… R<sub>N</sub></li></ul><p>并联：</p><ul><li><style>.yfsjlyvdnyun{zoom:33%;}</style><img src="/2025/07/15/zst-computer-system-notes/1752508984651-21f8e865-ba33-4f3c-899c-461cd436b35f.png" class="yfsjlyvdnyun"></li><li>R = 1 - (1-R<sub>1</sub>) (1-R<sub>2 </sub>) … (1-R<sub>N</sub>)</li></ul><h1 id="二十四-补充"><a class="markdownIt-Anchor" href="#二十四-补充"></a> 二十四、补充</h1><p>汇编语言中 程序员 可以访问 <strong>程序计数器</strong></p><p>寄存器的<strong>位数</strong>取决于<strong>指令字长</strong>。</p><p>计算机<strong>分级存储</strong>的主要<strong>目的</strong>是为了解决 <strong>存储容量、成本和速度之间的矛盾</strong> 的问题。</p><p>计算机中CPU对其访问速度最快的是 <strong>通用寄存器。</strong></p><p>**VLIW **是 超长指令字</p><p><strong>算术左移</strong>指令<strong>相当于</strong>对操作数<strong>乘以2</strong></p><p>CPU根据** 指令周期的不同阶段** 来<strong>区分</strong>内存中以二进制编码形式存放的<strong>指令和数据。</strong></p><p>平均CPI = （比例 × CPI ）相加</p><p>运算速度MIPS = CPU主频 / 平均CPI</p>]]></content>
    
    
    <summary type="html">【软考zst2001专辑笔记】001计算机系统</summary>
    
    
    
    
    <category term="软考" scheme="https://log.660066.xyz/tags/%E8%BD%AF%E8%80%83/"/>
    
  </entry>
  
  <entry>
    <title>【软考】中级-软件设计师-zst专辑笔记</title>
    <link href="https://log.660066.xyz/2025/07/15/soft-exam-software-designer-zst-album-notes/"/>
    <id>https://log.660066.xyz/2025/07/15/soft-exam-software-designer-zst-album-notes/</id>
    <published>2025-07-15T01:14:12.000Z</published>
    <updated>2025-09-29T05:46:33.896Z</updated>
    
    <content type="html"><![CDATA[<h1 id="一-前言"><a class="markdownIt-Anchor" href="#一-前言"></a> 一、前言</h1><p>在B站看到的zst2001博主的软考中级的讲解很不错。所以打算整理一下笔记。本文为后续文章的索引。</p><h1 id="二-索引"><a class="markdownIt-Anchor" href="#二-索引"></a> 二、索引</h1><ol><li><a href="../../../../2025/07/15/zst-computer-system-notes/">计算机系统</a>【软考zst2001专辑笔记】001计算机系统</li><li><a href="../../../../2025/08/05/zst-programming-language-notes/">程序设计语言</a>【软考zst2001专辑笔记】002程序设计语言</li><li><a href="../../../../2025/08/21/zst-data-structure-volume-roll-up-notes/">数据结构-上卷</a>【软考zst2001专辑笔记】003数据结构-上卷</li><li><a href="../../../../2025/08/27/zst-data-structure-volume-roll-down-notes/">数据结构-下卷</a>【软考zst2001专辑笔记】004数据结构-下卷</li><li><a href="../../../../2025/09/29/zst-intellectual-property-right/">知识产权</a>【软考zst2001专辑笔记】005知识产权</li></ol>]]></content>
    
    
    <summary type="html">【软考】中级-软件设计师-zst专辑笔记</summary>
    
    
    
    
    <category term="软考" scheme="https://log.660066.xyz/tags/%E8%BD%AF%E8%80%83/"/>
    
  </entry>
  
  <entry>
    <title>速率限制的交互式指南</title>
    <link href="https://log.660066.xyz/2025/06/13/interactive-guide-to-rate-limiting/"/>
    <id>https://log.660066.xyz/2025/06/13/interactive-guide-to-rate-limiting/</id>
    <published>2025-06-13T03:11:37.000Z</published>
    <updated>2025-06-13T03:33:30.841Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>[!NOTE]</p><p>本文非原创，原文由<a href="https://hashnode.com/@Sagyam">Sagyam Thapa</a>创作</p><p>原文链接：<a href="https://blog.sagyamthapa.com.np/interactive-guide-to-rate-limiting">https://blog.sagyamthapa.com.np/interactive-guide-to-rate-limiting</a></p><p>This article is not original. The original text was created by <a href="https://hashnode.com/@Sagyam">Sagyam Thapa</a></p><p>The original link: <a href="https://blog.sagyamthapa.com.np/interactive-guide-to-rate-limiting">https://blog.sagyamthapa.com.np/interactive-guide-to-rate-limiting</a></p></blockquote><h1 id="介绍"><a class="markdownIt-Anchor" href="#介绍"></a> 介绍</h1><p>限流是每个后端应用程序中的必备策略。它可以防止一个用户过度使用资源并降低其他用户的服务质量。以下是速率限制的一些好处：</p><ol><li>它呈现资源匮乏</li><li>降低服务器托管成本</li><li>提供针对 <a href="https://en.wikipedia.org/wiki/Denial-of-service_attack">DDoS</a> 的基本保护</li></ol><p>我制作了四个交互式应用程序，让您尝试常见的速率限制算法。</p><h1 id="令牌桶"><a class="markdownIt-Anchor" href="#令牌桶"></a> 令牌桶</h1><h2 id="工作原理"><a class="markdownIt-Anchor" href="#工作原理"></a> 工作原理</h2><p>桶中保存固定数量的令牌</p><p>令牌以固定速率添加到存储桶中</p><p>当收到请求时：</p><ul><li>如果令牌可用，则会将其从存储桶中删除并允许请求。</li><li>如果没有可用的令牌，则请求将被拒绝或延迟。</li></ul><p>如果令牌可用，则允许偶尔进行短暂的并发</p><p>我创建了一个<a href="https://tools.sagyamthapa.com.np/token-bucket">应用程序 </a>，让您玩转漏桶算法。</p><iframe src="https://tools.sagyamthapa.com.np/token-bucket" width="800" height="610"></iframe><h1 id="漏水桶"><a class="markdownIt-Anchor" href="#漏水桶"></a> 漏水桶</h1><h2 id="工作原理-2"><a class="markdownIt-Anchor" href="#工作原理-2"></a> 工作原理</h2><p>将其视为以固定速率泄漏的桶</p><p>传入请求将添加到存储桶中</p><p>请求以<strong>恒定速率</strong>处理（或“泄漏”）</p><p>如果新请求到达时存储桶已满，则会丢弃该请求</p><p>平滑连拍；以稳定的速率输出请求</p><p>我制作了一个<a href="https://tools.sagyamthapa.com.np/leaky-bucket">应用程序 </a>，让您玩转漏桶算法。</p><iframe src="https://tools.sagyamthapa.com.np/leaky-bucket" width="800" height="1000"></iframe><h1 id="固定窗口"><a class="markdownIt-Anchor" href="#固定窗口"></a> 固定窗口</h1><h2 id="工作原理-3"><a class="markdownIt-Anchor" href="#工作原理-3"></a> 工作原理</h2><p>时间被划分为固定大小的窗口（例如，1 分钟）</p><p>计数器跟踪当前窗口中每个客户端/IP 的请求数</p><p>如果计数超过限制，则进一步的请求将被拒绝，直到下一个窗口</p><p>简单高效，但允许在结束/开始时出现突发流量峰值</p><p>我创建了一个<a href="https://tools.sagyamthapa.com.np/fixed-window">应用程序 </a>，让您使用固定窗口算法。</p><iframe src="https://tools.sagyamthapa.com.np/fixed-window" width="800" height="1000"></iframe><h1 id="滑动窗口"><a class="markdownIt-Anchor" href="#滑动窗口"></a> 滑动窗口</h1><h2 id="工作原理-4"><a class="markdownIt-Anchor" href="#工作原理-4"></a> 工作原理</h2><p>保留每个请求的时间戳日志</p><p>当收到请求时，将检查日志以计算在过去 <code>X</code> 秒内发出的请求数</p><p>如果低于限制，则允许并记录请求;否则，它将被拒绝</p><p>我创建了一个<a href="https://tools.sagyamthapa.com.np/sliding-window">应用程序 </a>，让您玩滑桶算法。</p><iframe src="https://tools.sagyamthapa.com.np/sliding-window" width="800" height="1000"></iframe><h1 id="中文演示"><a class="markdownIt-Anchor" href="#中文演示"></a> 中文演示</h1><p>文章原有的演示页面为英文，我用“豆书记”简单的写了一下中文的演示页面，共大家参考：</p><ul><li>令牌桶：<a href="http://log.660066.xyz/2025/06/13/interactive-guide-to-rate-limiting/token-bucket.html">http://log.660066.xyz/2025/06/13/interactive-guide-to-rate-limiting/token-bucket.html</a></li><li>漏水桶：<a href="http://log.660066.xyz/2025/06/13/interactive-guide-to-rate-limiting/leaky-bucket.html">http://log.660066.xyz/2025/06/13/interactive-guide-to-rate-limiting/leaky-bucket.html</a></li><li>固定窗口：<a href="http://log.660066.xyz/2025/06/13/interactive-guide-to-rate-limiting/fixed-window.html">http://log.660066.xyz/2025/06/13/interactive-guide-to-rate-limiting/fixed-window.html</a></li><li>滑动窗口：<a href="http://log.660066.xyz/2025/06/13/interactive-guide-to-rate-limiting/sliding-window.html">http://log.660066.xyz/2025/06/13/interactive-guide-to-rate-limiting/sliding-window.html</a></li></ul>]]></content>
    
    
    <summary type="html">速率限制的交互式指南</summary>
    
    
    
    
    <category term="开发纪实" scheme="https://log.660066.xyz/tags/%E5%BC%80%E5%8F%91%E7%BA%AA%E5%AE%9E/"/>
    
  </entry>
  
  <entry>
    <title>Macos动态切换JDK版本</title>
    <link href="https://log.660066.xyz/2025/05/21/macos-jdk-version-switch/"/>
    <id>https://log.660066.xyz/2025/05/21/macos-jdk-version-switch/</id>
    <published>2025-05-21T06:36:25.000Z</published>
    <updated>2025-05-21T07:18:20.445Z</updated>
    
    <content type="html"><![CDATA[<h1 id="一-前言"><a class="markdownIt-Anchor" href="#一-前言"></a> 一、前言</h1><p>最近需要在MacOS上想装一个HMLC的启动器，因为开发的时候，使用的ZuluJDK8（最新版本），但是最新版本没带javaFX模块。HMLC又需要JavaFX模块启动，在网上搜索了一下，JDK8的JavaFX的好像没有支持的，都是自带的。</p><p>所以打算再装个JDK17，这样的话，我就需要可以动态切换JDK版本。开发的时候用8，玩MC的时候，就需要使用JDK17。</p><h1 id="二-安装zulujdk"><a class="markdownIt-Anchor" href="#二-安装zulujdk"></a> 二、安装ZuluJDK</h1><p><a href="https://www.azul.com/downloads/">https://www.azul.com/downloads/</a></p><p>自己去下载安装吧，反正这个安装起来，比Win都无脑。</p><h1 id="三-配置jdk切换"><a class="markdownIt-Anchor" href="#三-配置jdk切换"></a> 三、配置JDK切换</h1><h2 id="31-编辑zshrc"><a class="markdownIt-Anchor" href="#31-编辑zshrc"></a> 3.1 编辑.zshrc</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vim ~/.zshrc</span><br></pre></td></tr></table></figure><h2 id="32-调整配置"><a class="markdownIt-Anchor" href="#32-调整配置"></a> 3.2 调整配置</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">JDK版本切换</span></span><br><span class="line">export JAVA8_HOME=/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home</span><br><span class="line">export JAVA17_HOME=/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home</span><br><span class="line">CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:.</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置默认JDK版本</span></span><br><span class="line">export JAVA_HOME=$JAVA8_HOME</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置<span class="built_in">alias</span>命令可以动态切换JDK版本</span>  </span><br><span class="line">alias jdk8=&quot;export JAVA_HOME=$JAVA8_HOME&quot;</span><br><span class="line">alias jdk17=&quot;export JAVA_HOME=$JAVA17_HOME&quot;</span><br><span class="line">export JAVA_HOME</span><br><span class="line">export PATH</span><br><span class="line">export CLASSPATH</span><br></pre></td></tr></table></figure><p>追加到文件结尾就行</p><h2 id="33-生效zshrc"><a class="markdownIt-Anchor" href="#33-生效zshrc"></a> 3.3 生效.zshrc</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">source ~/.zshrc</span><br></pre></td></tr></table></figure><h2 id="34-测试"><a class="markdownIt-Anchor" href="#34-测试"></a> 3.4 测试</h2><p><img src="pic1.png" alt="测试图" /></p>]]></content>
    
    
    <summary type="html">Macos动态切换JDK版本【以ZuluJdk为例】</summary>
    
    
    
    
    <category term="MacOS" scheme="https://log.660066.xyz/tags/MacOS/"/>
    
  </entry>
  
  <entry>
    <title>世界这么大我想去看看-2</title>
    <link href="https://log.660066.xyz/2025/05/06/world-go-to-see-2/"/>
    <id>https://log.660066.xyz/2025/05/06/world-go-to-see-2/</id>
    <published>2025-05-06T02:56:57.000Z</published>
    <updated>2025-05-22T02:31:50.178Z</updated>
    
    <content type="html"><![CDATA[<p><strong>本文声明</strong>：可能部分用词措辞不当，但对香港特别行政区是祖国一部分的想念毫不动摇。如有措辞不当，请在评论区指出，以便及时改正。</p><h1 id="一-飞机延误"><a class="markdownIt-Anchor" href="#一-飞机延误"></a> 一、飞机延误</h1><p>本来是晚上9点的飞机，从遥墙飞宝安。飞机是从大连飞到济南，但是4月30日晚上，大连下大雨，导致飞机延误。一直拖了到12点半，才开始登机，当时买的春秋航空，都说上了飞机就卖东西，可能是太晚的原因，并没空姐推销东西，我立马进入入睡状态。</p><p>大约三点半，落地了宝安，在宝安附近定的酒店，打了个滴滴，立马飞奔睡觉。</p><h1 id="二-深圳一日游"><a class="markdownIt-Anchor" href="#二-深圳一日游"></a> 二、深圳一日游</h1><p>深圳本来打算的挺好的，要去深圳湾，要去各种地方。但是第一站，就是去看看腾讯大厦，看看国内的大厂。</p><p><img src="IMG_6955.JPG" alt="IMG_6955" /></p><p><img src="IMG_6959.JPG" alt="IMG_6959" /></p><p>第二站，去华强北，本来是奔着去买个安卓备用机的，但是去了才发现，全是苹果，全是苹果啊。再加上五一，很多档口的老板可能都休假了，有些档口直接处于无人的状态，不太清楚是黄了还是休假了。</p><p><img src="IMG_7008.JPG" alt="IMG_7008" /></p><p>第三站，去中英街。提前感受一下香港地区的风土人情，因为第二天打算去香港。中英街就是个商业街，卖各种东西的。各种免税店，这里的大店铺是用港币结算的，小店铺有可能是港币也可能是人民币，大家去的时候一定要问清是什么结算。</p><p>大概看了一下化妆品、保健品啥的价格，因为五一的时候，汇率是94:100，说实话，也没太大优惠，但是肯定是比直接在淘宝天猫京东这些网店买要便宜。索性来一趟，买了点零食，买了一小箱南洋罐。</p><p>下面请看图！</p><style>.elyeeiwtwrkg{zoom:33%;}</style><img src="/2025/05/06/world-go-to-see-2/IMG_6968.PNG" class="elyeeiwtwrkg" alt="IMG_6968"><p>高德显示的是香港，但是我看网上说是大陆和香港共管的状态。</p><p><img src="IMG_6970.JPG" alt="IMG_6970" /></p><p>这里是中英街的入口。</p><p><img src="IMG_6973.JPG" alt="IMG_6973" /></p><p>这条路好像是通往香港的，有武警战士在这站岗，这么多提示，一定是有大陆的游客曾经走进过去。</p><p><img src="IMG_6976.JPG" alt="IMG_6976" /></p><p><img src="IMG_6996.JPG" alt="IMG_6996" /></p><p>在深圳的当天晚上，是在皇岗口岸的格林豪泰入住的，因为三月就把酒店订好了，价格也不是很贵，订了两天。不打算晚上在香港过夜，主要是因为那边法律和大陆不同，再加上价格肯定高，所以就直接回深圳睡觉，反正也不是很远。</p><h1 id="三-香港一日半游"><a class="markdownIt-Anchor" href="#三-香港一日半游"></a> 三、香港一日半游</h1><p>因为看到网上有人说，过口岸会排长队，一大早就去了皇岗口岸。最后发现，过口岸的时候，几乎不用排队，直接进人工通道过境。</p><p><img src="IMG_7133.JPG" alt="IMG_7133" /></p><p><img src="IMG_7015.JPG" alt="IMG_7015" /></p><p><img src="IMG_7016.JPG" alt="IMG_7016" /></p><p>闸机人真的很少，几乎不用排队。过了闸机，需要坐大巴车去香港的口岸，然后刷通行证，拿过关小条。</p><p>因为是第一次去香港，不是很懂，边问边走。花了10港币，坐了皇巴，从大陆开到了香港口岸，然后过完关，再换车（只是换车，不用再交费用了），把你送出口岸。</p><p>其实当时不是很懂，不应该坐皇巴，因出了香港这边的口岸，不是很好找公交车，当时应该坐九巴这些，直接去想去的那些地方，很方便。</p><p><img src="IMG_7018.JPG" alt="IMG_7018" /></p><p>入境香港了，右舵车的天下。都说香港的冷气（空调）开得足，那确实是足，我本来就比较胖，所以说，冷一点也感觉不出啥来。不过大陆过来的小姑娘真的建议穿件防晒衣啥的。</p><p>这个图是我当时坐公交车，香港的公交车不便宜啊，12港币我记得。在车上的第一件事，就是换香港的手机卡。然后开香港银行卡，把汇丰、中银、众安都开了。</p><p>汇丰、众安都没啥太大问题。但是中银就不太好了，他需要识别我的身份证开启流动保安码，但是我名字里有个生僻字，OCR算法死活不认，没办法只能下次去香港的时候，线下营业厅搞一个实体的令牌了。如果不开启流动保安码，没法转账（有别的方式转）、没法修改通讯地址。</p><p>上面说的没法转账，其实也有办法，但是每天限额2W港币，对我来说，足够了。用BocPay+这个App去转账。</p><p>到了香港的第一站，就去了紫金广场，看看大海，看看紫荆花雕像。</p><p><img src="IMG_7021.JPG" alt="IMG_7021" /></p><p><img src="IMG_7023.JPG" alt="IMG_7023" /></p><p><img src="IMG_7049.JPG" alt="IMG_7049" /></p><p><img src="IMG_7084.JPG" alt="IMG_7084" /></p><p>这个图就是著名的星光大道，梁朝伟的手印哈哈哈哈。</p><p><img src="IMG_7099.JPG" alt="IMG_7099" /></p><p>ICAC查案，不方便透露。打卡点的人不是很多，我们去了，陆陆续续的有三四个人也来打卡。</p><p>去廉政公署打卡，旁边有个大厅，可以卖廉政公署的周边纪念品。我朋友买了个廉政公署的小咖啡杯，另一个朋友买了名片夹。我买了一个廉政公署的胸章和一个水瓶。</p><p>下午去了太平山，真的不建议去，出发不是旅游旺季。人太多，啥也不好看。</p><p><img src="IMG_7128.JPG" alt="IMG_7128" /></p><p><img src="IMG_7129.JPG" alt="IMG_7129" /></p><p>此时此刻，还不知道，一会下山要经历什么痛苦。大概拍了点照片，太累了，就去排队坐大巴下山了，一路上，我丢那个堵啊，那个要命啊。别问我为啥不坐缆车，那缆车排队2小时起步，哈哈哈哈哈扛不住。</p><p>当天还去了深水埗的鸭寮街，主要是去买大湾区的电信蓝卡，这样就有一个香港的手机号了，还能在大陆合法访问谷歌，就是流量有点贵，可以去参考参考小红书。</p><p>晚上回深圳，去皇岗村吃了个烧烤（真贵啊，不是一般的贵）。</p><p>第二天，有了经验，8点才去的皇岗口岸，人还是不多，这次直接坐的大巴，直捣油麻地警署，买点纪念品。</p><p><img src="IMG_7137.JPG" alt="IMG_7137" /></p><p>油麻地警署，人不少，可以早点去排队买点周边啥的，有很大一部分人，不是排队买周边，是排队打卡拍照哈哈哈哈。</p><p><img src="IMG_7139.JPG" alt="IMG_7139" /></p><p>哦豁，中午吃饭的时候，发现了一个BTC的ATM机，可以买比特币哈哈哈。</p><p>随后去了旺角中心，真没啥东西感觉，也可能是逛的时间短了？反正初印象就是，不如大陆宽敞。如果让我选一个地方生活，我还是喜欢在大陆生活。</p><h1 id="四-返程回国"><a class="markdownIt-Anchor" href="#四-返程回国"></a> 四、返程回国</h1><p>去苏州了，跳槽到了苏州，开启人生新篇章。</p><p><img src="IMG_7175.JPG" alt="IMG_7175" /></p><p><img src="IMG_7177.JPG" alt="IMG_7177" /></p><p>下一站去哪？新疆天山？西藏拉萨？韩国首尔？我还没想好。</p><p>但是，这次出镜去香港，本来是去见识见识资本主义是啥样的，但是发现，好像也没什么特别的地方。不知为啥，还是感觉大陆更自在更舒服。</p>]]></content>
    
    
    <summary type="html">2025年5月1日深港行</summary>
    
    
    
    
    <category term="生活" scheme="https://log.660066.xyz/tags/%E7%94%9F%E6%B4%BB/"/>
    
  </entry>
  
  <entry>
    <title>问题排查解决方案集合</title>
    <link href="https://log.660066.xyz/2025/04/23/solution-record/"/>
    <id>https://log.660066.xyz/2025/04/23/solution-record/</id>
    <published>2025-04-23T07:15:38.000Z</published>
    <updated>2025-05-09T02:15:07.031Z</updated>
    
    <content type="html"><![CDATA[<h1 id="一-前端"><a class="markdownIt-Anchor" href="#一-前端"></a> 一、前端</h1><ol><li>待整理……</li></ol><h1 id="二-后端"><a class="markdownIt-Anchor" href="#二-后端"></a> 二、后端</h1><ol><li>待整理……</li></ol><h1 id="三-数据库"><a class="markdownIt-Anchor" href="#三-数据库"></a> 三、数据库</h1><ol><li>MySQL死锁：<a href="https://mp.weixin.qq.com/s/l6E5otoON1CQIEfIUHDvdA">https://mp.weixin.qq.com/s/l6E5otoON1CQIEfIUHDvdA</a></li></ol><h1 id="四-运维"><a class="markdownIt-Anchor" href="#四-运维"></a> 四、运维</h1><ol><li>待整理……</li></ol><h1 id="五-其他"><a class="markdownIt-Anchor" href="#五-其他"></a> 五、其他</h1><ol><li>DDD架构：<a href="https://mp.weixin.qq.com/s/DAiGCgE0ZdBRw_ckhD8AQA">https://mp.weixin.qq.com/s/DAiGCgE0ZdBRw_ckhD8AQA</a><ul><li>DDD 系列 第一弹 - Domain Primitive：<a href="https://mp.weixin.qq.com/s?__biz=MzAxNDEwNjk5OQ==&amp;mid=2650403892&amp;idx=1&amp;sn=a91fa477392e80f9420a8ca4d26bcace">https://mp.weixin.qq.com/s?__biz=MzAxNDEwNjk5OQ==&amp;mid=2650403892&amp;idx=1&amp;sn=a91fa477392e80f9420a8ca4d26bcace</a></li><li>DDD系列 第二弹 - 应用架构：<a href="https://mp.weixin.qq.com/s?__biz=MzAxNDEwNjk5OQ==&amp;mid=2650404060&amp;idx=1&amp;sn=cacf40d19528f6c2d9fd165151d6e8b4">https://mp.weixin.qq.com/s?__biz=MzAxNDEwNjk5OQ==&amp;mid=2650404060&amp;idx=1&amp;sn=cacf40d19528f6c2d9fd165151d6e8b4</a></li><li>DDD系列 第三讲 - Repository模式：<a href="https://mp.weixin.qq.com/s?__biz=MzAxNDEwNjk5OQ==&amp;mid=2650406692&amp;idx=1&amp;sn=4a4ac4168299d8ca1905a4f457ae4c59">https://mp.weixin.qq.com/s?__biz=MzAxNDEwNjk5OQ==&amp;mid=2650406692&amp;idx=1&amp;sn=4a4ac4168299d8ca1905a4f457ae4c59</a></li><li>DDD系列第四讲：领域层设计规范：<a href="https://mp.weixin.qq.com/s?__biz=MzAxNDEwNjk5OQ==&amp;mid=2650414919&amp;idx=1&amp;sn=0ad1df1a1b0e2488f7faa21008fdbdd0">https://mp.weixin.qq.com/s?__biz=MzAxNDEwNjk5OQ==&amp;mid=2650414919&amp;idx=1&amp;sn=0ad1df1a1b0e2488f7faa21008fdbdd0</a></li><li>DDD系列第五讲：聊聊如何避免写流水账代码：<a href="https://mp.weixin.qq.com/s?__biz=MzAxNDEwNjk5OQ==&amp;mid=2650427571&amp;idx=1&amp;sn=bfc3c1c6f189965a1a4c7f3918012405">https://mp.weixin.qq.com/s?__biz=MzAxNDEwNjk5OQ==&amp;mid=2650427571&amp;idx=1&amp;sn=bfc3c1c6f189965a1a4c7f3918012405</a></li><li>DDD之于逛逛内容营销中的应用：<a href="https://mp.weixin.qq.com/s?__biz=MzAxNDEwNjk5OQ==&amp;mid=2650433660&amp;idx=1&amp;sn=cb424db17b96aa28b476edafa2bc3509">https://mp.weixin.qq.com/s?__biz=MzAxNDEwNjk5OQ==&amp;mid=2650433660&amp;idx=1&amp;sn=cb424db17b96aa28b476edafa2bc3509</a></li><li>DDD之于业务支撑的意义：<a href="https://mp.weixin.qq.com/s?__biz=MzAxNDEwNjk5OQ==&amp;mid=2650517536&amp;idx=1&amp;sn=926ba6f2c0fcc01aaf5abeea625aa260">https://mp.weixin.qq.com/s?__biz=MzAxNDEwNjk5OQ==&amp;mid=2650517536&amp;idx=1&amp;sn=926ba6f2c0fcc01aaf5abeea625aa260</a></li></ul></li></ol><p>备份仓库：<a href="https://github.com/BaseOrange/solution-record">https://github.com/BaseOrange/solution-record</a></p>]]></content>
    
    
    <summary type="html">问题排查解决方案集合</summary>
    
    
    
    
    <category term="开发纪实" scheme="https://log.660066.xyz/tags/%E5%BC%80%E5%8F%91%E7%BA%AA%E5%AE%9E/"/>
    
  </entry>
  
  <entry>
    <title>文档段落保留功能实现分析：基于层级与权限的标题保留策略</title>
    <link href="https://log.660066.xyz/2025/04/09/analysis-of-document-para-reservation-impl/"/>
    <id>https://log.660066.xyz/2025/04/09/analysis-of-document-para-reservation-impl/</id>
    <published>2025-04-09T06:32:28.000Z</published>
    <updated>2025-04-09T06:39:11.234Z</updated>
    
    <content type="html"><![CDATA[<h2 id="一-问题背景"><a class="markdownIt-Anchor" href="#一-问题背景"></a> 一、问题背景</h2><p>在文档处理场景中，用户踢出需求，需要根据以下规则隐藏或保留段落：</p><ol><li><strong>标题保留条件</strong>：仅当标题的子段落中存在<strong>有权限的填报项</strong>时，该标题才被保留。</li><li>段落类型区分<ul><li><strong>正文/表格</strong>：根据权限决定是否保留。</li><li><strong>标题</strong>：需结合子段落的保留状态判断是否保留。</li></ul></li><li><strong>层级嵌套复杂性</strong>：标题的层级（如一级标题、二级标题）需通过段落层级信息（<code>OutLevel</code>）动态计算其子段落范围。</li></ol><h3 id="存在的典型问题"><a class="markdownIt-Anchor" href="#存在的典型问题"></a> 存在的典型问题</h3><ul><li><strong>标题范围计算错误</strong>：未正确记录标题的结束位置，导致误判子段落范围。</li><li><strong>保留条件不精准</strong>：未区分“有权限填报项”与其他保留类型（如正文），导致标题被错误保留。</li></ul><hr /><h2 id="二-解决思路"><a class="markdownIt-Anchor" href="#二-解决思路"></a> 二、解决思路</h2><h3 id="1-分阶段处理逻辑"><a class="markdownIt-Anchor" href="#1-分阶段处理逻辑"></a> 1. 分阶段处理逻辑</h3><p>将问题拆解为三个阶段，逐步解决：</p><ol><li><strong>基础保留标记</strong>：标记每个段落的保留状态（<code>retained</code>数组）。</li><li><strong>标题范围与保留判断</strong>：通过层级嵌套关系确定标题的子段落范围，并判断是否保留。</li><li><strong>结果生成</strong>：根据保留标记生成最终的删除/保留指令。</li></ol><h3 id="2-关键逻辑设计"><a class="markdownIt-Anchor" href="#2-关键逻辑设计"></a> 2. 关键逻辑设计</h3><h4 id="1-标题范围计算"><a class="markdownIt-Anchor" href="#1-标题范围计算"></a> (1) 标题范围计算</h4><ul><li><strong>使用栈结构</strong>：通过栈记录当前层级的标题，动态维护标题的嵌套关系。</li><li><strong>层级比较</strong>：当遇到新标题时，若其层级≤栈顶标题层级，则弹出栈顶标题并记录其结束位置。</li><li><strong>结束位置处理</strong>：遍历结束后，栈中剩余标题的结束位置设为文档末尾。</li></ul><h4 id="2-保留条件细化"><a class="markdownIt-Anchor" href="#2-保留条件细化"></a> (2) 保留条件细化</h4><ul><li>段落保留规则<ul><li><strong>正文/表格</strong>：仅保留有权限的填报项。</li><li><strong>标题</strong>：仅保留子段落中存在有权限填报项的标题。</li></ul></li><li><strong>权限判断</strong>：通过<code>FillInfo</code>对象获取段落的填报项权限信息。</li></ul><h4 id="3-标题保留判断"><a class="markdownIt-Anchor" href="#3-标题保留判断"></a> (3) 标题保留判断</h4><ul><li><strong>遍历子段落</strong>：对每个标题的子段落范围（<code>start</code>到<code>end</code>），检查是否存在有权限的填报项。</li><li><strong>标记保留状态</strong>：若满足条件，将标题的<code>titleShouldKeep</code>标记为<code>true</code>。</li></ul><hr /><h2 id="三-关键代码解析"><a class="markdownIt-Anchor" href="#三-关键代码解析"></a> 三、关键代码解析</h2><h3 id="1-基础保留标记retained数组"><a class="markdownIt-Anchor" href="#1-基础保留标记retained数组"></a> 1. 基础保留标记（<code>retained</code>数组）</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 标记每个段落的保留状态</span></span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; size; i++) &#123;</span><br><span class="line">    <span class="type">Para</span> <span class="variable">p</span> <span class="operator">=</span> paras.get(i);</span><br><span class="line">    <span class="type">int</span> <span class="variable">paraOutLevel</span> <span class="operator">=</span> XxxUtil.getParaOutLevel(p, styles);</span><br><span class="line">    <span class="type">FillInfo</span> <span class="variable">fillItemPermission</span> <span class="operator">=</span> getFillItemPermission(fillItemList, p.getPos());</span><br><span class="line">    <span class="type">boolean</span> <span class="variable">hasPermission</span> <span class="operator">=</span> fillItemPermission.isHasPermission();</span><br><span class="line">    <span class="type">FillItem</span> <span class="variable">fillItem</span> <span class="operator">=</span> fillItemPermission.getFillItem();</span><br><span class="line">    <span class="keyword">if</span> (!hasPermission &amp;&amp; fillItem != <span class="literal">null</span>) &#123;</span><br><span class="line">        retained[i] = <span class="literal">false</span>; <span class="comment">// 无权限的填报项不保留</span></span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (paraOutLevel == <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="comment">// 正文或填报项：仅保留有权限的</span></span><br><span class="line">        retained[i] = hasPermission;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="comment">// 标题或表格：根据层级是否需要保留</span></span><br><span class="line">        <span class="keyword">if</span> (levelsToKeep.contains(paraOutLevel)) &#123;</span><br><span class="line">            retained[i] = <span class="literal">true</span>; <span class="comment">// 标题先标记为保留，后续根据子段落修正</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>关键点</strong>：</p><ul><li><strong>权限优先</strong>：无权限的填报项直接标记为不保留。</li><li><strong>层级过滤</strong>：仅保留需要显示的层级（如<code>levelsToKeep</code>中的层级）。</li></ul><hr /><h3 id="2-标题范围计算栈结构"><a class="markdownIt-Anchor" href="#2-标题范围计算栈结构"></a> 2. 标题范围计算（栈结构）</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 确定标题的子段落范围</span></span><br><span class="line">List&lt;Range&gt; titleRanges = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">Stack&lt;Range&gt; stack = <span class="keyword">new</span> <span class="title class_">Stack</span>&lt;&gt;();</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; size; i++) &#123;</span><br><span class="line">    <span class="type">Para</span> <span class="variable">p</span> <span class="operator">=</span> allPapx.get(i);</span><br><span class="line">    <span class="type">int</span> <span class="variable">paraOutLevel</span> <span class="operator">=</span> DocDataUtil.getParaOutLevel(p, styles);</span><br><span class="line">    <span class="keyword">if</span> (paraOutLevel &gt; <span class="number">0</span> &amp;&amp; levelsToKeep.contains(paraOutLevel)) &#123;</span><br><span class="line">        <span class="keyword">while</span> (!stack.isEmpty() &amp;&amp; paraOutLevel &lt;= stack.peek().getLevel()) &#123;</span><br><span class="line">            <span class="type">Range</span> <span class="variable">popped</span> <span class="operator">=</span> stack.pop();</span><br><span class="line">            popped.setEnd(i - <span class="number">1</span>); <span class="comment">// 当前段落的前一个位置为结束</span></span><br><span class="line">            titleRanges.add(popped);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="type">Range</span> <span class="variable">newRange</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Range</span>();</span><br><span class="line">        newRange.setStart(i);</span><br><span class="line">        newRange.setLevel(paraOutLevel);</span><br><span class="line">        stack.push(newRange);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 处理栈中剩余标题</span></span><br><span class="line"><span class="keyword">while</span> (!stack.isEmpty()) &#123;</span><br><span class="line">    <span class="type">Range</span> <span class="variable">r</span> <span class="operator">=</span> stack.pop();</span><br><span class="line">    r.setEnd(size - <span class="number">1</span>); <span class="comment">// 结束位置为文档末尾</span></span><br><span class="line">    titleRanges.add(r);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>关键点</strong>：</p><ul><li><strong>栈的层级判断</strong>：通过层级比较确保标题范围的正确嵌套。</li><li><strong>结束位置修正</strong>：遍历结束后，确保所有标题范围到文档末尾。</li></ul><hr /><h3 id="3-标题保留判断-2"><a class="markdownIt-Anchor" href="#3-标题保留判断-2"></a> 3. 标题保留判断</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 判断标题是否保留</span></span><br><span class="line"><span class="keyword">for</span> (Range r : titleRanges) &#123;</span><br><span class="line">    <span class="type">boolean</span> <span class="variable">hasPermissionFilledForm</span> <span class="operator">=</span> <span class="literal">false</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">j</span> <span class="operator">=</span> r.getStart() + <span class="number">1</span>; j &lt;= r.getEnd(); j++) &#123;</span><br><span class="line">        <span class="type">FillInfo</span> <span class="variable">fillItemPermission</span> <span class="operator">=</span> getFillItemPermission(fillItemList, allPapx.get(j).getPos());</span><br><span class="line">        <span class="keyword">if</span> (retained[j] &amp;&amp; fillItemPermission.isHasPermission()) &#123;</span><br><span class="line">            hasPermissionFilledForm = <span class="literal">true</span>;</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (hasPermissionFilledForm) &#123;</span><br><span class="line">        titleShouldKeep[r.getStart()] = <span class="literal">true</span>; <span class="comment">// 标记标题保留</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>关键点</strong>：</p><ul><li><strong>子段落遍历</strong>：检查标题的子段落（<code>start+1</code>到<code>end</code>）中是否存在有权限的填报项。</li><li><strong>权限双重验证</strong>：仅当<code>retained[j]</code>为<code>true</code>（被基础保留）且<code>hasPermission</code>为<code>true</code>（有权限）时，才视为有效。</li></ul><hr /><h3 id="4-结果生成"><a class="markdownIt-Anchor" href="#4-结果生成"></a> 4. 结果生成</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 生成最终的删除/保留指令</span></span><br><span class="line">List&lt;ResultItem&gt; result = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line"><span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"><span class="keyword">while</span> (i &lt; size) &#123;</span><br><span class="line">    <span class="type">Para</span> <span class="variable">p</span> <span class="operator">=</span> paras.get(i);</span><br><span class="line">    <span class="type">int</span> <span class="variable">paraOutLevel</span> <span class="operator">=</span> XxxUtil.getParaOutLevel(p, styles);</span><br><span class="line">    <span class="keyword">if</span> (paraOutLevel &gt; <span class="number">0</span> &amp;&amp; levelsToKeep.contains(paraOutLevel)) &#123;</span><br><span class="line">        <span class="comment">// 标题的保留状态由titleShouldKeep决定</span></span><br><span class="line">        retained[i] = titleShouldKeep[i];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 处理表格或普通段落</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="comment">/* 是表格 */</span>) &#123;</span><br><span class="line">        <span class="comment">// 删除表格并跳过所有表格段落</span></span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (!retained[i]) &#123;</span><br><span class="line">            <span class="comment">// 记录删除指令</span></span><br><span class="line">            result.add(<span class="keyword">new</span> <span class="title class_">ResultItem</span>(p.getPos(), p.getLen(), <span class="number">0</span>));</span><br><span class="line">        &#125;</span><br><span class="line">        i++;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>关键点</strong>：</p><ul><li><strong>标题保留状态更新</strong>：根据<code>titleShouldKeep</code>覆盖标题的<code>retained</code>标记。</li><li><strong>统一处理</strong>：通过<code>retained</code>数组统一判断段落的保留或删除。</li></ul><hr /><h2 id="四-验证与测试"><a class="markdownIt-Anchor" href="#四-验证与测试"></a> 四、验证与测试</h2><h3 id="1-测试案例"><a class="markdownIt-Anchor" href="#1-测试案例"></a> 1. 测试案例</h3><p>以用户提供的案例为例：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">段落索引 | 内容              | 层级 | 是否保留</span><br><span class="line">-----------------------------------------------</span><br><span class="line">0       | 一级1            | 1    | false（无子段落有权限填报项）</span><br><span class="line">1       | 二级1            | 2    | false</span><br><span class="line">...     | ... | ...  | ...</span><br><span class="line">18      | 一级2            | 1    | true（子段落包含有权限填报项）</span><br><span class="line">21      | 二级10           | 2    | true（子段落包含有权限填报项）</span><br><span class="line">25      | 有权限填报项      | 0    | true</span><br></pre></td></tr></table></figure><p><strong>验证逻辑</strong>：</p><ul><li><strong>一级2的保留</strong>：子段落（索引19-25）包含索引25的有权限填报项 → 保留。</li><li><strong>二级10的保留</strong>：子段落包含索引25的有权限填报项 → 保留。</li><li><strong>一级1的不保留</strong>：子段落中无有权限的填报项 → 不保留。</li></ul><h3 id="2-边界条件测试"><a class="markdownIt-Anchor" href="#2-边界条件测试"></a> 2. 边界条件测试</h3><ul><li><strong>无子段落的标题</strong>：若标题无子段落，不保留。</li><li><strong>层级嵌套交叉</strong>：如<code>一级→二级→三级</code>的复杂结构，确保范围计算正确。</li></ul><hr /><h2 id="五-总结与扩展"><a class="markdownIt-Anchor" href="#五-总结与扩展"></a> 五、总结与扩展</h2><h3 id="1-解决方案优势"><a class="markdownIt-Anchor" href="#1-解决方案优势"></a> 1. 解决方案优势</h3><ul><li><strong>精准控制</strong>：通过层级栈和权限双重判断，确保标题保留的条件严格符合需求。</li><li><strong>可扩展性</strong>：通过<code>levelsToKeep</code>和权限接口，可灵活适配不同业务场景。</li></ul><h3 id="2-可优化方向"><a class="markdownIt-Anchor" href="#2-可优化方向"></a> 2. 可优化方向</h3><ul><li><strong>性能优化</strong>：对大规模文档，可优化子段落遍历逻辑（如预处理子段落列表）。</li><li><strong>异常处理</strong>：增加对层级不合法或权限信息缺失的容错机制。</li></ul>]]></content>
    
    
    <summary type="html">文档段落保留功能实现分析：基于层级与权限的标题保留策略</summary>
    
    
    
    
    <category term="开发纪实" scheme="https://log.660066.xyz/tags/%E5%BC%80%E5%8F%91%E7%BA%AA%E5%AE%9E/"/>
    
  </entry>
  
  <entry>
    <title>OpenWRT部署及其使用</title>
    <link href="https://log.660066.xyz/2025/03/26/openwrt-and-openclash/"/>
    <id>https://log.660066.xyz/2025/03/26/openwrt-and-openclash/</id>
    <published>2025-03-26T01:05:28.000Z</published>
    <updated>2025-03-26T01:10:31.489Z</updated>
    
    <content type="html"><![CDATA[<div class="hbe hbe-container" id="hexo-blog-encrypt" data-wpm="抱歉, 这个密码看着不太对, 请再试试." data-whm="抱歉, 这个文章不能被校验, 不过您还是能看看解密后的内容.">  <script id="hbeData" type="hbeData" data-hmacdigest="ed2b05530f075e04653a3f5dc458919bd4ac32bb26ff02e51c59eba90de88699">c1b73eab8127d6e5450ef89a5c6005a87b4c19dcdc084411a258c01a3844a435aaa9ca06ccf8ebe3dfcadfb85cd2fa781accae79e5b8384462a18e1b85b5ce8aa87b88e86523f6999bd3c8e5305ce572db2c62c22dfb4d8671c4d9c5c62f7a14fc73102f57c4d379479ec7545b7a9e4c369222a6f7598cacffaa42989a82cc7c54597869d361a48301d41cc1b2cdf599fb7c8623e9e8292a302b04a8d5ec632e77d8f8ada2111f574b7e1217a1a9a6f128e9f6d5dfd6f1f40cd5acd3391316ac2f6dc9acf4f171b0de2f8ff1e5651992b1cb53d31e74ac6be2be6e4232db50f607e2401fa54c8610319954c752b832e736d4df6689aae7910fd194f9c7ac8a8e30acce55a205d21284308c22c08faf42af1b7054d63edd0be72ca12cb3c088696e2a1b08b201157bb639d51322101294d189fbc22e54bac48754844b8afda64acc1e7705b55e6a294723e6565d1fc017500c22822fe0c71f80d813a346e3b36dc143cd7ab905ba4767e4fbfe566c7f0a8c30935f50261d6283196933e2a4827ef854bc1e0603988f999062c8a4a58c1f8f53d3d87449ef5324112cbcafa362c21598eefb2ae13664976c15d97902f4e283212280dd2b9ab2ad0d9e3df4cad345123151178f7310c5a17fe2606d03564ef8736d5206038d58a9e48f09305d98e5599d9689d453ab97a3df29e649c9004bf2980ff4245c448ebd1fef0fe4644703e4d98b9adbb5aa170bad62206d402fb9d78153487281ccdde3cfb62ebcb010444f423c0b47f6d6aa27ff92c78981d41a14f33cce6f501843135327b3ed90bc0dec69efe043f9e35eaed4af16506f4474906698d402640c5c9f438ab5c2bca7c7aed249c19edecdb8061502b274c3675be9f0b5583a26c86f3096a1ed6d42165928600acdbf107cabe9cc35d93695f4a2bec607887460151954fc4140c34ff9c45960b81859b0a9edca411986a3188b0f6a6c591b62775e74467bdaf27b4da8c3e7133fb4a23c58d4603b45c7d0e026008552c464c868df85eb3b6eacb826d715eb549a952af003ca703a9296db2c7d9a01161e5f09302a78cec8ab42bef58f4fcdd5ee5c33402764f03039793145f2186c4b581d73bfe801c1a815c16f78b984d35f0129afe651334b505d900ca8d2e3398077f38b83d29f9562225c5fc6f0e84827f3092d8832ab9734a95428677bd6b6ba497e37c849a9e1314d3e82fbae103c426addd5fa06df47ea760fb2da8c841f1c32e3095d5d246beae804f26939fd0646675476fdcd581acd158d9cef82bccdaf1e91613821fb9df70dd9609ea9c283d54c8d311e39f96c47030800898fd025050e60e3174e064ab5b799e03fa83954beac6481755268d5b6ef38456b9c9802f655ef7552236030dfa50463060e3890edc92389f56b0a94f8ad581fe081d781c26f5c776f5ffefc266f88a044826878d9cf0df5e1a1198ca847a48f1f2e2dd7110cd54bb4c69ec32eb23e51252c23710f205b3b78519424d98ff9660fa456ae5e17e24a68020d6e9ce1285ea66ceef78990f32f0d99aba24de0d0fc2cdd13d766a72c7d7bc9a53fbc7c6f14bf7141c066ea908dfe6ce3baf3d613eee290fcc96327808c876298039b55256ef46cfc031908106a6526c31e19d59daf9b1ea1cf6abc07956a23565067cf8ddab3a492aff3e1e29cd9b5932200a46b4df1f8a22493042ace15f148554bf3dbcb9486eff74e28d372f1ac36c3e0a1976ef384731bdbaacc13d55cd0c4651c0c90aecfa199feb433af4ec0e3d90cb54ab121ba343e8fc14ab7ff86565a778ecc68d1bac21fd59a1f9308d723123f0ff54df262f5e404f690db5b2dfc79704c231f49bb5f1f8fcf4dc3ab2d103ee91cc3620c7ec4668d7e97b2cfe25fb980ec45a42fe8b52d78d8fb1c3815aca8576a80f2bb22000d882d16ec5876084e5c4fb98f5fde1b7e3021482b1895c9ccbe6c0b8003dea4ee7394332d6e713f6e2442d2375608ba2f276eb32a6d9a8180b4a940794481447fd6c10c7835ba8ba68e929c6374fa9a192893beb29db6b3513173c6526967c566d62e7e3a6ba784ab3475594fbd121781989ae955c050ddc178219e97ebc41ed79713a374481179fab61c359dc2ac010c47533917a7403181e3199acad3bbcdce033df363d986cd8d5b211652c6d46e74776440e94ed370998da4fda4c29790074e9adf7aea03d846c7818d9ffdc259ca38b320dc4442332eb2ce83b431def9bfcfad82d7a2cc305e50ff71e2c61211a7e70e640f852d4e96c4a52ae27613162e0d578c71c63757218cc29fefc00277ccdbf10cdf991a20bc8ea5517cc693f05acc6103f8b78a95053252dc6b00fc99bfea6e0e68e43fd2341b20bd059942a82b521af5bd24be7e720a43800dfb7c9f7e5c86041e381b8337bd8cfdc26e05fa432160345031293e0a21262278bab58dbec29a70c35ad95c6beb6bd4a9139511214b075be03ce9a22bd3614464cc1a1c6e89ebc751993007b42d77a3229aa789646fdd7408d69540d4ef923915fc3ff5743fa564daba1339d0b8af9f83f6e5eaaaf12103f4331420c8b3addffd34ea22dabf9bc88f267a25733ff433dfe867d98b0b12617b8f2ea7b0cfc6d843e19f1b6f39302ac01756b9292c44de182409eb7d70df2209c93da5dd6aab84f032ac9997e8c104375ba50d1a99f57d4358750be738065e3099acbfc3166c777ba0186aaff08738e376acc7fec6239402ebc45abf2688b85fa2fe7126725746d39e450f921b8f0461a199065f14773bd7cce5f1c4a6ce1d7480efbef442ce944e43cf4607dff1658f8f65b3f6eed0664c2bb073353120dc3b2daa46530ac6ac0182c087210bd5d77387fb0462ca84d3fbfc6abbd66be8113237ac5586bf6515ba0d9fd66f1d78b4ecadf1540a2806bddcf3789b43420e173e449abbe848ff67acb8e0cd96c1cfc184672fb8fd817e31e2aaf2e91d4dd6e61262aced49e7e006b30629f538df1f5fa2edbed47de7d7a1282748722b30c288431234ad7b04f95fb4e5242dd3220e87d874c51ac6ffcd01d45d2d8374e298d48cbf6b56b3f0c84d5c0c759ec509ba1edea4277a08d069764e35c75730b4d66b3ef3cdf134377ddcbe25772c7e24ac8dc12ed8e3c115be24e8370a42d57482d1e9fcb93b4cc0a2c17f86d533820ae0882ef91b89bc1c6aae8ff36467b045eff69939d837773c3be52e56e805e9cb18e33e53f6606e28beef15828df9a8f0f309166ad90ef5f9de036c414149e2d84b7698661c9aa5356dbd5bc8a877377767950c18d5f7481c3a8fb4309492e3b62e1f754b2c03204cc4e5145efa294749bf4372ba454b79545147fd2024493374a087981915ad9d0dc669f8e62728b3f074b85836772a9ea48d33aadb0f165e9bd26192d06c1e152c49bfa21005b4603b82933704004c04eb81d98f1b79e2e966f0695dcc42aa7179d0a17699174c62f291b9797be626ad0e7e3a18505a86724e2c2f264a3d00e872370c0ac6b8bc7216028440b3a75ae6bfb1bf57066ab8d0b08073d15cfcda13f124f0135393cb8ff8de07b33e6b2460c414bb3e9c5846de6ab82737e5e2ec89f6d280df897bccfd551886f84d7a78802e24c087813eac3f630a0525b1dd2fe7b05486198ea56d289d528981d552d7a3b0a292d1beb6c290d0bebc336858e1f506a8a0493bc2ae2c1f0beafdde5c0a2196df31f15fc9b4ff8b11d48093a4ee1568bcfcf9abddd6cac64b1f82dff60675661d180dc24773419883666aef00e4fa88624cfe5c82d33e3a4a27cb38137808e1fd6b7b9e24744333100aef2458e7ed30b77804a085c978a66f684f63e08d54d14952c0e3e6d322c746d9ed91f89e7fec359f7742e01d55357c2494e8c84f7d3be7a8409670133cf26c3c06f7f42458d28d73faa6782fae2585021e95a2374614452ae021d97d6fcffc6007862ef468cd1b49d027ccbb02cb8b9bbbc89ccdd2ba087819e34321d61f3867ce6ef65b81bf6d8c9ce8eb6c411823fd7c4b836694ad158d5730699497f53caa40d57285ebd4ea3694f7478b4fb47091dc3db1e953d2e037fdf9c2e8be154fb2df76565bfee6cf0ecfbbfd07fb51faf3b286fb7c38d8320f860d71a9e416da2d7411887bb7f4b9b44b6d9e1ef59b72a1132590868019af621b15f27fd93ac6bf1a2ca92ce0d924d1eeb0e9e5650a12675440144ffe0446789b05ece4b3afaeff2581310961115933c3bc5b3bdfae924b153565628e0ef1277eee831e4cef24c26fcdc52eb2a596c6594bd9fe5a1b148484e9e61f0fa8dff8e759c4e621cd6deedfa57cdbbcbe7bbff68f5101932c5de793d763c910cdee8f115b0de8d59ec4b0ea8fcbf3acb8d32dc86702447ffbe1382e9f3f50f93d933bc76858d65019ed7e88b6bff15f4320a7b2acd92d406ddecb7378c36784d1852ccb38d6f9dfcaec2f131d149826c312a9ece24dc14550ca63104fa9d1a16a328f325e856804e8ae1b2de58e4feeb58fc9ecbd58ab6c00bf365cb790874e30abc7ab234035c046abb964b2399e9c788d5acc6499a3912c58fc1c0809c94fd5081c712a556fb3a33c2ba6243ca5b9e7ad8343c7f85a280238e43da8520c9dd1079042ab2319d5790ef8ee37493fa8ba8c4646db4c32ef034ebfda8112acf42580f7981f3bf6deb0c0e56c2a2f6cde1ca4b886bfc68983d4e6d80f4ef25cfd2dd57e0aa16a0282d88de56b5592009709d6b0bdf03fcbb0449610d7ce77e1b3f0aec85c587b09b834e2c9ff70dba5deda441e25268d3db6b401e9d60ce5528d7f63ac53198ea742ad3cd90af1e38f2db6bd1312ad16661558d441f0042dcef1c2734f0260f197bbb0d1b93f774fb4e15dd026b3abf8cec4343b3ae38d940367c362f734b1e3780debb0a593d38300244dd29e079c4edcfdcc2a9bbed94c52c79ec069a5c3e8d70b3235fa36d17da5bedd84fae4c807fba8877449b0a79f92382ea129658dcfe167cff71ce302b5b1e12fd2ddf647c1c9a2e44f2b822c1a67c1cf08a6cdf8e0d9362d307333737af7b63525d975fa25fe736c46d26a0a722d715ff6a344470dfdd3af7aa9ed6af625ae98e799f4b5e519b1e64649a0c1276f85b8a66b7099408d351dba2f8add488f63e53811028e168c87ced67a2aca9485bf8be079988a51c3705f90cb1e3e0f7e31f6d64b19dddb69c8834f90805f887ff9bfffca2da0be9dbe4ae1f7ec0f8f901c45ea0dad25e14780999901479530b71d85acb7b4d12a629c4f43b42c8ab058557bed47395bf7e776a865c559863b2f8f954e628350933863789ba69ab2d426edd4bfab7215c4e687718b8a5010c6275bcb11cd130d0b962888da5837b3d070cdf0200ea8b8226fb1f08d810977127af6c6ea5bb31809f3af765e2bf7047d59fbd8f538193c58f3be6e46f34174c0b7cf6af860ade37c121bf0a4e13584dc73ed0d60bff3d6fab89255e8132cd6d02a33ea0424f0ee02b68d811d63d367f0cb6cee5019b001bb57326842093eb2639b41e7543e11e4c9b01810ecde096962a9422d15b94d8b29ef4b7582fb81c8b126cbd19c96b8cca6dc08092111d04f68d1283622172569503c09df4bc0891c04a1e3958d878b4c864a22f52ead7f39be08361c7fcdb313b4f14ecf17bc54ff04e0c197dc43b97167afa97fd76c13146dac5432a1e02906fe8d3c73473ba2a21153c05b0e411b503fc616d804b97ab189e2e127b74218a43acaf2ce27c4450edc89e556bcdab79d84d30fedf87e7099b042e951e05410746653349b59ce99cdecbd701071445792bc2bf2a6b59dddc0103c1208f59606517a9c07d506eab45e4fa292be0eadfc0c49fac064fe4c38e5a569766728abaf8730e17b69dd99d873dda11b1a85938e26ed8fd4d21b1a0ab3158230cb0dfd83d9ecdbeb0ee5f0bd8e6ba364842a0d8fc4ddb119879896c87b02f93c8cc7ed56be0e42b3079377327cc1077e5902755a6c6c7a36a79e27be359b39d6d97671cc7b4b0c3217872784b40c8c809fc474adb97dfac7b526d8ff02e7dc4e1c4bb5a8c2ca610282a1080c6e0462d056a870a2e352c33f7173c8fe82eaa45285a33705465cd33c8fb676c8899e031fdb2293ae74d96e4c2ee3d1c0c9e0c04bdd9726097001a74e2fabee1e261b9e614c544f83c6f017d5c711616f0cb380a035a9a58b8dd7e8ad755cf70c954a048750c25228cc035b533649a9cde5f48a8ccc0f44fbbef3c87bd21d298baed4ea2a26689e4f32d0bc52a1438e88321312143e6021461860a7a450ec20d6d0130de9a655f5f59a409f537d306338755d938d5bd12d8037fd9e2f7eea9f7a0ebb219d8c0ce7253468735f1f2198fc6815a0debee66c20d6d84cef30198317f53ba17b66135b3b884b48d0afc95d01711e0c53ba988c2903c864dbb84c327c09046c539d1aa3812c149e2d333f5c5c850e147843c9f7fa86758caf04da0824fd0945f3b8709fad2103b409a567319e2de8edc00562582a0fcea5f1390c2965b42c51007bf8bedc60b91d552ceb638c26baed8961193d8a1c2e4a44bdc3f5cb578a237f077aa57dbb087b50d45314be2d4d2e31243f3c972b9bf7f5ff9e19b5eef210b22b8c78ae308828dcde0fd5d894bd5c74c7ac08293a8f8177a26b156abcae01b0a5f0409029050e4a65094625e329f44b56148cf07e1eba1a0563d5cbdafeeb670a0fbc102b91c48e5cdf68d15246fb1c6bffb919618135cccca5f920cf54ef6fd5e20b69678105c47340ce78d3055dc0d09b9d17ef6ee811172e8afd72009b9760391bf31f9b5086f1b44807b8d0ffd0a4b936ae511db173ae445aad65dab9f58ed8d897c279102010ed358d07d5c526d279072772517b26932b52146cef7dfc705fb5affb4b2c4f6f30349930cd5c03b7a5a70aa44748bf84b99c48cb8ab0848813f8c062d50d73a6b5a73e7bc1e67a666912b1f9ef8dd6ab69661c65c9f4a609e2fa891ce2b58dfb55c8d6e646d4f83dd395b19331291bebc0c338f28a748126886ad55a1ec44f0a9a3952239ba864f24f7cb7b1be26cfa1b2aefd0d5d7cdc73b4564deada010a5f3b18d82ca56b9644993852b9d5a9911155de1aead193ed9b5496cf38ff93b6fada2b2ef7f1b18d97040c4c49900ce296116bb0f69a2f0521d45e795d8ae5aca4285c1f1ba29bb40d36eecfc26b0b4a4b54fb2f85841bbbd73c949ab4e3babfb247c6d31bcdef77aacb582aab21c2d8deada062343262cd618939c7ae3e4e1e5b96a30b4194d52b9f79189b371ea972e5472fc402498c9b78c380ae373ffc5eaa0751f6aa8c034dd773eb1b3c85bf261b93ad609723aee5951a533c3a739e0daaf9674597a37aa9fcc7e4cc94b4aaa8977997677e51d82a7a46c137549508d591f112b4ff44c61c3eee05266bf94ceea2e21c379267dc432faec3d39c4ecdded5cd03ac8fd080ecdb38b7badc0eb037ad8bcfe230723b994f19629797f9f30f4966cfe8623e57ff783994931355278b4cd1e7cb1267338e17f58f12dc6f34d5f9ba5ab7a30ebc60d50192618d790496aa1a4896364259e1f4efb3001f08108e9333585e9bc79fa9715a9c9b29522750538ead496eac7360c43a9762b7c83e3c3042b6fbc0660e4cb995796479026795b069c8d7f94b27f79a150d7a5b59771dab3d87631690a39ef078367521ba922ec19b3b9ec8c42670d451b912b7285f1bf6bea6cbfc01bf48cf48a92cb08b0b8c720271fa14a967f5b919176de891c74457e7997221b43376f23d4e46a2b7aeacac7dc46414c250d1f8fcea46eff21ed16638716745bd9e765db4f69e0ebd11e706cb97d5f0735bb2cf44632b5217082e77513f11a29d49b22b239954a4edf67030a293492ab72aaaeee3bb3cafa06fbcb59df907c535fb64c67e17715bba74a9021da6ec97d3462033d2f03a70cf08a08fc6de974a8e5273d0172a123b8743578b3388824411cadb3986b9844f6f96b20218ff2673bfa76a953d457fc9961501a4598daee39085f7bdedd211ad80fa17b16117e8675e3dbf19a40d1ea5433a62f3b54f037e0cb3faa773e653546d2b7e05b0146a68f8b113952acbd416779475c9a2b845e5b2e320c71f1957c6cca1e3623e97490304d6efab8c242ec1185c7d742a389be818ff40fdbe9387a1c387ba686ea0a72ddf273a603c91569b7be65e6d414101f4d371206a4d7bb4029b22f00a2b3b55fbfd4a29b11d406fa749fafbbc502577141e07bcd1730930b05e0f2547c7fc4afebd8f0a56cb9ea6a0c20e</script>  <div class="hbe hbe-content">    <div class="hbe hbe-input hbe-input-default">      <input class="hbe hbe-input-field hbe-input-field-default" type="password" id="hbePass">      <label class="hbe hbe-input-label hbe-input-label-default" for="hbePass">        <span class="hbe hbe-input-label-content hbe-input-label-content-default">您好, 这里需要密码.</span>      </label>    </div>  </div></div><script data-pjax src="/lib/hbe.js"></script><link href="/css/hbe.style.css" rel="stylesheet" type="text/css">]]></content>
    
    
    <summary type="html">OpenWRT部署及其使用</summary>
    
    
    
    
    <category term="开发纪实" scheme="https://log.660066.xyz/tags/%E5%BC%80%E5%8F%91%E7%BA%AA%E5%AE%9E/"/>
    
  </entry>
  
  <entry>
    <title>OnlyOffice部署【基于centos】</title>
    <link href="https://log.660066.xyz/2025/03/14/onlyoffice-deploy/"/>
    <id>https://log.660066.xyz/2025/03/14/onlyoffice-deploy/</id>
    <published>2025-03-14T11:12:27.000Z</published>
    <updated>2025-03-14T11:22:20.615Z</updated>
    
    <content type="html"><![CDATA[<h1 id="onlyoffice部署centos"><a class="markdownIt-Anchor" href="#onlyoffice部署centos"></a> onlyoffice部署【centos】</h1><h1 id="一-上传out文件夹"><a class="markdownIt-Anchor" href="#一-上传out文件夹"></a> 一、上传out文件夹</h1><p>基于上一篇打包文章，需要将out文件夹上传到CentOS。</p><p>此处不在赘述。</p><h1 id="二-安装rabbitmq及其配置"><a class="markdownIt-Anchor" href="#二-安装rabbitmq及其配置"></a> 二、安装rabbitmq及其配置</h1><ol><li><p>更新yum（基本操作）</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum -y update</span><br></pre></td></tr></table></figure></li><li><p>安装EPEL存储库</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">yum -y install epel-release</span><br><span class="line">yum -y update</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">(无网环境自行下载)https://packagecloud.io/rabbitmq/erlang</span></span><br></pre></td></tr></table></figure></li><li><p>安装Erlang语言</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">yum -y install erlang socat </span><br><span class="line"><span class="comment"># 查看是否成功安装</span></span><br><span class="line">erl -version</span><br></pre></td></tr></table></figure></li><li><p>下载并安装RabbitMq（自行选择方式，wget、curl、上传等）</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">https://github.com/rabbitmq/rabbitmq-server/releases/download/rabbitmq_v3_6_16/rabbitmq-server-3.6.16-1.el7.noarch.rpm</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装命令</span></span><br><span class="line">rpm -ivh rabbitmq-server-3.6.16-1.el7.noarch.rpm</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">启动服务</span></span><br><span class="line">systemctl start rabbitmq-server</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看服务状态</span></span><br><span class="line">systemctl status rabbitmq-server</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">停止服务</span></span><br><span class="line">systemctl stop rabbitmq-server</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">开启开机自启</span></span><br><span class="line">systemctl enable rabbitmq-server</span><br></pre></td></tr></table></figure></li><li><p>添加RabbitMq用户（根据自己需要配置，一般生产无需配置）</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建账号和密码</span></span><br><span class="line">rabbitmqctl add_user 用户名 密码</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置用户角色：</span></span><br><span class="line">rabbitmqctl set_user_tags 用户名 administrator</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">为用户添加资源权限，添加配置、写、读权限</span></span><br><span class="line">rabbitmqctl set_permissions -p &quot;/&quot; 用户名 &quot;.*&quot; &quot;.*&quot; &quot;.*&quot;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">修改用户密码</span></span><br><span class="line">rabbitmqctl change_password 用户名  新密码</span><br></pre></td></tr></table></figure></li></ol><h1 id="三-安装nginx及其配置"><a class="markdownIt-Anchor" href="#三-安装nginx及其配置"></a> 三、安装nginx及其配置</h1><ol><li><p>更新yum、安装EPEL存储库（Mq安装时一描述，不在赘述）</p></li><li><p>安装nginx</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">yum install nginx</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">启动Nginx服务：</span></span><br><span class="line">systemctl start nginx</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查Nginx服务状态：</span></span><br><span class="line">systemctl status nginx</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置Nginx开机自启：</span></span><br><span class="line">systemctl enable nginx</span><br></pre></td></tr></table></figure></li><li><p>配置Nginx配置</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">切换到配置文件目录</span></span><br><span class="line">cd /etc/nginx/conf.d/</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建配置文件</span></span><br><span class="line">touch nginx.conf</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">编辑(配置信息如下)</span></span><br><span class="line">vim nginx.conf</span><br></pre></td></tr></table></figure><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">map</span> <span class="variable">$http_host</span> <span class="variable">$this_host</span> &#123;</span><br><span class="line">  &quot;&quot; $host;</span><br><span class="line">  <span class="attribute">default</span> <span class="variable">$http_host</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="attribute">map</span> <span class="variable">$http_x_forwarded_proto</span> <span class="variable">$the_scheme</span> &#123;</span><br><span class="line">  <span class="attribute">default</span> <span class="variable">$http_x_forwarded_proto</span>;</span><br><span class="line">  &quot;&quot; $scheme;</span><br><span class="line">&#125;</span><br><span class="line"><span class="attribute">map</span> <span class="variable">$http_x_forwarded_host</span> <span class="variable">$the_host</span> &#123;</span><br><span class="line">  <span class="attribute">default</span> <span class="variable">$http_x_forwarded_host</span>;</span><br><span class="line">  &quot;&quot; $this_host;</span><br><span class="line">&#125;</span><br><span class="line"><span class="attribute">map</span> <span class="variable">$http_upgrade</span> <span class="variable">$proxy_connection</span> &#123;</span><br><span class="line">  <span class="attribute">default</span> upgrade;</span><br><span class="line">  &quot;&quot; close;</span><br><span class="line">&#125;</span><br><span class="line"><span class="attribute">proxy_set_header</span> Host <span class="variable">$http_host</span>;</span><br><span class="line"><span class="attribute">proxy_set_header</span> Upgrade <span class="variable">$http_upgrade</span>;</span><br><span class="line"><span class="attribute">proxy_set_header</span> Connection <span class="variable">$proxy_connection</span>;</span><br><span class="line"><span class="attribute">proxy_set_header</span> X-Forwarded-Host <span class="variable">$the_host</span>;</span><br><span class="line"><span class="attribute">proxy_set_header</span> X-Forwarded-Proto <span class="variable">$the_scheme</span>;</span><br><span class="line"><span class="section">server</span> &#123;</span><br><span class="line">  <span class="attribute">listen</span> <span class="number">0.0.0.0:80</span>;</span><br><span class="line">  <span class="attribute">listen</span> [::]:<span class="number">80</span> default_server;</span><br><span class="line">  <span class="attribute">server_tokens</span> <span class="literal">off</span>;</span><br><span class="line">  <span class="attribute">rewrite</span><span class="regexp"> ^\/OfficeWeb(\/apps\/.*)$</span> /web-apps<span class="variable">$1</span> <span class="literal">redirect</span>;</span><br><span class="line">  <span class="section">location</span> / &#123;</span><br><span class="line">    <span class="attribute">proxy_pass</span> http://localhost:8000;</span><br><span class="line">    <span class="attribute">proxy_http_version</span> <span class="number">1</span>.<span class="number">1</span>;</span><br><span class="line">  &#125;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>重启Nginx</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nginx -s reload</span><br></pre></td></tr></table></figure></li></ol><h1 id="四-修改项目配置文件"><a class="markdownIt-Anchor" href="#四-修改项目配置文件"></a> 四、修改项目配置文件</h1><p>配置文件路径：./out/linux_64/onlyoffice/documentserver/server/Common/config/</p><p><strong>不知道的配置项含义及其作用时，建议不要自己调整。</strong></p><ol><li><p>数据库（因项目需要，将数据库替换为Mysql）</p><ol><li><p>数据库SQL路径：./out/linux_64/onlyoffice/documentserver/server/schema/</p></li><li><p>搜索sql关键字。type根据需要进行调整。dbHost(数据库ip)、dbPort(端口)、dbName(库名)、dbUser(用户名)、dbPass(密码)</p><p><img src="./onlyoffice-deploy/image-20250314182832093.png" alt="image-20250314182832093" /></p></li></ol></li><li><p>Redis</p><ol><li><p>根据自己的需要，调整host、port、password(密码这个属性不一定存在，请自行测试！)</p><p><img src="./onlyoffice-deploy/image-20250314183248722.png" alt="image-20250314183248722" /></p></li></ol></li><li><p>RabbitMq</p><ol><li>使用vim搜索关键词rabbitmq，因为我的rabbitmq与服务在同一主机，所以无需调整。</li></ol><p><img src="./onlyoffice-deploy/image-20250314182528117.png" alt="image-20250314182528117" /></p></li></ol><h1 id="五-启动项目"><a class="markdownIt-Anchor" href="#五-启动项目"></a> 五、启动项目</h1><ol><li><p>生成字体数据信息</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">cd out/linux_64/onlyoffice/documentserver/</span><br><span class="line">mkdir fonts</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成命令</span></span><br><span class="line">LD_LIBRARY_PATH=$&#123;PWD&#125;/server/FileConverter/bin server/tools/allfontsgen \</span><br><span class="line">  --input=&quot;$&#123;PWD&#125;/core-fonts&quot; \</span><br><span class="line">  --allfonts-web=&quot;$&#123;PWD&#125;/sdkjs/common/AllFonts.js&quot; \</span><br><span class="line">  --allfonts=&quot;$&#123;PWD&#125;/server/FileConverter/bin/AllFonts.js&quot; \</span><br><span class="line">  --images=&quot;$&#123;PWD&#125;/sdkjs/common/Images&quot; \</span><br><span class="line">  --selection=&quot;$&#123;PWD&#125;/server/FileConverter/bin/font_selection.bin&quot; \</span><br><span class="line">  --output-web=&#x27;fonts&#x27; \</span><br><span class="line">  --use-system=&quot;true&quot;</span><br></pre></td></tr></table></figure></li><li><p>生成演示主题</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">cd out/linux_64/onlyoffice/documentserver/</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成命令</span></span><br><span class="line">LD_LIBRARY_PATH=$&#123;PWD&#125;/server/FileConverter/bin server/tools/allthemesgen \</span><br><span class="line">  --converter-dir=&quot;$&#123;PWD&#125;/server/FileConverter/bin&quot;\</span><br><span class="line">  --src=&quot;$&#123;PWD&#125;/sdkjs/slide/themes&quot;\</span><br><span class="line">  --output=&quot;$&#123;PWD&#125;/sdkjs/common/Images&quot;</span><br></pre></td></tr></table></figure></li><li><p>启动FileConverter</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">cd out/linux_64/onlyoffice/documentserver/server/FileConverter</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">环境变量</span></span><br><span class="line">export LD_LIBRARY_PATH=$PWD/bin</span><br><span class="line">export NODE_ENV=development-linux</span><br><span class="line">export NODE_CONFIG_DIR=$PWD/../Common/config ./converter</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">守护执行</span></span><br><span class="line">nohup ./converter &gt; /xxxx/converter.log 2&gt;&amp;1 &amp; </span><br></pre></td></tr></table></figure></li><li><p>启动DocService</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">cd out/linux_64/onlyoffice/documentserver/server/DocService</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">环境变量</span></span><br><span class="line">export NODE_ENV=development-linux</span><br><span class="line">export NODE_CONFIG_DIR=$PWD/../Common/config</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">守护执行</span></span><br><span class="line">nohup ./docservice &gt; /xxxx/docservice.log 2&gt;&amp;1 &amp; </span><br></pre></td></tr></table></figure></li></ol>]]></content>
    
    
    <summary type="html">OnlyOffice部署【基于centos】</summary>
    
    
    
    
    <category term="onlyoffice" scheme="https://log.660066.xyz/tags/onlyoffice/"/>
    
  </entry>
  
  <entry>
    <title>编译OnlyOffice【填坑教程】</title>
    <link href="https://log.660066.xyz/2025/03/14/onlyoffice-compile/"/>
    <id>https://log.660066.xyz/2025/03/14/onlyoffice-compile/</id>
    <published>2025-03-14T00:46:17.000Z</published>
    <updated>2025-03-14T11:21:45.632Z</updated>
    
    <content type="html"><![CDATA[<h1 id="一-编译环境"><a class="markdownIt-Anchor" href="#一-编译环境"></a> 一、编译环境</h1><table><thead><tr><th>系统、硬件</th><th></th></tr></thead><tbody><tr><td>物理机</td><td>ThinkPad</td></tr><tr><td>虚拟机</td><td>Vmware（建议硬盘大小40G）</td></tr><tr><td>系统</td><td><strong>Ubuntu Desktop 16.04</strong></td></tr><tr><td><strong>编译依赖软件</strong></td><td></td></tr><tr><td>Git</td><td>apt直接安装的即可</td></tr><tr><td>Python</td><td>Ubuntu Desktop 16.04自带版本即可，应该是2.7</td></tr><tr><td>NodeJs</td><td>应该是16，我看到编译时自动下载了16</td></tr><tr><td>Npm</td><td>apt直接安装的即可</td></tr></tbody></table><h1 id="二-注意事项"><a class="markdownIt-Anchor" href="#二-注意事项"></a> 二、注意事项</h1><p>因部分依赖在阿里云镜像中可能不存在，因此镜像源未进行更改，编译全过程使用依赖软件自带镜像源。</p><p><strong>系统版本、架构</strong>一定要按官方要求来，我踩坑路线：</p><ul><li>Ubuntu25（Arm）=&gt; 内嵌的python不支持arm架构</li><li>Ubuntu24.04（X64）=&gt; 编译V8相关内容是卡住，综合来看，可能是clang或其他打包工具版本过高的原因。</li><li>Ubuntu16.04（X64）=&gt; 目前跑过了上面的错误，还不知道有没有其他坑。</li></ul><p>系统的内存、Swap也不能随便搞（可以大，不能小！）：</p><p><img src="./onlyoffice-compile/image-20250314083925823.png" alt="image-20250314083925823" /></p><p>总结一下就是，系统版本得按照上图，CPU、RAM、HDD、SWAP都要安装上图官方的来！</p><p>如果你用的是带Gui的桌面版乌班图，建议吧RAM、SWAP适当的调高一些。</p><h1 id="三-编译"><a class="markdownIt-Anchor" href="#三-编译"></a> 三、编译</h1><h2 id="31-克隆编译工具build_tools"><a class="markdownIt-Anchor" href="#31-克隆编译工具build_tools"></a> 3.1 克隆编译工具（build_tools）</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/ONLYOFFICE/build_tools.git</span><br></pre></td></tr></table></figure><h2 id="32-切换到linux编译目录"><a class="markdownIt-Anchor" href="#32-切换到linux编译目录"></a> 3.2 切换到linux编译目录</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cd build_tools/tools/linux</span><br></pre></td></tr></table></figure><h2 id="33-执行编译命令"><a class="markdownIt-Anchor" href="#33-执行编译命令"></a> 3.3 执行编译命令</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./automate.py server</span><br></pre></td></tr></table></figure><h2 id="34-编译命令注意事项"><a class="markdownIt-Anchor" href="#34-编译命令注意事项"></a> 3.4 编译命令注意事项</h2><blockquote><p>如果在没有任何参数的情况下运行脚本，这将构建 <strong>ONLYOFFICE 文档</strong>以及 <strong>Document Builder</strong> 和 <strong>Desktop Editors</strong>。</p><p>如有必要，可以使用与必要产品对应的参数运行脚本，从而一次构建多个产品。</p></blockquote>]]></content>
    
    
    <summary type="html">编译OnlyOffice【填坑教程】</summary>
    
    
    
    
    <category term="onlyoffice" scheme="https://log.660066.xyz/tags/onlyoffice/"/>
    
  </entry>
  
  <entry>
    <title>2024年终总结</title>
    <link href="https://log.660066.xyz/2025/01/06/2024-summary/"/>
    <id>https://log.660066.xyz/2025/01/06/2024-summary/</id>
    <published>2025-01-06T06:42:16.000Z</published>
    <updated>2025-01-06T07:30:03.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="2024年总结"><a class="markdownIt-Anchor" href="#2024年总结"></a> 2024年总结</h1><h2 id="工作"><a class="markdownIt-Anchor" href="#工作"></a> 工作：</h2><ol><li>公司项目顺利的稳步开发中</li><li>沟通上，有了进步，不像一年前刚入职时候语无伦次的样子了。管理上老样子，插不进手，毕竟刚毕业，也没资格插手哈哈哈哈哈。</li><li>年内换了两次工位，从公共办公区进了会议室集中开发， 又从会议室搬到了经理室门口，“经理警卫排”。</li><li>木涨薪、木涨薪、木涨薪。就这就业环境及其恶劣的情况下，还好没辞退我，谢天谢地了也是。</li></ol><h2 id="生活"><a class="markdownIt-Anchor" href="#生活"></a> 生活：</h2><ol><li>24年总共去了三个地方。苏州-&gt;上海-&gt;南京</li><li>找到了女朋友</li><li>搬了新住处，在此提醒，济南的各位朋友，济南租房找中介、二房东的，95%你是拿不回押金的。（泊寓、冠寓等大概能拿回来，但是每年都涨租）</li></ol><h2 id="学习"><a class="markdownIt-Anchor" href="#学习"></a> 学习：</h2><ol><li>了解了一下React相关的知识，但是完全去开发还是比较困难</li><li>LLM了解的比较多，相关的专业概念、术语也有所了解。</li><li>软考划水的一年，很显然，过不了哈哈哈哈哈</li></ol><h2 id="资产"><a class="markdownIt-Anchor" href="#资产"></a> 资产：</h2><ol><li>资产上比较走运。买了债基，小赚一笔。</li><li>在低点买了沪指基金，也小赚了一点。</li><li>黄金也多少赚了一点点，很少，也就买杯奶茶的钱。</li><li>真是凑巧。24年，债牛、股牛都让我赶上了，虽然没赚到大钱，但是多少赚了点饭钱。</li><li>开了证券账户，买了一手股票，开始积累股票交易经验。（妥妥投机分子我）</li><li>年底置办了Mac mini m4的丐版。构建出了手机、手表、电脑的苹果生态。</li></ol><h1 id="2025年展望"><a class="markdownIt-Anchor" href="#2025年展望"></a> 2025年展望</h1><h2 id="工作-2"><a class="markdownIt-Anchor" href="#工作-2"></a> 工作：</h2><ol><li>一步一个脚印，稳扎稳打，保证别出现重大生产事故。</li><li>进一步提升沟通、管理能力。加强自己对系统架构的设计能力。</li><li>尽量避免摸鱼被经理抓包。</li></ol><h2 id="生活-2"><a class="markdownIt-Anchor" href="#生活-2"></a> 生活：</h2><ol><li>初步打算是五一去香港旅游，目前港澳通行证已经在审批了。</li><li>多出去转转、玩玩。</li><li>拔牙，公司给买的商业医疗补充险，把两个智齿拔了。</li></ol><h2 id="学习-2"><a class="markdownIt-Anchor" href="#学习-2"></a> 学习：</h2><ol><li>React还是要看啊，完成“全干”工程师的基本技能</li><li>拿到软考中级证书，多看题多刷题。</li><li>继续深耕LLM相关领域，重点是OCR识别、应用开发、微调相关方面。</li><li>打算拿一下A类业余无线电执照</li></ol><h2 id="资产-2"><a class="markdownIt-Anchor" href="#资产-2"></a> 资产：</h2><ol><li>也是稳扎稳打吧，以稳健投资为主体。</li><li>多元化布局投资，布局少量的激进投资产品。</li><li>学习一下金融投资相关的知识，少踩坑，多赚钱。</li></ol><h1 id="后话"><a class="markdownIt-Anchor" href="#后话"></a> 后话</h1><p>其实本来有个2023年总结来着，2024年写着写着就写到年中了，实在是太忙，索性不总结了。</p>]]></content>
    
    
    <summary type="html">2024年终总结</summary>
    
    
    
    
    <category term="生活" scheme="https://log.660066.xyz/tags/%E7%94%9F%E6%B4%BB/"/>
    
  </entry>
  
</feed>
