From aeb4e6077d30adec964f1e4cd3871f966b9332fd Mon Sep 17 00:00:00 2001 From: machangxin Date: Wed, 14 Dec 2022 17:18:32 +0800 Subject: [PATCH] Add C++, Python, Go code for chapter_hashing --- codes/cpp/chapter_hashing/array_hash_map.cpp | 139 +++++++++++ codes/cpp/chapter_hashing/hash_map.cpp | 52 ++++ codes/cpp/include/PrintUtil.hpp | 17 +- codes/go/chapter_hashing/array_hash_map.go | 96 ++++++++ .../go/chapter_hashing/array_hash_map_test.go | 52 ++++ codes/go/chapter_hashing/hash_map_test.go | 57 +++++ .../java/chapter_hashing/array_hash_map.java | 2 +- .../python/chapter_hashing/array_hash_map.py | 112 +++++++++ codes/python/chapter_hashing/hash_map.py | 46 ++++ docs/chapter_hashing/hash_map.md | 231 +++++++++++++++++- 10 files changed, 794 insertions(+), 10 deletions(-) create mode 100644 codes/cpp/chapter_hashing/array_hash_map.cpp create mode 100644 codes/cpp/chapter_hashing/hash_map.cpp create mode 100644 codes/go/chapter_hashing/array_hash_map.go create mode 100644 codes/go/chapter_hashing/array_hash_map_test.go create mode 100644 codes/go/chapter_hashing/hash_map_test.go create mode 100644 codes/python/chapter_hashing/array_hash_map.py create mode 100644 codes/python/chapter_hashing/hash_map.py diff --git a/codes/cpp/chapter_hashing/array_hash_map.cpp b/codes/cpp/chapter_hashing/array_hash_map.cpp new file mode 100644 index 000000000..bca27ca7a --- /dev/null +++ b/codes/cpp/chapter_hashing/array_hash_map.cpp @@ -0,0 +1,139 @@ +/* + * File: array_hash_map.cpp + * Created Time: 2022-12-14 + * Author: msk397 (machangxinq@gmail.com) + */ + +#include "../include/include.hpp" + +/* 键值对 int->String */ +struct Entry { +public: + int key; + string val; + Entry(int key, string val) { + this->key = key; + this->val = val; + } + Entry()=default; +}; + +/* 基于数组简易实现的哈希表 */ +class ArrayHashMap { +private: + vector bucket; +public: + ArrayHashMap() { + // 初始化一个长度为 100 的桶(数组) + bucket= vector(100); + } + + /* 哈希函数 */ + int hashFunc(int key) { + int index = key % 100; + return index; + } + + /* 查询操作 */ + string get(int key) { + int index = hashFunc(key); + Entry pair = bucket[index]; + return pair.val; + } + + /* 添加操作 */ + void put(int key, string val) { + Entry pair = Entry(key, val); + int index = hashFunc(key); + bucket[index] = pair; + } + + /* 删除操作 */ + void remove(int key) { + int index = hashFunc(key); + // 置为空字符,代表删除 + bucket[index] = *new Entry(); + } + + /* 获取所有键值对 */ + vector entrySet() { + vector entrySet; + for (Entry pair: bucket) { + if (pair.key != 0) { + entrySet.push_back(pair); + } + } + return entrySet; + } + + /* 获取所有键 */ + vector keySet() { + vector keySet; + for (Entry pair: bucket) { + if (pair.key != 0) { + keySet.push_back(pair.key); + } + } + return keySet; + } + + /* 获取所有值 */ + vector valueSet() { + vector valueSet; + for (Entry pair: bucket) { + if (pair.key != 0) + valueSet.push_back(pair.val); + } + return valueSet; + } + + /* 打印哈希表 */ + void print() { + for (Entry kv: entrySet()) { + cout << kv.key << " -> " << kv.val << endl; + } + } +}; +int main() { + /* 初始化哈希表 */ + ArrayHashMap map = ArrayHashMap(); + + /* 添加操作 */ + // 在哈希表中添加键值对 (key, value) + map.put(12836, "小哈"); + map.put(15937, "小啰"); + map.put(16750, "小算"); + map.put(13276, "小法"); + map.put(10583, "小鸭"); + cout << "\n添加完成后,哈希表为\nKey -> Value" << endl; + map.print(); + + /* 查询操作 */ + // 向哈希表输入键 key ,得到值 value + string name = map.get(15937); + cout << "\n输入学号 15937 ,查询到姓名 " << name << endl; + + /* 删除操作 */ + // 在哈希表中删除键值对 (key, value) + map.remove(10583); + cout << "\n删除 10583 后,哈希表为\nKey -> Value" << endl; + map.print(); + + /* 遍历哈希表 */ + cout << "\n遍历键值对 Key->Value" << endl; + for (auto kv: map.entrySet()) { + cout << kv.key << " -> " << kv.val << endl; + } + + cout << "\n单独遍历键 Key" << endl; + for (auto key: map.keySet()) { + cout << key << endl; + } + + cout << "\n单独遍历值 Value" << endl; + for (auto val: map.valueSet()) { + cout << val << endl; + } + + return 0; +} \ No newline at end of file diff --git a/codes/cpp/chapter_hashing/hash_map.cpp b/codes/cpp/chapter_hashing/hash_map.cpp new file mode 100644 index 000000000..6c8df4b81 --- /dev/null +++ b/codes/cpp/chapter_hashing/hash_map.cpp @@ -0,0 +1,52 @@ +/* + * File: hash_map.cpp + * Created Time: 2022-12-14 + * Author: msk397 (machangxinq@gmail.com) + */ + +#include "../include/include.hpp" + + +int main() { + /* 初始化哈希表 */ + unordered_map map; + + /* 添加操作 */ + // 在哈希表中添加键值对 (key, value) + map[12836] = "小哈"; + map[15937] = "小啰"; + map[16750] = "小算"; + map[13276] = "小法"; + map[10583] = "小鸭"; + cout << "\n添加完成后,哈希表为\nKey -> Value" << endl; + PrintUtil::printHashMap(map); + + /* 查询操作 */ + // 向哈希表输入键 key ,得到值 value + string name = map[15937]; + cout << "\n输入学号 15937 ,查询到姓名 " << name << endl; + + /* 删除操作 */ + // 在哈希表中删除键值对 (key, value) + map.erase(10583); + cout << "\n删除 10583 后,哈希表为\nKey -> Value" << endl; + PrintUtil::printHashMap(map); + + /* 遍历哈希表 */ + cout << "\n遍历键值对 Key->Value" << endl; + for (auto kv: map) { + cout << kv.first << " -> " << kv.second << endl; + } + + cout << "\n单独遍历键 Key" << endl; + for (auto key: map) { + cout << key.first << endl; + } + + cout << "\n单独遍历值 Value" << endl; + for (auto val: map) { + cout << val.second << endl; + } + + return 0; +} \ No newline at end of file diff --git a/codes/cpp/include/PrintUtil.hpp b/codes/cpp/include/PrintUtil.hpp index 772eb9b25..544ee85db 100644 --- a/codes/cpp/include/PrintUtil.hpp +++ b/codes/cpp/include/PrintUtil.hpp @@ -1,7 +1,7 @@ /* * File: PrintUtil.hpp * Created Time: 2021-12-19 - * Author: Krahets (krahets@163.com) + * Author: Krahets (krahets@163.com), msk397 (machangxinq@gmail.com) */ #pragma once @@ -277,4 +277,19 @@ class PrintUtil { } cout << "[" + s.str() + "]" << '\n'; } + + /** + * @brief Print a HashMap + * + * @tparam TKey + * @tparam TValue + * @param map + */ + // 定义模板参数 TKey 和 TValue,用于指定键值对的类型 + template + static void printHashMap(unordered_map map) { + for (auto kv : map) { + cout << kv.first << " -> " << kv.second << '\n'; + } + } }; diff --git a/codes/go/chapter_hashing/array_hash_map.go b/codes/go/chapter_hashing/array_hash_map.go new file mode 100644 index 000000000..c895ef84e --- /dev/null +++ b/codes/go/chapter_hashing/array_hash_map.go @@ -0,0 +1,96 @@ +// File: array_hash_map.go +// Created Time: 2022-12-14 +// Author: msk397 (machangxinq@gmail.com) + +package chapter_hashing + +import "fmt" + +// 键值对 int->String +type Entry struct { + key int + val string +} + +// 基于数组简易实现的哈希表 +type ArrayHashMap struct { + bucket []Entry +} + +func newArrayHashMap() *ArrayHashMap { + // 初始化一个长度为 100 的桶(数组) + bucket := make([]Entry, 100) + return &ArrayHashMap{bucket: bucket} +} + +// 哈希函数 +func (a *ArrayHashMap) hashFunc(key int) int { + index := key % 100 + return index +} + +// 查询操作 +func (a *ArrayHashMap) get(key int) string { + index := a.hashFunc(key) + pair := a.bucket[index] + if pair.key == 0 { + return "" + } + return pair.val +} + +// 添加操作 +func (a *ArrayHashMap) put(key int, val string) { + pair := Entry{key: key, val: val} + index := a.hashFunc(key) + a.bucket[index] = pair +} + +// 删除操作 +func (a *ArrayHashMap) remove(key int) { + index := a.hashFunc(key) + // 置为空字符,代表删除 + a.bucket[index] = Entry{} +} + +// 获取所有键对 +func (a *ArrayHashMap) entrySet() []Entry { + var pairs []Entry + for _, pair := range a.bucket { + if pair.key != 0 { + pairs = append(pairs, pair) + } + } + return pairs +} + +// 获取所有键 +func (a *ArrayHashMap) keySet() []int { + var keys []int + for _, pair := range a.bucket { + if pair.key != 0 { + keys = append(keys, pair.key) + } + } + return keys +} + +// 获取所有值 +func (a *ArrayHashMap) valueSet() []string { + var values []string + for _, pair := range a.bucket { + if pair.key != 0 { + values = append(values, pair.val) + } + } + return values +} + +// 打印哈希表 +func (a *ArrayHashMap) print() { + for _, pair := range a.bucket { + if pair.key != 0 { + fmt.Println(pair.key, "->", pair.val) + } + } +} diff --git a/codes/go/chapter_hashing/array_hash_map_test.go b/codes/go/chapter_hashing/array_hash_map_test.go new file mode 100644 index 000000000..218fd623f --- /dev/null +++ b/codes/go/chapter_hashing/array_hash_map_test.go @@ -0,0 +1,52 @@ +// File: array_hash_map_test.go +// Created Time: 2022-12-14 +// Author: msk397 (machangxinq@gmail.com) + +package chapter_hashing + +import ( + "fmt" + "testing" +) + +func TestArrayHashMap(t *testing.T) { + /* 初始化哈希表 */ + map1 := newArrayHashMap() + + /* 添加操作 */ + // 在哈希表中添加键值对 (key, value) + map1.put(12836, "小哈") + map1.put(15937, "小啰") + map1.put(16750, "小算") + map1.put(13276, "小法") + map1.put(10583, "小鸭") + fmt.Println("\n添加完成后,哈希表为\nKey -> Value") + map1.print() + + /* 查询操作 */ + // 向哈希表输入键 key ,得到值 value + name := map1.get(15937) + fmt.Println("\n输入学号 15937 ,查询到姓名 " + name) + + /* 删除操作 */ + // 在哈希表中删除键值对 (key, value) + map1.remove(10583) + fmt.Println("\n删除 10583 后,哈希表为\nKey -> Value") + map1.print() + + /* 遍历哈希表 */ + fmt.Println("\n遍历键值对 Key->Value") + for _, kv := range map1.entrySet() { + fmt.Println(kv.key, " -> ", kv.val) + } + + fmt.Println("\n单独遍历键 Key") + for _, key := range map1.keySet() { + fmt.Println(key) + } + + fmt.Println("\n单独遍历值 Value") + for _, val := range map1.valueSet() { + fmt.Println(val) + } +} diff --git a/codes/go/chapter_hashing/hash_map_test.go b/codes/go/chapter_hashing/hash_map_test.go new file mode 100644 index 000000000..ee7683367 --- /dev/null +++ b/codes/go/chapter_hashing/hash_map_test.go @@ -0,0 +1,57 @@ +// File: hash_map_test.go +// Created Time: 2022-12-14 +// Author: msk397 (machangxinq@gmail.com) + +package chapter_hashing + +import ( + "fmt" + "testing" +) + +func TestHashmap(t *testing.T) { + // 初始化哈希表 + Map := make(map[int]string) + + // 添加操作 + // 在哈希表中添加键值对 (key, value) + Map[12836] = "小哈" + Map[15937] = "小啰" + Map[16750] = "小算" + Map[13276] = "小法" + Map[10583] = "小鸭" + fmt.Println("\n添加完成后,哈希表为\nKey -> Value") + for key, value := range Map { + fmt.Printf("%d -> %s\n", key, value) + } + + // 查询操作 + // 向哈希表输入键 key ,得到值 value + name := Map[15937] + fmt.Println("\n输入学号 15937 ,查询到姓名 ", name) + + // 删除操作 + // 在哈希表中删除键值对 (key, value) + delete(Map, 10583) + fmt.Println("\n删除 10583 后,哈希表为\nKey -> Value") + for key, value := range Map { + fmt.Printf("%d -> %s\n", key, value) + } + + /* 遍历哈希表 */ + // 遍历键值对 key->value + fmt.Println("\n遍历键值对 Key->Value") + for key, value := range Map { + fmt.Println(key, "->", value) + } + // 单独遍历键 key + fmt.Println("\n单独遍历键 Key") + for key := range Map { + fmt.Println(key) + } + // 单独遍历值 value + fmt.Println("\n单独遍历值 Value") + for _, value := range Map { + fmt.Println(value) + } +} diff --git a/codes/java/chapter_hashing/array_hash_map.java b/codes/java/chapter_hashing/array_hash_map.java index 89082c2f9..12f23d5b5 100644 --- a/codes/java/chapter_hashing/array_hash_map.java +++ b/codes/java/chapter_hashing/array_hash_map.java @@ -21,7 +21,7 @@ class Entry { class ArrayHashMap { private List bucket; public ArrayHashMap() { - // 初始化一个长度为 10 的桶(数组) + // 初始化一个长度为 100 的桶(数组) bucket = new ArrayList<>(); for (int i = 0; i < 100; i++) { bucket.add(null); diff --git a/codes/python/chapter_hashing/array_hash_map.py b/codes/python/chapter_hashing/array_hash_map.py new file mode 100644 index 000000000..a9fbf58a3 --- /dev/null +++ b/codes/python/chapter_hashing/array_hash_map.py @@ -0,0 +1,112 @@ +""" +File: array_hash_map.py +Created Time: 2022-12-14 +Author: msk397 (machangxinq@gmail.com) +""" + +# 键值对 int->String +class Entry: + def __init__(self, key, val): + self.key = key + self.val = val + + +# 基于数组简易实现的哈希表 +class ArrayHashMap: + def __init__(self): + # 初始化一个长度为 100 的桶(数组) + self.bucket = [None] * 100 + + # 哈希函数 + def hashFunc(self, key): + index = key % 100 + return index + + # 查询操作 + def get(self, key): + index = self.hashFunc(key) + pair = self.bucket[index] + if pair is None: + return None + return pair.val + + # 添加操作 + def put(self, key, val): + pair = Entry(key, val) + index = self.hashFunc(key) + self.bucket[index] = pair + + # 删除操作 + def remove(self, key): + index = self.hashFunc(key) + # 置为空字符,代表删除 + self.bucket[index] = None + + # 获取所有键值对 + def entrySet(self): + result = [] + for pair in self.bucket: + if pair is not None: + result.append(pair) + return result + + # 获取所有键 + def keySet(self): + result = [] + for pair in self.bucket: + if pair is not None: + result.append(pair.key) + return result + + # 获取所有值 + def valueSet(self): + result = [] + for pair in self.bucket: + if pair is not None: + result.append(pair.val) + return result + + # 打印哈希表 + def print(self): + for pair in self.bucket: + if pair is not None: + print(pair.key, "->", pair.val) + + +if __name__ == "__main__": + """ 初始化哈希表 """ + Map = ArrayHashMap() + + """ 添加操作 """ + # 在哈希表中添加键值对 (key, value) + Map.put(12836, "小哈") + Map.put(15937, "小啰") + Map.put(16750, "小算") + Map.put(13276, "小法") + Map.put(10583, "小鸭") + print("\n添加完成后,哈希表为\nKey -> Value") + Map.print() + + """ 查询操作 """ + # 向哈希表输入键 key ,得到值 value + name = Map.get(15937) + print("\n输入学号 15937 ,查询到姓名 " + name) + + """ 删除操作 """ + # 在哈希表中删除键值对 (key, value) + Map.remove(10583) + print("\n删除 10583 后,哈希表为\nKey -> Value") + Map.print() + + """ 遍历哈希表 """ + print("\n遍历键值对 Key->Value") + for pair in Map.entrySet(): + print(pair.key, "->", pair.val) + + print("\n单独遍历键 Key") + for key in Map.keySet(): + print(key) + + print("\n单独遍历值 Value") + for val in Map.valueSet(): + print(val) diff --git a/codes/python/chapter_hashing/hash_map.py b/codes/python/chapter_hashing/hash_map.py new file mode 100644 index 000000000..98b7dedc4 --- /dev/null +++ b/codes/python/chapter_hashing/hash_map.py @@ -0,0 +1,46 @@ +""" +File: hash_map.py +Created Time: 2022-12-14 +Author: msk397 (machangxinq@gmail.com) +""" + +if __name__ == "__main__": + """ 初始化哈希表 """ + Map = {} + + """ 添加操作 """ + # 在哈希表中添加键值对 (key, value) + Map[12836] = "小哈" + Map[15937] = "小啰" + Map[16750] = "小算" + Map[13276] = "小法" + Map[10583] = "小鸭" + print("\n添加完成后,哈希表为\nKey -> Value") + for key, value in Map.items(): + print(key, "->", value) + + """ 查询操作 """ + # 向哈希表输入键 key ,得到值 value + name = Map[15937] + print("\n输入学号 15937 ,查询到姓名 " + name) + + """ 删除操作 """ + # 在哈希表中删除键值对 (key, value) + Map.pop(10583) + print("\n删除 10583 后,哈希表为\nKey -> Value") + for key, value in Map.items(): + print(key, "->", value) + + """ 遍历哈希表 """ + print("\n遍历键值对 Key->Value") + for key, value in Map.items(): + print(key, "->", value) + + print("\n单独遍历键 Key") + for key in Map.keys(): + print(key) + + print("\n单独遍历值 Value") + for val in Map.values(): + print(val) + diff --git a/docs/chapter_hashing/hash_map.md b/docs/chapter_hashing/hash_map.md index 793d90323..3ce9c08b8 100644 --- a/docs/chapter_hashing/hash_map.md +++ b/docs/chapter_hashing/hash_map.md @@ -63,19 +63,70 @@ comments: true === "C++" ```cpp title="hash_map.cpp" + /* 初始化哈希表 */ + unordered_map map; + /* 添加操作 */ + // 在哈希表中添加键值对 (key, value) + map[12836] = "小哈"; + map[15937] = "小啰"; + map[16750] = "小算"; + map[13276] = "小法"; + map[10583] = "小鸭"; + + /* 查询操作 */ + // 向哈希表输入键 key ,得到值 value + string name = map[15937]; + + /* 删除操作 */ + // 在哈希表中删除键值对 (key, value) + map.erase(10583); ``` === "Python" ```python title="hash_map.py" - + # 初始化哈希表 + Map = {} + + # 添加操作 + # 在哈希表中添加键值对 (key, value) + Map[12836] = "小哈" + Map[15937] = "小啰" + Map[16750] = "小算" + Map[13276] = "小法" + Map[10583] = "小鸭" + + # 查询操作 + # 向哈希表输入键 key ,得到值 value + name = Map[15937] + + # 删除操作 + # 在哈希表中删除键值对 (key, value) + Map.pop(10583) ``` === "Go" - ```go title="hash_map.go" - + ```go title="hash_map_test.go" + // 初始化哈希表 + Map := make(map[int]string) + + // 添加操作 + // 在哈希表中添加键值对 (key, value) + Map[12836] = "小哈" + Map[15937] = "小啰" + Map[16750] = "小算" + Map[13276] = "小法" + Map[10583] = "小鸭" + + // 查询操作 + // 向哈希表输入键 key ,得到值 value + name := Map[15937] + + // 删除操作 + // 在哈希表中删除键值对 (key, value) + delete(Map, 10583) ``` === "JavaScript" @@ -125,19 +176,52 @@ comments: true === "C++" ```cpp title="hash_map.cpp" - + /* 遍历哈希表 */ + // 遍历键值对 key->value + for (auto kv: map) { + cout << kv.first << " -> " << kv.second << endl; + } + // 单独遍历键 key + for (auto key: map) { + cout << key.first << endl; + } + // 单独遍历值 value + for (auto val: map) { + cout << val.second << endl; + } ``` === "Python" ```python title="hash_map.py" - + """ 遍历哈希表 """ + # 遍历键值对 key->value + for key, value in Map.items(): + print(key, "->", value) + # 单独遍历键 key + for key in Map.keys(): + print(key) + # 单独遍历值 value + for value in Map.values(): + print(value) ``` === "Go" - ```go title="hash_map.go" - + ```go title="hash_map_test.go" + /* 遍历哈希表 */ + // 遍历键值对 key->value + for key, value := range Map { + fmt.Println(key, "->", value) + } + // 单独遍历键 key + for key := range Map { + fmt.Println(key) + } + // 单独遍历值 value + for _, value := range Map { + fmt.Println(value) + } ``` === "JavaScript" @@ -242,19 +326,150 @@ $$ === "C++" ```cpp title="array_hash_map.cpp" + /* 键值对 int->String */ + struct Entry { + public: + int key; + string val; + Entry(int key, string val) { + this->key = key; + this->val = val; + } + Entry(){ + this->key = -1; + this->val = ""; + } + }; + /* 基于数组简易实现的哈希表 */ + class ArrayHashMap { + private: + vector bucket; + public: + ArrayHashMap() { + // 初始化一个长度为 100 的桶(数组) + bucket= vector(100); + } + + /* 哈希函数 */ + int hashFunc(int key) { + int index = key % 100; + return index; + } + + /* 查询操作 */ + string get(int key) { + int index = hashFunc(key); + Entry pair = bucket[index]; + return pair.val; + } + + /* 添加操作 */ + void put(int key, string val) { + Entry pair = Entry(key, val); + int index = hashFunc(key); + bucket[index] = pair; + } + + /* 删除操作 */ + void remove(int key) { + int index = hashFunc(key); + // 置为空,代表删除 + bucket[index] = *new Entry(); + } + }; ``` === "Python" ```python title="array_hash_map.py" - + # 键值对 int->String + class Entry: + def __init__(self, key, val): + self.key = key + self.val = val + + # 基于数组简易实现的哈希表 + class ArrayHashMap: + def __init__(self): + # 初始化一个长度为 100 的桶(数组) + self.bucket = [None] * 100 + + # 哈希函数 + def hashFunc(self, key): + index = key % 100 + return index + + # 查询操作 + def get(self, key): + index = self.hashFunc(key) + pair = self.bucket[index] + if pair is None: + return None + return pair.val + + # 添加操作 + def put(self, key, val): + pair = Entry(key, val) + index = self.hashFunc(key) + self.bucket[index] = pair + + # 删除操作 + def remove(self, key): + index = self.hashFunc(key) + # 置为空字符,代表删除 + self.bucket[index] = None ``` === "Go" ```go title="array_hash_map.go" + // 键值对 int->String + type Entry struct { + key int + val string + } + + // 基于数组简易实现的哈希表 + type ArrayHashMap struct { + bucket []Entry + } + + func newArrayHashMap() *ArrayHashMap { + // 初始化一个长度为 100 的桶(数组) + bucket := make([]Entry, 100) + return &ArrayHashMap{bucket: bucket} + } + // 哈希函数 + func (a *ArrayHashMap) hashFunc(key int) int { + index := key % 100 + return index + } + + // 查询操作 + func (a *ArrayHashMap) get(key int) string { + index := a.hashFunc(key) + pair := a.bucket[index] + if pair.key == 0 { + return "" + } + return pair.val + } + + // 添加操作 + func (a *ArrayHashMap) put(key int, val string) { + pair := Entry{key: key, val: val} + index := a.hashFunc(key) + a.bucket[index] = pair + } + + // 删除操作 + func (a *ArrayHashMap) remove(key int) { + index := a.hashFunc(key) + // 置为空字符,代表删除 + a.bucket[index] = Entry{} + } ``` === "JavaScript"