Serie: Angelia
java
86 righe
· Aggiornato 2026-09-27
LinearProbingIntSet.java
Angelia/Java/Week_6_7/code/07_hashing/LinearProbingIntSet.java
/**
* 用「線性探測」(linear probing,一種開放定址法 open addressing)實作的整數集合。
*
* 不用鏈結串列:所有元素直接放在桶陣列裡。
* 碰撞時就往下一格找(到尾端繞回開頭),直到找到空格為止。
*
* 優點:記憶體連續、快取友善。缺點:容易形成「群聚」(clustering)——
* 一長串被占用的格子會讓插入與查詢都變慢;因此負載因子要壓得更低(這裡 0.5)。
*
* 為了簡化,本類別只支援 add / contains(刪除需要「墓碑」標記,見教材說明)。
*
* 資料不變量:若 x 在集合中,則從 indexFor(x) 開始往後(繞回)掃到 x 之前,不會遇到空格。
*/
public class LinearProbingIntSet {
private static final int EMPTY = Integer.MIN_VALUE; // 哨兵值:代表「這格是空的」
private int[] table;
private int size = 0;
public int probes = 0; // 統計探測次數(教學用)
public LinearProbingIntSet(int capacity) {
this.table = new int[Math.max(2, capacity)];
java.util.Arrays.fill(this.table, EMPTY);
}
private int indexFor(int x, int length) {
return Math.floorMod(Integer.hashCode(x) * 0x9E3779B1, length); // 乘一個大奇數「攪亂」一下
}
public boolean add(int x) {
if (x == EMPTY) {
throw new IllegalArgumentException("此實作不能存放 Integer.MIN_VALUE(被當成哨兵值)");
}
if (contains(x)) {
return false;
}
if ((this.size + 1) * 2 > this.table.length) { // 負載因子超過 0.5:倍增並重新插入
resize();
}
int i = indexFor(x, this.table.length);
while (this.table[i] != EMPTY) { // 線性探測:往下一格找
this.probes = this.probes + 1;
i = (i + 1) % this.table.length; // 到尾端就繞回開頭
}
this.table[i] = x;
this.size = this.size + 1;
return true;
}
public boolean contains(int x) {
int i = indexFor(x, this.table.length);
while (this.table[i] != EMPTY) { // 遇到空格就可以確定不存在
this.probes = this.probes + 1;
if (this.table[i] == x) {
return true;
}
i = (i + 1) % this.table.length;
}
return false;
}
public int size() {
return this.size;
}
private void resize() {
int[] old = this.table;
this.table = new int[old.length * 2];
java.util.Arrays.fill(this.table, EMPTY);
this.size = 0;
for (int x : old) {
if (x != EMPTY) {
add(x); // 重新插入(索引會變)
}
}
}
/** 印出桶陣列:'.' 代表空格。 */
public void dump() {
StringBuilder sb = new StringBuilder(" ");
for (int x : this.table) {
sb.append(x == EMPTY ? "." : String.valueOf(x)).append(' ');
}
System.out.println(sb);
}
}
Articoli correlati
Angelia
haskell
EN
Aggiornato 2026-02-03
Adding.hs
Adding.hs — haskell source code from the Angelia learning materials (Angelia/Haskell/Adding.hs).
Leggi l'articolo →
Angelia
haskell
EN
Aggiornato 2026-02-03
Area.hs
Area.hs — haskell source code from the Angelia learning materials (Angelia/Haskell/Area.hs).
Leggi l'articolo →
Angelia
haskell
EN
Aggiornato 2026-02-03
Chess.hs
Chess.hs — haskell source code from the Angelia learning materials (Angelia/Haskell/Chess.hs).
Leggi l'articolo →
Angelia
haskell
EN
Aggiornato 2026-02-03
ChessGraphics.hs
ChessGraphics.hs — haskell source code from the Angelia learning materials (Angelia/Haskell/ChessGraphics.hs).
Leggi l'articolo →
Angelia
haskell
EN
Aggiornato 2026-02-03
Examples.hs
Examples.hs — haskell source code from the Angelia learning materials (Angelia/Haskell/Examples.hs).
Leggi l'articolo →
Angelia
haskell
EN
Aggiornato 2026-02-03
Fibonacci.hs
Fibonacci.hs — haskell source code from the Angelia learning materials (Angelia/Haskell/Fibonacci.hs).
Leggi l'articolo →