首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

康威生命遊戲:從暴力模擬到「主動通知鄰居」的 O(活細胞數) 優化演算法

     編輯:關於C語言

標準演算法:每輪全盤掃描

雙緩衝陣列 cur[R][C], nxt[R][C]。每輪對每個細胞計算 8 鄰居存活數,應用規則寫入 nxt,再交換指標。時間 O(R×C),與活細胞數無關。

優化演算法:事件驅動/主動通知

核心觀察

只有狀態發生變化的細胞(出生/死亡)會影響下一輪鄰居的鄰居計數。死寂區域無需重複計算。

資料結構擴充

typedef struct {
    char live;       // 當前狀態 0/1
    char nbr_old;    // 上一輪鄰居數(決策依據)
    char nbr_new;    // 本輪累積鄰居數(受本輪變化影響)
    char changed;    // 本輪是否狀態翻轉
} Cell;

演算法流程

  1. 初始化:讀入初始盤面,對每個活細胞,將其 8 鄰居的 nbr_old++。
  2. 每輪處理:
    • 遍歷所有細胞(或僅維護的「可能變化集合」):
      • 用 nbr_old 依規則決定新狀態 → 設 changed。
      • 若 changed:翻轉 live,對 8 鄰居 nbr_new += (new_live ? +1 : -1)。
    • 輪末:nbr_old = nbr_new; nbr_new = 0; changed = 0(或交換指標)。

代碼骨架(關鍵邏輯)

void process_cell(World *w, int r, int c) {
    Cell *cell = &w->grid[r][c];
    int live = cell->live;
    int nbr = cell->nbr_old;

    int new_live = (live && (nbr==2 || nbr==3)) || (!live && nbr==3);
    if (new_live != live) {
        cell->changed = 1;
        int delta = new_live ? +1 : -1;
        cell->live = new_live;
        w->live_cnt += delta;
        notify_neighbors(w, r, c, delta);  // 更新鄰居 nbr_new
    }
}

void notify_neighbors(World *w, int r, int c, int delta) {
    for (int dr=-1; dr<=1; ++dr)
        for (int dc=-1; dc<=1; ++dc)
            if (dr||dc) w->grid[r+dr][c+dc].nbr_new += delta;
}

複雜度對比

演算法時間/輪空間適用場景
全盤掃描O(R×C)O(R×C)小網格、密集活細胞
主動通知O(變化細胞數 × 8)O(R×C) + 額外欄位大稀疏網格、長期演化

進一步優化:稀疏集合

僅維護「活細胞」與「鄰近活細胞的死細胞」集合(哈希表/平衡樹),完全跳過死寂區域遍歷,實現真正 O(活躍區域)。適合無限網格或極大稀疏場景(如 Golly 模擬器核心思路)。

教學價值

  • 展示「從資料流向思考優化」:將「被動查詢」轉為「主動推播」。
  • 雙緩衝思想在 nbr_old/nbr_new、live/changed 中雙重體現。
  • 細胞自動機並行本質與序列化實作的橋樑。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved