<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="/atom.xsl" ?>

<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://blog.name666.top/zh-tw/</id>
    <title>靜奢之境</title>
    <updated>2026-03-29T00:57:19.383Z</updated>
    <generator>Astro-Theme-Retypeset with Feed for Node.js</generator>
    <author>
        <name>LongDz</name>
        <uri>https://blog.name666.top</uri>
    </author>
    <link rel="alternate" href="https://blog.name666.top/zh-tw/"/>
    <link rel="self" href="https://blog.name666.top/zh-tw/atom.xml"/>
    <subtitle>歡迎來到我的思想角落。我是LongDz，一位在程式碼與文字間遊走的探索者。這裡並非喧鬧的廣場，而是一方精心耕耘的自留地。我書寫歷史的幽微回響，剖析哲學的鋒利稜角，沉醉於文學的無垠宇宙。每一個觀點，都經過時間的沉澱與反覆的淬鍊。</subtitle>
    <rights>Copyright © 2026 LongDz</rights>
    <entry>
        <title type="html"><![CDATA[重温数据结构-查找]]></title>
        <id>https://blog.name666.top/zh-tw/posts/posts/%E9%87%8D%E6%B8%A9%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84-%E6%9F%A5%E6%89%BE/</id>
        <link href="https://blog.name666.top/zh-tw/posts/posts/%E9%87%8D%E6%B8%A9%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84-%E6%9F%A5%E6%89%BE/"/>
        <updated>2025-11-23T20:29:04.983Z</updated>
        <summary type="html"><![CDATA[减少一半比较次数 查找成功时，平均比较次数为(n+1)/2 查找不成功时，平均比较次数为n+1 int SearchBin(int a...]]></summary>
        <content type="html"><![CDATA[<h3>查找</h3>
<h4>线性查找</h4>
<h5>顺序查找</h5>
<p>减少一半比较次数<br />
查找成功时，平均比较次数为(n+1)/2<br />
查找不成功时，平均比较次数为n+1</p>
<h5>折半查找</h5>
<pre><code>int SearchBin(int a[],int n,int key)
{
    int low=1,high=n;
    while(low&lt;=high)
    {
        int mid=(low+high)/2;
        if(a[mid]==key)
            return mid;
        else if(a[mid]&lt;key)
            low=mid-1;
        else
            high=mid+1;
    }
    return 0;
}
</code></pre>
<p>折半查找的递归实现</p>
<pre><code>int SearchBin(int a[],int low,int high,int key)
{
    if(low &lt;= high)
    {
        int mid=(low+high)/2;
        if(a[mid]==key)
            return mid;
        else if(a[mid]&lt;key)
            return SearchBin(a,mid+1,high,key);
        else
            return SearchBin(a,low,mid-1,key);
    }
    else
    return 0;
}
</code></pre>
<p>查找成功时
$$
\mathrm{ASL_{bs}} = \frac{1}{n} \sum_{i=1}^{n} C_i = \frac{1}{n} \left[ \sum_{j=1}^{h} j \times 2^{j-1} \right] = \frac{n+1}{n} \log_2 (n+1) - 1
$$</p>
<p>在 $n&gt;50$ 时，可得近似结果：</p>
<p>$$
\mathrm{ASL_{bs}} \approx \log_2 (n+1) - 1
$$</p>
<p>若查找不成功，则</p>
<p>$$
\mathrm{ASL} = h \approx \log_2 n + 1
$$</p>
<h5>索引查找</h5>
<p>一般情况下，将长度为 $n$ 的主表分成 $b$ 块，每块含有 $s$ 条记录，即 $b \approx n/s$，假设查找概率相等，则每块查找的概率为 $1/b$，块中每条记录查找的概率为 $1/s$。
若索引表采用顺序查找，则</p>
<p>$$
\mathrm{ASL} = \frac{b+1}{2} + \frac{s+1}{2} = \frac{\frac{n}{s} + s}{2} + 1
$$</p>
<p>若索引采用折半查找，则</p>
<p>$$
\mathrm{ASL} \approx \log_2 (b+1) + \frac{s+1}{2} = \log_2 \left(\frac{n}{s}+1\right) + \frac{s+1}{2}
$$</p>
<h4>树表查找</h4>
<h5>二叉排序树查找</h5>
<p>特点：每个节点的值大于其左子树的所有节点的值，小于其右子树的所有节点的值。</p>
<pre><code>#include &lt;iostream&gt;
using namespace std;

template &lt;class T&gt;
class BiNode {
public:
    T data;
    BiNode&lt;T&gt; *lch;
    BiNode&lt;T&gt; *rch;
    BiNode() : lch(NULL), rch(NULL) {}
};

template &lt;class T&gt;
class BST {
public:
    BST(T r[], int n);
    ~BST() {}
    BiNode&lt;T&gt; *Search(BiNode&lt;T&gt; *R, T key);
    void InsertBST(BiNode&lt;T&gt; *&amp;R, BiNode&lt;T&gt; *s);
    void Delete(BiNode&lt;T&gt; *&amp;R);
    bool DeleteBST(BiNode&lt;T&gt; *&amp;R, T key);

private:
    BiNode&lt;T&gt; *Root;
};

template &lt;class T&gt;
BiNode&lt;T&gt; *BST&lt;T&gt;::Search(BiNode&lt;T&gt; *R, T key) {
    if (R == NULL)
        return NULL;
    if (key == R-&gt;data)
        return R;
    else if (key &lt; R-&gt;data)
        return Search(R-&gt;lch, key);
    else
        return Search(R-&gt;rch, key);
}

template &lt;class T&gt;
void BST&lt;T&gt;::InsertBST(BiNode&lt;T&gt; *&amp;R, BiNode&lt;T&gt; *s) {
    if (R == NULL)
        R = s;
    else if (s-&gt;data &lt; R-&gt;data)
        InsertBST(R-&gt;lch, s);
    else
        InsertBST(R-&gt;rch, s);
}

template &lt;class T&gt;
BST&lt;T&gt;::BST(T r[], int n) {
    Root = NULL;
    for (int i = 0; i &lt; n; i++) {
        BiNode&lt;T&gt; *s = new BiNode&lt;T&gt;;
        s-&gt;data = r[i];
        s-&gt;lch = s-&gt;rch = NULL;
        InsertBST(Root, s);
    }
}

template &lt;class T&gt;
bool BST&lt;T&gt;::DeleteBST(BiNode&lt;T&gt; *&amp;R, T key) {
    if (R == NULL)
        return false;
    else {
        if (key == R-&gt;data) {
            Delete(R);
            return true;
        } else if (key &lt; R-&gt;data)
            return DeleteBST(R-&gt;lch, key);
        else
            return DeleteBST(R-&gt;rch, key);
    }
}

template &lt;class T&gt;
void BST&lt;T&gt;::Delete(BiNode&lt;T&gt; *&amp;R) {
    BiNode&lt;T&gt; *q, *s;
    if (R-&gt;lch == NULL) {
        q = R;
        R = R-&gt;rch;
        delete q;
    } else if (R-&gt;rch == NULL) {
        q = R;
        R = R-&gt;lch;
        delete q;
    } else {
        q = R;
        s = R-&gt;lch;
        while (s-&gt;rch != NULL) {
            q = s;
            s = s-&gt;rch;
        }
        R-&gt;data = s-&gt;data;
        if (q != R)
            q-&gt;rch = s-&gt;lch;
        else
            R-&gt;lch = s-&gt;lch;
        delete s;
    }
}
template &lt;class T&gt;
BST&lt;T&gt;::~BST() {
    while (Root != NULL)
        Delete(Root);
}
</code></pre>
<p>最好情况：
$\log_2 (n+1)-1$<br />
最坏情况：
$(n+1)/2$</p>
<h5>平衡二叉树查找</h5>
<p>特点：任一节点的左、右子树的高度差不超过1，即平衡因子(左子树高度 - 右子树高度)的绝对值不超过1。
(1) LL 型
由于在结点 A 的左孩子的左子树上插入结点，使结点 A 的平衡因子由 1 增至 2 而失去平衡，需进行一次顺时针旋转操作</p>
<p><img src="/imgs/LL.png" alt="image.png" /></p>
<p>(2) RR 型
由于在结点 A 的右孩子的右子树上插入结点，使结点 A 的平衡因子由 $-1$ 减至 $-2$ 而失去平衡，需进行一次逆时针旋转操作，如图 6-17(b)所示。
<img src="/imgs/RR.png" alt="image-2.png" />
(3) LR 型
由于在结点 A 的左孩子的右子树上插入结点，使结点 A 的平衡因子由 1 增至 2 而失去平衡，需进行两次旋转操作(先逆时针，后顺时针)，如图 6-17(c)所示。
<img src="/imgs/LR.png" alt="image-3.png" />
(4) RL 型
由于在结点 A 的右孩子的左子树上插入结点，使结点 A 的平衡因子由 $-1$ 减至 $-2$ 而失去平衡，需进行两次旋转操作(先顺时针，后逆时针)，如图 6-17(d)所示。
<img src="/imgs/RL.png" alt="image-3.png" /></p>
<pre><code>B-树
</code></pre>
]]></content>
        <author>
            <name>LongDz</name>
            <uri>https://blog.name666.top</uri>
        </author>
        <published>2025-11-23T20:29:04.983Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[重温数据结构-图]]></title>
        <id>https://blog.name666.top/zh-tw/posts/posts/%E9%87%8D%E6%B8%A9%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84-%E5%9B%BE/</id>
        <link href="https://blog.name666.top/zh-tw/posts/posts/%E9%87%8D%E6%B8%A9%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84-%E5%9B%BE/"/>
        <updated>2025-11-23T20:28:52.969Z</updated>
        <summary type="html"><![CDATA[有n个点，n(n-1)/2条边的图为完全无向图。有n个点，n(n-1)条边的图为完全有向图。简单路径：路径序列中，顶点不重复出现的路径。简单...]]></summary>
        <content type="html"><![CDATA[<h3>图</h3>
<p>有n个点，n(n-1)/2条边的图为完全无向图。<br />
有n个点，n(n-1)条边的图为完全有向图。<br />
简单路径：路径序列中，顶点不重复出现的路径。<br />
简单回路：除了起点和终点外，其余顶点不重复出现。<br />
连通图：在无向图中，若任意一对顶点都存在路径，则称其为连通图，否则为非连通图。<br />
连通分量：<strong>无向图中的极大连通子图</strong>。极大连通子图包含所有连通的顶点以及和这些顶点相关联的所有边。<br />
强连通图：在有向图中，若任意一对顶点都存在路径，则称其为强连通图，否则为非强连通图。<br />
强连通分量：<strong>有向图中的极大强连通子图</strong>。极大强连通子图包含所有强连通的顶点以及和这些顶点相关联的所有边。<br />
生成树：连通图的一个极小连通子图，包含图中所有顶点且有n-1条边。<br />
生成森林：非连通图的极小连通子图，包含图中所有顶点且有n-k条边，k为连通分量个数。</p>
<pre><code>#include&lt;bits/stdc++.h&gt;
using namespace std;
int n, m;
vector&lt;bool&gt; vis;
vector&lt;vector&lt;int&gt;&gt; adj;
bool find_edge(int u, int v)
{
    for (int i = 0; i &lt; adj[u].size(); ++i)
    {
        if (adj[u][i] == v)
        {
            return true;
        }
    }
    return false;
}
void dfs(int u)
{
    if (vis[u])
        return;
    vis[u] = true;
    for (int i = 0; i &lt; adj[u].size(); ++i)
        dfs(adj[u][i]);
}
void bfs(int u)//广度优先搜索
{
    vector&lt;int&gt; queue;
    int front = 0, rear = 0;
    queue.push_back(u);
    rear++;
    vis[u] = true;
    while (front &lt; rear)
    {
        int v = queue[front];
        front++;
        for (int i = 0; i &lt; adj[v].size(); ++i)
        {
            int w = adj[v][i];
            if (!vis[w])
            {
                queue.push_back(w);
                rear++;
                vis[w] = true;
            }
        }
    }
}
int main()
{
    cin &gt;&gt; n &gt;&gt; m;

    vis.resize(n + 1);
    adj.resize(n + 1);

    for (int i = 1; i &lt;= m; ++i)
    {
        int u, v;
        cin &gt;&gt; u &gt;&gt; v;
        adj[u].push_back(v);
    }

    return 0;
}
</code></pre>
<pre><code>//Prim算法
#include&lt;bits/stdc++.h&gt;
using namespace std;
int n, m;
vector&lt;vector&lt;int&gt;&gt; graph;
vector&lt;bool&gt; inMST;
vector&lt;int&gt; minEdge;
void Prim(int start)//时间复杂度：O(n^2)
{
    inMST[start] = true;
    for (int i = 1; i &lt;= n; ++i)
    {
        minEdge[i] = graph[start][i];
    }
    for (int i = 1; i &lt; n; ++i)
    {
        int u = -1;
        int minWeight = INT_MAX;
        for (int j = 1; j &lt;= n; ++j)
        {
            if (!inMST[j] &amp;&amp; minEdge[j] &lt; minWeight)
            {
                minWeight = minEdge[j];
                u = j;
            }
        }
        if (u == -1)
            break; // 图不连通
        inMST[u] = true;
        for (int v = 1; v &lt;= n; ++v)
        {
            if (!inMST[v] &amp;&amp; graph[u][v] &lt; minEdge[v])
            {   
                minEdge[v] = graph[u][v];
            }
        }
    }
}
//使用优先队列优化的prim算法
void Prim_Optimized(int start)//时间复杂度：O(m log n)
{
    priority_queue&lt;pair&lt;int, int&gt;, vector&lt;pair&lt;int, int&gt;&gt;, greater&lt;pair&lt;int, int&gt;&gt;&gt; pq;
    inMST[start] = true;
    for (int i = 1; i &lt;= n; ++i)
    {
        if (graph[start][i] &lt; INT_MAX)
            pq.push({graph[start][i], i});
    }
    while (!pq.empty())
    {
        auto [weight, u] = pq.top();
        pq.pop();
        if (inMST[u])
            continue;
        inMST[u] = true;
        for (int v = 1; v &lt;= n; ++v)
        {
            if (!inMST[v] &amp;&amp; graph[u][v] &lt; INT_MAX)
            {
                pq.push({graph[u][v], v});
            }
        }
    }
}
</code></pre>
<pre><code>//使用邻接表存储的prim算法
#include &lt;bits/stdc++.h&gt;
using namespace std;
int n, m;
struct Edge
{
    int to;
    int weight;
};
vector&lt;vector&lt;Edge&gt;&gt; adj; // 邻接表，假设节点编号为 1..n

// 返回 MST 总权重，若图不连通则返回 -1；同时填 parent（父节点，root 的 parent = -1）
long long Prim_Simple(int start, vector&lt;int&gt; &amp;parent)//时间复杂度：O(n^2)
{
    vector&lt;bool&gt; inMST(n + 1, false);
    vector&lt;int&gt; minEdge(n + 1, INT_MAX);
    parent.assign(n + 1, -1);

    minEdge[start] = 0;
    long long total = 0;
    for (int i = 1; i &lt;= n; ++i)
    {
        int u = -1, best = INT_MAX;
        for (int v = 1; v &lt;= n; ++v)
        {
            if (!inMST[v] &amp;&amp; minEdge[v] &lt; best)
            {
                best = minEdge[v];
                u = v;
            }
        }
        if (u == -1)
            return -1; // 不连通
        inMST[u] = true;
        total += (best == INT_MAX ? 0 : best);
        for (const auto &amp;e : adj[u])
        {
            if (!inMST[e.to] &amp;&amp; e.weight &lt; minEdge[e.to])
            {
                minEdge[e.to] = e.weight;
                parent[e.to] = u;
            }
        }
    }
    return total;
}

// 使用优先队列的 Prim（更快），返回 MST 权重或 -1（不连通），并填 parent
long long Prim_Optimized(int start, vector&lt;int&gt; &amp;parent)//时间复杂度：O(m log n)
{
    vector&lt;bool&gt; inMST(n + 1, false);
    vector&lt;int&gt; minEdge(n + 1, INT_MAX);
    parent.assign(n + 1, -1);

    using P = pair&lt;int, int&gt;; // {weight, node}
    priority_queue&lt;P, vector&lt;P&gt;, greater&lt;P&gt;&gt; pq;

    minEdge[start] = 0;
    pq.push({0, start});
    long long total = 0;
    int cnt = 0;

    while (!pq.empty())
    {
        auto [w, u] = pq.top();
        pq.pop();
        if (inMST[u])
            continue;
        inMST[u] = true;
        total += w;
        ++cnt;
        for (const auto &amp;e : adj[u])
        {
            if (!inMST[e.to] &amp;&amp; e.weight &lt; minEdge[e.to])
            {
                minEdge[e.to] = e.weight;
                parent[e.to] = u;
                pq.push({e.weight, e.to});
            }
        }
    }
    if (cnt != n)
        return -1; // 不连通
    return total;
}
</code></pre>
<pre><code>//Kruskal算法，时间复杂度：O(m log m)
#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt;
using namespace std;
const int MAXN = 100; // 假设最大节点数为 100
const int INF = 1e9;  // 用于表示无穷大
int n;                // 节点数
int graph[MAXN][MAXN]; // 邻接矩阵表示图
struct Edge {
    int u, v, weight;
    bool operator&lt;(const Edge &amp;other) const {
        return weight &lt; other.weight;
    }
};
vector&lt;Edge&gt; edges; // 边列表
int parent[MAXN];  // 并查集父节点数组
int find(int x) {
    if (parent[x] != x) {
        parent[x] = find(parent[x]); // 路径压缩
    }
    return parent[x];
}
void unionSets(int x, int y) {
    int rootX = find(x);
    int rootY = find(y);
    if (rootX != rootY) {
        parent[rootY] = rootX; // 合并集合
    }
}
long long Kruskal() {
    // 初始化并查集
    for (int i = 0; i &lt; n; i++) {
        parent[i] = i;
    }
    // 按权重排序边
    sort(edges.begin(), edges.end());
    long long mstWeight = 0;
    int edgesUsed = 0;  // 记录已使用的边数
    for (const auto &amp;edge : edges) {
        if (find(edge.u) != find(edge.v)) {
            unionSets(edge.u, edge.v);
            mstWeight += edge.weight;
            edgesUsed++;
            if (edgesUsed == n - 1) break; // 提前结束
        }
    }
    // 检查是否所有节点都连通
    if (edgesUsed != n - 1) return -1; // 图不连通
    return mstWeight;
}
</code></pre>
<pre><code>#define MAX_EDGE 100
#define MAX_VERTEX 100
#define MAX 9999

struct VEdge {
    int fromV;  // 起始顶点
    int endV;    // 终止顶点
    int weight; // 边的权值
};

VEdge EdgeList[MAX_EDGE];
void GenSortEdge(MGraph G, VEdge EdgeList[]) {
    int k = 0, i, j;
    for (i = 0; i &lt; G.vNum; i++) { // 边赋值
        for (j = i; j &lt; G.vNum; j++) {
            if (G.arcs[i][j] != MAX) {
                EdgeList[k].fromV = i;
                EdgeList[k].endV = j;
                EdgeList[k].weight = G.arcs[i][j];
                k++;
            }
        }
    }
    for (i = 0; i &lt; G.e - 1; i++) { // 边排序，这里用起泡排序，可以用其他排序方法替代
        for (j = i + 1; j &lt; G.e; j++) {
            if (EdgeList[i].weight &gt; EdgeList[j].weight) {
                VEdge t = EdgeList[i];
                EdgeList[i] = EdgeList[j];
                EdgeList[j] = t;
            }
        }
    }
}
void Kruskal(VEdge EdgeList[], int n, int e) {
    int vset[MAX_VERTEX];
    int i;
    for (i = 0; i &lt; n; i++) {
        vset[i] = i; // 初始化vset
    }
    int k = 0, j = 0;
    while (k &lt; n - 1) {
        int m = EdgeList[j].fromV, n_edge = EdgeList[j].endV;
        int sn1 = vset[m]; // m所属集合
        int sn2 = vset[n_edge]; // n所属集合
        if (sn1 != sn2) { // 两个顶点属于不同的集合
            printf("V%d -&gt; V%d\n", m, n_edge);
            k++;
            for (i = 0; i &lt; n; i++) {
                if (vset[i] == sn2) { // 集合编号为sn2的全部改为sn1
                    vset[i] = sn1;
                }
            }
        }
        j++;
    }
}
</code></pre>
<pre><code>#include &lt;bits/stdc++.h&gt;
using namespace std;
const int MAXV = 100;
const int MAX_VALUE = INT_MAX / 4;
int i, j, k;
int dist[MAXV][MAXV];
string path[MAXV][MAXV];
struct MGraph {
    int vNum;
    string vertex[MAXV];
    int arc[MAXV][MAXV];
};

void Floyd(MGraph G)
{
    for (i = 0; i &lt; G.vNum; i++)
        for (j = 0; j &lt; G.vNum; j++)
        {
            dist[i][j] = G.arc[i][j];
            if (dist[i][j] != MAX_VALUE)
                path[i][j] = G.vertex[i] + G.vertex[j];
            else
                path[i][j] = "";
        }
    for (k = 0; k &lt; G.vNum; k++)
        for (i = 0; i &lt; G.vNum; i++)
            for (j = 0; j &lt; G.vNum; j++)
                if (dist[i][k] + dist[k][j] &lt; dist[i][j])
                {
                    dist[i][j] = dist[i][k] + dist[k][j];
                    path[i][j] = path[i][k] + path[k][j];
                }
}

</code></pre>
<p>dijkstra算法：单源最短路径</p>
<pre><code>#include &lt;bits/stdc++.h&gt;
using namespace std;
#define MAX_VERTEX 100
#define MAX 65535

typedef struct
{
    int arcs[MAX_VERTEX][MAX_VERTEX];
    int vNum;
} MGraph;

int FindMin(int Disk[], bool S[], int n)
{
    int k = 0, min = MAX;
    for (int i = 0; i &lt; n; i++)
    {
        if (!S[i] &amp;&amp; min &gt; Disk[i])
        {
            min = Disk[i];
            k = i;
        }
    }
    if (min == MAX)
        return -1;
    return k;
}

void Print(int D[], int P[], int n)
{
    for (int i = 0; i &lt; n; i++)
    {
        cout &lt;&lt; "V" &lt;&lt; i &lt;&lt; ": " &lt;&lt; D[i] &lt;&lt; "\tV" &lt;&lt; i;
        int pre = P[i];
        while (pre != -1)
        {
            cout &lt;&lt; "&lt;-V" &lt;&lt; pre;
            pre = P[pre];
        }
        cout &lt;&lt; endl;
    }
}

void ShortPath(MGraph G, int v, int Disk[], int Path[])
{
    bool S[MAX_VERTEX];
    for (int i = 0; i &lt; G.vNum; i++)
    {
        S[i] = false;
        Disk[i] = G.arcs[v][i];
        if (Disk[i] != MAX)
            Path[i] = v;
        else
            Path[i] = -1;
    }
    S[v] = true;
    Disk[v] = 0;
    for (int i = 0; i &lt; G.vNum; i++)
    {
        if ((v = FindMin(Disk, S, G.vNum)) == -1)
            return;
        S[v] = true;
        for (int j = 0; j &lt; G.vNum; j++)
        {
            if (!S[j] &amp;&amp; (Disk[j] &gt; G.arcs[v][j] + Disk[v]))
            {
                Disk[j] = G.arcs[v][j] + Disk[v];
                Path[j] = v;
            }
        }
    }
    Print(Disk, Path, G.vNum);
}

void ShortPath_Optimized(MGraph G, int v, int Disk[], int Path[]){
    bool S[MAX_VERTEX];
    for(int i = 0;i &lt; G.vNum;i++){
        S[i] = false;
        Disk[i] = G.arcs[v][i];
        if(Disk[i] != MAX)
        Path[i] = v;
        else
        Path[i] = -1;
    }
    S[v] = true;
    Disk[v] = 0;
    priority_queue&lt;pair&lt;int,int&gt;,vector&lt;pair&lt;int,int&gt;&gt;,greater&lt;pair&lt;int,int&gt;&gt;&gt; pq;
    for(int i = 0;i &lt; G.vNum;i++){
        pq.push({Disk[i],i});
    }
    while(!pq.empty()){
        auto p = pq.top();
        pq.pop();
        int u = p.second;
        if(S[u]) continue;
        S[u] = true;
        for(int j = 0;j &lt; G.vNum;j++){
            if(!S[j] &amp;&amp; (Disk[j] &gt; G.arcs[u][j] + Disk[u])){
                Disk[j] = G.arcs[u][j] + Disk[u];
                Path[j] = u;
                pq.push({Disk[j],j});
            }
        }
    }
    Print(Disk,Path,G.vNum);
}

</code></pre>
]]></content>
        <author>
            <name>LongDz</name>
            <uri>https://blog.name666.top</uri>
        </author>
        <published>2025-11-23T20:28:52.969Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[重温数据结构-树]]></title>
        <id>https://blog.name666.top/zh-tw/posts/posts/%E9%87%8D%E6%B8%A9%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84-%E6%A0%91/</id>
        <link href="https://blog.name666.top/zh-tw/posts/posts/%E9%87%8D%E6%B8%A9%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84-%E6%A0%91/"/>
        <updated>2025-11-23T20:28:37.440Z</updated>
        <summary type="html"><![CDATA[二叉树可以结点为0，但是树的结点最少为1 完全二叉树：倒数第二层是满的，且最后一层必须左对齐 性质 1：一棵非空二叉树的第 $i$ 层上至多...]]></summary>
        <content type="html"><![CDATA[<h3>树</h3>
<h4>二叉树</h4>
<p>二叉树可以结点为0，但是树的结点最少为1<br />
完全二叉树：倒数第二层是满的，且最后一层必须左对齐</p>
<hr />
<h5>二叉树性质</h5>
<p><strong>性质 1：</strong> 一棵非空二叉树的第 $i$ 层上至多有 $2^{i - 1}$ 个结点（$i \geq 1$）。</p>
<p><strong>性质 2：</strong> 深度为 $h$ 的二叉树至多有 $2^h - 1$ 个结点（其中 $h \geq 1$）。</p>
<p><strong>性质 3：</strong> 对于任何一棵二叉树 $T$，如果其终端结点数（叶子结点数）为 $n_0$，度为 2 的结点数为 $n_2$，则 $n_0 = n_2 + 1$。</p>
<p><strong>性质 4：</strong> 具有 $n$ 个结点的完全二叉树的深度为 $\lfloor \log_2 n \rfloor + 1$（其中 $\lfloor x \rfloor$ 表示不大于 $x$ 的最大整数）。</p>
<p><strong>性质 5：</strong> 对于具有 $n$ 个结点的完全二叉树，如果按照从上到下、同一层次上的结点按从左到右的顺序对二叉树中的所有结点从 1 开始顺序编号，则对于序号为 $i$ 的结点，有：</p>
<ol>
<li><strong>双亲结点：</strong> 如果 $i &gt; 1$，则序号为 $i$ 的结点的双亲结点的序号为 $\lfloor i/2 \rfloor$（$\lfloor i/2 \rfloor$ 表示对 $i/2$ 的值取整）。如果 $i = 1$，则结点 $i$ 为根结点，没有双亲。</li>
<li><strong>左孩子结点：</strong> 如果 $2i &gt; n$，则结点 $i$ 无左孩子（此时结点 $i$ 为终端结点）；否则其左孩子结点的序号为 $2i$。</li>
<li><strong>右孩子结点：</strong> 如果 $2i + 1 &gt; n$，则结点 $i$ 无右孩子；否则其右孩子结点的序号为 $2i + 1$。</li>
</ol>
<hr />
<h3>树的遍历</h3>
<p>前序遍历、后序遍历、层序遍历</p>
<h4>二叉树的遍历</h4>
<p>前中后三种遍历，两种遍历方式(一定要包含中序遍历)才能确定唯一二叉树</p>
<h4>森林的遍历</h4>
<p>前序遍历和后序遍历<br />
① 前序遍历森林 ≡ 前序遍历该森林转换为的二叉树；<br />
② 后序遍历森林 ≡ 中序遍历该森林转换为的二叉树；<br />
③ 前序遍历树 ≡ 前序遍历该树对应的二叉树；<br />
④ 后序遍历树 ≡ 中序遍历该树对应的二叉树。</p>
<h3>树、森林与二叉树的转换</h3>
<h4>树转化为二叉树</h4>
<p>1、将树的各兄弟结点连线<br />
2、每个结点仅保留于其长子的连线，去掉该结点与其他子结点的连线<br />
<img src="/imgs/%E6%A0%91%E5%88%B0%E4%BA%8C%E5%8F%89%E6%A0%91.png" alt="树到二叉树" /></p>
<h4>森林转化为二叉树</h4>
<p>先把每个树转化为二叉树然后再把每个树的根结点连线作为兄弟节点
<img src="/imgs/%E6%A3%AE%E6%9E%97%E5%88%B0%E4%BA%8C%E5%8F%89%E6%A0%91.png" alt="森林到二叉树" /></p>
<h4>二叉树转换为树、森林</h4>
<p>如果一个节点 x 是它双亲 y 的左孩子，那就要把 x 的右孩子、x 右孩子的右孩子这些，都直接和 y 连起来。连好之后，把所有双亲到右孩子的连线都去掉
<img src="/imgs/%E4%BA%8C%E5%8F%89%E6%A0%91%E5%88%B0%E6%A0%91.png" alt="过程" /></p>
]]></content>
        <author>
            <name>LongDz</name>
            <uri>https://blog.name666.top</uri>
        </author>
        <published>2025-11-23T20:28:37.440Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[重温数据结构-拓展线性表]]></title>
        <id>https://blog.name666.top/zh-tw/posts/posts/%E9%87%8D%E6%B8%A9%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84-%E6%8B%93%E5%B1%95%E7%BA%BF%E6%80%A7%E8%A1%A8/</id>
        <link href="https://blog.name666.top/zh-tw/posts/posts/%E9%87%8D%E6%B8%A9%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84-%E6%8B%93%E5%B1%95%E7%BA%BF%E6%80%A7%E8%A1%A8/"/>
        <updated>2025-11-23T20:28:21.129Z</updated>
        <summary type="html"><![CDATA[const int StackSize = 1024; template<class T> class SeqStack { public...]]></summary>
        <content type="html"><![CDATA[<h3>线性表的拓展</h3>
<h4>顺序栈</h4>
<pre><code>const int StackSize = 1024;
template&lt;class T&gt;
class SeqStack
{
    public:
        SeqStack(){top = -1;}
        void Push(T x);
        T Pop();
        T GetTop();
        bool Empty(){return top == -1};
    private:
        int top;
        T data[StackSize];
};
template&lt;class T&gt;
void SeqStack&lt;T&gt;::Push(T x){
    if(top &gt;= StackSize - 1)
    throw"溢出";
    data[++top] = x;
}
template &lt;class T&gt;
T SeqStack&lt;T&gt;::GetTop()
{
    if(Empty())
    throw"溢出";
    return data[top];
}
template &lt;class T&gt;
T SeqStack&lt;T&gt;::Pop(){
    if(Empty())
    throw"溢出";
    return data[top--];
}
</code></pre>
<h5>共享双栈</h5>
<p>栈满 ：top1 +1 == top2</p>
<pre><code>#include &lt;iostream&gt;
using namespace std;

template &lt;class T, int N = 1024&gt;
class TwoStack
{
public:
    TwoStack() : top1(-1), top2(N) {}

    // 第一个栈（左侧）
    void Push1(const T &amp;x)
    {
        if (top1 + 1 == top2)
            throw "栈满";
        data[++top1] = x;
    }
    T Pop1()
    {
        if (Empty1())
            throw "栈1为空";
        return data[top1--];
    }
    T Top1() const
    {
        if (Empty1())
            throw "栈1为空";
        return data[top1];
    }
    bool Empty1() const { return top1 == -1; }
    int Size1() const { return top1 + 1; }

    // 第二个栈（右侧）
    void Push2(const T &amp;x)
    {
        if (top1 + 1 == top2)
            throw "栈满";
        data[--top2] = x;
    }
    T Pop2()
    {
        if (Empty2())
            throw "栈2为空";
        return data[top2++];
    }
    T Top2() const
    {
        if (Empty2())
            throw "栈2为空";
        return data[top2];
    }
    bool Empty2() const { return top2 == N; }
    int Size2() const { return N - top2; }

    // 剩余可用空间
    int FreeSpace() const { return top2 - top1 - 1; }

private:
    T data[N];
    int top1; // 初始 -1，向右增长
    int top2; // 初始 N，向左增长
};
</code></pre>
<h3>链式栈</h3>
<pre><code>template&lt;class T&gt;
struct Node
{
    T data;
    Node&lt;T&gt; *next;
};
template &lt;class T&gt;
class LinkStack
{
private:
    Node&lt;T&gt; *top;
public:
    LinkStack(){top = NULL;}
    ~LinkStack();
    void push(T x);
    T pop();
    T GetTop();
    bool Empty(){return top == nullptr;}

};

template &lt;class T&gt;
LinkStack&lt;T&gt;::~LinkStack()
{
    while(top){
        Node&lt;T&gt; *p = top;
        top = top-&gt;next;
        delete p;
    }
}
template&lt;class T&gt;
void LinkStack&lt;T&gt;::push(T x){
    Node&lt;T&gt; *now = new Node&lt;T&gt;;
    now-&gt;data = x;
    now-&gt;next = top;
    top = now;
}
template &lt;class T&gt;
T LinkStack&lt;T&gt;::pop()
{
    if(Empty())
    throw"栈空";
    T x = top-&gt;data;
    Node&lt;T&gt; *tmp = top;
    top = top-&gt;next;
    delete tmp;
    return x;
}
template&lt;class T&gt;
T LinkStack&lt;T&gt;::GetTop(){
    if (Empty())
        throw "栈空";
    return top-&gt;data;
}

</code></pre>
<h3>循环队列</h3>
<pre><code>const int QueueSize = 1000;
template&lt;class T&gt;
class CircleQueue
{
    public:
        CircleQueue(){front=rear = 0;}
        void EnQueue(T x);
        T DeQueue();
        T GetFront();
        int GetLength();
        bool Empty(){return front == rear;}

    private:
        T data[QueueSize];
        int front;
        int rear;
};
template &lt;class T&gt;
void CircleQueue&lt;T&gt;::EnQueue(T x){
    if((rear + 1)%QueueSize == front)
    throw"满";
    rear = (rear + 1) % QueueSize
    data[rear] = x;
}
template&lt;class T&gt;
int CircleQueue&lt;T&gt;::GetLength(){
    return (rear - front + QueueSize)%QueueSize;
}
template &lt;class T&gt;
T CircleQueue&lt;T&gt;::DeQueue(){
    if(Empty())
    throw"空";
    T x = data[(front+1)%QueueSize];
    front = (front + 1) % QueueSize;\
    return x;
}
template &lt;class T&gt;
T CircleQueue&lt;T&gt;::GetFront(){
    if (Empty())
        throw "空";
    return data[(front + 1) % QueueSize];
}
</code></pre>
<h3>链式队列</h3>
<pre><code>template &lt;class T&gt;
struct Node
{
    T data;
    Node&lt;T&gt; *next;
};
template &lt;class T&gt;
class LinkQueue
{
    public:
        LinkQueue(){
            front = rear = new Node&lt;T&gt;;
            front -&gt; next = NULL;
        }
        ~LinkQueue();
        void EnQueue(T x);
        T DeQueue();
        T GetQueue();
        bool Empty(){return rear == front;}
    private:
        Node&lt;T&gt; *front;
        Node&lt;T&gt; *rear;
};
template &lt;class T&gt;
LinkQueue&lt;T&gt;:: ~LinkQueue(){
    while(front){
        rear = front-&gt;next;
        delete front;
        front = rear;
    }
}
template &lt;class T&gt;
void LinkQueue&lt;T&gt;::EnQueue(T x){
    Node&lt;T&gt; *now = new Node&lt;T&gt;;
    now-&gt;data = x;
    rear-&gt;next = now;
    rear = now;
    rear-&gt;next = NULL;
}
template &lt;class T&gt;
T LinkQueue&lt;T&gt;::DeQueue(){
    
    if(Empty())
    throw"空";
    Node&lt;T&gt; *now = front-&gt;next;
    front-&gt;next = now-&gt;next;
    T x = now-&gt;data;
    if(!(front-&gt;next))//if (rear == now)
    rear = front;
    delete now;
    return x;
}
template &lt;class T&gt;
T LinkQueue&lt;T&gt;::GetQueue(){
    if (Empty())
        throw "空";
    return front-&gt;next-&gt;data;
}
</code></pre>
<h3>字符串</h3>
<pre><code>// bf 字符串匹配
int SeqString::Index(SeqString &amp;t){
    int i = j = 1; // 注意 这里字符串以1为起始，如果是0
    while(i &lt;= GetLength() and j &lt;= t.GetLength()){
        if(Get(i) == t.Get(j)){
            i++;j++;
        }
        else{
            i = j - i + 2;j = 1;//i = j - i + 1,j = 0;
        }
    }
    if(j &gt; t.GetLength())
        return i+1-j; //i- j;
    else
    return -1;
}

// KMP 算法
void SeqString::GetNextArray(SeqString &amp;t,int *&amp;next){
    next = new int[t.GetLength() +1];
    next[1] = 0;
    next[2] = 1;
    int p = 1;
    for(int i = 3;i &gt;= t.GetLength();j++){
        while (p &gt; 1 and t.Get(p) != t.Get(i-1))
        {
            p = next[p];
            if(t.Get(p) == t.Get(j-1))
                ++p;
            next[j] = p;
        }
        
    }
}

int SeqString::KMP(SeqString &amp;t){
    int *next;
    GetNextArray(t,next);
    int i = 1,j = 1;
    while(i &lt;= GetLength() and j &lt;= t.GetLength()){
        if(Get(i) == t.Get(j)){
            i++,j++;
        }
        else{
            if(!next(j))
            j = 1,i++;
            else
            j = next(j);
        }
    }
    delete []next;
    if(j &gt; t.GetLength())
        return i-j+1;
    else
        return -1;
}
</code></pre>
<h3>多维数组</h3>
<ul>
<li>二维数组<br />
行优先存储<br />
<code>Loc(a[i][j] = Loc(a[1][1]) + (i-1) * n + j-1) *c</code><br />
列优先存储<br />
<code>Loc(a[i][j] = Loc(a[1][1]) + (j-1) * m + i-1) *c</code></li>
<li>k维数组<br />
行优先存储：<br />
$\text{Loc}(A[i_1][i_2]...[i_k]) = \text{Loc}(A[1][1]...[1]) + \left( \sum_{p=1}^{k} \left[ (i_p - 1) \cdot \left( \prod_{q=p+1}^{k} D_q \right) \right] \right) \cdot c$<br />
列优先存储：<br />
$\text{Loc}(A[i_1][i_2]...[i_k]) = \text{Loc}(A[1][1]...[1]) + \left( \sum_{p=1}^{k} \left[ (i_p - 1) \cdot \left( \prod_{q=1}^{p-1} D_q \right) \right] \right) \cdot c$</li>
</ul>
<h4>多维矩阵的转置</h4>
<pre><code># define MAX_ELEMENT_NYMBER 1000
template&lt;class T&gt;
struct MatrixNode
{
    int row;
    int col;
    int value;
};
template &lt;class T&gt;
struct SpareMatrix
{
    int m;
    int n;
    int t;
    MatrixNode&lt;T&gt;data[MAX_ELEMENT_NYMBER];
};

// O(nt)
template &lt;class T&gt;
void TransMat(SpareMatrix&lt;T&gt; *OrigMat, SpareMatrix&lt;T&gt; *TransMat)
{
    TransMat-&gt;m = OrigMat-&gt;n; // 设置转置矩阵的行数
    TransMat-&gt;n = OrigMat-&gt;m; // 设置转置矩阵的列数
    TransMat-&gt;t = 0;          // 初始时转置矩阵的非零元素个数为零

    for (int col = 0; col &lt; OrigMat-&gt;n; col++)
        for (int j = 0; j &lt; OrigMat-&gt;t; j++)
            if (OrigMat-&gt;data[j].col == col) // 找出列号为 col 的三元组
            {
                TransMat-&gt;data[TransMat-&gt;t].col = OrigMat-&gt;data[j].row;
                TransMat-&gt;data[TransMat-&gt;t].row = OrigMat-&gt;data[j].col;
                TransMat-&gt;data[TransMat-&gt;t].value = OrigMat-&gt;data[j].value;
                TransMat-&gt;t++; // 非零元素个数增加
            }
}
// 优化版O(n+t)

template &lt;class T&gt;
void QuickTransMat(SpareMatrix&lt;T&gt; *OrigMat, SpareMatrix&lt;T&gt; *TransMat)
{
    int i;
    TransMat-&gt;m = OrigMat-&gt;n;
    TransMat-&gt;n = OrigMat-&gt;m;
    TransMat-&gt;t = OrigMat-&gt;t;
    if (OrigMat-&gt;t)
    {
        int *number = new int[OrigMat-&gt;n];
        memset(number, 0, OrigMat-&gt;n * sizeof(int));// 存储每一列的非零元素个数
        
        for (i = 0; i &lt; OrigMat-&gt;t; i++)
            number[OrigMat-&gt;data[i].col]++;

        int *position = new int[OrigMat-&gt;n];// 存储每一列第一个非零元素在转置矩阵中的位置
        position[0] = 0;
        for (i = 1; i &lt; OrigMat-&gt;n; i++)
            position[i] = position[i - 1] + number[i - 1];

        for (i = 0; i &lt; OrigMat-&gt;t; i++)
        {
            int pos = position[OrigMat-&gt;data[i].col]++;
            TransMat-&gt;data[pos].col = OrigMat-&gt;data[i].row;
            TransMat-&gt;data[pos].row = OrigMat-&gt;data[i].col;
            TransMat-&gt;data[pos].value = OrigMat-&gt;data[i].value;
        }
        delete[] number;
        delete[] position;
    }
}
</code></pre>
]]></content>
        <author>
            <name>LongDz</name>
            <uri>https://blog.name666.top</uri>
        </author>
        <published>2025-11-23T20:28:21.129Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[重温数据结构-线性表]]></title>
        <id>https://blog.name666.top/zh-tw/posts/posts/%E9%87%8D%E6%B8%A9%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84-%E7%BA%BF%E6%80%A7%E8%A1%A8/</id>
        <link href="https://blog.name666.top/zh-tw/posts/posts/%E9%87%8D%E6%B8%A9%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84-%E7%BA%BF%E6%80%A7%E8%A1%A8/"/>
        <updated>2025-11-23T20:27:51.825Z</updated>
        <summary type="html"><![CDATA[特点：相同类型元素、有限集合 template <class T, int N> class SeqList { public: SeqLi...]]></summary>
        <content type="html"><![CDATA[<h3>1.线性表</h3>
<p><code>特点：相同类型元素、有限集合</code></p>
<h4>1.1顺序表</h4>
<pre><code>template &lt;class T, int N&gt;
class SeqList
{
public:
    SeqList() { length = 0 };
    SeqList(T a[], int n);
    int GetLength() { return length; }
    void PrintList();
    void Insert(int i, T x);
    T Delete(int i);
    T Get(int i);
    int Locate(T x);

private:
    T data[N];
    int length;
};
template &lt;class T, int N&gt;
SeqList&lt;T, N&gt;::SeqList(T a[], int n)
{
    if (n &gt; N)
        throw("数组长度超过最大限制");
    for (int i = 0; i &lt; n; i++)
        data[i] = a[i];
    length = n;
}
template &lt;class T, int N&gt;
void SeqList&lt;T, N&gt;::PrintList()
{
    for (int i = 0; i &lt; length; i++)
        cout &lt;&lt; data[i] &lt;&lt; " ";
    cout &lt;&lt; endl;
}
template &lt;class T, int N&gt;
void SeqList&lt;T, N&gt;::Insert(int i, T x)
{
    if (n + 1 &gt; N)
        throw("超出最大长度");
    if (i &lt; 1 || i &gt;= length)
        throw("位置异常");
    for (int j = length; j &gt;= i; j--)
    {
        data[j] = data[j - 1];
    }
    data[i] = x;
    length++;
}
template &lt;class T, int N&gt;
T SeqList&lt;T, N&gt;::Delete(int i)
{
    if (i &lt; 1 || i &gt; length)
        throw("位置异常");
    if (length == 0)
        throw("溢出");
    T x = data[i];
    for (int j = i; j &lt; length; j++)
    {
        data[j] = data[j + 1];
    }
    length--;
    return x;
}
template &lt;class T, int N&gt;
T SeqList&lt;T, N&gt;::Get(int i)
{
    if (i &lt; 1 || i &gt; length)
        throw("位置异常");
    return data[i - 1];
}
template &lt;class T, int N&gt;
int SeqList&lt;T, N&gt;::Locate(T x)
{
    int ans = 0;
    for (int i = 0; i &lt; length; i++)
    {
        if (data[i] == x) // 注意除了基本数据类型外，需要对==进行重载
        {
            ans = i + 1;
            break;
        }·
    }
    return ans;
}

</code></pre>
<h4>单链表</h4>
<pre><code>#include&lt;iostream&gt;
using namespace std;

template &lt;class T&gt;
struct Node
{
    T data;
    struct Node &lt;T&gt; *next;
};
template &lt;class T&gt;
class LinkList
{
    public:
        LinkList(){front = new Node&lt;T&gt;;front -&gt; next = NULL;}
        LinkList(T a[],int n);
        ~LinkList();
        void PrintList();
        int GetLength();
        Node&lt;T&gt; *Get(int i);
        T Delete(int i);
        void Insert(int i,T x);
        void Insert1(int i, T x);
        int Locate(T x);
    private:
        Node&lt;T&gt; *front;
};

//带头结点的头插法
template&lt;class T&gt;
LinkList&lt;T&gt;::LinkList(T a[],int n){
    Node&lt;T&gt; *front = new Node&lt;T&gt;;
    front-&gt;next = NULL;
    for(int i = n-1;i &gt;= 0;i--){
        Node&lt;T&gt; *tmp = new Node&lt;T&gt;;
        tmp-&gt;data = a[i];
        tmp-&gt;next = front-&gt;next;
        front-&gt;next = tmp;
    }
}
//不带头结点的头插法
template&lt;class T&gt;
LinkList&lt;T&gt;::LinkList(T a[],int n){
    if(n == 0)
    return NULL;
    else
    Node&lt;T&gt; *front = new Node&lt;T&gt;;
    front-&gt;data = a[n-1];
    for(int i = n-2;i &gt;= 0;i--){
        Node&lt;T&gt; *tmp = new Node&lt;T&gt;;
        tmp-&gt;next = front;
        tmp-&gt;data = a[i];
        front = tmp;
    }
}
//尾插法
template &lt;class T&gt;
LinkList&lt;T&gt;::LinkList(T a[], int n)
{
    Node&lt;T&gt;* front = new Node&lt;T&gt;;
    front-&gt;next = nullptr;
    Node&lt;T&gt;* now = front;
    for(int i = 0;i &lt; n;i++){
        Node&lt;T&gt; *p = new Node&lt;T&gt;;
        p -&gt; data = a[i];
        now-&gt;next = p;
        now = p;
    }
    now-&gt;next = NULL;//注意
}

template&lt;class T&gt;
LinkList&lt;T&gt;::~LinkList(){
    Node&lt;T&gt;* p = front;
    while(p){
        front = p;
        p = p -&gt; next;
        delete front;
    }
}

template&lt;class T&gt;
int LinkList&lt;T&gt;::GetLength(){
    Node&lt;T&gt; *p = front-&gt;next;
    int len = 1;
    while(p){
        len++;
        p = p-&gt;next;
    }
    return len;
}

template&lt;class T&gt;
void LinkList&lt;T&gt;::PrintList(){
    Node&lt;T&gt; *p = front-&gt;next;
    while(p){
        cout&lt;&lt;p-&gt;data&lt;&lt;" ";
        p = p-&gt;next;
    }
    cout&lt;&lt;endl;
}
template&lt;class T&gt;
Node&lt;T&gt; * LinkList&lt;T&gt;::Get(int i){
    if(i &lt; 1)throw"位置异常";

    Node&lt;T&gt;*p = front -&gt; next;
    while(i &gt; 1){
        i--;
        if(p){
            p = p-&gt;next;
        }
        else throw"溢出";
    }
    return p;
}
//优化后的
template &lt;class T&gt;
Node&lt;T&gt; *LinkList&lt;T&gt;::Get(int i)
{
    if (i &lt; 1)
        throw "位置异常";
    Node&lt;T&gt; *p = front-&gt;next; // 第1个数据结点
    if (!p)
        throw "溢出"; // 空表没有第1个节点
    for (int k = 1; k &lt; i; ++k)
    {
        p = p-&gt;next;
        if (!p)
            throw "溢出";
    }
    return p;
}

template&lt;class T&gt;
int LinkList&lt;T&gt;::Locate(T x){
    int ans = 0;
    Node&lt;T&gt; *p = front-&gt;next;
    while(p){
        ans++;
        if (p-&gt;data == x) // 重载
            return ans;
        p = p-&gt; next;
    }
    return -1;
}

template&lt;class T&gt;
void LinkList&lt;T&gt;::Insert(int i,T x){
   
    Node&lt;T&gt; *p = front;
    Node&lt;T&gt; *tmp = new Node&lt;T&gt;;
    tmp-&gt;data = x;
    int count = 1;
    while(p){
        if(count == i){
            tmp-&gt;next = p-&gt;next;
            p-&gt;next = tmp;
            break;
        }
        count++;
        p = p -&gt; next;
    }
    if(p == NULL and count == i)//这种写法的问题就是如何保证我第i-1个数存在
    throw "位置异常";
    if(count &lt; i || i &lt; 1)
    throw"位置异常";
}
//使用Get的写法
template &lt;class T&gt;
void LinkList&lt;T&gt;::Insert1(int i, T x){
    Node&lt;T&gt; *p = front;
    if(i!=1) p = Get(i-1);//这里细节一下。如果是1就是更新头结点，为了防止Get函数抛出异常，一定要判断
    if(p){

        Node&lt;T&gt; tmp = new Node&lt;T&gt;;
        tmp-&gt;data = x;
        tmp-&gt;next = p-&gt;next;
        p-&gt;next = tmp;
    }
    else
    throw"位置异常";
}
/*
如果 给定某节点p 要求在该节点后插入，那么流程:
new --&gt; new.data --&gt; new-&gt;next = p-&gt;next --&gt; p-&gt;next = new;
对于前插操作流程
只需 交换p 与 new的值

*/
template&lt;class T&gt;
T LinkList&lt;T&gt;::Delete(int i){
    Node &lt;T&gt; *p = front;
    if(i!=1) p = Get(i-1);
    p-&gt;next = p-&gt;next-&gt;next;
    T x = del-&gt;data;
    delete p;
    return x;
}

</code></pre>
<h5>循环链表</h5>
<p>使用尾指针就够了rear-&gt;next 就是头指针、</p>
<h4>双链表</h4>
<pre><code>template&lt;class T&gt;
struct Node
{
   T data;
   Node&lt;T&gt; * prior;
   Node&lt;T&gt; * next;
};
//p后插入q

q-&gt;prior = p; 1️⃣
p-&gt;next-&gt;prior = q; 2️⃣
q-&gt;next = p-&gt;next; 3️⃣
p -&gt;next = q;4️⃣
// ⚠️ 2️⃣ 3️⃣ 一定要在 4️⃣前面

 // 删除p的后继
q = p-&gt;next 1️⃣
p-&gt;next-&gt;next-&gt;prior = p; 2️⃣
p-&gt;next = p-&gt;next-&gt;next 3️⃣
// ⚠️ 1️⃣一定要在3️⃣前面
// 删除p所指的节点
思路：交换 p 与 next 的值 == 删除p的后继
</code></pre>
]]></content>
        <author>
            <name>LongDz</name>
            <uri>https://blog.name666.top</uri>
        </author>
        <published>2025-11-23T20:27:51.825Z</published>
    </entry>
</feed>