基础hashTable实现
const defaultToString = function defaultToString(key) {
if (typeof key === null) {
return "NULL";
}
if (typeof key === undefined) {
return "UNDEFINED";
}
if (key instanceof String) {
return `${key}`;
}
return key.toString();
};
class ValuePair {
constructor(key, value) {
this.key = key;
this.value = value;
}
}
class HashTable {
constructor(toStrFn = defaultToString) {
this.toStrFn = toStrFn;
this.table = {};
}
loseLoseHashCode(key) {
if (typeof key === "number") {
return key;
}
let hash = 0;
let tableKey = this.toStrFn(key);
for (let i = 0; i < tableKey.length; i++) {
hash += tableKey.charCodeAt(i);
}
return hash % 37;
}
hashCode(key) {
return this.loseLoseHashCode(key);
}
put(key, value) {
if (key !== null && value !== null) {
const position = this.hashCode(key);
this.table[position] = new ValuePair(key, value);
return true;
}
return false;
}
get(key) {
let valuePair = this.table[this.hashCode(key)];
return valuePair === null ? "undefined" : valuePair.value;
}
remove(key) {
let hashCode = this.hashCode(key);
let valuePair = this.table[hashCode];
if (valuePair) {
delete this.table[hashCode];
return true;
}
return false;
}
}
单链表实现
/**
* 单链表
*/
function defaultEquals(a, b) {
return a === b;
}
const COMPARE = {
LESS_THEN: -1,
BIGGER_THEN: 1
};
function defaultCompar(a, b) {
if (a === b) return 0;
return a < b ? COMPARE.LESS_THEN : COMPARE.BIGGER_THEN;
}
class SingleLikedListNode {
constructor(data) {
this.node = data ?? null;
this.next = null;
}
}
class SingleLikedList {
constructor(equals = defaultEquals) {
this.head = null;
this.length = 0;
this.equals = equals;
}
append(data) {
const newNode = new SingleLikedListNode(data);
if (!this.head) {
this.head = newNode;
} else {
let current = this.head;
while (current.next) {
current = current.next;
}
current.next = newNode;
}
this.length++;
return this;
}
isEmpty() {
return this.length === 0 && this.head == null;
}
// 返回链表的长度
size() {
return this.length;
}
// 查找具体位置的元素
getNodeAt(index) {
if (index < 0 || index >= this.length) return null;
let node = this.head;
for (let i = 0; i < index; i++) {
node = node.next;
}
return node;
}
// 删除链表中指定位置的元素
removeAt(index) {
if (index < 0 || index >= this.length) return null;
let current = this.head;
let previous = null;
if (index === 0) {
this.head = current.next;
} else {
previous = this.getNodeAt(index - 1);
current = previous.next;
previous.next = current.next;
}
this.length--;
return current.node;
}
// 在链表指定的位置插入元素
insertAt(node, index) {
if (index < 0 || index > this.length) return false;
let newNode = new SingleLikedListNode(node);
let current = null;
if (index === 0) {
if (!this.head) {
this.head = newNode;
} else {
current = this.head;
newNode.next = current;
this.head = newNode;
}
} else {
let previous = this.getNodeAt(index - 1);
current = previous.next;
newNode.next = current;
previous.next = newNode;
}
this.length++;
return true;
}
// 返回每个元素的下标
indexOf(node) {
let current = this.head;
for (let i = 0; i < this.length && current; i++) {
if (this.equals(node, current.node)) return i;
current = current.next;
}
return -1;
}
remove(node) {
let index = this.indexOf(node);
this.removeAt(index);
}
getHead() {
return this.head;
}
toString() {
if (!this.head) {
return "";
}
let str = this.head.node + "";
let current = this.head.next;
for (let i = 1; i < this.length && current; i++) {
str = `${str}, ${current.node}`;
current = current.next;
}
return str;
}
}
基于单链表和分离链接法实现hashTable
// 分离链接法
class HashTableSeparateChaining extends HashTable {
constructor(toStrFn = defaultToString) {
super(toStrFn);
}
put(key, value) {
if (key !== null && value !== null) {
const position = this.hashCode(key);
if (this.table[position] == null) {
this.table[position] = new SingleLikedList();
}
this.table[position].append(new ValuePair(key, value));
return true;
}
return false;
}
get(key) {
const position = this.hashCode(key);
const singleLinkedList = this.table[position];
if (singleLinkedList != null && !singleLinkedList.isEmpty()) {
let current = singleLinkedList.getHead();
while (current) {
if (current.node.key === key) {
return current.node.value;
}
current = current.next;
}
}
return undefined;
}
remove(key) {
const position = this.hashCode(key);
const singleLinkedList = this.table[position];
if (singleLinkedList != null && !singleLinkedList.isEmpty()) {
let current = singleLinkedList.getHead();
while (current) {
if (current.node.key === key) {
singleLinkedList.remove(current.node);
if (singleLinkedList.isEmpty()) {
delete this.table[position];
}
return true;
}
current = current.next;
}
}
return false;
}
}