Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
bc76ef88
V
vscode
项目概览
xxadev
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
bc76ef88
编写于
10月 12, 2017
作者:
A
Alex Dima
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Implement interval searching
上级
648e6f6a
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
334 addition
and
194 deletion
+334
-194
src/vs/editor/common/model/intervalTree.ts
src/vs/editor/common/model/intervalTree.ts
+42
-19
src/vs/editor/test/common/model/intervalTree.test.ts
src/vs/editor/test/common/model/intervalTree.test.ts
+292
-175
未找到文件。
src/vs/editor/common/model/intervalTree.ts
浏览文件 @
bc76ef88
...
...
@@ -73,7 +73,7 @@ export class IntervalNode {
this
.
interval
=
interval
;
this
.
maxEnd
=
this
.
interval
.
end
;
this
.
resultInterval
=
n
ull
;
this
.
resultInterval
=
n
ew
Interval
(
0
,
0
)
;
}
public
detach
():
void
{
...
...
@@ -417,28 +417,51 @@ export class IntervalTree {
this
.
root
=
SENTINEL
;
}
//
public intervalSearch(interval: Interval): IntervalNode[] {
//
let result: IntervalNode[] = [];
//
if (this.root !== SENTINEL) {
// this._intervalSearch(this.root, 0, interval
, result);
//
}
//
return result;
//
}
public
intervalSearch
(
interval
:
Interval
):
IntervalNode
[]
{
let
result
:
IntervalNode
[]
=
[];
if
(
this
.
root
!==
SENTINEL
)
{
this
.
_intervalSearch
(
this
.
root
,
0
,
interval
.
start
,
interval
.
end
,
result
);
}
return
result
;
}
// private _intervalSearch(node: IntervalNode, delta: number, interval: Interval
, result: IntervalNode[]): void {
//
// https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree
//
// Now, it is known that two intervals A and B overlap only when both
// // A.low ≤ B.high and A.high ≥
B.low. When searching the trees for
//
// nodes overlapping with a given interval, you can immediately skip:
// // -
all nodes to the right of nodes whose low value is past the end of the given interval.
// // -
all nodes that have their maximum 'high' value below the start of the given interval.
private
_intervalSearch
(
node
:
IntervalNode
,
delta
:
number
,
intervalStart
:
number
,
intervalEnd
:
number
,
result
:
IntervalNode
[]):
void
{
// https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree
// Now, it is known that two intervals A and B overlap only when both
// A.low <= B.high and A.high >=
B.low. When searching the trees for
// nodes overlapping with a given interval, you can immediately skip:
// a)
all nodes to the right of nodes whose low value is past the end of the given interval.
// b)
all nodes that have their maximum 'high' value below the start of the given interval.
// if (delta + node.maxEnd < interval.start) {
// return;
// }
const
nodeMaxEnd
=
delta
+
node
.
maxEnd
;
if
(
nodeMaxEnd
<
intervalStart
)
{
// Cover b) from above
return
;
}
if
(
node
.
left
!==
SENTINEL
)
{
this
.
_intervalSearch
(
node
.
left
,
delta
,
intervalStart
,
intervalEnd
,
result
);
}
// }
const
nodeStart
=
delta
+
node
.
interval
.
start
;
if
(
nodeStart
>
intervalEnd
)
{
// Cover a) from above
return
;
}
const
nodeEnd
=
delta
+
node
.
interval
.
end
;
if
(
nodeEnd
>=
intervalStart
)
{
// There is overlap
node
.
resultInterval
.
start
=
nodeStart
;
node
.
resultInterval
.
end
=
nodeEnd
;
result
.
push
(
node
);
}
if
(
node
.
right
!==
SENTINEL
)
{
this
.
_intervalSearch
(
node
.
right
,
delta
+
node
.
delta
,
intervalStart
,
intervalEnd
,
result
);
}
}
public
insert
(
interval
:
Interval
):
IntervalNode
{
if
(
this
.
root
===
SENTINEL
)
{
...
...
src/vs/editor/test/common/model/intervalTree.test.ts
浏览文件 @
bc76ef88
...
...
@@ -43,6 +43,17 @@ suite('IntervalTree', () => {
}
}
}
public
search
(
interval
:
Interval
):
Interval
[]
{
let
result
:
Interval
[]
=
[];
for
(
let
i
=
0
,
len
=
this
.
intervals
.
length
;
i
<
len
;
i
++
)
{
let
int
=
this
.
intervals
[
i
];
if
(
int
.
start
<=
interval
.
end
&&
int
.
end
>=
interval
.
start
)
{
result
.
push
(
int
);
}
}
return
result
;
}
}
class
TestState
{
...
...
@@ -62,7 +73,7 @@ suite('IntervalTree', () => {
let
nodeId
=
(
++
this
.
_lastNodeId
);
this
.
_treeNodes
[
nodeId
]
=
this
.
_tree
.
insert
(
new
Interval
(
op
.
begin
,
op
.
end
));
this
.
_oracleNodes
[
nodeId
]
=
this
.
_oracle
.
insert
(
new
Interval
(
op
.
begin
,
op
.
end
));
}
else
{
}
else
if
(
op
.
type
===
'
delete
'
)
{
if
(
PRINT_TREE
)
{
console
.
log
(
`delete: {
${
JSON
.
stringify
(
this
.
_oracleNodes
[
op
.
id
])}
}`
);
}
...
...
@@ -71,6 +82,12 @@ suite('IntervalTree', () => {
this
.
_treeNodes
[
op
.
id
]
=
null
;
this
.
_oracleNodes
[
op
.
id
]
=
null
;
}
else
{
let
actualNodes
=
this
.
_tree
.
intervalSearch
(
new
Interval
(
op
.
begin
,
op
.
end
));
let
actual
=
actualNodes
.
map
(
n
=>
n
.
resultInterval
);
let
expected
=
this
.
_oracle
.
search
(
new
Interval
(
op
.
begin
,
op
.
end
));
assert
.
deepEqual
(
actual
,
expected
);
return
;
}
if
(
PRINT_TREE
)
{
...
...
@@ -110,7 +127,13 @@ suite('IntervalTree', () => {
id
:
number
;
}
type
IOperation
=
IInsertOperation
|
IDeleteOperation
;
interface
ISearchOperation
{
type
:
'
search
'
;
begin
:
number
;
end
:
number
;
}
type
IOperation
=
IInsertOperation
|
IDeleteOperation
|
ISearchOperation
;
function
testIntervalTree
(
ops
:
IOperation
[]):
void
{
let
state
=
new
TestState
();
...
...
@@ -123,6 +146,19 @@ suite('IntervalTree', () => {
return
Math
.
floor
(
Math
.
random
()
*
(
max
-
min
+
1
))
+
min
;
}
function
getRandomRange
(
min
:
number
,
max
:
number
):
[
number
,
number
]
{
let
begin
=
getRandomInt
(
min
,
max
);
let
length
:
number
;
if
(
getRandomInt
(
1
,
10
)
<=
2
)
{
// large range
length
=
getRandomInt
(
0
,
max
-
begin
);
}
else
{
// small range
length
=
getRandomInt
(
0
,
Math
.
min
(
max
-
begin
,
10
));
}
return
[
begin
,
begin
+
length
];
}
class
AutoTest
{
private
_ops
:
IOperation
[]
=
[];
private
_state
:
TestState
=
new
TestState
();
...
...
@@ -143,19 +179,11 @@ suite('IntervalTree', () => {
type
=
'
delete
'
;
}
if
(
type
===
'
insert
'
)
{
let
begin
=
getRandomInt
(
MIN_INTERVAL_START
,
MAX_INTERVAL_END
);
let
length
:
number
;
if
(
getRandomInt
(
1
,
10
)
<=
2
)
{
// large range
length
=
getRandomInt
(
0
,
MAX_INTERVAL_END
-
begin
);
}
else
{
// small range
length
=
getRandomInt
(
0
,
Math
.
min
(
MAX_INTERVAL_END
-
begin
,
10
));
}
let
range
=
getRandomRange
(
MIN_INTERVAL_START
,
MAX_INTERVAL_END
);
this
.
_run
({
type
:
'
insert
'
,
begin
:
begin
,
end
:
begin
+
length
begin
:
range
[
0
]
,
end
:
range
[
1
]
});
this
.
_insertCnt
--
;
this
.
_deleteCnt
++
;
...
...
@@ -166,8 +194,15 @@ suite('IntervalTree', () => {
id
:
this
.
_state
.
getExistingNodeId
(
idx
)
});
this
.
_deleteCnt
--
;
// this._deleteCnt = 0;
}
// Let's also search for something...
let
searchRange
=
getRandomRange
(
MIN_INTERVAL_START
,
MAX_INTERVAL_END
);
this
.
_run
({
type
:
'
search
'
,
begin
:
searchRange
[
0
],
end
:
searchRange
[
1
]
});
}
}
...
...
@@ -182,6 +217,7 @@ suite('IntervalTree', () => {
}
suite
(
'
generated
'
,
()
=>
{
test
(
'
gen01
'
,
()
=>
{
testIntervalTree
([
{
type
:
'
insert
'
,
begin
:
28
,
end
:
35
},
...
...
@@ -344,6 +380,7 @@ suite('IntervalTree', () => {
{
type
:
'
delete
'
,
id
:
6
}
]);
});
});
// TEST_COUNT = 0;
// PRINT_TREE = true;
...
...
@@ -362,4 +399,84 @@ suite('IntervalTree', () => {
return
;
}
}
suite
(
'
searching
'
,
()
=>
{
function
createCormenTree
():
IntervalTree
{
let
r
=
new
IntervalTree
();
let
data
:
[
number
,
number
][]
=
[
[
16
,
21
],
[
8
,
9
],
[
25
,
30
],
[
5
,
8
],
[
15
,
23
],
[
17
,
19
],
[
26
,
26
],
[
0
,
3
],
[
6
,
10
],
[
19
,
20
]
];
data
.
forEach
((
int
)
=>
{
r
.
insert
(
new
Interval
(
int
[
0
],
int
[
1
]));
});
return
r
;
}
const
T
=
createCormenTree
();
function
assertIntervalSearch
(
start
:
number
,
end
:
number
,
expected
:
[
number
,
number
][]):
void
{
let
actualNodes
=
T
.
intervalSearch
(
new
Interval
(
start
,
end
));
let
actual
=
actualNodes
.
map
((
n
)
=>
<
[
number
,
number
]
>
[
n
.
resultInterval
.
start
,
n
.
resultInterval
.
end
]);
assert
.
deepEqual
(
actual
,
expected
);
}
test
(
'
cormen 1->2
'
,
()
=>
{
assertIntervalSearch
(
1
,
2
,
[
[
0
,
3
],
]
);
});
test
(
'
cormen 4->8
'
,
()
=>
{
assertIntervalSearch
(
4
,
8
,
[
[
5
,
8
],
[
6
,
10
],
[
8
,
9
],
]
);
});
test
(
'
cormen 10->15
'
,
()
=>
{
assertIntervalSearch
(
10
,
15
,
[
[
6
,
10
],
[
15
,
23
],
]
);
});
test
(
'
cormen 21->25
'
,
()
=>
{
assertIntervalSearch
(
21
,
25
,
[
[
15
,
23
],
[
16
,
21
],
[
25
,
30
],
]
);
});
test
(
'
cormen 24->24
'
,
()
=>
{
assertIntervalSearch
(
24
,
24
,
[
]
);
});
});
});
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录