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

PHP 核心 HashTable 實現機制深度剖析

     編輯:PHP 綜合知識

HashTable:PHP 萬物之基

PHP 陣列、全域/區域變數符號表、物件屬性、函數表、類別表……全部建構在同一套 HashTable 之上。理解其結構,等於掌握 PHP 運行時的核心資料結構。

四大核心組件

  1. 雜湊函式:DJBX33A (Times 33),將字串鍵映射為無符號長整數。
  2. C 陣列:儲存 Bucket* 指標的桶陣列,大小為 2 的冪次,動態擴容。
  3. 衝突鏈表:每個桶維護一個雙向鏈表,掛載同雜湊值的 Bucket,解決衝突。
  4. 全域遍歷鏈表:將所有 Bucket 依插入順序串聯成雙向鏈表,支援 foreach、reset/next/prev/end 等順序操作。

關鍵結構體(簡化)

typedef struct _hashtable {
    uint nTableSize;        // 桶陣列大小
    uint nTableMask;        // nTableSize - 1,用於索引計算
    uint nNumOfElements;    // 元素個數
    ulong nNextFreeElement; // 下一個數字索引
    Bucket *pInternalPointer; // 內部指標(foreach 用)
    Bucket *pListHead;      // 全域鏈表頭
    Bucket *pListTail;      // 全域鏈表尾
    Bucket **arBuckets;     // 桶陣列指標
    // ... 擴容/銷毀/複製 等回調函式指標
} HashTable;

typedef struct bucket {
    ulong h;                // 雜湊值
    uint nKeyLength;        // 鍵長度(0 表示數字索引)
    void *pData;            // 值指標
    void *pDataPtr;         // 指標值優化
    struct bucket *pListNext, *pListLast; // 全域鏈表指標
    struct bucket *pNext, *pLast;         // 衝突鏈表指標
    char arKey[1];          // 柔性陣列儲存字串鍵
} Bucket;

核心 API 概覽(zend_hash.c/h)

分類代表函式
初始化/銷毀_zend_hash_init, zend_hash_destroy, zend_hash_clean, zend_hash_graceful_destroy
增/改_zend_hash_add_or_update, _zend_hash_quick_add_or_update, _zend_hash_index_update_or_next_insert
刪除zend_hash_del_key_or_index
查找zend_hash_find, zend_hash_quick_find, zend_hash_index_find, zend_hash_exists
遍歷zend_hash_internal_pointer_reset_ex, zend_hash_move_forward_ex, zend_hash_get_current_data_ex, zend_hash_get_current_key_ex
複製/合併zend_hash_copy, _zend_hash_merge, zend_hash_merge_ex
排序/比較zend_hash_sort, zend_hash_compare, zend_hash_minmax
應用/回調zend_hash_apply, zend_hash_apply_with_argument(s), zend_hash_reverse_apply
指標管理zend_hash_get_pointer, zend_hash_set_pointer
除錯zend_hash_display, zend_hash_display_pListTail

設計精妙之處

雙向鏈表雙重用途

  • 衝突鏈:pNext/pLast 解決雜湊衝突,查找時只遍歷同桶鏈表,平均 O(1)。
  • 全域鏈:pListNext/pListLast 維護插入順序,foreach 直接走此鏈表,無需排序。

數字索引優化

鍵長為 0 時視為數字索引,直接用 nNextFreeElement 分配,跳過雜湊計算,極快。

擴容策略

負載因子超過閾值時,zend_hash_do_resize 分配 2x 桶陣列,重新雜湊所有元素(Rehash),並重建衝突鏈。pListHead/Tail 不變,遍歷順序不受影響。

給擴充套件開發者的啟示

  • 使用 zend_hash_* API 操作符號表、屬性表,而非直接存取結構體。
  • 遍歷時優先用 zend_hash_internal_pointer_reset_ex + zend_hash_move_forward_ex,支援巢狀 foreach。
  • 需保持插入順序時,切勿在遍歷中刪除當前元素(會破壞全域鏈表),改用 zend_hash_apply 配合 ZEND_HASH_APPLY_REMOVE。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved