mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-30 10:50:08 +00:00
rewritten binSearch(...) impementation, still needs testing...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
e7196b76e9
commit
46c3164271
118
ui/data.js
118
ui/data.js
@ -86,8 +86,8 @@ function imageNameCmp(a, b, data){
|
|||||||
//
|
//
|
||||||
// This will return:
|
// This will return:
|
||||||
// - 0 if a is equal to position i
|
// - 0 if a is equal to position i
|
||||||
// - -1 if a is less position i
|
// - -1 if a is less than position i
|
||||||
// - +1 if a is greater position i
|
// - +1 if a is greater than position i
|
||||||
//
|
//
|
||||||
// NOTE: the signature is different from the traditional cmp(a, b) so as
|
// NOTE: the signature is different from the traditional cmp(a, b) so as
|
||||||
// to enable more complex comparisons involving adjacent elements
|
// to enable more complex comparisons involving adjacent elements
|
||||||
@ -113,9 +113,15 @@ function cmp(a, i, lst){
|
|||||||
//
|
//
|
||||||
// NOTE: this is here mostly to make debuging easy...
|
// NOTE: this is here mostly to make debuging easy...
|
||||||
function isBetween(a, i, lst){
|
function isBetween(a, i, lst){
|
||||||
//console.log('>>>', a, i, lst)
|
|
||||||
var b = lst[i]
|
var b = lst[i]
|
||||||
|
|
||||||
|
// special case: tail...
|
||||||
|
if(i == lst.length-1 && a >= b){
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
var c = lst[i+1]
|
var c = lst[i+1]
|
||||||
|
|
||||||
// hit...
|
// hit...
|
||||||
if(a == b || (a > b && a < c)){
|
if(a == b || (a > b && a < c)){
|
||||||
return 0
|
return 0
|
||||||
@ -130,18 +136,8 @@ function isBetween(a, i, lst){
|
|||||||
|
|
||||||
|
|
||||||
// Basic liner search...
|
// Basic liner search...
|
||||||
function linSearch(target, lst, check, return_position, disable_direct_indexing){
|
function linSearch(target, lst, check, return_position){
|
||||||
// XXX is this the correct default?
|
check = check == null ? cmp : check
|
||||||
check = check == null ? isBetween : check
|
|
||||||
// special case: target in the list directly...
|
|
||||||
if(disable_direct_indexing
|
|
||||||
&& check(target, lst.indexOf(target), lst) == 0){
|
|
||||||
return target
|
|
||||||
}
|
|
||||||
// special case: tail...
|
|
||||||
if(check(target, lst.length-1, lst) >= 0){
|
|
||||||
return lst[lst.length-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
for(var i=0; i < lst.length; i++){
|
for(var i=0; i < lst.length; i++){
|
||||||
if(check(target, i, lst) == 0){
|
if(check(target, i, lst) == 0){
|
||||||
@ -152,78 +148,88 @@ function linSearch(target, lst, check, return_position, disable_direct_indexing)
|
|||||||
// no hit...
|
// no hit...
|
||||||
return return_position ? -1 : null
|
return return_position ? -1 : null
|
||||||
}
|
}
|
||||||
|
Array.prototype.linSearch = function(target, cmp){
|
||||||
|
return linSearch(target, this, cmp, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Basic binary search implementation...
|
// Basic binary search implementation...
|
||||||
//
|
//
|
||||||
// NOTE: this will return the object by default, to return position set
|
// NOTE: this will return the object by default, to return position set
|
||||||
// return_position to true.
|
// return_position to true.
|
||||||
// NOTE: by default this will use isBetween as a predicate.
|
// NOTE: by default this will use cmp as a predicate.
|
||||||
// NOTE: this still depends on .indexOf(...), to disable set
|
function binSearch(target, lst, check, return_position){
|
||||||
// disable_direct_indexing to true
|
check = check == null ? cmp : check
|
||||||
// XXX BUGGY
|
var h = 0
|
||||||
// XXX this is a mess, needs revision...
|
var t = lst.length - 1
|
||||||
function binSearch(target, lst, check, return_position, disable_direct_indexing){
|
var m, res
|
||||||
// XXX is this the correct default?
|
|
||||||
check = check == null ? isBetween : check
|
while(h <= t){
|
||||||
// special case: target in the list directly...
|
m = Math.floor((h + t)/2)
|
||||||
if(disable_direct_indexing
|
res = check(target, m, lst)
|
||||||
&& check(target, lst.indexOf(target), lst) == 0){
|
|
||||||
return target
|
// match...
|
||||||
}
|
|
||||||
// special case: tail...
|
|
||||||
if(check(target, lst.length-1, lst) >= 0){
|
|
||||||
return lst[lst.length-1]
|
|
||||||
}
|
|
||||||
// special case: head...
|
|
||||||
var res = check(target, 0, lst)
|
|
||||||
if(res == 0){
|
if(res == 0){
|
||||||
return lst[0]
|
return return_position ? m : lst[m]
|
||||||
} else if(res < 0){
|
|
||||||
// no hit...
|
|
||||||
return return_position ? -1 : null
|
|
||||||
}
|
|
||||||
|
|
||||||
var l = Math.ceil(lst.length/2)
|
// below...
|
||||||
var i = l
|
|
||||||
|
|
||||||
while(l > 0){
|
|
||||||
// XXX this is a hack -- should we reach 0 using floor(..) instead?
|
|
||||||
l = l <= 1 ? 0 : Math.ceil(l/2)
|
|
||||||
res = check(target, i, lst)
|
|
||||||
// right branch...
|
|
||||||
if(res > 0){
|
|
||||||
i += l
|
|
||||||
// left branch...
|
|
||||||
} else if(res < 0){
|
} else if(res < 0){
|
||||||
i -= l
|
t = m - 1
|
||||||
// hit...
|
|
||||||
|
// above...
|
||||||
} else {
|
} else {
|
||||||
return return_position ? i : lst[i]
|
h = m + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// no hit...
|
|
||||||
|
// no result...
|
||||||
return return_position ? -1 : null
|
return return_position ? -1 : null
|
||||||
}
|
}
|
||||||
|
Array.prototype.binSearch = function(target, cmp){
|
||||||
|
return binSearch(target, this, cmp, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function match(f0, f1){
|
||||||
|
return function(){
|
||||||
|
var a = f0.apply(f0, arguments)
|
||||||
|
var b = f1.apply(f1, arguments)
|
||||||
|
if(a != b){
|
||||||
|
console.warn('Result mismatch: f0:'+a+' f1:'+b)
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Same as getImageBefore, but uses gids and searches in DATA...
|
// Same as getImageBefore, but uses gids and searches in DATA...
|
||||||
|
//
|
||||||
|
// NOTE: this uses it's own predicate...
|
||||||
function getGIDBefore(gid, ribbon, search){
|
function getGIDBefore(gid, ribbon, search){
|
||||||
search = search == null ? linSearch : search
|
search = search == null ? binSearch : search
|
||||||
|
//search = search == null ? match(linSearch, binSearch) : search
|
||||||
ribbon = DATA.ribbons[ribbon]
|
ribbon = DATA.ribbons[ribbon]
|
||||||
var order = DATA.order
|
var order = DATA.order
|
||||||
|
|
||||||
var target = order.indexOf(gid)
|
var target = order.indexOf(gid)
|
||||||
|
|
||||||
return search(target, ribbon, function (a, i, lst){
|
return search(target, ribbon, function(a, i, lst){
|
||||||
var b = order.indexOf(lst[i])
|
var b = order.indexOf(lst[i])
|
||||||
|
|
||||||
|
// special case: tail...
|
||||||
|
if(i == lst.length-1 && a >= b){
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
var c = order.indexOf(lst[i+1])
|
var c = order.indexOf(lst[i+1])
|
||||||
|
|
||||||
// hit...
|
// hit...
|
||||||
if(a == b || (a > b && a < c)){
|
if(a == b || (a > b && a < c)){
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
// before...
|
// before...
|
||||||
} else if(a < b){
|
} else if(a < b){
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
// later...
|
// later...
|
||||||
} else {
|
} else {
|
||||||
return 1
|
return 1
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user