哈希表详解 1. 引言 哈希表(Hash Table)是一种常用于快速查找的数据结构,它通过哈希函数将键映射到数组的特定位置,以实现快速的插入、删除和查找操作。
2. 哈希表原理 哈希表的原理基于哈希函数,这是一种能够将任意大小的数据映射到固定大小范围的函数。哈希表由一个数组和一个哈希函数组成。当插入一个键值对时,哈希函数计算键的哈希值,然后将该值映射到数组的特定位置。在查找时,哈希表再次使用哈希函数找到键的位置,从而实现快速的查找。
3. 解决冲突的方法 由于哈希函数的映射并非唯一,可能出现多个键映射到同一个位置的情况,称为冲突。解决冲突的常见方法有:
3.1 链地址法 每个哈希表位置维护一个链表,所有映射到该位置的键值对都存储在链表中。
3.2 开放地址法 当冲突发生时,通过线性探测、二次探测等方法在哈希表中寻找下一个可用位置。
4. 哈希表的应用场景 哈希表广泛应用于各种场景,包括:
数据库索引:加速数据库中记录的查找。
缓存实现:存储最近访问的数据,提高访问速度。
字典数据结构:实现键值对的快速插入、删除和查找。
5. 哈希表的代码示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class HashTable : def __init__ (self, size ): self .size = size self .table = [None ] * size def _hash (self, key ): return hash (key) % self .size def insert (self, key, value ): index = self ._hash (key) if self .table[index] is None : self .table[index] = [(key, value)] else : self .table[index].append((key, value)) def search (self, key ): index = self ._hash (key) if self .table[index] is not None : for k, v in self .table[index]: if k == key: return v return None def delete (self, key ): index = self ._hash (key) if self .table[index] is not None : for i, (k, v) in enumerate (self .table[index]): if k == key: del self .table[index][i] return
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 package org.example; import java.util.Scanner; public class HashTableDemo { public static void main (String[] args) { HashTable hashTable = new HashTable (7 ); String key = "" ; Scanner scanner = new Scanner (System.in); while (true ) { System.out.println("add:添加雇员" ); System.out.println("list:显示雇员" ); System.out.println("find:查找雇员" ); System.out.println("exit:退出系统" ); key = scanner.next(); switch (key) { case "add" : System.out.println("输入id" ); int id = scanner.nextInt(); System.out.println("输入名字" ); String name = scanner.next(); Emp emp = new Emp (id, name); hashTable.add(emp); break ; case "list" : hashTable.list(); break ; case "find" : System.out.println("输入要查找的id" ); id = scanner.nextInt(); hashTable.findEmpById(id); break ; case "exit" : scanner.close(); System.exit(0 ); default : break ; } } } } class HashTable { private EmpLinkedList[] empLinkedListArray; private int size; public HashTable (int size) { this .size = size; empLinkedListArray = new EmpLinkedList [size]; for (int i = 0 ; i < size; i++) { empLinkedListArray[i] = new EmpLinkedList (); } } public void add (Emp emp) { int empLinkedListNO = hashFun(emp.id); empLinkedListArray[empLinkedListNO].add(emp); } public void list () { for (int i = 0 ; i < size; i++) { empLinkedListArray[i].list(i); } } public int hashFun (int id) { return id % size; } public void findEmpById (int id) { int empLinkedListNO = hashFun(id); Emp emp = empLinkedListArray[empLinkedListNO].findEmpById(id); if (emp != null ) { System.out.printf("在第%d条链表中找到 雇员id = %d\n" , empLinkedListNO + 1 , id); } else { System.out.println("在表中未找到" ); } } } class Emp { public int id; public String name; public Emp next; public Emp (int id, String name) { super (); this .id = id; this .name = name; } } class EmpLinkedList { private Emp head; public void add (Emp emp) { if (head == null ) { head = emp; return ; } Emp curEmp = head; while (true ) { if (curEmp.next == null ) { break ; } curEmp = curEmp.next; } curEmp.next = emp; } public void list (int no) { if (head == null ) { System.out.println("第" + (no + 1 ) + "链表信息为空" ); return ; } System.out.print("第" + (no + 1 ) + "链表信息为:" ); Emp curEmp = head; while (true ) { System.out.printf("=> id=%d name=%s\t" , curEmp.id, curEmp.name); if (curEmp.next == null ) { break ; } curEmp = curEmp.next; } System.out.println(); } public Emp findEmpById (int id) { if (head == null ) { System.out.println("链表为空" ); return null ; } Emp curEmp = head; while (true ) { if (curEmp.id == id) { break ; } if (curEmp.next == null ) { curEmp = null ; break ; } curEmp = curEmp.next; } return curEmp; } }
6. 总结 在选择哈希函数时,需要考虑均匀性和碰撞的处理方法,以确保哈希表的高效性。