考虑以下情况:
100万客户访问商店并使用信用卡支付一定数额的钱。信用卡代码使用16位数字生成,并用字符'A', 'B', 'C', 'D'
替换其4位(随机)。 16位数字随机生成一次,用于每张信用卡,卡片之间唯一的变化就是上述字符串中的位置(即可能的不同代码)。
我必须使用我选择的哈希函数在哈希表中组织客户端,并使用开放寻址(线性探测)来处理冲突。一旦在表格中组织,我必须找到
的客户我对哈希表的实现如下,似乎可以正常运行1000个客户端的测试。但是,一旦我将客户端数量增加到10000,页面就永远不会完成加载。这是一个很大的问题,因为"购物会议的总数"必须是一百万,我甚至没有接近这个数字。
class HashTable{
constructor(size){
this.size = size;
this.items = new Array(this.size);
this.collisions = 0;
}
put(k, v){
let hash = polynomial_evaluation(k);
//evaluating the index to the array
//using modulus a prime number (size of the array)
//This works well as long as the numbers are uniformly
//distributed and sparse.
let index = hash%this.size;
//if the array position is empty
//then fill it with the value v.
if(!this.items[index]){
this.items[index] = v;
}
//if not, search for the next available position
//and fill that with value v.
//if the card already is in the array,
//update the amount paid.
//also increment the collisions variable.
else{
this.collisions++;
let i=1, found = false;
//while the array at index is full
//check whether the card is the same,
//and if not then calculate the new index.
while(this.items[index]){
if(this.items[index] == v){
this.items[index].increaseAmount(v.getAmount());
found = true;
break;
}
index = (hash+i)%this.size;
i++;
}
if(!found){
this.items[index] = v;
}
found = false;
}
return index;
}
get(k){
let hash = polynomial_evaluation(k);
let index = hash%this.size, i=1;
while(this.items[index] != null){
if(this.items[index].getKey() == k){
return this.items[index];
}
else{
index = (hash+i)%this.size;
i++;
}
}
return null;
}
findBiggestSpender(){
let max = {getAmount: function () {
return 0;
}};
for(let item of this.items){
//checking whether the specific item is a client
//since many of the items will be null
if(item instanceof Client){
if(item.getAmount() > max.getAmount()){
max = item;
}
}
}
return max;
}
findMostFrequentBuyer(){
let max = {getTimes: function () {
return 0;
}};
for(let item of this.items){
//checking whether the specific item is a client
//since many of the items will be null
if(item instanceof Client){
if(item.getTimes() > max.getTimes()){
max = item;
}
}
}
return max;
}
}
to key我用来计算数组的索引是一个4个整数的列表,范围从0到15,表示'A', 'B', 'C', 'D'
在字符串中的位置
这是我正在使用的哈希函数:
function polynomial_evaluation(key, a=33){
//evaluates the expression:
// x1*a^(d-1) + x2*a^(d-2) + ... + xd
//for a given key in the form of a tuple (x1,x2,...,xd)
//and for a nonzero constant "a".
//for the evaluation of the expression horner's rule is used:
// x_d + a*(x_(d-1) + a(x_(d-2) + .... + a*(x_3 + a*(x_2 + a*x1))... ))
//defining a new key with the elements of the
//old times 2,3,4 or 5 depending on the position
//this helps for "spreading" the values of the keys
let nKey = [key[0]*2, key[1]*3, key[2]*4, key[3]*5];
let sum=0;
for(let i=0; i<nKey.length; i++){
sum*=a;
sum+=nKey[i];
}
return sum;
}
与哈希函数生成的密钥对应的值是Client
类的实例,其中包含字段amount
(支付的金额),times
(此时间为特定客户购物),key
(上面提到的4个整数数组),以及这些字段的getter函数。此外,还有一种方法可以在同一客户端多次出现时增加amount
。
哈希表的大小为87383
(素数),主文件中的代码如下所示:
//initializing the clients array
let clients = createClients(10000);
//creating a new hash table
let ht = new HashTable(N);
for(let client of clients){
ht.put(client.getKey(), client);
}
这种情况一直持续到谷歌浏览器提供的页面没有响应&#34;错误。有什么方法可以让它更快吗?我对这个主题的态度(甚至是我选择的语言)是否正确?
提前致谢。
答案 0 :(得分:0)
由于主(UI)线程被锁定,页面没有响应。使用WebWorker或ServiceWorker处理计算,并将它们作为消息发布到主线程。
关于优化代码,我看到的一件事是findBiggestSpender
。我会逐行打破它。
let max = {getAmount: function () {
return 0;
}};
这是一种浪费。只需分配一个局部变量,无需在每次迭代中调用max.getAmount()
。
for(let item of this.items){
在Javascript中迭代列表的最快方法是使用缓存的循环长度:for (let item, len = this.items.length; i < len; i ++)
if(item instanceof Client){
这比硬空检查慢,只需使用item !== null
。