fineui是帆软报表和BI产品线所使用的前端框架。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

180 lines
4.8 KiB

// 线段树
(function () {
var parent = function (node) {
return Math.floor(node / 2);
};
var Int32Array = _global.Int32Array || function (size) {
var xs = [];
for (var i = size - 1; i >= 0; --i) {
xs[i] = 0;
}
return xs;
};
var ceilLog2 = function (x) {
var y = 1;
while (y < x) {
y *= 2;
}
return y;
};
BI.PrefixIntervalTree = function (xs) {
this._size = xs.length;
this._half = ceilLog2(this._size);
// _heap是一个_size两倍以上的堆
this._heap = new Int32Array(2 * this._half);
var i;
// 初始化 >= _size 的堆空间, 即叶子节点
for (i = 0; i < this._size; ++i) {
this._heap[this._half + i] = xs[i];
}
// 初始化 < _size 的堆空间, 即非叶子节点,根节点包含整个区间
for (i = this._half - 1; i > 0; --i) {
this._heap[i] = this._heap[2 * i] + this._heap[2 * i + 1];
}
};
BI.PrefixIntervalTree.prototype = {
constructor: BI.PrefixIntervalTree,
// 往_half之后的空间set值,需要更新其所有祖先节点的值
set: function (index, value) {
var node = this._half + index;
this._heap[node] = value;
node = parent(node);
for (; node !== 0; node = parent(node)) {
this._heap[node] =
this._heap[2 * node] + this._heap[2 * node + 1];
}
},
get: function (index) {
var node = this._half + index;
return this._heap[node];
},
getSize: function () {
return this._size;
},
/**
* get(0) + get(1) + ... + get(end - 1).
*/
sumUntil: function (end) {
if (end === 0) {
return 0;
}
var node = this._half + end - 1;
var sum = this._heap[node];
for (; node !== 1; node = parent(node)) {
if (node % 2 === 1) {
sum += this._heap[node - 1];
}
}
return sum;
},
/**
* get(0) + get(1) + ... + get(inclusiveEnd).
*/
sumTo: function (inclusiveEnd) {
return this.sumUntil(inclusiveEnd + 1);
},
/**
* sum get(begin) + get(begin + 1) + ... + get(end - 1).
*/
sum: function (begin, end) {
return this.sumUntil(end) - this.sumUntil(begin);
},
/**
* Returns the smallest i such that 0 <= i <= size and sumUntil(i) <= t, or
* -1 if no such i exists.
*/
greatestLowerBound: function (t) {
if (t < 0) {
return -1;
}
var node = 1;
if (this._heap[node] <= t) {
return this._size;
}
while (node < this._half) {
var leftSum = this._heap[2 * node];
if (t < leftSum) {
node = 2 * node;
} else {
node = 2 * node + 1;
t -= leftSum;
}
}
return node - this._half;
},
/**
* Returns the smallest i such that 0 <= i <= size and sumUntil(i) < t, or
* -1 if no such i exists.
*/
greatestStrictLowerBound: function (t) {
if (t <= 0) {
return -1;
}
var node = 1;
if (this._heap[node] < t) {
return this._size;
}
while (node < this._half) {
var leftSum = this._heap[2 * node];
if (t <= leftSum) {
node = 2 * node;
} else {
node = 2 * node + 1;
t -= leftSum;
}
}
return node - this._half;
},
/**
* Returns the smallest i such that 0 <= i <= size and t <= sumUntil(i), or
* size + 1 if no such i exists.
*/
leastUpperBound: function (t) {
return this.greatestStrictLowerBound(t) + 1;
},
/**
* Returns the smallest i such that 0 <= i <= size and t < sumUntil(i), or
* size + 1 if no such i exists.
*/
leastStrictUpperBound: function (t) {
return this.greatestLowerBound(t) + 1;
}
};
BI.PrefixIntervalTree.uniform = function (size, initialValue) {
var xs = [];
for (var i = size - 1; i >= 0; --i) {
xs[i] = initialValue;
}
return new BI.PrefixIntervalTree(xs);
};
BI.PrefixIntervalTree.empty = function (size) {
return BI.PrefixIntervalTree.uniform(size, 0);
};
})();