<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>不再、悔</title>
  
  
  <link href="https://wzm996.github.io/atom.xml" rel="self"/>
  
  <link href="https://wzm996.github.io/"/>
  <updated>2026-03-12T11:52:32.112Z</updated>
  <id>https://wzm996.github.io/</id>
  
  <author>
    <name>wzm996</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>数据结构（二）———线性表和线性表的顺序存储结构</title>
    <link href="https://wzm996.github.io/2018/11/06/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%BA%8C%E7%BA%BF%E6%80%A7%E8%A1%A8%E5%92%8C%E7%BA%BF%E6%80%A7%E8%A1%A8%E7%9A%84%E9%A1%BA%E5%BA%8F%E5%AD%98%E5%82%A8%E7%BB%93%E6%9E%84/"/>
    <id>https://wzm996.github.io/2018/11/06/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%BA%8C%E7%BA%BF%E6%80%A7%E8%A1%A8%E5%92%8C%E7%BA%BF%E6%80%A7%E8%A1%A8%E7%9A%84%E9%A1%BA%E5%BA%8F%E5%AD%98%E5%82%A8%E7%BB%93%E6%9E%84/</id>
    <published>2018-11-06T13:55:24.000Z</published>
    <updated>2026-03-12T11:52:32.112Z</updated>
    
    <content type="html"><![CDATA[<hr><blockquote><p>数据结构分为物理结构和逻辑结构，逻辑结构分为线性结构、集合结构、树形结构和图形结构。线性表就属于线性结构，线性表是最基本、最简单、也是最常用的一种数据结构。</p></blockquote><span id="more"></span><h1 id="线性表"><a href="#线性表" class="headerlink" title="线性表"></a>线性表</h1><h2 id="线性表的性质"><a href="#线性表的性质" class="headerlink" title="线性表的性质"></a>线性表的性质</h2><p><strong>线性表</strong> 就是具有像线一样的性质的表。它是由<strong>零个</strong>或<strong>多个</strong>数据元素组成的<strong>有限序列</strong>。当线性表的长度为0时，称为空表。</p><pre><code>在稍复杂的线性表中，一个数据元素可由多个数据项组成，此种情况下常把数据元素称为记录，含有大量记录的线性表又称为文件。</code></pre><figure class="highlight plain"><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">graph LR</span><br><span class="line">数据元素1-.-数据元素2</span><br><span class="line">数据元素2-.-数据元素3</span><br><span class="line">数据元素3-.-...</span><br><span class="line">数据元素n-.-...</span><br></pre></td></tr></table></figure><p>线性表中数据元素之间的关系是<strong>一对一的关系</strong>，<br>数据元素1是线性表的第一个元素，只有一个<strong>直接后继</strong>。<br>数据元素n是线性表的最后一个元素，只有一个<strong>直接前驱</strong>。<br>除数据元素1和数据元素n的其他数据元素，既有直接前驱，也有直接后继，并且有且只有一个。</p><h2 id="线性表的特点"><a href="#线性表的特点" class="headerlink" title="线性表的特点"></a>线性表的特点</h2><ul><li>线性表存储的数据是同类型的</li><li>线性表中各数据元素之间的相对位置是固定的</li></ul><h2 id="线性表的分类"><a href="#线性表的分类" class="headerlink" title="线性表的分类"></a>线性表的分类</h2><blockquote><p>逻辑结构上相邻的数据在实际的物理存储中有两中形式：分散存储和集中存储。</p></blockquote><p>跟据这两种形式线性表可分为两种：</p><ul><li>数据元素在内存中集中存储，采用顺序存储结构，简称“顺序存储”，也称顺序表</li><li>数据元素在内存中分散存储，采用链式表示结构，简称“链式存储”，也称链表</li></ul><h1 id="线性表的顺序存储结构"><a href="#线性表的顺序存储结构" class="headerlink" title="线性表的顺序存储结构"></a>线性表的顺序存储结构</h1><p>线性表的顺序存储结构是用一段地址连续的存储单元依次存储线性表的数据元素。</p><table><thead><tr><th style="text-align:center">a1</th><th style="text-align:center">a2</th><th style="text-align:center">…</th><th style="text-align:center">ai-1</th><th style="text-align:center">ai</th><th style="text-align:center">ai+1</th><th style="text-align:center">…</th><th style="text-align:center">an</th></tr></thead><tbody><tr><td style="text-align:center"></td></tr></tbody></table><p>顺序表一般使用数组实现，事实上就是在内存中找个初始地址，然后通过占位的形式，把一定连续的内存空间给占了，然后把相同数据类型的数据元素依次放在这块空地中，数组大小有两种方式指定，一是静态分配，二是动态扩展。</p><pre><code>注：数组的长度是存放线性表的存储空间的长度，存储分配后这个量一般是不变得。线性表的长度是线性表中数据元素的个数，随着线性表的插入和删除操作的进行，这个量是变化的。线性表的长度应该小于等于数组的长度。</code></pre><h2 id="顺序表的顺序存储表示"><a href="#顺序表的顺序存储表示" class="headerlink" title="顺序表的顺序存储表示"></a>顺序表的顺序存储表示</h2><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="comment">//----- 顺序表的顺序存储表示 -----</span></span><br><span class="line"><span class="keyword">typedef</span>  <span class="keyword">int</span>  ElemType;</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="keyword">int</span> length; <span class="comment">// 表长</span></span><br><span class="line">    <span class="keyword">int</span> size;<span class="comment">// 存储容量</span></span><br><span class="line"><span class="keyword">int</span> increment; <span class="comment">// 扩容时，增加的存储容量</span></span><br><span class="line">&#125; SqList;  <span class="comment">//顺序表</span></span><br></pre></td></tr></table></figure><p>使用顺序存储结构需要四个属性：</p><ul><li>存储空间的起始位置：指针elem,它存储的位置就是存储空间的存储位置</li><li>顺序存储表的最大存储容量：size</li><li>顺序存储表的当前长度：length</li><li>顺序存储表扩容时增加的容量：increment </li></ul><h2 id="顺序表的创建"><a href="#顺序表的创建" class="headerlink" title="顺序表的创建"></a>顺序表的创建</h2><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="function">Status <span class="title">InitSqlist</span><span class="params">(SqList &amp;L)</span></span>&#123;</span><br><span class="line">L.elem = (ElemType *)<span class="built_in">malloc</span>(LIST_INIT_SIZE * <span class="keyword">sizeof</span>(ElemType));</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.size = LIST_INIT_SIZE;             <span class="comment">// 初始存储容量</span></span><br><span class="line">L.increment = LISTINCREMENT;</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> void <em>malloc(unsigned int num_bytes)：动态内存分配，用于申请一块连续的指定大小的内存块区域，void </em>       表示未确定类型的指针，void *      可以指向任何类型的数据，更明确的说是指申请内存空间时还不知道用这段空间来存储什么类型的数据。如果分配内存成功则函数返回被分配内存的指针，否则返回空指针NULL。当内存不再使用时，应使用free()函数将内存块释放。</p></blockquote><p>顺序表的的初始化操作就是为了顺序表分配一个预定义大小的数组空间，并将线性表的当前长度设为“0”。</p><h2 id="顺序表的插入"><a href="#顺序表的插入" class="headerlink" title="顺序表的插入"></a>顺序表的插入</h2><p>插入算法的思路：</p><ul><li>如果插入位置不合理，抛出异常</li><li>如果线性表长度大于等于数组长度，则抛出异常或动态增加容量</li><li>从最后一个元素开始向前遍历到第i个位置，分别将它们都向后移动一个位置</li><li>将要插入元素填入位置i处</li><li>表的长度</li></ul><p>示例</p><p>当前有一个长度为7的顺序表</p><table><thead><tr><th style="text-align:center">1</th><th style="text-align:center">2</th><th style="text-align:center">3</th><th style="text-align:center">4</th><th style="text-align:center">5</th><th style="text-align:center">6</th><th style="text-align:center">7</th><th style="text-align:center">空闲</th></tr></thead><tbody><tr><td style="text-align:center"></td></tr></tbody></table><p>在顺序表第三的位置上插入一个元素“8”，因此当前顺序表的第三个元素及其以后的所有元素要向后移动一位，从顺序表的表尾开始</p><figure class="highlight plain"><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">graph LR</span><br><span class="line">8</span><br></pre></td></tr></table></figure><table><thead><tr><th style="text-align:center">1</th><th style="text-align:center">2</th><th style="text-align:center"></th><th style="text-align:center">3</th><th style="text-align:center">4</th><th style="text-align:center">5</th><th style="text-align:center">6</th><th style="text-align:center">7</th></tr></thead><tbody><tr><td style="text-align:center"></td></tr></tbody></table><p>当移动完成后，元素“8”插入顺序表的第三个位置上。顺序表的长度增加1。</p><table><thead><tr><th style="text-align:center">1</th><th style="text-align:center">2</th><th style="text-align:center">8</th><th style="text-align:center">3</th><th style="text-align:center">4</th><th style="text-align:center">5</th><th style="text-align:center">6</th><th style="text-align:center">7</th></tr></thead><tbody><tr><td style="text-align:center"></td></tr></tbody></table><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"><span class="comment">//顺序表插入函数</span></span><br><span class="line"><span class="function">Status <span class="title">ListInsert_Sq</span><span class="params">(SqList &amp;L, <span class="keyword">int</span> i ,ElemType e)</span></span>&#123;</span><br><span class="line"><span class="keyword">int</span> j;  </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>) &#123;      <span class="comment">//对i的合法性判断</span></span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"\n插入位置不合法！，i值必须大于等于1，小于等于%d\n"</span>,L.length+<span class="number">1</span>);</span><br><span class="line"><span class="keyword">return</span> ERROR;</span><br><span class="line">&#125;      </span><br><span class="line">   </span><br><span class="line">   <span class="keyword">if</span>(L.length&gt;=L.size) &#123;        <span class="comment">//对顺序表是否满判断 </span></span><br><span class="line">       <span class="comment">//当前存储空间已满，增加分配</span></span><br><span class="line">      L.elem = (ElemType *)<span class="built_in">realloc</span>(L.elem, (L.size + LISTINCREMENT)*<span class="keyword">sizeof</span>(ElemType));</span><br><span class="line"><span class="keyword">if</span>(<span class="literal">NULL</span> == L.elem)       <span class="comment">//分配内存失败，退出程序</span></span><br><span class="line">    <span class="keyword">return</span>  OVERFLOW;</span><br><span class="line">L.size += LISTINCREMENT;     <span class="comment">//增加存储容量</span></span><br><span class="line">   &#125;</span><br><span class="line">  </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--)&#123;</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">   &#125; </span><br><span class="line">   </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><blockquote><p>void <em>realloc(void </em>ptr, size_t new_Size ) 用于对动态内存进行扩容（及已申请的动态空间不够使用，需要进行空间扩容操作），ptr为指向原来空间基址的指针，new_size为接下来需要扩充容量的大小。</p></blockquote><p>执行realloc函数的几种情况</p><ul><li>如果当前内存段后面有需要的内存空间，则直接扩展这段内存空间，realloc()将返回指向原地址的指针。</li><li>如果当前内存段后面的空闲字节不够，那么就是用堆中的第一个能够满足这一要求的内存块，将目前的数据复制到新的位置，并将原来的数据块释放掉，返回新的内存块位置。</li><li>如果申请失败，将返回NULL，此时，原来的指针仍然有效。</li></ul><pre><code>注：如果调用成功，不管当前内存段后面的空闲空间是否满足要求，都会释放掉原来的指针</code></pre><p>顺序表插入操作的时间复杂度为<strong>O(n)</strong>。</p><h2 id="顺序表的按位获取元素"><a href="#顺序表的按位获取元素" class="headerlink" title="顺序表的按位获取元素"></a>顺序表的按位获取元素</h2><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="function">ElemType <span class="title">ListQuery_Sq</span><span class="params">(SqList L,<span class="keyword">int</span> i)</span></span>&#123;</span><br><span class="line">ElemType e;</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>) &#123;    <span class="comment">//对i的合法性判断</span></span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"\n查询位置不合法！，i值必须大于等于1，小于等于%d\n"</span>,L.length+<span class="number">1</span>);</span><br><span class="line"><span class="keyword">return</span> ERROR;</span><br><span class="line">&#125;      </span><br><span class="line"><span class="keyword">if</span> (L.length!=<span class="number">0</span>) &#123;  <span class="comment">//判断顺序表是否为空表</span></span><br><span class="line">e=L.elem[i<span class="number">-1</span>];</span><br><span class="line"><span class="keyword">return</span> e;</span><br><span class="line">&#125;<span class="keyword">else</span> &#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"\n这是个空表\n"</span>);</span><br><span class="line"><span class="keyword">return</span> ERROR;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>顺序表本质是一个数组，利用数组的下标，可以获取到顺序表的元素。数组下标从0开始，顺序表位置从1开始，所以在获取顺序表中的元素，需要（i-1）才是数组的下标。</p><p>顺序表按位查找操作的时间复杂度为<strong>O(1)</strong>。</p><h2 id="顺序表的删除"><a href="#顺序表的删除" class="headerlink" title="顺序表的删除"></a>顺序表的删除</h2><p>删除算法的思路：</p><ul><li>如果删除位置不合理，抛出异常</li><li>取出删除元素</li><li>从删除元素位置开始遍历到最后一个元素位置，分别将它们都向前移动一个位置</li><li>表的长度减少1</li></ul><p>示例</p><table><thead><tr><th style="text-align:center">1</th><th style="text-align:center">2</th><th style="text-align:center">8</th><th style="text-align:center">3</th><th style="text-align:center">4</th><th style="text-align:center">5</th><th style="text-align:center">6</th><th style="text-align:center">7</th></tr></thead><tbody><tr><td style="text-align:center"></td></tr></tbody></table><p>当前是一个长度为8的顺序表，我们要删除第三个位置上的元素。我们只需要将第四个位置上的元素覆盖掉第三个位置上的元素，第五个位置上的元素覆盖掉第四个位置上的元素，依此类推，直到执行至表尾。</p><table><thead><tr><th style="text-align:center">1</th><th style="text-align:center">2</th><th style="text-align:center">3</th><th style="text-align:center">4</th><th style="text-align:center">5</th><th style="text-align:center">6</th><th style="text-align:center">7</th><th style="text-align:center">空闲</th></tr></thead><tbody><tr><td style="text-align:center"></td></tr></tbody></table><p>执行完删除操作后，顺序表的长度减1.</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></pre></td><td class="code"><pre><span class="line"><span class="comment">//顺序表删除元素函数</span></span><br><span class="line"><span class="function">Status <span class="title">ListDelete_Sq</span><span class="params">(SqList &amp;L, <span class="keyword">int</span> i, ElemType  &amp;e)</span></span>&#123;</span><br><span class="line">   <span class="comment">//请在此填写代码，将该算法补充完整</span></span><br><span class="line">   <span class="keyword">int</span> j;</span><br><span class="line">   <span class="keyword">if</span>((i&lt;<span class="number">1</span>)||(i&gt;L.length)) &#123;</span><br><span class="line">   <span class="built_in">printf</span>(<span class="string">"\n删除位置不合法！，i值必须大于等于1，小于等于%d\n"</span>,L.length);</span><br><span class="line">   <span class="keyword">return</span> ERROR; <span class="comment">//i值不合法</span></span><br><span class="line">   &#125;</span><br><span class="line">   e = L.elem [ i <span class="number">-1</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><p>一般情况下，删除第i个元素时需要将从第i+1至第n个元素依次向前移动一个位置。</p><p>顺序表删除操作的时间复杂度为<strong>O(n)</strong>。</p><h2 id="线性表顺序存储结构的优缺点"><a href="#线性表顺序存储结构的优缺点" class="headerlink" title="线性表顺序存储结构的优缺点"></a>线性表顺序存储结构的优缺点</h2><p>优点：</p><ul><li>无须为表示表中元素之间的逻辑关系而增加额外的存储空间</li><li>可以快速的存取表中任一位置的元素</li></ul><p>缺点</p><ul><li>插入和删除操作需要移动大量元素</li><li>当线性表长度变化较大时，难以确定存储空间容量</li><li>造成存储空间的“碎片”</li></ul>]]></content>
    
    
    <summary type="html">&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;数据结构分为物理结构和逻辑结构，逻辑结构分为线性结构、集合结构、树形结构和图形结构。线性表就属于线性结构，线性表是最基本、最简单、也是最常用的一种数据结构。&lt;/p&gt;
&lt;/blockquote&gt;</summary>
    
    
    
    <category term="数据结构与算法" scheme="https://wzm996.github.io/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/"/>
    
    
    <category term="数据结构" scheme="https://wzm996.github.io/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
    
    <category term="线性表" scheme="https://wzm996.github.io/tags/%E7%BA%BF%E6%80%A7%E8%A1%A8/"/>
    
  </entry>
  
  <entry>
    <title>初识代理服务器和常用的代理技术</title>
    <link href="https://wzm996.github.io/2018/10/22/%E5%88%9D%E8%AF%86%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%92%8C%E5%B8%B8%E7%94%A8%E7%9A%84%E4%BB%A3%E7%90%86%E6%8A%80%E6%9C%AF/"/>
    <id>https://wzm996.github.io/2018/10/22/%E5%88%9D%E8%AF%86%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%92%8C%E5%B8%B8%E7%94%A8%E7%9A%84%E4%BB%A3%E7%90%86%E6%8A%80%E6%9C%AF/</id>
    <published>2018-10-22T13:41:06.000Z</published>
    <updated>2026-03-12T11:52:32.112Z</updated>
    
    <content type="html"><![CDATA[<hr><blockquote><p>服务器，也称伺服器。指一个管理资源并为用户提供服务的计算机设备。根据服务器提供的服务类型不同，可分为文件服务器，数据库服务器，应用程序服务器，WEB服务器等。</p></blockquote><span id="more"></span><h1 id="代理服务器"><a href="#代理服务器" class="headerlink" title="代理服务器"></a>代理服务器</h1><p><strong>代理服务器</strong> 是介于浏览器和Web服务器之间的一台服务器，它的功能是代理网络用户取得网络信息。可以形象的称为网络信息的中转站。</p><h2 id="完整的代理请求过程"><a href="#完整的代理请求过程" class="headerlink" title="完整的代理请求过程"></a>完整的代理请求过程</h2><p>客户端首先与代理服务器创建连接，接着根据代理服务器所使用的代理协议，请求对目标服务器创建连接、或者获得目标服务器的指定资源。</p><p>代理服务器可能对目标服务器的资源下载至本地缓存，如果客户端所要获取的资源在代理服务器的缓存之中，则代理服务器不会向目标服务器发送请求，而是直接返回缓存了得资源。</p><figure class="highlight plain"><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">sequenceDiagram</span><br><span class="line">    客户端-&gt;&gt;代理服务器: 发送请求</span><br><span class="line">    代理服务器--&gt;&gt;服务器: 转发请求</span><br><span class="line">    服务器--&gt;&gt;代理服务器: 返回结果，代理服务器下载资源</span><br><span class="line">    代理服务器-&gt;&gt;客户端: 返回结果</span><br></pre></td></tr></table></figure><pre><code>注：实线是表示客户端与代理服务器端同属一个内网中。</code></pre><h2 id="代理服务器的主要功能"><a href="#代理服务器的主要功能" class="headerlink" title="代理服务器的主要功能"></a>代理服务器的主要功能</h2><pre><code>1.突破自身IP访问限制，访问国外站点。2.访问一些单位或团体内部资源，如某大学FTP（前提是该代理地址在资源的允许访问范围之内），使用教育网内地址段免费代理服务器，就可以用教育网开放的各类FTP下载上传，以及各类资料查询共享等服务。3.提高访问速度：通常代理服务器都设置一个较大的硬盘缓冲区，当有外界的信息通过时，同时也将其保存到缓冲区中，当其他用户再访问相同的信息时，则直接由缓冲区中取出信息，传给用户，以提高访问速度。4.隐藏真实IP：上网者也可以通过这种方法隐藏自己的IP，免受攻击。代理服务器还可以改变客户端的原始请求、目标服务器的原始响应。5.防火墙作用：由于所有的客户机请求都是必须通过代理服务器访问远程站点，因此可以在代理服务器上设限，过滤某些不安全信息。</code></pre><h1 id="常用的代理技术"><a href="#常用的代理技术" class="headerlink" title="常用的代理技术"></a>常用的代理技术</h1><blockquote><p>实现代理技术，常用的方法有：<strong>正向代理</strong>、<strong>反向代理</strong>和<strong>透明代理</strong>三种。</p></blockquote><h2 id="正向代理"><a href="#正向代理" class="headerlink" title="正向代理"></a>正向代理</h2><p><strong>正向代理</strong>的技术实现方式就是<strong>代理服务器</strong>，又叫做<strong>转发代理服务器</strong>。</p><p>正向代理是一个位于客户端和原始服务器(origin server)之间的服务器，为了从原始服务器取得内容，客户端向代理发送一个请求并指定目标(原始服务器)，然后代理向原始服务器转交请求并将获得的内容返回给客户端。</p><pre><code>注：客户端必须设置正向代理服务器，当然前提是要知道正向代理服务器的IP地址，还有代理程序的端口。</code></pre><h3 id="代理服务器软件————CCProxy的应用场景"><a href="#代理服务器软件————CCProxy的应用场景" class="headerlink" title="代理服务器软件————CCProxy的应用场景"></a>代理服务器软件————CCProxy的应用场景</h3><p>CCProxy的功能介绍</p><p> 1.代理共享上网。只要局域网内有一台机器能够上网，其他机器就可以通过这台机器上安装的CCProxy来代理共享上网，最大程度的减少了硬件费用和上网费用。<br> 2.客户端代理权限管理。只需要在服务器上CCProxy代理服务器软件里进行账号设置，就可以方便的管理客户端代理上网的权限。提高了员工工作效率和企业信息安全管理。</p><h2 id="反向代理"><a href="#反向代理" class="headerlink" title="反向代理"></a>反向代理</h2><p><strong>反向代理</strong>与正向代理正好相反，对于客户端而言它就像是原始服务器，并且客户端不需要进行任何特别的设置。客户端向反向代理服务器发送请求，反向代理服务器会判断向内网中的某个原始服务器转交请求，并将获得的内容返回给客户端。</p><figure class="highlight plain"><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">sequenceDiagram</span><br><span class="line">    客户端--&gt;&gt;代理服务器: 发送请求</span><br><span class="line">    代理服务器-&gt;&gt;服务器集群: 判断转交给内网中的那个服务器</span><br><span class="line">    服务器集群-&gt;&gt;代理服务器: 返回结果</span><br><span class="line">    代理服务器--&gt;&gt;客户端: 返回结果</span><br></pre></td></tr></table></figure><pre><code>注：实线是表示服务器与代理服务器端同属一个内网中。</code></pre><h3 id="反向代理的功能"><a href="#反向代理的功能" class="headerlink" title="反向代理的功能"></a>反向代理的功能</h3><p> 1、保证内网的安全，可以使用反向代理提供WAF功能，阻止web攻击。大型网站，通常将反向代理作为公网访问地址，Web服务器是内网。<br> 2、负载均衡，通过反向代理服务器来优化网站的负载。<br> 3、缓存，减少服务器的压力。</p><h3 id="反向代理软件——Nginx"><a href="#反向代理软件——Nginx" class="headerlink" title="反向代理软件——Nginx"></a>反向代理软件——Nginx</h3><p><strong>Nginx</strong>是一款轻量级的Web服务器（高性能的HTTP）/反向代理服务器及电子邮件（IMAP/POP3）代理服务器，并在一个BSD-like协议下发行。其特点是占有内存少，并发能力强，事实上nginx的并发能力确实在同类型的网页服务器中表现较好，中国使用Nginx网站用户有：百度、京东、新浪、网易、腾讯、淘宝等。</p><h3 id="正向代理和反向代理的区别"><a href="#正向代理和反向代理的区别" class="headerlink" title="正向代理和反向代理的区别"></a>正向代理和反向代理的区别</h3><p> 1、位置不同<br>    正向代理，架设在客户机和目标主机之间;<br>    反向代理，架设在服务器端;<br> 2、代理对象不同<br>    正向代理，代理客户端，服务器端不知道实际发起请求的客户端;<br>    反向代理，代理服务端，客户端不知道实际提供服务的服务器端;<br> 3、用途不同<br>    正向代理，为在防火墙的局域网客户端提供访问Internet的途径;<br>    反向代理，将防火墙后面的服务器提供给Internet访问;<br> 4、安全性不同<br>    正向代理允许客户端通过他访问任意网站并且隐藏客户端自身，因此必须采取安全措施以确保仅为授权的客户端提供服务;</p><h2 id="透明代理"><a href="#透明代理" class="headerlink" title="透明代理"></a>透明代理</h2><p><strong>透明代理</strong>是客户端不需要知道有代理服务器的存在，代理服务器会改编客户端请求，但会传送真实的IP。加密的透明代理是属于匿名代理，透明代理与正向代理的请求过程是一样的，唯一不同的是客户端不用再设置使用代理了。</p><h3 id="透明代理的应用————行为管理软件"><a href="#透明代理的应用————行为管理软件" class="headerlink" title="透明代理的应用————行为管理软件"></a>透明代理的应用————行为管理软件</h3><p>行为管理软件就是管理上网行为的软件。帮助管理者全面了解使用者上网情况和网络使用情况。可以最大限度地避免不当的上网行为带来的潜在风险和损失。</p><h2 id="Tomcat与Nginx-apache的区别是什么？"><a href="#Tomcat与Nginx-apache的区别是什么？" class="headerlink" title="Tomcat与Nginx,apache的区别是什么？"></a>Tomcat与Nginx,apache的区别是什么？</h2><p>HTTP服务器本质上也是一种应用程序————它通常运行在服务器之上，绑定服务器的IP地址并监听某一个TCP端口来接收并处理HTTP请求，这样客户端（一般来说是IE,Firefox,Chrome这样的浏览器）就能通过HTTP协议来获取服务器上的网页（HTML格式）、文档（PDF格式）、音频(MP4格式)、视频(MOV格式)等资源。</p><p>Tomcat与Apache HTTP Server相比，Tomcat能够动态的生成资源并返回到客户端。Apache HTTP Server和Nginx都能够将某一个文本文件的内容通过HTTP协议返回到客户端,但是这个文本文件的内容是固定的。这个文本文件的内容是固定的————也就是说无论何时、任何人访问它得到的内容都是完全相同的，这样的资源我们称之为静态资源。<br>Apsche HTTP Server和Nginx本身不支持生成动态页面，但它们可通过其他模块来支持（例如通过Shell、PHP、Python脚本程序来动态生成内容）。<br>如果想要使用java程序来动态生成资源内容，Java Servlet技术以及衍生的Java Server Pages技术可以让Java程序也具有处理HTTP请求并且返回内容（由程序动态控制）的能力，Tomcat正是支持运行Servlet/JSP应用程序的容器（Container）:Tomcat运行在JVM之上，它和HTTP服务器一样，绑定IP地址并监听TCP端口。<br>虽然Tomcat也可以认为是HTTP服务器，但通常它仍然会和Nginx配合在一起使用:</p><ul><li>动静态资源分离————运用Nginx的反向代理功能分发请求：所有动态资源的请求交给Tomcat,而静态资源的请求（例如图片、视频、CSS、JavaScript文件等）则直接由Nginx返回到浏览器，这样能大大减轻Tomcat的压力。</li><li>负载均衡，当业务压力增大时，可能一个Tomcat的实例不足以处理，那么这时可以启动多个Tomcat实例进行水平扩展，而Nginx的负载均衡功能可以把请求通过算法分发到各个不同的实例进行处理。</li></ul>]]></content>
    
    
    <summary type="html">&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;服务器，也称伺服器。指一个管理资源并为用户提供服务的计算机设备。根据服务器提供的服务类型不同，可分为文件服务器，数据库服务器，应用程序服务器，WEB服务器等。&lt;/p&gt;
&lt;/blockquote&gt;</summary>
    
    
    
    <category term="计算机网络" scheme="https://wzm996.github.io/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/"/>
    
    
    <category term="代理" scheme="https://wzm996.github.io/tags/%E4%BB%A3%E7%90%86/"/>
    
    <category term="网络" scheme="https://wzm996.github.io/tags/%E7%BD%91%E7%BB%9C/"/>
    
    <category term="服务器" scheme="https://wzm996.github.io/tags/%E6%9C%8D%E5%8A%A1%E5%99%A8/"/>
    
  </entry>
  
  <entry>
    <title>数据结构（一）——算法的时间和空间复杂度</title>
    <link href="https://wzm996.github.io/2018/10/08/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%80%E7%AE%97%E6%B3%95%E7%9A%84%E6%97%B6%E9%97%B4%E5%92%8C%E7%A9%BA%E9%97%B4%E5%A4%8D%E6%9D%82%E5%BA%A6/"/>
    <id>https://wzm996.github.io/2018/10/08/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%80%E7%AE%97%E6%B3%95%E7%9A%84%E6%97%B6%E9%97%B4%E5%92%8C%E7%A9%BA%E9%97%B4%E5%A4%8D%E6%9D%82%E5%BA%A6/</id>
    <published>2018-10-08T09:09:59.000Z</published>
    <updated>2026-03-12T11:52:32.112Z</updated>
    
    <content type="html"><![CDATA[<hr><blockquote><p><strong>算法</strong> 的优劣主要体现在算法的复杂性上。<br><strong>算法复杂度</strong> 是运行该算法时所占用计算机资源的多少。<br><strong>计算机资源</strong> 主要分为时间和空间资源。</p></blockquote><span id="more"></span><h1 id="时间复杂度"><a href="#时间复杂度" class="headerlink" title="时间复杂度"></a>时间复杂度</h1><p><strong>时间频度</strong> 是计算一个程序语句执行的次数，通常情况下时间频度计算的是具体的数值。记作T(n)。</p><p><strong>时间复杂度</strong> 是算法运行时所占用的时间资源，用来度量算法的运行时间，算法占用的时间短算法效率就高，反之占用的时间长算法的效率就低。时间复杂度记作O(f(n))。</p><p>时间复杂度与时间频度的关系：T(n)=O(f(n))</p><pre><code>注：时间复杂度不是计算程序的运行时间，时间复杂度实际上就是一个函数，该函数计算的是执行基本操作的次数，与时间频度不同的是它计算的不是具体的数值。</code></pre><h2 id="时间复杂度的计算方法"><a href="#时间复杂度的计算方法" class="headerlink" title="时间复杂度的计算方法"></a>时间复杂度的计算方法</h2><blockquote><p>1、若是程序执行次数常数，都是常数阶用O(1)表示。<br>2、若程序执行次数为不固定项，选取相对执行次数最多的项，也就是最高项。<br>3、若选取的最高项系数不为1，则最高项系数化为1。</p></blockquote><pre><code>注：1、如果算法的执行时间不随着问题规模n的增加而增长，即使算法中有上千条语句，其执行时间也不过是一个较大的常数。此类算法的时间复杂度是O(1)。    2、当有若干个循环语句时，算法的时间复杂度是由嵌套层数最多的循环语句中最内层语句的频度f(n)决定的。</code></pre><p><strong>示例</strong><br><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">for</span> (i=<span class="number">1</span>; i&lt;=n; i++)</span><br><span class="line">　　       x++;               <span class="comment">//执行n次</span></span><br><span class="line">　<span class="keyword">for</span> (i=<span class="number">1</span>; i&lt;=n; i++)</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">　　          x++;            <span class="comment">//执行n^2次</span></span><br></pre></td></tr></table></figure></p><p>此段代码的执行次数为n+n^2次，根据时间复杂度的计算方法，选出最高项你n^2，因此时间复杂度为O(n^2)。</p><h2 id="常见的时间复杂度"><a href="#常见的时间复杂度" class="headerlink" title="常见的时间复杂度"></a>常见的时间复杂度</h2><table><thead><tr><th style="text-align:center">术语</th><th style="text-align:center">阶</th><th style="text-align:center">举例</th></tr></thead><tbody><tr><td style="text-align:center">常数阶</td><td style="text-align:center">O(1)</td><td style="text-align:center">输出一句话 </td></tr><tr><td style="text-align:center">对数阶</td><td style="text-align:center">O(log2n)</td><td style="text-align:center">对有序数组进行折半查找      </td></tr><tr><td style="text-align:center">线性阶</td><td style="text-align:center">O(n)</td><td style="text-align:center">对数组进行顺序查找</td></tr><tr><td style="text-align:center">线性对数阶</td><td style="text-align:center">O(nlog2n)</td><td style="text-align:center">归并排序</td></tr><tr><td style="text-align:center">平方阶</td><td style="text-align:center">O(n^2)</td><td style="text-align:center">选择排序</td></tr><tr><td style="text-align:center">立方阶</td><td style="text-align:center">O(n^3)</td><td style="text-align:center">传统的矩阵相乘</td></tr><tr><td style="text-align:center">k次方阶</td><td style="text-align:center">O(n^k)</td></tr><tr><td style="text-align:center">指数阶</td><td style="text-align:center">O(2^n)</td><td style="text-align:center">汉诺塔</td></tr></tbody></table><p>随着问题规模n的不断增大，上述时间复杂度不断增大，算法的执行效率越低。<br>常见的算法时间复杂度由小到大依次为：<br>Ο(1)＜Ο(log2n)＜Ο(n)＜Ο(nlog2n)＜Ο(n2)＜Ο(n3)＜…＜Ο(2^n)＜Ο(n!)</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="function"><span class="keyword">int</span> <span class="title">test</span><span class="params">(<span class="keyword">void</span>)</span> </span>&#123;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"Hello, World!\n"</span>);      <span class="comment">//  需要执行 1 次</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;       <span class="comment">// 需要执行 1 次</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>上面这段代码一共需执行语句2次，是常数，因此是常数阶O(1)。</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="function"><span class="keyword">int</span> <span class="title">test</span><span class="params">(<span class="keyword">void</span>)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> x=<span class="number">1</span>;      </span><br><span class="line">    <span class="keyword">while</span> (x &lt;<span class="number">10</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        x++;      <span class="comment">//需要循环执行10次</span></span><br><span class="line">    &#125;</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><p>上面这段代码一共需执行语句10次，也是常数，因此也是常数阶O(1)。</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">int</span> i = <span class="number">1</span>, n = <span class="number">100</span>;</span><br><span class="line"><span class="keyword">while</span>(i &lt; n)&#123;</span><br><span class="line">    i = i * <span class="number">2</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>求这段代码的时间复杂度,首先设执行次数为x, 2^x=n 即 x=log2n，因此是对数阶O(log2n)</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"><span class="function"><span class="keyword">int</span> <span class="title">test</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i&lt;n; i++) &#123;         <span class="comment">// 需要执行 (n + 1) 次</span></span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">"Hello, World!\n"</span>);      <span class="comment">// 需要执行 n 次</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">// 需要执行 1 次</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这段代码执行了(n+1+n+1)=2n+2次,运用计算方法去掉常数，化系数为1得到n，因此是线性阶O(n)。</p><h3 id="线性对数阶"><a href="#线性对数阶" class="headerlink" title="线性对数阶"></a>线性对数阶</h3><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">int</span> sum=<span class="number">0</span>；                 </span><br><span class="line">  <span class="keyword">for</span>(i=<span class="number">1</span>;i&lt;=n;i++)        <span class="comment">//需要执行n次</span></span><br><span class="line">     <span class="keyword">for</span>(j=<span class="number">1</span>;j&lt;=n;j++)   <span class="comment">//需要执行n^2次</span></span><br><span class="line">       sum++；</span><br></pre></td></tr></table></figure><p>这段代码执行了n^2+n，运用计算方法去选取最高项，得到n^2，因此是平方阶O(n^2)。</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(i=<span class="number">0</span>;i&lt;n;i++)</span><br><span class="line">    &#123;  </span><br><span class="line">       <span class="keyword">for</span>(j=<span class="number">0</span>;j&lt;i;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;j;k++)</span><br><span class="line">             x=x+<span class="number">2</span>;  </span><br><span class="line">       &#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>这段代码执行了0+(1-1)*1/2+···+(n-1)n/2=n(n+1)(n-1)/6，运用计算方法去选取最高项，得到n^3，因此是平方阶O(n^3)。</p><h3 id="指数阶"><a href="#指数阶" class="headerlink" title="指数阶"></a>指数阶</h3><h2 id="时间复杂度的最坏情况与平均情况"><a href="#时间复杂度的最坏情况与平均情况" class="headerlink" title="时间复杂度的最坏情况与平均情况"></a>时间复杂度的最坏情况与平均情况</h2><p>对于算法分析，一种是计算所有情况的平均值，这种时间复杂度的计算方法称为平均时间复杂度，它是最有意义的，因为是期望的运行时间。另一种是计算最坏情况下的时间复杂度，这种方法称为最坏时间复杂度。在一般情况下都是计算最坏时间复杂度。</p><h1 id="空间复杂度"><a href="#空间复杂度" class="headerlink" title="空间复杂度"></a>空间复杂度</h1><p><strong>空间复杂度</strong> 是算法在运行时所占用的空间资源，程序在运行时产生临时变量需要占用存储空间，占用存储空间资源少算法效率高，占用存储空间资源多算法效率低。利用算法的空间复杂度，可以对算法的运行所需要的内存空间有个预先估计。</p><pre><code>注：空间复杂度强调的是使用的辅助空间的大小，而不是指所有的数据所占用的空间大小。</code></pre><h2 id="空间复杂度的计算方法"><a href="#空间复杂度的计算方法" class="headerlink" title="空间复杂度的计算方法"></a>空间复杂度的计算方法</h2><blockquote><p>1、若创建的变量为常数，则用O(1)表示。<br>2、若是递归算法，则空间复杂度=递归调用次数N*每次递归所要的辅助空间。</p></blockquote><p><strong>示例</strong><br><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">int</span> a,b,c;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%d %d %d\n"</span>,a,b,c);</span><br></pre></td></tr></table></figure></p><p>这段代码的存储3个变量，为常数，因此是O(1)。</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="function"><span class="keyword">int</span> <span class="title">fun</span><span class="params">(<span class="keyword">int</span> n)</span></span>&#123;</span><br><span class="line"><span class="keyword">int</span> k=<span class="number">10</span>;</span><br><span class="line"><span class="keyword">if</span>(n==k)</span><br><span class="line"><span class="keyword">return</span> n;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line"><span class="keyword">return</span> fun(++n);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这段代码是递归算法，每次递归调用时都会创建1个变量，调用n次，空间复杂度O(n*1)=O(n)。</p><h1 id="常用排序算法的时间复杂度和空间复杂度"><a href="#常用排序算法的时间复杂度和空间复杂度" class="headerlink" title="常用排序算法的时间复杂度和空间复杂度"></a>常用排序算法的时间复杂度和空间复杂度</h1><table><thead><tr><th style="text-align:center">排序方法</th><th style="text-align:center">平均时间复杂度</th><th style="text-align:center">最坏时间复杂度</th><th style="text-align:center">空间复杂度</th><th style="text-align:center">稳定性</th></tr></thead><tbody><tr><td style="text-align:center">冒泡排序</td><td style="text-align:center">O(n^2)</td><td style="text-align:center">O(n^2)</td><td style="text-align:center">O(1)</td><td style="text-align:center">是</td></tr><tr><td style="text-align:center">选择排序</td><td style="text-align:center">O(n^2)</td><td style="text-align:center">O(n^2)</td><td style="text-align:center">O(1)</td><td style="text-align:center">不是    </td></tr><tr><td style="text-align:center">直接插入排序</td><td style="text-align:center">O(n^2)</td><td style="text-align:center">O(n^2)</td><td style="text-align:center">O(1)</td><td style="text-align:center">是</td></tr><tr><td style="text-align:center">归并排序</td><td style="text-align:center">O(nlogn)</td><td style="text-align:center">O(nlogn)</td><td style="text-align:center">O(n)</td><td style="text-align:center">是</td></tr><tr><td style="text-align:center">快速排序</td><td style="text-align:center">O(nlogn)</td><td style="text-align:center">O(n^2)</td><td style="text-align:center">O(logn)</td><td style="text-align:center">不是</td></tr><tr><td style="text-align:center">堆排序</td><td style="text-align:center">O(nlongn)</td><td style="text-align:center">O(nlogn)</td><td style="text-align:center">O(1)</td><td style="text-align:center">不是</td></tr><tr><td style="text-align:center">希尔排序</td><td style="text-align:center">O(nlongn)</td><td style="text-align:center">O(n^s)</td><td style="text-align:center">O(1)</td><td style="text-align:center">不是</td></tr><tr><td style="text-align:center">计数排序</td><td style="text-align:center">O(n+k)</td><td style="text-align:center">O(n+k)</td><td style="text-align:center">O(n+k)</td><td style="text-align:center">是</td></tr><tr><td style="text-align:center">基数排序</td><td style="text-align:center">O(N*M)</td><td style="text-align:center">O(N*M)</td><td style="text-align:center">O(M)</td><td style="text-align:center">是</td></tr></tbody></table>]]></content>
    
    
    <summary type="html">&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;算法&lt;/strong&gt; 的优劣主要体现在算法的复杂性上。&lt;br&gt;&lt;strong&gt;算法复杂度&lt;/strong&gt; 是运行该算法时所占用计算机资源的多少。&lt;br&gt;&lt;strong&gt;计算机资源&lt;/strong&gt; 主要分为时间和空间资源。&lt;/p&gt;
&lt;/blockquote&gt;</summary>
    
    
    
    <category term="数据结构与算法" scheme="https://wzm996.github.io/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/"/>
    
    
    <category term="数据结构" scheme="https://wzm996.github.io/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
    
    <category term="算法" scheme="https://wzm996.github.io/tags/%E7%AE%97%E6%B3%95/"/>
    
    <category term="复杂度" scheme="https://wzm996.github.io/tags/%E5%A4%8D%E6%9D%82%E5%BA%A6/"/>
    
  </entry>
  
</feed>
