連結串列

d3genera7e發表於2024-09-16

連結串列可以 \(O(1)\) 插入/刪除

單向連結串列

顧名思義 只有後繼指標

鄰接表

我習慣叫做鏈式前向星, 一般用來儲存圖, 挺好理解的, 這裡直接給出存圖的應用

struct edge {
    int to, nxt;
} eg[M];
int head[N], egtot;

void add (int u, int v) {
    eg[++egtot].to = v;
    eg[egtot].nxt = head[u];
    head[u] = egtot;
}

雜湊表

透過連結串列實現一個整型到任意值的對映, 利用了取模意義下的剩餘系, 程式碼:

struct hash_table {
    int head[P], nxt[N], key[N], val[N], cnt;

    int & operator [] (const int &x) {
        int tmp = x % P;
        for (int i = head[tmp]; i; i = nxt[i]) 
            if (key[i] == x) return val[i];
        nxt[++cnt] = head[tmp], head[tmp] = cnt;
        key[cnt] = x, val[cnt] = 0;
        return val[cnt];
    }
};

一般來講模數選一個稍大的質數使得衝突機率降低,同時使資料分佈更均勻

由於雜湊表本身在資料較少的情況下執行很快,單次查詢可以近似看做是 \(O(1)\) 的,那麼可以用來代替 STL 的 map 實現更快的對映儲存

  • [SDOI2019] 快速查詢

發現只有全域性操作, 所以可以維護 \(x \times mul + add\) 以及全域性和 \(sum\)

然後全域性賦值就是清空, 使用雜湊表維護一個下標到值的對映, 單點修改就可以使用對映完成

雙向連結串列

顧名思義, 記錄前驅和後繼

考慮一個問題, 有一個陣列, 如何按順序從左到右刪除這個數, 並實時維護它的排序陣列?

使用 \(set\) 或者 平衡樹?

實際上沒有修改, 只有刪除, 可以使用雙向連結串列, 首先排序一下, 然後我們刪除就可以做成 \(O(1)\) 的了

總複雜度就是 \(O(n)\) 的了

  • [NOIP2012 提高組] 開車旅行

初始化就是上述的問題了, 剩下的內容是一個倍增, 因為決策點始終唯一所以可以倍增

迴圈連結串列

把雙向連結串列頭尾套接到一起, 一般用於處理有環的問題

十字連結串列

需要維護上下左右四個指標, 常見應用是 \(DLX\)

相關文章