-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
46 lines (21 loc) · 173 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>数据结构</title>
<link href="/2023/01/13/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
<url>/2023/01/13/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/</url>
<content type="html"><![CDATA[<h2 id="一、基本概念引入"><a href="#一、基本概念引入" class="headerlink" title="一、基本概念引入"></a>一、基本概念引入</h2><h3 id="存储结构-x2F-物理结构"><a href="#存储结构-x2F-物理结构" class="headerlink" title="存储结构/物理结构"></a>存储结构/物理结构</h3><p>数据元素与数据元素间有两种结构:逻辑结构,存储结构/物理结构</p><img src="https://picbed.koko2pp.cc/f92ec4a8ca52cafb9f5ca5fb9560671.png" alt="f92ec4a8ca52cafb9f5ca5fb9560671" style="zoom:67%;" /><p><strong>逻辑结构</strong>分类:</p><ul><li><p><strong>线性结构</strong>(线性表、栈、队列、串,有且仅有一个前趋和后继);<strong>非线性结构</strong>(树、图,有多个前趋和后继)</p></li><li><p>四类基本逻辑结构:集合结构;线性结构(1v1);树形结构( 1v多);图状结构(多v多)</p></li></ul><p><strong>存储结构</strong>分类:</p><ul><li><strong>顺序存储结构</strong>(用存储先后位置表示逻辑先后关系);<strong>链式存储结构</strong>(任意存储位置,但有指针表示前后逻辑关系);索引存储结构;散列存储结构;</li></ul><h3 id="时间-x2F-空间复杂度"><a href="#时间-x2F-空间复杂度" class="headerlink" title="时间/空间复杂度"></a>时间/空间复杂度</h3><p><strong>对比不同算法</strong>:时间空间复杂度,即时间和空间增长的趋势</p><ul><li><p><strong>时间渐进复杂度</strong></p><p>(BigO: 当一个问题量级增加的时候,<u>时间增长的趋势)</u>:T(n) = O(f(n)),其中f(n)代表代码执行次数,O表示正比例关系<br><strong>Eg: O(n)</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>; i<=n; i++){</span><br><span class="line"> x++;</span><br><span class="line">}</span><br><span class="line"><span class="comment">//若n = 3:</span></span><br><span class="line"><span class="comment">//1. int i = 1;</span></span><br><span class="line"><span class="comment">//2. i<=n;</span></span><br><span class="line"><span class="comment">//3. x++;</span></span><br><span class="line"><span class="comment">//4. i++; (i=2)</span></span><br><span class="line"><span class="comment">//5. i<=n;</span></span><br><span class="line"><span class="comment">//6. x++;</span></span><br><span class="line"><span class="comment">//7. i++; (i=3)</span></span><br><span class="line"><span class="comment">//8. i<=n;</span></span><br><span class="line"><span class="comment">//9. x++;</span></span><br><span class="line"><span class="comment">//10.i++;</span></span><br><span class="line"><span class="comment">//11.i<=n → 退出</span></span><br><span class="line"><span class="comment">//执行次数为:i=1 执行一次; x++ i++ 会执行 n次,i<=n执行n+1次,因此f(n) = 3n+2</span></span><br><span class="line"><span class="comment">//O(f(n)) = O(3n+2) =O(n),n接近于无限大的比例,常数和倍数意义不大,因此简略为O(n)</span></span><br></pre></td></tr></table></figure><p><strong>Eg: O(n<sup>2</sup>)</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>; i <= n; i++){</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> <span class="variable">j</span> <span class="operator">=</span> <span class="number">1</span>; j <=n; j++){</span><br><span class="line"> x++;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="comment">//同理,O(f(n)) = O(n^2)</span></span><br></pre></td></tr></table></figure><ul><li><p>常用时间复杂度量级</p><img src="https://picbed.koko2pp.cc/image-20230107174312125.png" alt="" style="zoom:40%" /><p><strong>Eg: O(1): 交换x和y的值,是一个常量</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line"><span class="type">int</span> <span class="variable">y</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line"><span class="type">int</span> <span class="variable">temp</span> <span class="operator">=</span> x;</span><br><span class="line">x = y;</span><br><span class="line">y = temp;</span><br></pre></td></tr></table></figure><p><strong>Eg: O(logN): 2<sup>k</sup> = n,k是循环次数即算法复杂度,k = logN</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line"><span class="keyword">while</span>(i<n){</span><br><span class="line"> i = i*<span class="number">2</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>Eg: O(nlogN)</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i<=n; i++){</span><br><span class="line"> <span class="type">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span>(x<n){</span><br><span class="line"> x = x*<span class="number">2</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>其它时间复杂度指标:</p></li></ul></li></ul><img src="https://picbed.koko2pp.cc/image-20230107175332971.png" alt="" style="zoom:50%;" /><ul><li><p><strong>空间复杂度(内存增长的趋势)</strong></p><ul><li><p>常用空间复杂度:O(1), O(n), O(n<sup>2</sup>)</p></li><li><p><strong>Eg: O(1)</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line"><span class="type">int</span> <span class="variable">y</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">x++;</span><br><span class="line">y++;</span><br></pre></td></tr></table></figure><p><strong>Eg: O(n),1D Array, 算法复杂度取决于newArray的长度,长度越大,需要分配的内存空间就越多</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span>[] newArray = <span class="keyword">new</span> <span class="title class_">int</span>[n];</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i < n; i++){</span><br><span class="line"> newArray[i] = i;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>Eg: O(n<sup>2</sup>),计算Matrix,或者2D Array</strong></p></li></ul></li><li><p>计算:</p><img src="https://picbed.koko2pp.cc/image-20230107180552237.png" alt="image-20230107180552237" style="zoom:80%;" /><p>找变量和不变量,i++或者i–就是写本身,对于乘除写原表达式</p><p>例1中:变得是变量:{x=x-10;y–}与x++,不变得是限制条件:while(y>0){}与if(x>100)中得0和100,先看外层: 左式(变)=右式(不变),最后相乘:y = O(o),x = O(100) y*x = O(1),复杂度为O(1)</p><p>例2中:i = O(n), j = O(m) → 最后相乘 复杂度为O(n*m)</p><p>例3中:i = O(n), j=O(n), s=O(1) → 最后相乘 复杂度为O(n*n)</p><p>例4中:3<sup>i</sup>= O(n) → j = O(log n) → 最后复杂度为O(log n)</p></li></ul><h2 id="二、线性表(顺序表、链表)"><a href="#二、线性表(顺序表、链表)" class="headerlink" title="二、线性表(顺序表、链表)"></a>二、线性表(顺序表、链表)</h2><h3 id="2-1-线性表的定义、特点、基本操作"><a href="#2-1-线性表的定义、特点、基本操作" class="headerlink" title="2.1 线性表的定义、特点、基本操作"></a>2.1 线性表的定义、特点、基本操作</h3><h4 id="线性表的定义:"><a href="#线性表的定义:" class="headerlink" title="线性表的定义:"></a>线性表的定义:</h4><p>一个线性表是n个具有相同特性的数据元素的有限序列。</p><img src="https://picbed.koko2pp.cc/3cd109bd8e29e2ab0688da279fa147f.png" alt="3cd109bd8e29e2ab0688da279fa147f" style="zoom:67%;" /><h4 id="线性表的逻辑结构:线性结构"><a href="#线性表的逻辑结构:线性结构" class="headerlink" title="线性表的逻辑结构:线性结构"></a>线性表的逻辑结构:线性结构</h4><ul><li>在非空的线性表,有且仅有一个开始结点 a<sub>1</sub>,它没有直接前趋,且仅有一个直接后继a<sub>2</sub></li><li>有且仅有一个终端结点 a<sub>n</sub>,它没有直接后继,且仅有一个直接后继a<sub>n-1</sub></li><li>其余的内部结点( 2 ≤ i ≤ n-1)都有且仅有一个直接前趋a<sub>i-1</sub>和一个一个直接后继a<sub>i-1</sub></li></ul><h4 id="线性表的特点:"><a href="#线性表的特点:" class="headerlink" title="线性表的特点:"></a>线性表的特点:</h4><ul><li>元素<strong>个数有限</strong>(区别于数学中的集合,如自然数集合/实数集合等是无限且无序)</li><li>元素逻辑上有顺序性,即<strong>元素间有先后次序</strong></li><li>元素都是数据元素,每个元素都是单个元素且<strong>数据类型相同,即每个元素占有相同大小的存储空间</strong></li><li>元素具有<strong>抽象性</strong>,只讨论元素间的逻辑关系,不管元素的具体内容</li></ul><h4 id="线性表的分类:顺序存储、链式存储"><a href="#线性表的分类:顺序存储、链式存储" class="headerlink" title="线性表的分类:顺序存储、链式存储"></a>线性表的分类:顺序存储、链式存储</h4><p>线性表指的是逻辑结构,元素之间1v1的线性关系;链式存储和顺序存储指的是存储结构;</p><img src="https://picbed.koko2pp.cc/image-20230108141904629.png" alt="" style="zoom:70%;" /><h4 id="线性表的基本操作:"><a href="#线性表的基本操作:" class="headerlink" title="线性表的基本操作:"></a>线性表的基本操作:</h4><img src="https://picbed.koko2pp.cc/image-20230108142840398.png" alt="image-20230108142840398" style="zoom:67%;" /><h3 id="2-2-线性表的顺序存储—顺序表"><a href="#2-2-线性表的顺序存储—顺序表" class="headerlink" title="2.2 线性表的顺序存储—顺序表"></a>2.2 线性表的顺序存储—顺序表</h3><h4 id="顺序表的定义:"><a href="#顺序表的定义:" class="headerlink" title="顺序表的定义:"></a>顺序表的定义:</h4><p>逻辑顺序与物理顺序相同</p><p>逻辑上相邻的数据元素存储在物理上相邻的存储单元的存储结构,即逻辑顺序与物理顺序相同。</p><img src="https://picbed.koko2pp.cc/image-20230108145335301.png" alt="image-20230108145335301" style="zoom:60%;" /><h4 id="顺序表中元素存储位置的计算:"><a href="#顺序表中元素存储位置的计算:" class="headerlink" title="顺序表中元素存储位置的计算:"></a>顺序表中元素存储位置的计算:</h4><p>Loc(a<sub>i</sub>) = Loc(a<sub>1</sub>)+(i-1)*sizeof(ElemType)</p><img src="https://picbed.koko2pp.cc/00fbed045245e5e3c2ecf22fd218e01.jpg" alt="" style="zoom: 25%;" /><img src="https://picbed.koko2pp.cc/image-20230108145708935.png" alt="image-20230108145708935" style="zoom:63%;" /><h4 id="顺序表的特点:随机存取"><a href="#顺序表的特点:随机存取" class="headerlink" title="顺序表的特点:随机存取"></a>顺序表的特点:随机存取</h4><ul><li><p>主要特点是随机存取,<u>通过首地址和元素序号可在时间O(1)内找到任一元素</u></p></li><li><p>存储密度高,每个结点只存储数据元素</p></li><li><p>顺序表逻辑上相邻元素物理上也相邻,因此<u>插入和删除操作需要移动大量元素</u></p></li></ul><h4 id="顺序表的存储结构描述:静态分配-x2F-动态分配"><a href="#顺序表的存储结构描述:静态分配-x2F-动态分配" class="headerlink" title="顺序表的存储结构描述:静态分配/动态分配"></a>顺序表的存储结构描述:静态分配/动态分配</h4><p>一维数组可以<strong>静态分配</strong>,也可以<strong>动态分配</strong>。</p><p><strong>静态分配</strong>:由于数组大小和空间已提前固定,一旦空间占满,再加入新数据则造成溢出、程序崩溃;</p><p><strong>动态分配</strong>:<u>动态存储分配语句</u>进行存储数据的空间分配,<u>一旦空间占满,就另外开辟更大的存储空间去替换原存储空间以扩充存储数组空间</u>,不需要为线性表提前一次性地划分所有空间</p><ul><li><p>静态分配:假设线性表的元素类型为ElemType</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="meta">#<span class="keyword">define</span> MaxSize 50 <span class="comment">//定义线性表的最大长度</span></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"> ElemType data[MaxSize]; <span class="comment">//顺序表的元素 使用数组表示</span></span><br><span class="line"> <span class="type">int</span> length; <span class="comment">//顺序表的当前长度</span></span><br><span class="line">}SqList; <span class="comment">//顺序表的类型定义,使用该名称</span></span><br></pre></td></tr></table></figure></li><li><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> InitSize 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></span><br><span class="line"> ElemType *data; <span class="comment">//指示动态分配数组的指针(数组第一个元素所在位置的地址)</span></span><br><span class="line"> <span class="type">int</span> MaxSize,length; <span class="comment">//数组的最大容量和当前个数</span></span><br><span class="line">}SqList; <span class="comment">//动态分配数组顺序表的类型定义</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//C初始动态分配语句: (空间类型/指针类型)malloc(需要分配的空间大小)</span></span><br><span class="line">L.data = (ElemType*)<span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(ElemType)*InitSize);</span><br><span class="line"><span class="comment">//原型:分配长度为num-byte字节的内存块; 分配成功,则返回指向被分配的指针;分配失败,返回空指针NULL</span></span><br><span class="line"><span class="comment">//malloc函数通常与free函数成对使用,分配空间使用结束后使用free函数释放</span></span><br><span class="line"><span class="keyword">extern</span> <span class="type">void</span>*<span class="title function_">malloc</span><span class="params">(<span class="type">unsigned</span> <span class="type">int</span> num-bytes)</span>;</span><br><span class="line"><span class="comment">//Eg:</span></span><br><span class="line"><span class="type">int</span> *A;</span><br><span class="line">A = (<span class="type">int</span>*)<span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(<span class="type">int</span>)*<span class="number">20</span>); <span class="comment">// A可以被当作做A[20]进行使用</span></span><br></pre></td></tr></table></figure><p>问题:InitSize=10 即A[10],放入15个元素,则动态分配的另外空间是A[5]/A[10]/A[15]?</p><p>答案:A[15],要求逻辑上相邻的元素物理上也相邻,没有办法保证中间断开的两个元素的物理位置是相邻的,因此需要分配一个更大长度的连续物理存储空间放入所有元素</p></li></ul><h4 id="顺序表的基本操作:"><a href="#顺序表的基本操作:" class="headerlink" title="顺序表的基本操作:"></a>顺序表的基本操作:</h4><p>插入O(n) /删除O(n)/ 查找( 按位查找O(1) 按值查找O(n) )</p><ul><li><p><strong>插入:</strong>在顺序表 L 的<strong>第 i ( 1 <= i <= L.length+1 )个位置</strong>插入新元素 e</p><p>若 i 的输入不合法,则返回 false,表示插入失败; </p><p>若 i 合法,则将第 i 个元素及其后面的所有元素一次向后移动一个位置,腾出一个空位插入新元素e,顺序表长度增加 1 ,插入成功,返回true;</p><p>或者插入失败 #define false 0; 插入成功 #define true 1; 那么<strong>bool</strong> ListInsert() 改为 <strong>int</strong> ListInsert()</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="comment">//插入操作需要Input: 哪个顺序表(指针类型),第几个元素进行插入,插入元素的值</span></span><br><span class="line"><span class="type">bool</span> <span class="title function_">ListInsert</span><span class="params">(SqList *L, <span class="type">int</span> i, ElemType e)</span>{</span><br><span class="line"> <span class="keyword">if</span>(i<<span class="number">1</span> || i>L.length+<span class="number">1</span>) <span class="comment">//首先判断是否合法,即判断i插入位置是否有效</span></span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> <span class="keyword">if</span>(L.length >= MaxSize) <span class="comment">//看当前存储空间是否已满,若没满 还是可以继续插入</span></span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> j=L.length; j>=i; j--){ <span class="comment">//从最后一个元素开始,将第i个元素及之后的元素进行后移</span></span><br><span class="line"> L.data[j] = L.data[j<span class="number">-1</span>]; <span class="comment">//把j-1位置的元素赋值给j位置</span></span><br><span class="line"> } </span><br><span class="line"> L.data[i<span class="number">-1</span>] = e; <span class="comment">//在位置i处放入e,i是位序,位序和下标差1</span></span><br><span class="line"> L.length++; <span class="comment">//线性表程度加1</span></span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="https://picbed.koko2pp.cc/image-20230108182819617.png" alt="image-20230108182819617" style="zoom:57%;" /><img src="https://picbed.koko2pp.cc/image-20230108184949032.png" alt="image-20230108184949032" style="zoom:57%;" /></p></li><li><p><strong>删除:</strong>删除顺序表L中<strong>第 i (1 <= i <= L.length)个位置的元素</strong>,用引用变量e返回。</p><p>输入不合法返回false;</p><p>输入合法,将被删除元素赋值给引用变量e (指针),并将第i+1个元素及其后的所有元素依次向前移动一格位置,返回true;</p><p>先把删除结点内容赋值给变量e,数组的删除是<strong>覆盖操作</strong>, 原来的值(如图63)还会存在,但是length–,我们认为变化后的length长度为我们的表长,后面的63已经不在表内</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">bool</span> <span class="title function_">ListDelete</span><span class="params">(SqList *L, <span class="type">int</span> i, Elemtype *e)</span>{</span><br><span class="line"> <span class="keyword">if</span>(i<<span class="number">1</span> || i>L.length){ <span class="comment">//先判断i的范围是否合法</span></span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> }</span><br><span class="line"> e = L.data[i<span class="number">-1</span>]; <span class="comment">//将被删除的元素赋值给e</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> j=i; j<L.length;j++){ <span class="comment">//将第i个位置后的元素前移,提供的i是位置,j是下标</span></span><br><span class="line"> L.data[j<span class="number">-1</span>] = L.data[j];</span><br><span class="line"> }</span><br><span class="line"> L.length--;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>; <span class="comment">//线性表长度减1</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="https://picbed.koko2pp.cc/image-20230108184120437.png" alt="image-20230108184120437" style="zoom:57%;" /><img src="https://picbed.koko2pp.cc/image-20230108184853875.png" alt="image-20230108184853875" style="zoom:57%;" /></p></li><li><p><strong>查找:</strong></p><p>按位查找(input位置 output值,直接找O(1)) 、按值查找(input值 output位置,需要从头遍历)</p><p><strong>按值查找:</strong>在顺序表L中查找<strong>第一个元素值等于 e 的元素</strong>,并<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><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_">LocateElem</span><span class="params">(Sqlist L,ElemType e)</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<L.length;i++){ <span class="comment">//从头开始找 i = 0 开始,一直到L.length-1</span></span><br><span class="line"> <span class="keyword">if</span>(L.data[i] == e){ </span><br><span class="line"> <span class="keyword">return</span> i+<span class="number">1</span>; <span class="comment">//下标为i的元素值等于e,返回其位序 i+1</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>; <span class="comment">//退出循环,说明查找失败</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><img src="https://picbed.koko2pp.cc/image-20230108190701727.png" alt="image-20230108190701727" style="zoom:40%;" /></li></ul><h4 id="顺序表总结:"><a href="#顺序表总结:" class="headerlink" title="顺序表总结:"></a>顺序表总结:</h4><p> <img src="https://picbed.koko2pp.cc/20230120223240.png" alt="20230120223240" style="zoom:20%;" /><img src="https://picbed.koko2pp.cc/20230120223258.png" alt="20230120223258" style="zoom:15%;" /></p><h3 id="2-3-线性表的链式存储—链表-单链表"><a href="#2-3-线性表的链式存储—链表-单链表" class="headerlink" title="2.3 线性表的链式存储—链表(单链表)"></a>2.3 线性表的链式存储—链表(单链表)</h3><p>由于<u>顺序表的插入、删除操作需要移动大量元素</u>,因此引入链式存储结构的线性表。<strong>链表不需要使用地址连续的存储单元,通过指针建立起数据元素之间的逻辑关系</strong>,因此插入和删除不需要移动元素,只需要<strong>修改指针</strong>,也因此<u>失去了顺序表随机存取的优点</u>。</p><h4 id="链表-单链表-x2F-双链表-x2F-循环链表的定义:"><a href="#链表-单链表-x2F-双链表-x2F-循环链表的定义:" class="headerlink" title="链表(单链表)/双链表/循环链表的定义:"></a>链表(单链表)/双链表/循环链表的定义:</h4><ul><li><p>线性表的<strong>链式存储又称为单链表</strong>,即通过一组任意存储单元来存数据元素。每个链表结点由<strong>数据域</strong>(存放元素数值数据)和<strong>指针域</strong>(存储直接后继节点的指针 )构成</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></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>{</span> <span class="comment">//定义单链表结点类型</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">}LNode,*LinkList; <span class="comment">//LNode普通类型,*LinkList为指针类型,Linklist A;和LNode *B; 类型等价</span></span><br></pre></td></tr></table></figure><p>结点<u>只有一个指针域</u>的链表为单链表</p><img src="https://picbed.koko2pp.cc/image-20230108205033986.png" alt="image-20230108205033986" style="zoom:80%;" /></li><li><p>双链表:结点有<u>两个指针域</u>的链表</p><img src="https://picbed.koko2pp.cc/image-20230108205103948.png" alt="image-20230108205103948" style="zoom:80%;" /></li><li><p>循环链表:<u>首尾相接</u>的单链表</p><img src="https://picbed.koko2pp.cc/image-20230108205128475.png" alt="image-20230108205128475" style="zoom:80%;" /></li></ul><h4 id="链表的头指针、头结点、首元结点的定义:"><a href="#链表的头指针、头结点、首元结点的定义:" class="headerlink" title="链表的头指针、头结点、首元结点的定义:"></a>链表的头指针、头结点、首元结点的定义:</h4><p>使用<strong>头指针</strong>来标识一个单链表(Eg:单链表L,头指针为NULL的时候表示为一个空表),在单链表第一个结点之前附加一个结点,称为<strong>头结点</strong>,头结点的数据域可以不放任何信息,也可以用于记录表长,头结点的指针域指向线性表的<strong>首元结点</strong>(第一个元素结点)。 <u>头结点可以有可无</u></p><img src="https://picbed.koko2pp.cc/image-20230108205338932.png" alt="image-20230108205338932" style="zoom:55%;" /><img src="https://picbed.koko2pp.cc/image-20230108210235792.png" alt="image-20230108210235792" style="zoom:63%;" /><h4 id="链表的基本操作:"><a href="#链表的基本操作:" class="headerlink" title="链表的基本操作:"></a>链表的基本操作:</h4><p>创建链表O(n)(头插法/尾插法、删除、查找O(n)(按序/按值)</p><ul><li><p><strong>创建链表</strong></p><ul><li><p><strong>头插法</strong>:从一个空表开始生成新结点,并将读取到的数据存放到新结点的数据域中,然后**将新结点插入到当前链表的<u>表头,即头结点之后</u>**。 </p><p>(需要**<u>先操作后端,再操作前端</u>**,如图,在表头插入a<sub>i</sub>新结点,首先将a<sub>i</sub>的指针域指向原来的首元结点a<sub>l</sub>,再将头结点的指针域指向a<sub>i</sub>;错误做法:先前端再后端,先将头结点的指针指向a<sub>i</sub>,则此时丢失了指向a<sub>l</sub>的指针域,即无法找到a<sub>l</sub>结点)</p><p>头插法输出后得到的是一个<strong>倒序的序列</strong></p><p><img src="https://picbed.koko2pp.cc/image-20230108211504514.png" alt="image-20230108211504514" style="zoom:57%;" /><img src="https://picbed.koko2pp.cc/image-20230108230623649.png" alt="image-20230108230623649" style="zoom:50%;" /></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">LinkList <span class="title function_">List_HeadInsert</span><span class="params">(LinkList &L)</span>{ <span class="comment">//输入:头指针,输出LinkList类型的链表</span></span><br><span class="line"> <span class="comment">//逆向建立单链表:</span></span><br><span class="line"> LNode *s; <span class="type">int</span> x; <span class="comment">// 新结点s以及新结点存放的数据x</span></span><br><span class="line"> L = (LinkList)<span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(LNode)); <span class="comment">//创建头结点,指针类型</span></span><br><span class="line"> L->next = <span class="literal">NULL</span>; <span class="comment">//头结点赋空,初始化为空链表</span></span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>,&x); <span class="comment">//输入结点的值</span></span><br><span class="line"> <span class="keyword">while</span>(x!=<span class="number">9999</span>){ <span class="comment">//输入9999表示循环/插入结束</span></span><br><span class="line"> s=(LNode*)<span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(LNode)); <span class="comment">//创建新结点s</span></span><br><span class="line"> s->data = x; <span class="comment">//把x赋值给s结点的数据域</span></span><br><span class="line"> s->next = L->next; <span class="comment">//先操作后端</span></span><br><span class="line"> L->next = s; <span class="comment">//再操作前端,将新结点插入链表,L头指针</span></span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>,&x);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> L;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>每个结点插入时间为O(1),设单链表的表长为n,则<strong>总时间复杂度为O(n)</strong></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><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//输入:头指针L,输出LinkList类型</span></span><br><span class="line">LinkList <span class="title function_">List_HeadInsert</span><span class="params">(LinkList &L)</span>{ <span class="comment">//逆向建立单链表:</span></span><br><span class="line"> LNode *s; <span class="type">int</span> x; <span class="comment">// 新结点s以及新结点存放的数据x</span></span><br><span class="line"> L = (LinkList)<span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(LNode)); <span class="comment">//创建头结点,指针类型</span></span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>,&x); <span class="comment">//输入结点的值</span></span><br><span class="line"> <span class="keyword">while</span>(x!=<span class="number">9999</span>){ <span class="comment">//输入9999表示循环/插入结束</span></span><br><span class="line"> s=(LNode*)<span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(LNode)); <span class="comment">//创建新结点s</span></span><br><span class="line"> s->data = x; <span class="comment">//把x赋值给s结点的数据域</span></span><br><span class="line"> <span class="keyword">if</span>(L==<span class="literal">NULL</span>){</span><br><span class="line"> L = s; <span class="comment">//先操作后端</span></span><br><span class="line"> s->next = <span class="literal">NULL</span>; <span class="comment">//再操作前端</span></span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> s->next = L; <span class="comment">//先操作后端</span></span><br><span class="line"> L = s; <span class="comment">//再操作前端</span></span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>,&x);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> L;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>个人理解:如果不设置头结点,L头指针就直接指向第一个结点(L=s);设置了头结点则头指针存放在头结点的指针域中,当作一个结点使用 (L->next = s)</p></li><li><p><strong>尾插法:</strong>尾插法生成的链表中,结点的次序和输入数据的顺序一致。该方法将新结点插入当前链表的表尾,因此<strong>需要一个尾指针 r ,使其始终指向当前链表的尾结点</strong></p><p>依然先操作后端再操作前端:先将a<sub>j</sub>的指针域NULL赋给a<sub>i</sub>的后端,再将a<sub>i</sub>的结点地址赋给a<sub>j</sub>的指针域</p><p><img src="https://picbed.koko2pp.cc/image-20230108233100283.png" alt="image-20230108233100283" style="zoom:60%;" /><img src="https://picbed.koko2pp.cc/image-20230108233454888.png" alt="image-20230108233454888" style="zoom:67%;" /> </p><p>① <img src="https://picbed.koko2pp.cc/image-20230108233913488.png" alt="image-20230108233913488" style="zoom:67%;" /> ②<img src="https://picbed.koko2pp.cc/image-20230108234236458.png" alt="image-20230108234236458" style="zoom:67%;" />③<img src="https://picbed.koko2pp.cc/image-20230108234302176.png" alt="image-20230108234302176" style="zoom:67%;" /></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="comment">//输入:头指针L,输出LinkList类型</span></span><br><span class="line">LinkList List <span class="title function_">TailInsert</span><span class="params">(LinkList &L)</span>{</span><br><span class="line"> <span class="type">int</span> x; <span class="comment">//设元素类型为整形</span></span><br><span class="line"> L = (LinkList)<span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(LNode)); <span class="comment">//创建头结点</span></span><br><span class="line"> LNode *s, *r=L; <span class="comment">//① r为表尾指针(上面右图 和L一样指向头节点)</span></span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &x); <span class="comment">//输入结点的值</span></span><br><span class="line"> <span class="keyword">while</span>(x!=<span class="number">9999</span>){</span><br><span class="line"> s=(LNode *)<span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(LNode)); <span class="comment">//新结点</span></span><br><span class="line"> s->data = x; <span class="comment">//新结点数据域</span></span><br><span class="line"> r->next = s; <span class="comment">//② 最后结点的指针域指向s,连接尾结点和s结点</span></span><br><span class="line"> r = s; <span class="comment">//③ r指向新的表尾结点s</span></span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>,&x);</span><br><span class="line"> }</span><br><span class="line"> r->next = <span class="literal">NULL</span>; <span class="comment">//尾结点指针置空</span></span><br><span class="line"> <span class="keyword">return</span> L;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>因为附设了一个指向表尾结点的指针,因此时间复杂度和头插法相同为<strong>O(n)</strong></p></li></ul></li><li><p><strong>查找</strong>:复杂度为O(n)</p><ul><li><p><strong>按序查找</strong>:<u>从第一个结点出发,顺着指针next域逐个向下搜索,知道找到第i个结点为止</u>,否则返回最后一个结点指针域NULL。 遍历操作,复杂度为O(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></pre></td><td class="code"><pre><span class="line"><span class="comment">//输入:链表 序号;输出:结点</span></span><br><span class="line">LNode *<span class="title function_">GetElem</span><span class="params">(LinkList L, <span class="type">int</span> i)</span>{</span><br><span class="line"> <span class="type">int</span> j = <span class="number">1</span>; <span class="comment">//计数,初始为1</span></span><br><span class="line"> LNode *p = L->next; <span class="comment">//移动的指针,L指向头结点,p此时指向的是第一个数据结点即首元结点</span></span><br><span class="line"> <span class="keyword">if</span>(i==<span class="number">0</span>) <span class="keyword">return</span> L; <span class="comment">//若i等于0,返回头结点</span></span><br><span class="line"> <span class="keyword">if</span>(i<<span class="number">1</span>) <span class="keyword">return</span> <span class="literal">NULL</span>; <span class="comment">//若i不合法,返回NULL</span></span><br><span class="line"> <span class="comment">//这里p等价于p→next!=null,while循环进行判断,如果p不等于空且j<i(即没到尾节点并且还没有查到i节点)判断为真,继续执行循环;若p指向NULL即P已经是尾结点,跳出循环</span></span><br><span class="line"> <span class="keyword">while</span>(p && j<i){ <span class="comment">//从第一个结点开始找,找到第i个结点</span></span><br><span class="line"> p = p->next; <span class="comment">//</span></span><br><span class="line"> j++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> p; <span class="comment">//返回第i个结点的指针,若i大于表长,则返回NULL</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>按值查找:从表的第一个结点开始,从前往后依次比较各结点数据域的值,若某结点数据域的值等于给定值e,则返回该结点的指针;若整个单链表中没有该结点,则返回NULL。遍历操作,复杂度为O(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></pre></td><td class="code"><pre><span class="line">LNode *<span class="title function_">LocateElem</span><span class="params">(LinkList L, ElemType e)</span>{</span><br><span class="line"> LNode *p = L->next;</span><br><span class="line"> <span class="keyword">while</span>(p!=<span class="literal">NULL</span> && p->data!=e){ <span class="comment">//从第一个结点开始查找data域为e的结点</span></span><br><span class="line"> p = p -> next;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> p; <span class="comment">//找到后返回该指针,不然返回NULL(p此时是尾结点,返回尾结点的指针域)</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul></li><li><p><strong>插入 O(n)</strong></p><ul><li><p>将值为 x 的新结点插入到单链表的第 i 个位置上。先检查插入位置的合法性,**找到带插入位置的<u>前驱节点</u>**,即第 i-1 个结点,再在其后插入新结点。 算法:首先调用按序查找函数找到第 i-1 个结点GetElem(L, i-1),返回的是第 i-1 个结点为 *p ,让新结点 *s 的指针域指向 *p 的后继节点,再令结点 *p 的指针域指向新插入的结点 *s</p><img src="https://picbed.koko2pp.cc/image-20230111123256478.png" alt="image-20230111123256478" style="zoom:50%;" /><img src="https://picbed.koko2pp.cc/image-20230112170213266.png" alt="image-20230112170213266" style="zoom:70%;" /></li></ul></li><li><p><strong>删除结点操作</strong></p><ul><li><p>删除结点操作是将单链表的第 i 个结点删除。先检查删除位置的合法性,后查找表中第 i-1 个结点,即被删结点的前驱节点,再将其删除</p><img src="https://picbed.koko2pp.cc/image-20230112172744627.png" alt="image-20230112172744627" style="zoom:70%;" /><img src="https://picbed.koko2pp.cc/image-20230112173023710.png" alt="image-20230112173023710" style="zoom:77%;" /></li></ul></li><li><p><strong>求表长</strong>:计数器,算法复杂度为O(n)</p></li></ul><h4 id="双链表及双链表的基本操作"><a href="#双链表及双链表的基本操作" class="headerlink" title="双链表及双链表的基本操作"></a>双链表及双链表的基本操作</h4><p><strong>插入O(1) 删除O(1)</strong> </p><p>已知单链表中访问某结点的前驱结点(插入、删除操作),只能够从头遍历。为克服该缺点,引入双链表:双链表结点中有两个指针 prior 和 next,分别指向其前驱结点和后继结点</p><img src="https://picbed.koko2pp.cc/image-20230112173500926.png" alt="image-20230112173500926" style="zoom:67%;" /><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></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">DNode</span>{</span> <span class="comment">//定义双链表结点类型</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">DNode</span> *<span class="title">prior</span>, *<span class="title">next</span>;</span> <span class="comment">//前驱和后继指针</span></span><br><span class="line">}DNode, *DLinklist;</span><br></pre></td></tr></table></figure><ul><li><p>双链表的插入操作</p><p>为了不断链,同样是先后端再前端:</p><img src="https://picbed.koko2pp.cc/image-20230112174351490.png" alt="image-20230112174351490" style="zoom:65%;" /></li><li><p>双链表的删除操作</p><img src="https://picbed.koko2pp.cc/image-20230112174614214.png" alt="image-20230112174614214" style="zoom:70%;" /></li></ul><h4 id="循环单链表"><a href="#循环单链表" class="headerlink" title="循环单链表"></a>循环单链表</h4><p>循环链表中,**最后一个结点的指针不是NULL,而改为<u>指向头结点</u>**,整个链表形成一个环。</p><p>循环单链表中,表尾结点<em>r的next域指向L,因此表中没有指针域为NULL的结点,因此*<em>循环单链表的<u>判空条件</u>不是头结点是否为空,而是判断它是否等于头指针</em></em></p><img src="https://picbed.koko2pp.cc/image-20230112180618280.png" alt="image-20230112180618280" style="zoom:57%;" /><img src="https://picbed.koko2pp.cc/image-20230112180635258.png" alt="image-20230112180635258" style="zoom:80%;" /><h4 id="循环双链表"><a href="#循环双链表" class="headerlink" title="循环双链表"></a>循环双链表</h4><img src="https://picbed.koko2pp.cc/image-20230112180820291.png" alt="image-20230112180820291" style="zoom:67%;" /><h4 id="链表的总结"><a href="#链表的总结" class="headerlink" title="链表的总结"></a>链表的总结</h4><img src="https://picbed.koko2pp.cc/image-20230112182235386.png" alt="image-20230112182235386" style="zoom:60%;" /><h3 id="2-4-链表与顺序表的对比"><a href="#2-4-链表与顺序表的对比" class="headerlink" title="2.4 链表与顺序表的对比"></a>2.4 链表与顺序表的对比</h3><img src="https://picbed.koko2pp.cc/image-20230112182319550.png" alt="image-20230112182319550" style="zoom:50%;" /><img src="https://picbed.koko2pp.cc/image-20230112182455628.png" alt="image-20230112182455628" style="zoom:55%;" /><img src="https://picbed.koko2pp.cc/image-20230112182531931.png" alt="image-20230112182531931" style="zoom:53%;" /><h2 id="三、栈和队列"><a href="#三、栈和队列" class="headerlink" title="三、栈和队列"></a>三、栈和队列</h2><h3 id="3-1-栈-后进先出-和队列-先进先出-的定义、特点"><a href="#3-1-栈-后进先出-和队列-先进先出-的定义、特点" class="headerlink" title="3.1 栈(后进先出)和队列(先进先出)的定义、特点"></a>3.1 栈(后进先出)和队列(先进先出)的定义、特点</h3><p>栈和队列是限定插入操作和删除操作只能在表的“端点”进行的线性表</p><img src="https://picbed.koko2pp.cc/image-20230122002730350.png" alt="image-20230122002730350" style="zoom:30%;" /><h4 id="栈的定义和特点:"><a href="#栈的定义和特点:" class="headerlink" title="栈的定义和特点:"></a>栈的定义和特点:</h4><p>栈(stack)是一个特殊的线性表,是**<u>限定仅在一端(表尾),进行插入和删除操作的线性表</u>**;又称为后进先出(Last In First Out)的线性表,简称LIFO结构。元素间的逻辑结构为<u>1 v 1</u>。根据存储结构不同分为<u>顺序栈和链栈</u>。</p><p><img src="https://picbed.koko2pp.cc/image-20230122004525083.png" alt="image-20230122004525083" style="zoom:40%;" /><img src="https://picbed.koko2pp.cc/image-20230122010725542.png" alt="image-20230122010725542" style="zoom:40%;" /></p><ul><li>举例:<img src="https://picbed.koko2pp.cc/image-20230122005658822.png" alt="image-20230122005658822" style="zoom:23%;" /></li><li>补充:<img src="https://picbed.koko2pp.cc/image-20230122011023328.png" alt="image-20230122011023328" style="zoom:39%;" /></li></ul><h5 id="栈的应用举例"><a href="#栈的应用举例" class="headerlink" title="栈的应用举例"></a>栈的应用举例</h5><p>① <strong>表达式求值</strong>;② <strong>递归工作栈</strong>;③ 括号匹配;④ 迷宫求解;⑤ 进制转换;⑥ 行编辑程序;⑦悔棋操作</p><ul><li><p>表达式求值:在计算机中任何一个表达式都可以由<u>操作数 operand</u>(常数),<u>运算符 operator</u> (算数运算符、关系运算符和逻辑运算符)和<u>界限符 delimiter</u>(左右括号和标识表达式结束的结束符)组成。</p><img src="https://picbed.koko2pp.cc/image-20230122210523931.png" alt="image-20230122210523931" style="zoom:53%;" /><img src="https://picbed.koko2pp.cc/image-20230122210555469.png" alt="image-20230122210555469" style="zoom:33%;" /></li><li><p>递归:</p><ul><li>定义和举例:<img src="https://picbed.koko2pp.cc/image-20230122211100152.png" alt="image-20230122211100152" style="zoom:63%;" /></li><li>算法设计:<img src="https://picbed.koko2pp.cc/image-20230122210937589.png" alt="image-20230122210937589" style="zoom:35%;" /></li></ul></li><li><p>进制转换:<img src="https://picbed.koko2pp.cc/image-20230122210325770.png" alt="image-20230122210325770" style="zoom:60%;" /></p></li><li><p>括号匹配:<img src="https://picbed.koko2pp.cc/image-20230122210454031.png" alt="image-20230122210454031" style="zoom:60%;" /></p></li></ul><h4 id="队列的定义和特点:"><a href="#队列的定义和特点:" class="headerlink" title="队列的定义和特点:"></a>队列的定义和特点:</h4><ul><li>队列(queue)是一种先进先出(First In First Out, FIFO)的线性表。**<u>在表尾插入,在表头删除</u>**。与线性表相同,逻辑结构为<u>1 v 1</u>,根据存储结构不同分为<u>顺序队与链队</u>。 </li><li><strong>队头Front,允许删除</strong>的一端,又称为队首;<strong>队尾Rear,允许插入</strong>的一端。</li><li><img src="https://picbed.koko2pp.cc/image-20230122010525367.png" alt="image-20230122010525367" style="zoom:73%;" /></li><li>举例: <img src="https://picbed.koko2pp.cc/image-20230122010557406.png" alt="image-20230122010557406" style="zoom:50%;" /><img src="https://picbed.koko2pp.cc/image-20230122211257191.png" alt="image-20230122211257191" style="zoom:50%;" /></li></ul><h3 id="3-2-栈的表示和操作实现"><a href="#3-2-栈的表示和操作实现" class="headerlink" title="3.2 栈的表示和操作实现"></a>3.2 栈的表示和操作实现</h3><p>栈的基本操作:</p><img src="https://picbed.koko2pp.cc/image-20230122164946764.png" alt="image-20230122164946764" style="zoom:50%;" /><h4 id="栈的顺序存储:顺序栈"><a href="#栈的顺序存储:顺序栈" class="headerlink" title="栈的顺序存储:顺序栈"></a>栈的顺序存储:顺序栈</h4><h5 id="顺序栈的定义"><a href="#顺序栈的定义" class="headerlink" title="顺序栈的定义"></a>顺序栈的定义</h5><p>同一般线性表的顺序存储结构完全相同,利用一组地址连续的存储单元一次存放自栈底到栈顶的数据元素,栈底一般在低地址端。</p><h5 id="顺序栈的表示"><a href="#顺序栈的表示" class="headerlink" title="顺序栈的表示"></a>顺序栈的表示</h5><ul><li><p>使用base指针,指示<strong>栈底元素</strong>在顺序栈中的位置</p></li><li><p>使用<strong>top指针</strong>,指示栈顶元素在顺序栈中的位置(一般指的是**<u><em>栈顶元素上一个元素的存储单元</em></u>**)</p></li><li><p>用<strong>stacksize</strong>表示栈可用的最大容量</p><img src="https://picbed.koko2pp.cc/image-20230122170215713.png" alt="image-20230122170215713" style="zoom:60%;" /></li></ul> <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></span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span>{</span><br><span class="line"> SElemType *base; <span class="comment">//栈底指针</span></span><br><span class="line"> SElemType *top; <span class="comment">//栈顶指针</span></span><br><span class="line"> <span class="type">int</span> stacksize; <span class="comment">//最大容量</span></span><br><span class="line">}SqStack;</span><br></pre></td></tr></table></figure><ul><li><p>判断顺序栈的栈空和栈满:</p><p><strong><u>栈空</u><strong>标志:</strong>base == top</strong></p><p><strong><u>栈满</u><strong>标志:</strong>top-base==stacksize</strong></p><p>栈中**<u>元素个数</u><strong>:</strong>top - base**</p><p><img src="https://picbed.koko2pp.cc/image-20230122174040199.png" alt="image-20230122174040199" style="zoom:60%;" /><img src="https://picbed.koko2pp.cc/image-20230122174127699.png" alt="image-20230122174127699" style="zoom:50%;" /></p><ul><li>栈满时候的处理方法:1.报错,返回操作系统;2.分配更大的空间。</li><li>进行出栈和入栈操作可能会遇到上溢/下溢(因为数组大小提前已使用stacksize固定)<ul><li><strong>上溢(overflow):栈已经满,依然入栈</strong></li><li><strong>下溢(underflow):栈已经空,还要出栈</strong></li><li>上溢是一种错误,使问题的处理无法执行;而下溢被认为是一种结束条件,即问题处理结束</li></ul></li></ul></li></ul><h5 id="顺序栈的基本操作"><a href="#顺序栈的基本操作" class="headerlink" title="顺序栈的基本操作"></a>顺序栈的基本操作</h5><ul><li><p>顺序栈的初始化:分配空间,初始化S.base; S.top; S.stacksize</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">Status <span class="title">InitStack</span><span class="params">(SqStack &S)</span></span>{<span class="comment">//构造一个空栈</span></span><br><span class="line"> S.base = <span class="keyword">new</span> SElemType[MaXSIZE]; <span class="comment">//S.base指针指向内存中构造数组的首元素</span></span><br><span class="line"> <span class="keyword">if</span>(!S.base) <span class="built_in">exit</span> (OVERFLOW); <span class="comment">//内存空间满,存储分配失败</span></span><br><span class="line"> S.top = S.base; <span class="comment">// 空栈标志,让栈顶指针top等于栈底指针base</span></span><br><span class="line"> S.stacksize = MAXSIZE; <span class="comment">//初始化S.stacksize的值</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><img src="https://picbed.koko2pp.cc/image-20230122175851375.png" alt="image-20230122175851375" style="zoom:50%;" /></li><li><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"><span class="function">Status <span class="title">StackEmpty</span><span class="params">(SqStack S)</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(S.top == S.base){</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="keyword">else</span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>; <span class="comment">// 栈不空</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">StackLength</span><span class="params">(SqStack S)</span></span>{</span><br><span class="line"> <span class="keyword">return</span> S.top-S.base;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><img src="https://picbed.koko2pp.cc/image-20230122175906979.png" alt="image-20230122175906979" style="zoom:50%;" /><ul><li><p>清空顺序栈:若栈存在 S.top = S.base 让栈空就可以</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"><span class="function">Status <span class="title">ClearStack</span><span class="params">(SqStack &S)</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(S.base) S.top=S.base;<span class="comment">//若栈存在 S.top = S.base 让栈空就可以</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><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></pre></td><td class="code"><pre><span class="line"><span class="function">Status <span class="title">DestroyStack</span><span class="params">(SqStack &S)</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(S.base){</span><br><span class="line"> <span class="keyword">delete</span> S.base; <span class="comment">//如果栈存在,删除栈底指针</span></span><br><span class="line"> <span class="comment">//delete操作释放了指针原本所指部分内存,此时base指针值并非NULL,而是随机值成为了野指针</span></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 class="comment">//指针置空</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><img src="https://picbed.koko2pp.cc/image-20230122180615781.png" alt="image-20230122180615781" style="zoom:50%;" /></li><li><p>顺序栈的入栈</p><ol><li>首先是否判断是否栈满,栈满则报错 上溢</li><li>将元素e压入栈顶</li><li>栈顶指针top加1</li></ol><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">Status <span class="title">Push</span><span class="params">(SqStack &S,SElemType e)</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(S.top-S.base==S.stacksize) <span class="keyword">return</span> ERROR; <span class="comment">//栈满</span></span><br><span class="line"> *S.top = e;</span><br><span class="line"> S.top++;</span><br><span class="line"> <span class="comment">//或者集成为 *S.top++ = e;</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><img src="https://picbed.koko2pp.cc/image-20230122181100375.png" alt="image-20230122181100375" style="zoom:50%;" /></li><li><p>顺序栈的出栈</p><ol><li>判断是否栈空,若栈空则报错 下溢</li><li>获取栈顶元素 e 用于返回</li><li>栈顶指针 S.top 减 1</li></ol><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">Status <span class="title">Pop</span><span class="params">(SqStack &S, SElemType &e)</span></span>{</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"> S.top--; <span class="comment">//先将top指针下移一位</span></span><br><span class="line"> e = *S.top; <span class="comment">//再提值</span></span><br><span class="line"> <span class="comment">// 等价于e = *--S.top</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><h4 id="栈的链式存储:链栈"><a href="#栈的链式存储:链栈" class="headerlink" title="栈的链式存储:链栈"></a>栈的链式存储:链栈</h4><h5 id="链栈的定义"><a href="#链栈的定义" class="headerlink" title="链栈的定义"></a>链栈的定义</h5><p>采用<strong>链式存储</strong>的栈称为链栈,采用单链表实现,<u>只能在链表的头部进行操作</u>。**<u>next域中存放的是前驱元素的地址</u>**</p><p>特点:</p><ul><li>链表的头指针就是栈顶;</li><li>不需要头结点;</li><li>基本不存在栈满的情况</li><li>空栈相当于头指针指向空</li><li>插入操作和删除操作仅在栈顶处执行</li></ul><img src="https://picbed.koko2pp.cc/image-20230122185635905.png" alt="image-20230122185635905" style="zoom:67%;" /><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span> <span class="title class_">StackNode</span>{</span><br><span class="line"> SElemType data;<span class="comment">// 数据域</span></span><br><span class="line"> <span class="keyword">struct</span> <span class="title class_">StackNode</span> *next; <span class="comment">// 指针域</span></span><br><span class="line">}StackNode,*LinkStack;</span><br></pre></td></tr></table></figure><img src="https://picbed.koko2pp.cc/image-20230122185616364.png" alt="image-20230122185616364" style="zoom:43%;" /><h5 id="链栈的基本操作"><a href="#链栈的基本操作" class="headerlink" title="链栈的基本操作"></a>链栈的基本操作</h5><ul><li><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="function">Status <span class="title">InitStack</span><span class="params">(LinkStack &S)</span></span>{</span><br><span class="line"> <span class="comment">// 构造一个空栈,栈顶指针置空</span></span><br><span class="line"> S = <span class="literal">NULL</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><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><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">Status <span class="title">StackEmpty</span><span class="params">(LinkStack S)</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(S==<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="keyword">else</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>; <span class="comment">//栈不空</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p><strong>链栈的入栈</strong></p><p>1.创建新结点</p><p>2.将新结点插入栈顶</p><p>3.更新栈顶指针</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">Status <span class="title">Push</span><span class="params">(LinkStack &S,SElemType e)</span></span>{</span><br><span class="line"> p = <span class="keyword">new</span> StackNode; <span class="comment">//生成新结点p</span></span><br><span class="line"> p->data = e; <span class="comment">//设置新结点的数据域</span></span><br><span class="line"> p->next = S; <span class="comment">//将新结点插入栈顶</span></span><br><span class="line"> S = p; <span class="comment">// 修改栈顶指针</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><img src="https://picbed.koko2pp.cc/image-20230122194524461.png" alt="image-20230122194524461" style="zoom:67%;" /></li><li><p><strong>链栈的出栈</strong></p><p>1.首先判断是否栈空,栈空报错</p><p>2.保存删除结点的数据域</p><p>3.删除结点</p><p>4.更新栈顶指针</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">Status <span class="title">Pop</span><span class="params">(LinkStack &S,SElemType e)</span></span>{</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->data; <span class="comment">// 将data值保存在元素e中</span></span><br><span class="line"> LinkStack p = S; <span class="comment">//生成新结点p指向S</span></span><br><span class="line"> S = S->next; <span class="comment">// 移动S指向栈顶</span></span><br><span class="line"> <span class="keyword">delete</span> p; <span class="comment">//释放p所指向的内存</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>; </span><br><span class="line">}</span><br></pre></td></tr></table></figure><img src="https://picbed.koko2pp.cc/image-20230122195213622.png" alt="image-20230122195213622" style="zoom:50%;" /></li><li><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></pre></td><td class="code"><pre><span class="line"><span class="function">SElemType <span class="title">GetTop</span><span class="params">(LInkStack S)</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(S!=<span class="literal">NULL</span>) <span class="keyword">return</span> S->data;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><img src="https://picbed.koko2pp.cc/image-20230122195301932.png" alt="image-20230122195301932" style="zoom:50%;" /><h3 id="3-3-队列的表示和操作实现"><a href="#3-3-队列的表示和操作实现" class="headerlink" title="3.3 队列的表示和操作实现"></a>3.3 队列的表示和操作实现</h3><p>队列的基本操作</p><img src="https://picbed.koko2pp.cc/image-20230122211458762.png" alt="image-20230122211458762" style="zoom:47%;" /><h4 id="顺序队列:"><a href="#顺序队列:" class="headerlink" title="顺序队列:"></a>顺序队列:</h4><h5 id="顺序队列的定义"><a href="#顺序队列的定义" class="headerlink" title="顺序队列的定义"></a>顺序队列的定义</h5><p>队列的顺序存储结构是指分配一块连续的存储单元 来存放队列中的元素,并附设两个指针:队头指针front指向队头元素,队尾指针rear指向队尾元素的下一个位置。</p><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> MAXQSIZE 100 <span class="comment">// 指定队列的最大长度</span></span></span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span>{ <span class="comment">//定义顺序队列的结构体</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> rea; <span class="comment">//尾指针,队尾 用于插入</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>初始状态(队空条件):Q.front == Q.rear = 0</p><p>进队操作:队若不满,先送值到队尾元素,再将队尾元素指针加1</p><p>出队操作:队不空时,先取队头元素值,再将队头元素加1</p><p>会发生假(上)溢出操作,超过MaxSize的大小,因此使用<strong>循环顺序队列</strong></p><img src="https://picbed.koko2pp.cc/image-20230122212816983.png" alt="image-20230122212816983" style="zoom:50%;" /><h5 id="循环顺序队列的定义"><a href="#循环顺序队列的定义" class="headerlink" title="循环顺序队列的定义"></a>循环顺序队列的定义</h5><p>将顺序队列想象为一个环状的空间,即把<strong>存储队列元素的表从逻辑上视为一个环</strong>,称为 循环队列。可以用除法<strong>取余%运算</strong>来实现。当队首指针Q.front = MaxSize-1后,再进一个位置就自动到0的操作。</p><p><strong>初始时</strong>:Q.front = Q.rear = 0</p><p>删除操作,队头指针进1:( Q.front = Q.front + 1) % MaxSize</p><img src="https://picbed.koko2pp.cc/image-20230122213917886.png" alt="image-20230122213917886" style="zoom:50%;" /><p>插入操作,<strong>队尾指针进1</strong>:( Q.rear = Q.rear + 1) % MaxSize</p><p><strong>队列长度</strong>:(Q.rear + MaxSize - Q.front) % MaxSize</p><img src="https://picbed.koko2pp.cc/image-20230122214028006.png" alt="image-20230122214028006" style="zoom:53%;" /><img src="https://picbed.koko2pp.cc/image-20230122214010825.png" alt="image-20230122214010825" style="zoom:43%;" /><img src="https://picbed.koko2pp.cc/image-20230122214155660.png" alt="image-20230122214155660" style="zoom:60%;" /><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> MAXQSIZE 100 <span class="comment">//设置最大队列长度</span></span></span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">struct</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">}SqQueue;</span><br></pre></td></tr></table></figure><h5 id="循环顺序队列的基本操作"><a href="#循环顺序队列的基本操作" class="headerlink" title="循环顺序队列的基本操作"></a>循环顺序队列的基本操作</h5><ul><li><p>队列初始化:分配空间,初始化Q.base; Q.front, Q.rear</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="function">Status <span class="title">InitQueue</span><span class="params">(SqQueue &Q)</span></span>{</span><br><span class="line"> Q.base = <span class="keyword">new</span> QElemType[MAXQSIZE]; <span class="comment">//分配固定数组空间</span></span><br><span class="line"> <span class="keyword">if</span>(!Q.base) <span class="built_in">exit</span>(OVERFLOW); <span class="comment">// 内存已满,分配空间失败,报错</span></span><br><span class="line"> Q.front = Q.rear = <span class="number">0</span>;<span class="comment">//头指针和尾指针置为0,创建空队列</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">QueueLength</span><span class="params">(SqQueue Q)</span></span>{</span><br><span class="line"> <span class="keyword">return</span> ((Q.rear + MaxSize - Q.front) % MaxSize);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><img src="https://picbed.koko2pp.cc/image-20230122215208129.png" alt="image-20230122215208129" style="zoom:50%;" /></li><li><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></pre></td><td class="code"><pre><span class="line"><span class="function">Status <span class="title">EnQueue</span><span class="params">(SqQueue &Q, QElemType e)</span></span>{</span><br><span class="line"> <span class="keyword">if</span>((Q.rear+<span class="number">1</span>)%MAXQSIZE == Q.font) <span class="keyword">return</span> ERROR; <span class="comment">// 队满报错</span></span><br><span class="line"> Q.base[rear] = e; <span class="comment">//将新元素放在尾指针位置</span></span><br><span class="line"> Q.rear = (Q.rear+<span class="number">1</span>)%MAXQSIZE; <span class="comment">//更新尾指针位置,队尾指针+1</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><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></pre></td><td class="code"><pre><span class="line"><span class="function">Status <span class="title">DeQueue</span><span class="params">(SqQueue &Q, QElemType &e)</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(Q.rear==Q.front) <span class="keyword">return</span> ERROR; <span class="comment">//队空报错</span></span><br><span class="line"> e = Q.base[front]; <span class="comment">//用元素e保存要删除的队头元素</span></span><br><span class="line"> Q.front = (Q.front+<span class="number">1</span>)%MAXQSIZE; <span class="comment">//更新头指针位置,队头指针+1</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><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></pre></td><td class="code"><pre><span class="line"><span class="function">QElemType <span class="title">GetHead</span><span class="params">(SqQueue Q)</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(Q.front != Q.rear) <span class="comment">//队列不为空</span></span><br><span class="line"> <span class="keyword">return</span> Q.base[front]; <span class="comment">//返回队列头指针元素</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">return</span> ERROR;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><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></pre></td><td class="code"><pre><span class="line"><span class="function">Status <span class="title">isEmpty</span><span class="params">(SqQueue Q)</span>)</span>{</span><br><span class="line"> <span class="keyword">if</span>(Q.front == Q.rear) </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="keyword">else</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>; <span class="comment">//队列不为空</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><h4 id="链队列:"><a href="#链队列:" class="headerlink" title="链队列:"></a>链队列:</h4><h5 id="链队列的定义"><a href="#链队列的定义" class="headerlink" title="链队列的定义"></a>链队列的定义</h5><p>队列的链式表示称为链队列,实际上是一个同时带有队头指针和队尾指针的单链表,头指针指向队头结点,尾指针指向队尾结点,即单链表的最后一个结点(注意:与顺序存储 不同)</p><img src="https://picbed.koko2pp.cc/image-20230122225519857.png" alt="image-20230122225519857" style="zoom:50%;" /><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span> <span class="title class_">QNode</span>{ <span class="comment">//定义结构:链式队列的结点</span></span><br><span class="line"> QlemType data;<span class="comment">//数据域</span></span><br><span class="line"> <span class="keyword">struct</span> <span class="title class_">QNode</span> *next;<span class="comment">//指针域</span></span><br><span class="line">}QNode,*QuenePtr;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span>{<span class="comment">//定义结构:链式队列</span></span><br><span class="line"> QuenePtr front,rear; <span class="comment">//队头和队尾指针</span></span><br><span class="line">}LinkQueue;</span><br></pre></td></tr></table></figure><p>空队列:Q.front == NULL 切 Q.rear == NULL</p><img src="https://picbed.koko2pp.cc/image-20230122230035685.png" alt="image-20230122230035685" style="zoom:50%;" /><h5 id="链队列的基本操作"><a href="#链队列的基本操作" class="headerlink" title="链队列的基本操作"></a>链队列的基本操作</h5><ul><li><p>链队列的初始化:初始化 链表和 front和rear指针</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">Status <span class="title">InitQueue</span><span class="params">(LinkQueue &Q)</span></span>{</span><br><span class="line"> <span class="comment">//让front和rear指针指向分配的新空间 ,并让首尾指针都指向头结点</span></span><br><span class="line"> Q.front = Q.rear = (QueuePtr)<span class="built_in">malloc</span>(<span class="built_in">sizeof</span>(QNode)); </span><br><span class="line"> <span class="keyword">if</span>(!Q.front) <span class="built_in">exit</span>(OVERFLOW); <span class="comment">//内存满,分配失败</span></span><br><span class="line"> Q.front -> next = <span class="literal">NULL</span>; <span class="comment">//将头结点next域置空</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><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></pre></td><td class="code"><pre><span class="line"><span class="function">Status <span class="title">isEmpty</span><span class="params">(LinkQueue Q)</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(Q.rear == Q.front)</span><br><span class="line"> <span class="keyword">return</span> <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> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><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="function">Status <span class="title">DestroyQueue</span><span class="params">(LinkQueue &Q)</span></span>{</span><br><span class="line"> <span class="keyword">while</span>(Q.front){ <span class="comment">//判断队列是否存在</span></span><br><span class="line"> <span class="comment">//p指向下一结点,删除原结点,更新front指针</span></span><br><span class="line"> p=(QNode*)<span class="built_in">malloc</span>(<span class="built_in">sizeof</span>(QNode));</span><br><span class="line"> p = Q.front->next; <span class="built_in">free</span>(Q.front); Q.front = p;</span><br><span class="line"> <span class="comment">//或者使用已有的指针,实现思路一样:</span></span><br><span class="line"> <span class="comment">//rear = Q.front->next; free(Q.front); Q.front = rear;</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>链队列的入队:尾结点插入。建立一个新结点,将新结点插入到链表的尾部,并该让 Q.rear 指向这个新插入的结点(若原队列是一个空对,则令 Q.front 也指向该结点)</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">Status <span class="title">EnQueue</span><span class="params">(LinkQueue &Q, QlemType e)</span></span>{</span><br><span class="line"> p = (QNode*)<span class="built_in">malloc</span>(<span class="built_in">sizeof</span>(QNode)); <span class="comment">//创建新结点:找一块内存,让指针p指向它</span></span><br><span class="line"> <span class="keyword">if</span>(!p) <span class="built_in">exit</span>(OVERFLOW); <span class="comment">//内存满分配失败</span></span><br><span class="line"> p->data = e; p->next = null; <span class="comment">//准备好新结点</span></span><br><span class="line"> Q.rear->next = p; <span class="comment">//插入新结点</span></span><br><span class="line"> Q.rear = p; <span class="comment">//更新尾指针</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="https://picbed.koko2pp.cc/image-20230122232243916.png" alt="image-20230122232243916" style="zoom:50%;" /><img src="https://picbed.koko2pp.cc/image-20230122232309706.png" alt="image-20230122232309706" style="zoom:50%;" /></p></li><li><p>链队列的出队:首先判断队列是否为空,若不空则取出队头元素,将其从链表中摘除,并让 Q.front 指向下一个结点(若该结点为最后一个结点,则置 Q.front 和 Q.rear 都为 NULL)</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="function">Status <span class="title">DeQueue</span><span class="params">(LinkQueue &Q, QlemType &e)</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(Q.rear == Q.front) <span class="keyword">return</span> ERROR;</span><br><span class="line"> p = (QNode*)<span class="built_in">malloc</span>(<span class="built_in">sizeof</span>(QNode)); </span><br><span class="line"> p = Q.front->next; <span class="comment">//指针p指向要删除的结点</span></span><br><span class="line"> e = p->data;<span class="comment">//保存要删除结点的数据域</span></span><br><span class="line"> <span class="keyword">if</span>(Q.rear == p) Q.rear = Q.front; <span class="comment">//尾结点指向的就是首元结点,就先把Q.rear一走</span></span><br><span class="line"> Q.front->next = p->next; <span class="comment">// 链表中删除头结点</span></span><br><span class="line"> <span class="keyword">delete</span> p;<span class="comment">//内存中释放删除结点内存</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="https://picbed.koko2pp.cc/image-20230122232356126.png" alt="image-20230122232356126" style="zoom:50%;" /><img src="https://picbed.koko2pp.cc/image-20230122232418658.png" alt="image-20230122232418658" style="zoom:50%;" /> </p><p>if语句:</p><p><img src="https://picbed.koko2pp.cc/image-20230122232601973.png" alt="image-20230122232601973" style="zoom:50%;" /><img src="https://picbed.koko2pp.cc/image-20230122232616766.png" alt="image-20230122232616766" style="zoom:50%;" /></p></li><li><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></pre></td><td class="code"><pre><span class="line"><span class="function">Status <span class="title">GetHead</span><span class="params">(LinkQueue Q, QlemType &e)</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(Q.rear == Q.front) <span class="keyword">return</span> ERROR;</span><br><span class="line"> e = Q.front->next->data;</span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><h2 id="四、串、数组、广义表"><a href="#四、串、数组、广义表" class="headerlink" title="四、串、数组、广义表"></a>四、串、数组、广义表</h2><p><u>线性表</u> 和 <u>栈和队列</u>(操作受限的线性表)的线性结构 可以表示为:(a<sub>1</sub>, a<sub>2</sub>, a<sub>3</sub>, …, a<sub>n</sub>)</p><p>串:是内容受限的线性表,每个数据元素只能是字符;</p><p>数组:是线性结构的推广,线性表的每个元素又是线性表;</p><p>广义表:是线性结构的推广,广义表的数据元素是原子或者广义表;</p><h3 id="4-1-串的类型定义、存储结构"><a href="#4-1-串的类型定义、存储结构" class="headerlink" title="4.1 串的类型定义、存储结构"></a>4.1 串的类型定义、存储结构</h3><h4 id="4-1-1-串的定义"><a href="#4-1-1-串的定义" class="headerlink" title="4.1.1 串的定义"></a>4.1.1 串的定义</h4><p>串(string)是由**<u>零个或多个字符组成的有限序列</u>**,一般记作 S = “a<sub>1</sub> a<sub>2</sub> … a<sub>n</sub>“, (n>=0,串长度),S为串名。a<sub>i</sub> (1≤i≤n)可以是字符(字母、数字、或者其它字符)</p><p><strong>几个术语</strong>:</p><p><strong>子串</strong>:一个传中任意连续字符组成的子序列(含空串)称为该串的子串。例如,”abcde”的字串有:””, “a”,”ab”,”abc”,”abcd”,”abcde”等。<strong>真子串</strong>是指不包含自身的所有子串。</p><p><strong>主串</strong>:包含子串的串相应地称为主串,空串是任意串的子串,任意串是其自身的子串。</p><p><strong>字符位置</strong>:字符在序列中的位置为该字符在串中的位置</p><p><strong>子串位置</strong>:子串第一个字符在主串中的位置</p><p><strong>空串</strong>:<u>长度为零</u>的串,不包含任何字符””</p><p><strong>空格串</strong>:由一个或者多个空格组成的串,与空串不同,空格串” “的<u>长度≥1</u></p><p><strong>串相等</strong>:当且仅当两个串的长度相等并且各个对应位置上的字符都相同时,这两个串是相等的。所有空串相等</p><p><strong>模式匹配</strong>:确定子串<u>从主串的某个位置开始后,在主串中<strong>首次出现的位置</strong>的运算</u>。在串匹配中,一般将主串称为目标串,子串称为模式串。</p><p>例:假设串A、B、C、D分别为:</p><p>A = ‘data’,B = ‘structure’,C = ‘datastructure’,D = ‘data structure’</p><p>长度分别为4、9、13、14,A和B都是C和D的子串,A在C和D的位置都是1,B在C和D的位置分别是5和6。</p><h4 id="4-1-2-串的抽象数据类型定义"><a href="#4-1-2-串的抽象数据类型定义" class="headerlink" title="4.1.2 串的抽象数据类型定义"></a>4.1.2 串的抽象数据类型定义</h4><img src="https://picbed.koko2pp.cc/image-20230129233509244.png" alt="image-20230129233509244" style="zoom:50%;" /><p>串的实现方法有:<u>定长顺序串、堆串和块链串</u>。串中元素逻辑关系和线性表相同,串可以采用与线性表相同的存储结构,串→ 顺序存储结构→顺序串;串 → 链式存储结构→链串</p><h4 id="4-1-3-顺序串的表示"><a href="#4-1-3-顺序串的表示" class="headerlink" title="4.1.3 顺序串的表示"></a>4.1.3 顺序串的表示</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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> MAXLEN 50 <span class="comment">//字符串的最大长度</span></span></span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span>{</span><br><span class="line"> <span class="type">char</span> ch[MAXLEN+<span class="number">1</span>]; <span class="comment">//存储串的一维字符型数组,+1是因为一般0号不用</span></span><br><span class="line"> <span class="type">int</span> length; <span class="comment">//串的当前长度</span></span><br><span class="line">}SString;</span><br></pre></td></tr></table></figure><h4 id="4-1-4-块串"><a href="#4-1-4-块串" class="headerlink" title="4.1.4 块串"></a>4.1.4 块串</h4><p>一般链串的存储密度较低,将多个字符放在一个结点中,即块串</p><img src="https://picbed.koko2pp.cc/image-20230129234548582.png" alt="image-20230129234548582" style="zoom:50%;" /><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> CHUNKSIZE 80 <span class="comment">//块,即每个结点的元素多少由用户定义</span></span></span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span> <span class="title class_">Chunk</span>{</span><br><span class="line"> <span class="type">char</span> ch[CHUNKSIZE]; <span class="comment">//数据域:存储一个块的一维字符数组</span></span><br><span class="line"> <span class="keyword">struct</span> <span class="title class_">Chunk</span> *next; <span class="comment">//指针域:指向下一个块</span></span><br><span class="line">}Chunk;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span>{</span><br><span class="line"> Chunk *head,*tail; <span class="comment">//串的头指针和尾指针</span></span><br><span class="line"> <span class="type">int</span> curlen; <span class="comment">//串的当前长度</span></span><br><span class="line">}LString <span class="comment">//字符串的块链结构</span></span><br></pre></td></tr></table></figure><h3 id="4-2-串的模式匹配"><a href="#4-2-串的模式匹配" class="headerlink" title="4.2 串的模式匹配"></a>4.2 串的模式匹配</h3><p>确定主串中所含子串在某位置后第一次出现的位置。主串S称为目标串,子串T为模式串</p><h4 id="4-2-4-BF模式匹配算法"><a href="#4-2-4-BF模式匹配算法" class="headerlink" title="4.2.4 BF模式匹配算法"></a>4.2.4 BF模式匹配算法</h4><p>Brute-Froce暴力解法:从S的每一个字母开始一次与T的字符进行匹配。假定使用顺序串</p><img src="https://picbed.koko2pp.cc/d5fe7968d973df602f9510d81ccf423.jpg" alt="d5fe7968d973df602f9510d81ccf423" style="zoom:67%;" /><p><strong>BF算法实现:</strong></p><p>Index(S,T,pos):将主串的第pos个字符和模式串的第一个字符比较,若相等,继续逐个比较后续字符;若不等,从主串的下一个字符起,重新与模式串的第一个字符比较。直到S和T相等,返回匹配的第一个字符序号,否则匹配失败返回0;</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="function"><span class="type">int</span> <span class="title">Index_BF</span><span class="params">(SString S, SString T, <span class="type">int</span> pos)</span></span>{</span><br><span class="line"> <span class="type">int</span> i=pos,j=<span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span>( i<=S.length && j<=T.length ){<span class="comment">//循环条件:若i指针在主串内且j在子串内</span></span><br><span class="line"> <span class="keyword">if</span>(S.ch[i]==T.ch[i]){ <span class="comment">//主串和子串对应pos的字符相等,则依次匹配下一个</span></span><br><span class="line"> ++i;++j;</span><br><span class="line"> }<span class="keyword">else</span>{ <span class="comment">//主串和子串对应pos的字符不相等,则i回溯到原来的下一个位置,j变为1</span></span><br><span class="line"> i=i-j+<span class="number">2</span>;</span><br><span class="line"> j=<span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(j>=T.length){</span><br><span class="line"> <span class="keyword">return</span> i-T.length; <span class="comment">//j已出子串,证明匹配成功,返回第一个字符位置</span></span><br><span class="line"> }<span class="keyword">else</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><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>BF算法的时间复杂度:O(n*m)</strong></p><img src="https://picbed.koko2pp.cc/image-20230130001836055.png" alt="image-20230130001836055" style="zoom:50%;" /><h4 id="4-2-5-KMP模式匹配算法"><a href="#4-2-5-KMP模式匹配算法" class="headerlink" title="4.2.5 KMP模式匹配算法"></a>4.2.5 KMP模式匹配算法</h4><p>特点:采用next指针数组消除指针回溯,用next数组告诉i和j应该回溯到哪里,而不是从头开始,省去重复部分。如图P0不等于t1且P0不等于t2,因此指针i不用回到pos2重新比较</p><p><img src="https://picbed.koko2pp.cc/GIF 2023-1-30 0-31-57.gif" alt="GIF 2023-1-30 0-31-57" style="zoom: 50%;" /><img src="https://picbed.koko2pp.cc/image-20230130003330341.png" alt="image-20230130003330341" style="zoom:33%;" /></p><p>KMP:</p><img src="https://picbed.koko2pp.cc/GIF 2023-1-30 0-37-22.gif" alt="GIF 2023-1-30 0-37-22" style="zoom:50%;" /><p>主串不同子串动</p><p><strong>KMP算法的时间复杂度:O(n+m)</strong></p><p>next数组求法:</p><p>① 写出模式串;</p><p>②模式串的第一位写0,第二位写1;</p><p>③从第3位到第n位:比较前n-1位,得出最长公共前后缀匹配长度K,则填K+1;K为0 则填1</p><img src="https://picbed.koko2pp.cc/221c1d44e8968b72ec8acfda4ae32e2.jpg" alt="221c1d44e8968b72ec8acfda4ae32e2" style="zoom:57%;" /><p><strong>KMP算法表示:</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><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">Index_KMP</span><span class="params">(SString S, SString T, <span class="type">int</span> pos)</span></span>{</span><br><span class="line"> i=pos,j=<span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span>( i<=S.length && j<=T.length ){<span class="comment">//循环条件:若i指针在主串内且j在子串内</span></span><br><span class="line"> <span class="keyword">if</span>(S.ch[i]==T.ch[i]){ <span class="comment">//主串和子串对应pos的字符相等,则依次匹配下一个</span></span><br><span class="line"> ++i;++j;</span><br><span class="line"> }<span class="keyword">else</span>{ <span class="comment">//主串和子串对应pos的字符不相等,则i不变,j后退</span></span><br><span class="line"> j=next[j];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(j>=T.length){</span><br><span class="line"> <span class="keyword">return</span> i-T.length; <span class="comment">//j已出子串,证明匹配成功,返回第一个字符位置</span></span><br><span class="line"> }<span class="keyword">else</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><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">get_next</span><span class="params">(SString T, <span class="type">int</span> &next[])</span></span>{</span><br><span class="line"> <span class="type">int</span> i=<span class="number">1</span>,j=<span class="number">0</span>;</span><br><span class="line"> next[<span class="number">1</span>]=<span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span>(i<T.length){</span><br><span class="line"> <span class="keyword">if</span>(j==<span class="number">0</span> || T.ch[i]==T.ch[j]){</span><br><span class="line"> ++i;++j;</span><br><span class="line"> next[i]=j;</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> j=next[j];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="4-3-多维数组-地址运算"><a href="#4-3-多维数组-地址运算" class="headerlink" title="4.3 多维数组(地址运算)"></a>4.3 多维数组(地址运算)</h3><p>多为数组和广义表可以看为是线性表的扩展,即它们的数据元素构成线性表,而数据元素本身又是一个线性结构。</p><ul><li><p><strong>数组定义</strong>:按照一定格式排列的,具有相同类型的数据元素的集合;</p></li><li><p>数组特点:结构固定——定义后,维数和维界不变;</p></li><li><p>数组基本操作:除了结构的初始化和销毁,只有取元素和修改元素。因此,一般使用顺序存储结构</p></li><li><p><strong>一维数组</strong>:线性表中的数据元素为非结构的简单元素为一维数组。Eg:int num[5] = {0, 1, 2, 3, 4}; 线性结构。</p><ul><li><img src="https://picbed.koko2pp.cc/image-20230130233353056.png" alt="image-20230130233353056" style="zoom:50%;" /></li></ul></li><li><p><strong>二维数组</strong>:一维数组中的元素又是一维数组结构,则为二维数组。二维数组的逻辑结构可以堪为线性结构(以行优先行/或以列优先),也可以看为非线性结构(如图,a<sub>11</sub>有两个前趋和两个后继,不是1v1的线性结构)。声明格式:数组类型 变量名称[行数] [列数];</p><ul><li><img src="https://picbed.koko2pp.cc/image-20230130232738038.png" alt="image-20230130232738038" style="zoom:57%;" /><img src="https://picbed.koko2pp.cc/image-20230130232914103.png" alt="image-20230130232914103" style="zoom:43%;" /></li><li><img src="https://picbed.koko2pp.cc/image-20230130233722965.png" alt="image-20230130233722965" style="zoom:37%;" /></li><li><img src="https://picbed.koko2pp.cc/image-20230130233833524.png" alt="image-20230130233833524" style="zoom:60%;" /></li><li>例题:<img src="https://picbed.koko2pp.cc/image-20230130233944184.png" alt="image-20230130233944184" style="zoom:67%;" /></li></ul></li><li><p>三维数组:页,行,列。二维数组中的元素又是一个一维数组,称为三维数组。</p><ul><li><img src="https://picbed.koko2pp.cc/image-20230130234025637.png" alt="image-20230130234025637" style="zoom:37%;" /><img src="https://picbed.koko2pp.cc/image-20230130234053424.png" alt="image-20230130234053424" style="zoom:50%;" /></li></ul></li><li><p>n维数组:<img src="https://picbed.koko2pp.cc/image-20230130234446293.png" alt="image-20230130234446293" style="zoom:60%;" /></p></li><li><p>求地址的例题:<img src="https://picbed.koko2pp.cc/image-20230130234514462.png" alt="image-20230130234514462" style="zoom:53%;" /></p></li></ul><h3 id="4-4-矩阵的压缩存储"><a href="#4-4-矩阵的压缩存储" class="headerlink" title="4.4 矩阵的压缩存储"></a>4.4 矩阵的压缩存储</h3><p>用二维数组表示矩阵,但高阶矩阵中存在许多值相同或者值为零的元素,并且这些元素的分布存在一定规律,称这类矩阵为特殊矩阵。如果使用传统的二维数组对特殊矩阵进行存储会造成很大的空间浪费,为节省存储空间,对这类矩阵进行压缩存储。Eg: 对称矩阵,对角矩阵,三角矩阵,稀疏矩阵</p><ul><li><p>对称矩阵:元素沿着主对角线对称</p><img src="https://picbed.koko2pp.cc/image-20230130235147418.png" alt="image-20230130235147418" style="zoom:57%;" /><img src="https://picbed.koko2pp.cc/image-20230130235235377.png" alt="image-20230130235235377" style="zoom:60%;" /></li><li><p>三角矩阵</p><img src="https://picbed.koko2pp.cc/image-20230130235332302.png" alt="image-20230130235332302" style="zoom:50%;" /></li><li><p>对角矩阵</p><p><img src="https://picbed.koko2pp.cc/image-20230130235408270.png" alt="image-20230130235408270" style="zoom:45%;" /><img src="https://picbed.koko2pp.cc/image-20230130235422750.png" alt="image-20230130235422750" style="zoom:50%;" /></p></li><li><p>稀疏矩阵</p><img src="https://picbed.koko2pp.cc/image-20230130235514073.png" alt="image-20230130235514073" style="zoom:60%;" /><ul><li><p><u>三元组顺序表存储稀疏矩阵</u>。三元组顺序表又称为有序的双下标法。优点:非零元素在表中按照行序有序存储,便于进行以行顺序处理的矩阵运算。缺点:不能随机存储,<u>插入修改不便(元素变成0,需要踢出该三元组顺序表;或者0元素修改为非零元素,三元组顺序表需要插入该元素)</u></p><img src="https://picbed.koko2pp.cc/image-20230130235532276.png" alt="image-20230130235532276" style="zoom:60%;" /><img src="https://picbed.koko2pp.cc/image-20230130235559161.png" alt="image-20230130235559161" style="zoom:67%;" /></li><li><p>链式矩阵的链式存储结构,十字链表</p><img src="https://picbed.koko2pp.cc/image-20230131000012383.png" alt="image-20230131000012383" style="zoom:50%;" /><img src="https://picbed.koko2pp.cc/image-20230131000027910.png" alt="image-20230131000027910" style="zoom:50%;" /><p>例题:</p><img src="https://picbed.koko2pp.cc/image-20230131000041145.png" alt="image-20230131000041145" style="zoom:50%;" /></li></ul></li></ul><h3 id="4-5-广义表"><a href="#4-5-广义表" class="headerlink" title="4.5 广义表"></a>4.5 广义表</h3><p><img src="https://picbed.koko2pp.cc/image-20230131000125369.png" alt="image-20230131000125369" style="zoom:45%;" /><img src="https://picbed.koko2pp.cc/image-20230131000135800.png" alt="image-20230131000135800" style="zoom:45%;" /></p><img src="https://picbed.koko2pp.cc/image-20230131000147069.png" alt="image-20230131000147069" style="zoom:57%;" /><p><img src="https://picbed.koko2pp.cc/image-20230131000221557.png" alt="image-20230131000221557" style="zoom:47%;" /><img src="https://picbed.koko2pp.cc/image-20230131000234635.png" alt="image-20230131000234635" style="zoom:47%;" /></p><img src="https://picbed.koko2pp.cc/image-20230131000247551.png" alt="image-20230131000247551" style="zoom:47%;" />]]></content>
</entry>
<entry>
<title>第三篇文章</title>
<link href="/2023/01/01/%E7%AC%AC%E4%B8%89%E7%AF%87%E6%96%87%E7%AB%A0/"/>
<url>/2023/01/01/%E7%AC%AC%E4%B8%89%E7%AF%87%E6%96%87%E7%AB%A0/</url>
<content type="html"><![CDATA[<h2 id="这是我的第三篇文章-test"><a href="#这是我的第三篇文章-test" class="headerlink" title="这是我的第三篇文章 test"></a>这是我的第三篇文章 test</h2>]]></content>
</entry>
<entry>
<title>剑指offer</title>
<link href="/2023/01/01/%E5%89%91%E6%8C%87offer/"/>
<url>/2023/01/01/%E5%89%91%E6%8C%87offer/</url>
<content type="html"><![CDATA[<p>#暑期实习剑指offer记录 c++</p><h4 id="剑指-Offer-03-数组中重复的数字"><a href="#剑指-Offer-03-数组中重复的数字" class="headerlink" title="剑指 Offer 03. 数组中重复的数字"></a>剑指 Offer 03. <a href="https://leetcode.cn/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/">数组中重复的数字</a></h4><img src="https://picbed.koko2pp.cc/image-20230225215409756.png" alt="image-20230225215409756" style="zoom:67%;" /><ul><li><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">findRepeatNumber</span><span class="params">(vector<<span class="type">int</span>>& nums)</span> </span>{</span><br><span class="line"> <span class="type">int</span> n = nums.<span class="built_in">size</span>();</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i < n; i++){</span><br><span class="line"> <span class="keyword">while</span>(i != nums[i] && nums[nums[i]] != nums[i])</span><br><span class="line"> <span class="built_in">swap</span>(nums[i], nums[nums[i]]);</span><br><span class="line"> <span class="comment">//一个标号一个坑,nums做自己的map数组</span></span><br><span class="line"> <span class="keyword">if</span>(i != nums[i] && nums[nums[i]] == nums[i]) <span class="keyword">return</span> nums[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure></li></ul><h4 id="剑指-Offer-04-二维数组中的查找"><a href="#剑指-Offer-04-二维数组中的查找" class="headerlink" title="剑指 Offer 04 二维数组中的查找"></a>剑指 Offer 04 <a href="https://leetcode.cn/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/">二维数组中的查找</a></h4><img src="https://picbed.koko2pp.cc/image-20230225211938838.png" alt="image-20230225211938838" style="zoom:67%;" /><ul><li><p>题解1:</p><img src="https://picbed.koko2pp.cc/image-20230226111011800.png" alt="image-20230226111011800" style="zoom: 50%;" /><img src="https://picbed.koko2pp.cc/image-20230226111040716.png" alt="image-20230226111040716" style="zoom:67%;" /><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="comment">//target<右上角,右上角的列都比target大;</span></span><br><span class="line"><span class="comment">//target>右上角,右上角的行都比target小</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">findNumberIn2DArray</span><span class="params">(vector<vector<<span class="type">int</span>>>& matrix, <span class="type">int</span> target)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(matrix.<span class="built_in">empty</span>() || matrix[<span class="number">0</span>].<span class="built_in">empty</span>()) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> <span class="comment">//从右上角往左下角走</span></span><br><span class="line"> <span class="type">int</span> i = <span class="number">0</span>, j = matrix[<span class="number">0</span>].<span class="built_in">size</span>() - <span class="number">1</span>; </span><br><span class="line"> <span class="keyword">while</span>(i < matrix.<span class="built_in">size</span>() && j >= <span class="number">0</span>){</span><br><span class="line"> <span class="keyword">if</span>(target == matrix[i][j]) <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> <span class="keyword">if</span>(target < matrix[i][j]) j--; </span><br><span class="line"> <span class="keyword">else</span> i++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure></li><li><p>题解2:</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="comment">//逐行进行二分查找</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">findNumberIn2DArray</span><span class="params">(vector<vector<<span class="type">int</span>>>& matrix, <span class="type">int</span> target)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(matrix.<span class="built_in">empty</span>() || matrix[<span class="number">0</span>].<span class="built_in">empty</span>()) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i < matrix.<span class="built_in">size</span>(); i ++){</span><br><span class="line"> <span class="type">int</span> l = <span class="number">0</span>, r = matrix[<span class="number">0</span>].<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span>(l <= r){</span><br><span class="line"> <span class="type">int</span> mid = (l + r) / <span class="number">2</span>;</span><br><span class="line"> <span class="keyword">if</span>(matrix[i][mid] == target) <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(matrix[i][mid] > target) r = mid - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">else</span> l = mid + <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure></li></ul><h4 id="剑指-Offer-05-替换空格"><a href="#剑指-Offer-05-替换空格" class="headerlink" title="剑指 Offer 05 替换空格"></a>剑指 Offer 05 <a href="https://leetcode.cn/problems/ti-huan-kong-ge-lcof">替换空格</a></h4><img src="https://picbed.koko2pp.cc/image-20230225213115528.png" alt="image-20230225213115528" style="zoom:67%;" /><ul><li><p>题解:开一个新string,从前往后遍历,遇到新空格 后面加”%20” 否则补原来正常字符串</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="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function">string <span class="title">replaceSpace</span><span class="params">(string s)</span> </span>{</span><br><span class="line"> string tmp;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i < s.<span class="built_in">size</span>(); i ++){</span><br><span class="line"> <span class="keyword">if</span>(s[i]==<span class="string">' '</span>) tmp += <span class="string">"%20"</span>;</span><br><span class="line"> <span class="keyword">else</span> tmp += s[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> tmp;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure></li></ul><h4 id="剑指-Offer-06-从尾到头打印链表"><a href="#剑指-Offer-06-从尾到头打印链表" class="headerlink" title="剑指 Offer 06. 从尾到头打印链表"></a>剑指 Offer 06. <a href="https://leetcode.cn/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof/">从尾到头打印链表</a></h4><img src="https://picbed.koko2pp.cc/image-20230225213614660.png" alt="image-20230225213614660" style="zoom:67%;" /><ul><li><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="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function">vector<<span class="type">int</span>> <span class="title">reversePrint</span><span class="params">(ListNode* head)</span> </span>{</span><br><span class="line"> vector<<span class="type">int</span>> ans;</span><br><span class="line"> <span class="keyword">while</span>(head != <span class="literal">NULL</span>) ans.<span class="built_in">push_back</span>(head -> val), head = head -> next;</span><br><span class="line"> <span class="built_in">reverse</span>(ans.<span class="built_in">begin</span>(), ans.<span class="built_in">end</span>());</span><br><span class="line"> <span class="keyword">return</span> ans;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure></li></ul><h4 id="剑指-Offer-07-重建二叉树"><a href="#剑指-Offer-07-重建二叉树" class="headerlink" title="剑指 Offer 07. 重建二叉树"></a>剑指 Offer 07. <a href="https://leetcode.cn/problems/zhong-jian-er-cha-shu-lcof/">重建二叉树</a></h4><img src="https://picbed.koko2pp.cc/image-20230225220019609.png" alt="image-20230225220019609" style="zoom: 67%;" /><ul><li><p>题解:</p><ul><li><img src="https://picbed.koko2pp.cc/image-20230226110735081.png" alt="image-20230226110735081"></li><li><strong>先根据先序遍历找出根节点3</strong>,中序遍历中根节点左边数的在根的左边[9],根节点右边数的在根的右边[15, 50, 7];</li><li><strong>递归</strong> 左子树[9] 和 右子树[15, 50, 7],先序遍历找根节点.. 中序遍历 根节点左和右为其左子树和右子树</li></ul><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//递归+哈希表(需要快速找出中序遍历里根节点的位置)</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Definition for a binary tree node.</span></span><br><span class="line"><span class="comment"> * struct TreeNode {</span></span><br><span class="line"><span class="comment"> * int val;</span></span><br><span class="line"><span class="comment"> * TreeNode *left;</span></span><br><span class="line"><span class="comment"> * TreeNode *right;</span></span><br><span class="line"><span class="comment"> * TreeNode(int x) : val(x), left(NULL), right(NULL) {}</span></span><br><span class="line"><span class="comment"> * };</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> vector<<span class="type">int</span>> preorder;</span><br><span class="line"> unordered_map<<span class="type">int</span>, <span class="type">int</span>> dic;<span class="comment">// 标记中序遍历</span></span><br><span class="line"> <span class="function">TreeNode* <span class="title">recur</span><span class="params">(<span class="type">int</span> root, <span class="type">int</span> left, <span class="type">int</span> right)</span> </span>{ </span><br><span class="line"> <span class="keyword">if</span>(left > right) <span class="keyword">return</span> <span class="literal">nullptr</span>; <span class="comment">/// 相等的话就是自己,递归终止</span></span><br><span class="line"> TreeNode* node = <span class="keyword">new</span> <span class="built_in">TreeNode</span>(preorder[root]); <span class="comment">//建立根节点</span></span><br><span class="line"> <span class="comment">//根节点在中序遍历 inorder 中的索引i, 划分根节点、左子树 右子树</span></span><br><span class="line"> <span class="type">int</span> i = dic[preorder[root]];</span><br><span class="line"> node->left = <span class="built_in">recur</span>(root + <span class="number">1</span>, left, i - <span class="number">1</span>); <span class="comment">// 开启左子树递归</span></span><br><span class="line"> node->right = <span class="built_in">recur</span>(root + i - left + <span class="number">1</span>, i + <span class="number">1</span>, right); <span class="comment">// 开启右子树递归</span></span><br><span class="line"> <span class="keyword">return</span> node; <span class="comment">// 回溯返回根节点</span></span><br><span class="line"> }</span><br><span class="line"> <span class="function">TreeNode* <span class="title">buildTree</span><span class="params">(vector<<span class="type">int</span>>& preorder, vector<<span class="type">int</span>>& inorder)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>->preorder = preorder;</span><br><span class="line"> <span class="comment">//将中序遍历的值及索引放在map中,方便递归时获取左子树与右子树的数量及其根的索引</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i < inorder.<span class="built_in">size</span>(); i++) dic[inorder[i]] = i;</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">recur</span>(<span class="number">0</span>, <span class="number">0</span>, inorder.<span class="built_in">size</span>() - <span class="number">1</span>); </span><br><span class="line"> <span class="comment">//当前根的的索引,递归树的左边界/数组左边界,递归树的右边界/数组右边界</span></span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure></li></ul><h4 id="剑指-Offer-09-用两个栈实现队列"><a href="#剑指-Offer-09-用两个栈实现队列" class="headerlink" title="剑指 Offer 09. 用两个栈实现队列"></a>剑指 Offer 09. <a href="https://leetcode.cn/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/">用两个栈实现队列</a></h4><img src="https://picbed.koko2pp.cc/image-20230226113854594.png" alt="image-20230226113854594" style="zoom:67%;" /><ul><li><p>题解:出队栈和入队栈,入队栈无条件入栈,出队栈如果为空则从入队栈压入元素后再删除</p><img src="C:\Users\16210\AppData\Local\Temp\WeChat Files\0b0a3a6e3c08ca8b403ad55522a6711.jpg" alt="0b0a3a6e3c08ca8b403ad55522a6711" style="zoom:57%;" /><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"><span class="keyword">class</span> <span class="title class_">CQueue</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> stack<<span class="type">int</span>> stack1,stack2;</span><br><span class="line"> <span class="built_in">CQueue</span>() {</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//队列尾部插入整数</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">appendTail</span><span class="params">(<span class="type">int</span> value)</span> </span>{</span><br><span class="line"> stack1.<span class="built_in">push</span>(value);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//队列头部删除整数(若队列中没有元素,deleteHead 操作返回 -1 )</span></span><br><span class="line"> <span class="comment">//出队操作需要优先检查出队栈是否有数据,若无,需要从入队栈倒入后再操作。</span></span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">deleteHead</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(stack2.<span class="built_in">empty</span>()){</span><br><span class="line"> <span class="comment">//优先检查出队栈是否有数据,若无,需要从入队栈倒入后再操作</span></span><br><span class="line"> <span class="keyword">while</span>(!stack1.<span class="built_in">empty</span>()){</span><br><span class="line"> stack2.<span class="built_in">push</span>(stack1.<span class="built_in">top</span>());</span><br><span class="line"> stack1.<span class="built_in">pop</span>();</span><br><span class="line"> }</span><br><span class="line"> } </span><br><span class="line"> <span class="comment">//把入队栈元素已压入出队栈元素中 入队栈stk1已空</span></span><br><span class="line"> <span class="keyword">if</span>(stack2.<span class="built_in">empty</span>()) <span class="keyword">return</span> <span class="number">-1</span>; <span class="comment">//两个栈均为空</span></span><br><span class="line"> <span class="keyword">else</span>{</span><br><span class="line"> <span class="comment">//出队栈不空,执行删除元素操作</span></span><br><span class="line"> <span class="type">int</span> tmp = stack2.<span class="built_in">top</span>();</span><br><span class="line"> stack2.<span class="built_in">pop</span>();</span><br><span class="line"> <span class="keyword">return</span> tmp;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Your CQueue object will be instantiated and called as such:</span></span><br><span class="line"><span class="comment"> * CQueue* obj = new CQueue();</span></span><br><span class="line"><span class="comment"> * obj->appendTail(value);</span></span><br><span class="line"><span class="comment"> * int param_2 = obj->deleteHead();</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure></li></ul><h4 id="剑指-Offer-10-I-斐波那契数列"><a href="#剑指-Offer-10-I-斐波那契数列" class="headerlink" title="剑指 Offer 10- I. 斐波那契数列"></a>剑指 Offer 10- I. <a href="https://leetcode.cn/problems/fei-bo-na-qi-shu-lie-lcof/description/">斐波那契数列</a></h4><ul><li><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="type">const</span> <span class="type">int</span> MOD = <span class="number">1e9</span>+<span class="number">7</span>;</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">fib</span><span class="params">(<span class="type">int</span> n)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(n == <span class="number">0</span>) <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">if</span>(n == <span class="number">1</span>) <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">return</span> (<span class="built_in">fib</span>(n<span class="number">-1</span>) + <span class="built_in">fib</span>(n<span class="number">-2</span>)) % MOD;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure></li><li><p>题解2:仅记录前两项的值f(n-2) f(n-1)即可 </p><img src="C:\Users\16210\AppData\Local\Temp\WeChat Files\12651b24d1ec60b0e9c6f01d41e2193.jpg" alt="12651b24d1ec60b0e9c6f01d41e2193" style="zoom:37%;" /><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">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="type">const</span> <span class="type">int</span> MOD = <span class="number">1e9</span> + <span class="number">7</span>;</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">fib</span><span class="params">(<span class="type">int</span> n)</span> </span>{</span><br><span class="line"> <span class="type">int</span> a = <span class="number">0</span>, b = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span>(n--){</span><br><span class="line"> <span class="type">int</span> c = (a + b) % MOD;<span class="comment">//求下一项</span></span><br><span class="line"> a = b % MOD, b = c % MOD; <span class="comment">//a:f(n-2), b:f(n-1) </span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> a % MOD;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure></li></ul><h4 id="剑指-Offer-10-II-青蛙跳台阶问题"><a href="#剑指-Offer-10-II-青蛙跳台阶问题" class="headerlink" title="剑指 Offer 10- II. 青蛙跳台阶问题"></a>剑指 Offer 10- II. <a href="https://leetcode.cn/problems/qing-wa-tiao-tai-jie-wen-ti-lcof/">青蛙跳台阶问题</a></h4><img src="https://picbed.koko2pp.cc/image-20230226140050001.png" alt="image-20230226140050001" style="zoom:67%;" /><ul><li><p>题解:和斐波那契数列一样,但初始条件 改为a =1,b=1</p><img src="C:\Users\16210\AppData\Local\Temp\WeChat Files\c3db6aeb320d2771d550d19c9887716.jpg" alt="c3db6aeb320d2771d550d19c9887716" style="zoom:30%;" /><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">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="type">const</span> <span class="type">int</span> MOD = <span class="number">1e9</span> + <span class="number">7</span>;</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">numWays</span><span class="params">(<span class="type">int</span> n)</span> </span>{</span><br><span class="line"> <span class="type">int</span> a = <span class="number">1</span>, b = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span>(n--){</span><br><span class="line"> <span class="type">int</span> c = (a + b) % MOD;</span><br><span class="line"> a = b % MOD, b = c % MOD;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> a % MOD;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure></li></ul><h4 id="剑指-Offer-11-旋转数组的最小数字"><a href="#剑指-Offer-11-旋转数组的最小数字" class="headerlink" title="剑指 Offer 11. 旋转数组的最小数字"></a>剑指 Offer 11. <a href="https://leetcode.cn/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/">旋转数组的最小数字</a></h4><img src="https://picbed.koko2pp.cc/image-20230226141343884.png" alt="image-20230226141343884" style="zoom:70%;" /><ul><li><p>题解1:for循环比较前后两个数</p><img src="C:\Users\16210\AppData\Local\Temp\WeChat Files\697f3d5bc39372cfb69b18141a0412d.jpg" alt="697f3d5bc39372cfb69b18141a0412d" style="zoom:33%;" /><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">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">minArray</span><span class="params">(vector<<span class="type">int</span>>& numbers)</span> </span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i < numbers.<span class="built_in">size</span>() - <span class="number">1</span>; i ++){</span><br><span class="line"> <span class="keyword">if</span>(numbers[i] > numbers[i + <span class="number">1</span>]) <span class="keyword">return</span> numbers[i + <span class="number">1</span>];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> numbers[<span class="number">0</span>];</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure></li><li><p>题解2:二分出来 第一个比第一个元素小的数,就是目标值 及最小值</p><p><img src="https://picbed.koko2pp.cc/image-20230226142955555.png" alt="image-20230226142955555" style="zoom:25%;" />旋转之前 单调递增→旋转之后,部分单增 <img src="https://picbed.koko2pp.cc/image-20230226143016020.png" alt="image-20230226143016020" style="zoom:25%;" /></p><p>发现假如去除后面重复元素,则 第一个比nums[0]小的数,就是目标值 及最小值<img src="https://picbed.koko2pp.cc/image-20230226143538138.png" alt="image-20230226143538138" style="zoom:33%;" /></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="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">minArray</span><span class="params">(vector<<span class="type">int</span>>& numbers)</span> </span>{</span><br><span class="line"> <span class="type">int</span> n = numbers.<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span>(n > <span class="number">0</span> && numbers[n] == numbers[<span class="number">0</span>]) n--; <span class="comment">//去掉后面重复元素 </span></span><br><span class="line"> <span class="keyword">if</span>( numbers[n] >= numbers[<span class="number">0</span>] ) <span class="keyword">return</span> numbers[<span class="number">0</span>]; <span class="comment">//只有前面单增的部分</span></span><br><span class="line"> <span class="comment">// 二分:第一个比第一个元素小的数,就是目标值 及最小值</span></span><br><span class="line"> <span class="type">int</span> l = <span class="number">0</span>, r = n;</span><br><span class="line"> <span class="keyword">while</span>(l < r){</span><br><span class="line"> <span class="type">int</span> mid = (l + r) >> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span>(numbers[mid] < numbers[<span class="number">0</span>] ) r = mid; <span class="comment">//[l,mid] [mid+1,r]</span></span><br><span class="line"> <span class="keyword">else</span> l = mid + <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> numbers[r];</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure></li></ul><h4 id="剑指-Offer-12-矩阵中的路径"><a href="#剑指-Offer-12-矩阵中的路径" class="headerlink" title="剑指 Offer 12. 矩阵中的路径"></a>剑指 Offer 12. <a href="https://leetcode.cn/problems/ju-zhen-zhong-de-lu-jing-lcof/description/">矩阵中的路径</a></h4><img src="https://picbed.koko2pp.cc/image-20230226161208584.png" alt="image-20230226161208584" style="zoom:67%;" /><ul><li><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><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//经典搜索问题:枚举所有可能的路径,如果存在字符串返回true 不存在返回False</span></span><br><span class="line"><span class="comment">//如何枚举所有路径? 枚举起点 再枚举方向至无路可走</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">exist</span><span class="params">(vector<vector<<span class="type">char</span>>>& board, string word)</span> </span>{</span><br><span class="line"> rows = board.<span class="built_in">size</span>();</span><br><span class="line"> cols = board[<span class="number">0</span>].<span class="built_in">size</span>();</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i < rows; i ++) {</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">0</span>; j < cols; j ++) {</span><br><span class="line"> <span class="comment">//第0个字符串开始枚举 起点坐标是所有(i,j)</span></span><br><span class="line"> <span class="keyword">if</span>(<span class="built_in">dfs</span>(board, word, i, j, <span class="number">0</span>)) <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> }</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> <span class="type">int</span> rows, cols;</span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">dfs</span><span class="params">(vector<vector<<span class="type">char</span>>>& board, string word, <span class="type">int</span> i, <span class="type">int</span> j, <span class="type">int</span> k)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(i >= rows || i < <span class="number">0</span> || j >= cols || j < <span class="number">0</span> || board[i][j] != word[k]) <span class="keyword">return</span> <span class="literal">false</span>; <span class="comment">//超边界</span></span><br><span class="line"> <span class="keyword">if</span>(k == word.<span class="built_in">size</span>() - <span class="number">1</span>) <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> board[i][j] = <span class="string">'\0'</span>;</span><br><span class="line"> <span class="type">bool</span> res = <span class="built_in">dfs</span>(board, word, i + <span class="number">1</span>, j, k + <span class="number">1</span>) || <span class="built_in">dfs</span>(board, word, i - <span class="number">1</span>, j, k + <span class="number">1</span>) ||<span class="built_in">dfs</span>(board, word, i, j + <span class="number">1</span>, k + <span class="number">1</span>) || <span class="built_in">dfs</span>(board, word, i , j - <span class="number">1</span>, k + <span class="number">1</span>); <span class="comment">//四个方向</span></span><br><span class="line"> board[i][j] = word[k];</span><br><span class="line"> <span class="keyword">return</span> res;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure></li></ul><h4 id="剑指-Offer-14-I-剪绳子"><a href="#剑指-Offer-14-I-剪绳子" class="headerlink" title="剑指 Offer 14- I. 剪绳子"></a>剑指 Offer 14- I. <a href="https://leetcode.cn/problems/jian-sheng-zi-lcof/">剪绳子</a></h4><img src="https://picbed.koko2pp.cc/image-20230226174450194.png" alt="image-20230226174450194" style="zoom:70%;" /><ul><li><p>题解:分成尽可能多的3,剩下的数分成2</p><p><img src="https://picbed.koko2pp.cc/image-20230226173856445.png" alt="image-20230226173856445"></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="comment">// 一个整数划分为若干个正整数的和,使切出来的若干个正整数的乘积最大 </span></span><br><span class="line"><span class="comment">// N%3==0 拆成多个3; N%3==1 拆成2个2和多个3; N%3==2 1个2和多个3</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">cuttingRope</span><span class="params">(<span class="type">int</span> n)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>( n <= <span class="number">3</span>) <span class="keyword">return</span> <span class="number">1</span> * (n - <span class="number">1</span>); <span class="comment">//特判 边界</span></span><br><span class="line"> <span class="type">int</span> res = <span class="number">0</span>, count3 = n / <span class="number">3</span>;</span><br><span class="line"> <span class="keyword">if</span>(n % <span class="number">3</span> == <span class="number">0</span>) <span class="keyword">return</span> <span class="built_in">pow</span>(<span class="number">3</span>, count3);</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>( n % <span class="number">3</span> == <span class="number">1</span>) <span class="keyword">return</span> <span class="built_in">pow</span>(<span class="number">3</span>, --count3) * <span class="number">4</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">return</span> <span class="built_in">pow</span>(<span class="number">3</span>, count3) * <span class="number">2</span>;</span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"></span><br></pre></td></tr></table></figure></li></ul><h4 id="剑指-Offer-14-II-剪绳子-II"><a href="#剑指-Offer-14-II-剪绳子-II" class="headerlink" title="剑指 Offer 14- II. 剪绳子 II"></a>剑指 Offer 14- II. <a href="https://leetcode.cn/problems/jian-sheng-zi-ii-lcof/">剪绳子 II</a></h4><img src="https://picbed.koko2pp.cc/image-20230226180806392.png" alt="image-20230226180806392" style="zoom:67%;" /><ul><li><p>题解:分成尽可能多的3,剩下的数分成2</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="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"> <span class="keyword">public</span>:</span><br><span class="line"> <span class="type">const</span> <span class="type">int</span> N = <span class="number">1e9</span>+<span class="number">7</span>;</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">cuttingRope</span><span class="params">(<span class="type">int</span> n)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>( n <= <span class="number">3</span>) <span class="keyword">return</span> <span class="number">1</span> * (n - <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(n == <span class="number">4</span>) <span class="keyword">return</span> n;</span><br><span class="line"> <span class="type">long</span> res = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span>(n > <span class="number">4</span>){</span><br><span class="line"> res *= <span class="number">3</span>;</span><br><span class="line"> res %= N;</span><br><span class="line"> n -= <span class="number">3</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> (<span class="type">int</span>) (res * n % N);</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure></li></ul><h4 id="剑指-Offer-15-二进制中1的个数"><a href="#剑指-Offer-15-二进制中1的个数" class="headerlink" title="剑指 Offer 15. 二进制中1的个数"></a>剑指 Offer 15. <a href="https://leetcode.cn/problems/er-jin-zhi-zhong-1de-ge-shu-lcof/">二进制中1的个数</a></h4><img src="https://picbed.koko2pp.cc/image-20230226201121172.png" alt="image-20230226201121172" style="zoom:67%;" /><ul><li><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//正数的补码和原码相同,负数的补码为反码+1</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">hammingWeight</span><span class="params">(<span class="type">uint32_t</span> n)</span> </span>{</span><br><span class="line"> <span class="type">int</span> s = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span>(n) s += n & <span class="number">1</span>, n = n >> <span class="number">1</span>;</span><br><span class="line"> <span class="comment">//每次比较个位 如果是1 s++,如果不是i不加;取完之后右移一位 把个位删掉</span></span><br><span class="line"> <span class="keyword">return</span> s;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure></li></ul><h4 id="剑指-Offer-16-数值的整数次方"><a href="#剑指-Offer-16-数值的整数次方" class="headerlink" title="剑指 Offer 16. 数值的整数次方"></a>剑指 Offer 16. <a href="https://leetcode.cn/problems/shu-zhi-de-zheng-shu-ci-fang-lcof/description/?orderBy=newest_to_oldest&languageTags=cpp">数值的整数次方</a></h4><img src="https://picbed.koko2pp.cc/image-20230226204704647.png" alt="image-20230226204704647" style="zoom:67%;" /><ul><li><p>题解:n是偶数 <code>res=res*x*x</code>,是奇数: <code>res=res*x</code> 。假如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></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">double</span> <span class="title">myPow</span><span class="params">(<span class="type">double</span> x, <span class="type">int</span> n)</span> </span>{</span><br><span class="line"> <span class="type">long</span> <span class="type">long</span> m = n; <span class="comment">//n = -2^31,没法用abs取绝对值 用一个longlong类型变量接收n,再取abs</span></span><br><span class="line"> m = <span class="built_in">abs</span>(m);</span><br><span class="line"> <span class="keyword">if</span>(x == <span class="number">1</span>) <span class="keyword">return</span> x;</span><br><span class="line"> <span class="type">double</span> res = <span class="number">1.0</span>;</span><br><span class="line"> <span class="keyword">while</span> (m){ </span><br><span class="line"> <span class="comment">///该数二进制的最后一位是0的话那么就为偶数。是1的话就为奇数</span></span><br><span class="line"> <span class="keyword">if</span> (m & <span class="number">1</span>) res = res * x; </span><br><span class="line"> x = x * x;</span><br><span class="line"> m = m >> <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (n < <span class="number">0</span>) res = <span class="number">1</span> / res;</span><br><span class="line"> <span class="keyword">return</span> res;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure></li></ul><h4 id="剑指-Offer-17-打印从1到最大的n位数"><a href="#剑指-Offer-17-打印从1到最大的n位数" class="headerlink" title="剑指 Offer 17. 打印从1到最大的n位数"></a>剑指 Offer 17. <a href="https://leetcode.cn/problems/da-yin-cong-1dao-zui-da-de-nwei-shu-lcof/description/">打印从1到最大的n位数</a></h4><img src="https://picbed.koko2pp.cc/image-20230226205716377.png" alt="image-20230226205716377" style="zoom:67%;" /><ul><li><p>题解1:for循环打印输出</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="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function">vector<<span class="type">int</span>> <span class="title">printNumbers</span><span class="params">(<span class="type">int</span> n)</span> </span>{</span><br><span class="line"> <span class="type">int</span> max = <span class="built_in">pow</span>(<span class="number">10</span>, n) - <span class="number">1</span>;</span><br><span class="line"> vector<<span class="type">int</span>> ans;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i < max; i ++){</span><br><span class="line"> ans.<span class="built_in">push_back</span>(i + <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> ans;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure></li><li><p>题解2:用STL库函数解决。<font color='red'> <strong>定义在 numeric 头文件中的 iota() 函数模板会用连续的 T 类型值填充序列</strong>。</font>前两个参数是定义序列的正向迭代器,第三个参数是初始的 T 值。第三个指定的值会被保存到序列的第一个元素中。保存在第一个元素后的值是通过对前面的值运用<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><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">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function">vector<<span class="type">int</span>> <span class="title">printNumbers</span><span class="params">(<span class="type">int</span> n)</span> </span>{</span><br><span class="line"> <span class="function">vector<<span class="type">int</span>> <span class="title">ans</span><span class="params">(pow(<span class="number">10</span>, n) - <span class="number">1</span>, <span class="number">0</span>)</span></span>; <span class="comment">//初始化具有10^n-1个0的vector</span></span><br><span class="line"> <span class="built_in">iota</span>(ans.<span class="built_in">begin</span>(), ans.<span class="built_in">end</span>(), <span class="number">1</span>); <span class="comment">//iota() 是用来批量递增赋值vector的元素</span></span><br><span class="line"> <span class="keyword">return</span> ans;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure></li></ul><h4 id="剑指-Offer-18-删除链表的节点"><a href="#剑指-Offer-18-删除链表的节点" class="headerlink" title="剑指 Offer 18. 删除链表的节点"></a>剑指 Offer 18. <a href="https://leetcode.cn/problems/shan-chu-lian-biao-de-jie-dian-lcof/">删除链表的节点</a></h4><img src="https://picbed.koko2pp.cc/image-20230226210715384.png" alt="image-20230226210715384" style="zoom:67%;" /><ul><li><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"> </span><br></pre></td></tr></table></figure></li></ul>]]></content>
</entry>
</search>