連結串列可以 \(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\)