ハッシュ表


ハッシュ表
  • キーに入力値が格納データ構造
  • .
    代表的なハッシュ表タイプは
  • Python dictionaryタイプ→Python単独でハッシュを実装する必要はありません.dictionary
  • を使用します.
    ハッシュ・テーブルに関する用語
  • ハッシュ:任意の値を固定長
  • に変換
  • ハッシュ関数:Keyを使用してデータ位置を検索する関数→ハッシュアドレスを返す関数
  • ハッシュ値/ハッシュアドレス:鍵をハッシュ関数として演算し、ハッシュ値を探し出し、これに基づいてハッシュテーブルにおいて鍵のデータ位置
  • を一致して見つける.
  • スロット:
  • スペース、1つのデータを格納可能
  • には、格納されるデータの鍵を抽出するための個別の関数も存在する.
    ハッシュの例
    ハッシュ・テーブルの作成
    hash_table = list([i for i in range(10)])
    list comprehension
    使用方法
    [入力シーケンス内の要素の出力式[if条件式]
  • 入力シーケンスは反復可能なデータシーケンスまたはセット
  • である.
  • [if条件式]では、[]はリストカッコではなく、オプションを表し、条件がある場合にのみ使用されます.
    サンプル#異なるタイプのデータからのみ整数リストをインポート
    dadtaset = [4, True, 'Dave', 2.1, 3]
    int_data = [num for num in dataset if type(num)==int]
    print(int_data) //[4,3]
    Set comprehension
    使用方法
    {入力シーケンス内の要素の出力式[if条件式]}
  • の条件を満たす新しいセット
  • を返す.
  • セットデータ構造
  • 、冗長性なし、変更可能
    Dictionary comprehension
    使用方法
    入力シーケンスの要素{Key:Value for[if条件式]}
    id_name = {1: 'Dave', 2: 'David', 3: 'Anthony'}
    # 아이디가 2 이상인 데이터를 이름:아이디 형식으로 새로운 dic 만들기
    name_id = {val:key for key,val in id_name.items() if key>1 }
    ハッシュ関数
    ハッシュ関数を作成する方法はいくつかありますが、最も簡単な方法はDivisionです.
  • Division:キー値を特定の値に分割し、残りの値をハッシュアドレスとする方法(ハッシュアドレスは一定の長さ)
  • .
    def hash_func(key):
    	return key%5
    
    data1 = 'Andy'
    data2 = 'Dave'
    data3 = 'Trump'
    
    print(ord(data1[0]) #ord(): 문자의 아스키 코드 값 리턴해주는 함수
    # 65
    print(hash_func(ord(data1[0]))
    
    #여기서 key는 ord(data1[0])
    #hash_func(ord(data1[0]))는 해쉬 값 (해쉬 주소)
    ハッシュ使用関数
  • ハッシュ・テーブルに値
  • を保存
    def storage_data(data, value):
    	key = ord(data[0]) #key
    	hash_address = hash_func(key) #해쉬주소
    	hash_table[hash_address] = value
    
    #우리가 원하는 data, 우리가 진짜 저장하고 싶은 값을 넣으면 data로
    #key값을 만들고 그 key값으로 만든 address에 해당하는 slot에 value 저장
    
    storage_data('Andy', '01035134211')
  • ハッシュテーブルの値
  • を読み込む
    def get_data(data):
        key = ord(data[0])
        hash_address = hash_func(key)
        return hash_table[hash_address]
    # data로 키, address 만들고 그 address에 저장된 value 리턴하는 함수
    ハッシュ・テーブルのメリットとデメリット/主な用途
  • の利点
  • データストレージ/読み取り速度が速い(検索速度が速い)
    鍵データの検証が容易
  • 欠点
  • より多くのストレージ容量が必要
    複数の鍵のアドレスが同じである場合、競合を解決するために追加のアルゴリズムが必要です.
  • 主な用途
  • 大量の検索が必要
    頻繁に保存、削除または読み込み
    キャッシュの実装時
    練習1:リスト変数を使用してハッシュテーブルを実装する

  • ハッシュ関数:key%8

  • ハッシュキーの生成:hash(data)#内蔵関数
  • hash_table = list([i for i in range(8)])
    
    def get_key(data):
    	return hash(data)
    
    def hash_func(key):
    	return key % 8
    
    def add(data, value):
    	address = hash_func(get_key(data))
    	hash_table[address] = value
    	
    def read_data(data):
    	address = hash_func(get_key(data))
    	return hash_table[address]
    競合解決アルゴリズム
    :1つ以上のデータが同じハッシュに格納されているときに競合が発生します.
    1.Open Hashing(Chaning代表)
    オープン
    :競合が発生した場合は、ハッシュ・テーブル以外のスペースに保存します.
    :リンクリストを使用してデータを後に添付して保存する方法
    :リンクリストではなくPythonのリストを使用してコードに貼り付けます.
  • Chaining
  • hash_table = list([0 for i in range(8)])
    
    def get_key(data):
        return hash(data)
    
    def hash_function(key):
        return key % 8
    
    def save_data(data, value):
        index_key = get_key(data) #index_key를 추후에 value와 같이 저장하기 위해서 따로 변수로 지정
        hash_address = hash_function(index_key)
        if hash_table[hash_address] != 0: #이미 데이터가 들어가 있다는 뜻 -> 링크드 리스트 만들기~
            for index in range(len(hash_table[hash_address])): #데이터가 몇개 들어가있는지 파악하기 위해서
                if hash_table[hash_address][index][0] == index_key: #만약에 저장돼있는 데이터의 key와 저장하려는 데이터의 key가 동일하다면~
                    hash_table[hash_address][index][1] = value #그 위치에 저장하려던 value 넣기
                    return
            hash_table[hash_address].append([index_key, value]) #만약 key가 다르다면 뒤에 추가 연결, 이중 배열같은 느낌
        else:
            hash_table[hash_address] = [[index_key, value]] #데이터가 없기 때문에 key와 value 저장
        
    def read_data(data):
        index_key = get_key(data)
        hash_address = hash_function(index_key)
    
        if hash_table[hash_address] != 0:
            for index in range(len(hash_table[hash_address])):
                if hash_table[hash_address][index][0] == index_key:
                    return hash_table[hash_address][index][1]
            return None
        else:
            return None
    2.オンライン構成に代表されるClose Hashing
    クローズド
    :競合が発生した場合、ハッシュ・テーブルの空き領域を検索して保存→空き領域を使用するため、ストレージ領域の使用率が高い
    hash_table = list([0 for i in range(8)])
    
    def get_key(data):
        return hash(data)
    
    def hash_function(key):
        return key % 8
    
    def save_data(data, value):
        index_key = get_key(data)
        hash_address = hash_function(index_key)
        if hash_table[hash_address] != 0: #데이터가 들어가있는 경우
            for index in range(hash_address, len(hash_table)): #넣으려고 했던 칸의 index부터 해당 배열의 끝까지
                if hash_table[index] == 0: #다른 칸에 데이터가 없으면 바로 저장
                    hash_table[index] = [index_key, value]
                    return
                elif hash_table[index][0] == index_key: #해당 칸에 데이터가 있긴한데 index_key가 동일한 경우 value 업데이트
                    hash_table[index][1] = value
                    return
        else: # 데이터가 들어간 적이 없는 경우 바로 저장
            hash_table[hash_address] = [index_key, value]
    
    def read_data(data):
        index_key = get_key(data)
        hash_address = hash_function(index_key)
        
        if hash_table[hash_address] != 0:#데이터가 있는 경우
            for index in range(hash_address, len(hash_table)):
                if hash_table[index] == 0:#해당 데이터에 대한 값이 저장된 적이 없다~, 왜냐면 빈 공간이 나왔으면 내가 저장했을거기때문에 빈공간이 있을수가 없음
                    return None
                elif hash_table[index][0] == index_key:
                    return hash_table[index][1]
        else:
            return None #데이터가 없는 경우 none 리턴
    頻繁な衝突を防止する方法
    ストレージ領域の50%以上に格納しようとすると、競合が発生する確率が高くなります.そのため、ストレージ領域を拡張すると、競合が発生する確率が低くなります.
    ハッシュ関数と鍵生成関数
    :hash()関数は、実行時に異なる値がある場合があります.
    :典型的なハッシュ関数SHA(セキュリティハッシュアルゴリズム)
    :任意のデータは、固有の固定サイズの固定値を返します.
    :SHAはライブラリのインストール後に使用する必要があります→import hashlib(pip install)
    SHA-1
    import hashlib
    
    data = 'test'.encode() # = (b.'test'), 스트링을 바이트로 바꿔줌
    hash_object = hashlib.sha1()
    hash_object.update(data) # update(b.'test')로 써도 됨
    hex_dig = hash_object.hexdigest() #몇진수로 추출할 것 이냐 -> 16진수 (hexdigest())
    print (hex_dig) #해쉬 주소임, 문자열
    SHA-256(ブロックチェーンでもよく使われる)の使い方は同じです
    def get_key(data):
            hash_object = hashlib.sha256()
            hash_object.update(data.encode())
            hex_dig = hash_object.hexdigest()
            return int(hex_dig, 16) #hexdigest로 문자열로 뽑았기 때문에 int로 바꿔줘야 하는데 이거는 또 16진수이기 떄문에 10주소 이루어진 주소로 만들어주기 위해서는 int(hex_id,16) 꼭 해줘야함
    時間の複雑さ
    一般的な場合:O(1)
    すべての競合の最悪の場合:O(n)(読み取りまたは保存の場合)
    ハッシュテーブルは格納と検索の面で配列より良い資料構造~!