阿摩線上測驗 登入

申論題資訊

試卷:105年 - 105 專技高考_資訊技師:資料結構與資料庫及資料探勘#85803
科目:公職◆資料結構
年份:105年
排序:0

申論題內容

三、對資料庫系統的永久儲存結構而言,通常必須能夠隨著檔案紀錄的增多,進而動態的新增儲存區塊(block),例如:B-tree 樹狀檔案資料結構,即可隨著資料量變大而增加葉節點區塊(leaf node block)或增加樹的高度來因應。傳統的雜湊(hashing)方法為靜態雜湊(static hashing)結構,雖然有快速搜尋資料的優點,但是無法有效率的擴充儲存區塊;為改善靜態雜湊的缺點,動態雜湊(dynamic hashing)結構則能夠同時達成快速搜尋資料和動態擴充儲存區塊的功能。假設每一儲存區塊最多可以儲存 3 筆紀錄資料,試設計一動態雜湊資料結構與相對應的新增函數(Insert(key)),用以下的鍵值(key)新增順序為例:
 1, 3, 5, 7, 2, 4, 6, 8, 10, 9, 11, 21
說明你所設計的動態雜湊結構方法。

詳解 (共 1 筆)

詳解 提供者:hchungw
動態雜湊(Dynamic Hashing)結構設計
動態雜湊結構能夠根據資料量的變化動態調整儲存區塊。常見的動態雜湊方法有可延展雜湊(Extendible Hashing)和線性雜湊(Linear Hashing)。這裡我們以可延展雜湊為例,設計一個能夠處理資料量變化的雜湊結構。
可延展雜湊(Extendible Hashing)
可延展雜湊通過使用目錄(directory)和桶(bucket)來存儲數據,目錄包含指向桶的指針。當桶滿時,會進行分裂(split),並相應地更新目錄。這種方法可以動態地擴展雜湊表,避免重新雜湊所有數據。
資料結構和新增函數設計
初始設置:
目錄深度(global depth, gd):初始為1。
每個桶的深度(local depth, ld):初始為1。
每個桶可以存儲3筆記錄。
資料結構:

class Bucket:
    def __init__(self, local_depth):
        self.local_depth = local_depth
        self.records = []
class Directory:
    def __init__(self, global_depth):
        self.global_depth = global_depth
        self.buckets = [Bucket(local_depth=1) for _ in range(2 ** global_depth)]
雜湊函數(簡化示例,實際應根據具體需求設計):
python
複製程式碼
def hash_function(key, depth):
    return key & ((1 << depth) - 1)
插入函數:
python
複製程式碼
def insert(directory, key):
    # 計算目錄索引
    index = hash_function(key, directory.global_depth)
    bucket = directory.buckets[index]
    
    # 如果桶未滿,直接插入
    if len(bucket.records) < 3:
        bucket.records.append(key)
    else:
        # 桶滿了,需分裂
        split_bucket(directory, index)
        # 重新插入記錄
        insert(directory, key)
def split_bucket(directory, index):
    old_bucket = directory.buckets[index]
    old_local_depth = old_bucket.local_depth
    
    # 如果局部深度等於全局深度,擴展目錄
    if old_local_depth == directory.global_depth:
        directory.global_depth += 1
        directory.buckets.extend(directory.buckets)
    
    # 創建新桶
    new_bucket = Bucket(local_depth=old_local_depth + 1)
    old_bucket.local_depth += 1
    
    # 重新分配舊桶中的記錄
    rehash_records(directory, old_bucket, new_bucket)
    
    # 更新目錄指向
    for i in range(2 ** directory.global_depth):
        if hash_function(i, old_bucket.local_depth) == hash_function(index, old_bucket.local_depth):
            directory.buckets[i] = old_bucket
        else:
            directory.buckets[i] = new_bucket
def rehash_records(directory, old_bucket, new_bucket):
    records = old_bucket.records
    old_bucket.records = []
    for record in records:
        index = hash_function(record, directory.global_depth)
        if directory.buckets[index] == old_bucket:
            old_bucket.records.append(record)
        else:
            new_bucket.records.append(record)
示例插入順序
以鍵值插入順序為 1, 3, 5, 7, 2, 4, 6, 8, 10, 9, 11, 21 為例:
插入 1, 3, 5:
這些鍵值分配到初始的兩個桶中,沒有分裂發生。
插入 7:
桶滿,進行分裂。更新目錄,重新分配現有記錄。
插入 2, 4:
直接插入適當桶中。
插入 6:
桶滿,再次分裂。更新目錄。
插入 8, 10:
直接插入適當桶中。
插入 9:
桶滿,再次分裂。更新目錄。
插入 11, 21:
直接插入適當桶中。
總結
動態雜湊(如可延展雜湊)結構能夠有效地應對數據量增加,通過桶的動態分裂和目錄擴展來保持高效的數據存取性能。上述設計展示了如何使用可延展雜湊來實現動態的資料插入和儲存區塊擴展。