Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
yangql
googletest
Commits
1b61f16a
Commit
1b61f16a
authored
Jun 25, 2009
by
zhanyong.wan
Browse files
Makes list traversal O(N) instead of O(N^2) (by Zhanyong Wan).
parent
aaebfcdc
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
51 additions
and
12 deletions
+51
-12
src/gtest-internal-inl.h
src/gtest-internal-inl.h
+51
-12
No files found.
src/gtest-internal-inl.h
View file @
1b61f16a
...
@@ -257,7 +257,8 @@ class List {
...
@@ -257,7 +257,8 @@ class List {
public:
public:
// Creates an empty list.
// Creates an empty list.
List
()
:
head_
(
NULL
),
last_
(
NULL
),
size_
(
0
)
{}
List
()
:
head_
(
NULL
),
last_
(
NULL
),
size_
(
0
),
last_read_index_
(
-
1
),
last_read_
(
NULL
)
{}
// D'tor.
// D'tor.
virtual
~
List
();
virtual
~
List
();
...
@@ -276,8 +277,9 @@ class List {
...
@@ -276,8 +277,9 @@ class List {
}
}
// 2. Resets the member variables.
// 2. Resets the member variables.
head_
=
last_
=
NULL
;
last_read_
=
head_
=
last_
=
NULL
;
size_
=
0
;
size_
=
0
;
last_read_index_
=
-
1
;
}
}
}
}
...
@@ -298,7 +300,8 @@ class List {
...
@@ -298,7 +300,8 @@ class List {
// Adds an element to the end of the list. A copy of the element is
// Adds an element to the end of the list. A copy of the element is
// created using the copy constructor, and then stored in the list.
// created using the copy constructor, and then stored in the list.
// Changes made to the element in the list doesn't affect the source
// Changes made to the element in the list doesn't affect the source
// object, and vice versa.
// object, and vice versa. This does not affect the "last read"
// index.
void
PushBack
(
const
E
&
element
)
{
void
PushBack
(
const
E
&
element
)
{
ListNode
<
E
>
*
new_node
=
new
ListNode
<
E
>
(
element
);
ListNode
<
E
>
*
new_node
=
new
ListNode
<
E
>
(
element
);
...
@@ -312,7 +315,8 @@ class List {
...
@@ -312,7 +315,8 @@ class List {
}
}
}
}
// Adds an element to the beginning of this list.
// Adds an element to the beginning of this list. The "last read"
// index is adjusted accordingly.
void
PushFront
(
const
E
&
element
)
{
void
PushFront
(
const
E
&
element
)
{
ListNode
<
E
>*
const
new_node
=
new
ListNode
<
E
>
(
element
);
ListNode
<
E
>*
const
new_node
=
new
ListNode
<
E
>
(
element
);
...
@@ -324,12 +328,18 @@ class List {
...
@@ -324,12 +328,18 @@ class List {
head_
=
new_node
;
head_
=
new_node
;
size_
++
;
size_
++
;
}
}
if
(
last_read_index_
>=
0
)
{
// A new element at the head bumps up an existing index by 1.
last_read_index_
++
;
}
}
}
// Removes an element from the beginning of this list. If the
// Removes an element from the beginning of this list. If the
// result argument is not NULL, the removed element is stored in the
// result argument is not NULL, the removed element is stored in the
// memory it points to. Otherwise the element is thrown away.
// memory it points to. Otherwise the element is thrown away.
// Returns true iff the list wasn't empty before the operation.
// Returns true iff the list wasn't empty before the operation. The
// "last read" index is adjusted accordingly.
bool
PopFront
(
E
*
result
)
{
bool
PopFront
(
E
*
result
)
{
if
(
size_
==
0
)
return
false
;
if
(
size_
==
0
)
return
false
;
...
@@ -346,13 +356,21 @@ class List {
...
@@ -346,13 +356,21 @@ class List {
}
}
delete
old_head
;
delete
old_head
;
if
(
last_read_index_
>
0
)
{
last_read_index_
--
;
}
else
if
(
last_read_index_
==
0
)
{
last_read_index_
=
-
1
;
last_read_
=
NULL
;
}
return
true
;
return
true
;
}
}
// Inserts an element after a given node in the list. It's the
// Inserts an element after a given node in the list. It's the
// caller's responsibility to ensure that the given node is in the
// caller's responsibility to ensure that the given node is in the
// list. If the given node is NULL, inserts the element at the
// list. If the given node is NULL, inserts the element at the
// front of the list.
// front of the list. The "last read" index is adjusted
// accordingly.
ListNode
<
E
>*
InsertAfter
(
ListNode
<
E
>*
node
,
const
E
&
element
)
{
ListNode
<
E
>*
InsertAfter
(
ListNode
<
E
>*
node
,
const
E
&
element
)
{
if
(
node
==
NULL
)
{
if
(
node
==
NULL
)
{
PushFront
(
element
);
PushFront
(
element
);
...
@@ -367,6 +385,11 @@ class List {
...
@@ -367,6 +385,11 @@ class List {
last_
=
new_node
;
last_
=
new_node
;
}
}
// We aren't sure whether this insertion will affect the last read
// index, so we invalidate it to be safe.
last_read_index_
=
-
1
;
last_read_
=
NULL
;
return
new_node
;
return
new_node
;
}
}
...
@@ -431,20 +454,27 @@ class List {
...
@@ -431,20 +454,27 @@ class List {
}
}
// Returns a pointer to the i-th element of the list, or NULL if i is not
// Returns a pointer to the i-th element of the list, or NULL if i is not
// in range [0, size()).
// in range [0, size()).
The "last read" index is adjusted accordingly.
const
E
*
GetElement
(
int
i
)
const
{
const
E
*
GetElement
(
int
i
)
const
{
if
(
i
<
0
||
i
>=
size
())
if
(
i
<
0
||
i
>=
size
())
return
NULL
;
return
NULL
;
const
ListNode
<
E
>*
node
=
Head
();
if
(
last_read_index_
<
0
||
last_read_index_
>
i
)
{
for
(
int
index
=
0
;
index
<
i
&&
node
!=
NULL
;
++
index
,
node
=
node
->
next
())
// We have to count from the start.
continue
;
last_read_index_
=
0
;
last_read_
=
Head
();
}
return
node
?
&
(
node
->
element
())
:
NULL
;
while
(
last_read_index_
<
i
)
{
last_read_
=
last_read_
->
next
();
last_read_index_
++
;
}
return
&
(
last_read_
->
element
());
}
}
// Returns the i-th element of the list, or default_value if i is not
// Returns the i-th element of the list, or default_value if i is not
// in range [0, size()).
// in range [0, size()).
The "last read" index is adjusted accordingly.
E
GetElementOr
(
int
i
,
E
default_value
)
const
{
E
GetElementOr
(
int
i
,
E
default_value
)
const
{
const
E
*
element
=
GetElement
(
i
);
const
E
*
element
=
GetElement
(
i
);
return
element
?
*
element
:
default_value
;
return
element
?
*
element
:
default_value
;
...
@@ -455,6 +485,15 @@ class List {
...
@@ -455,6 +485,15 @@ class List {
ListNode
<
E
>*
last_
;
// The last node of the list.
ListNode
<
E
>*
last_
;
// The last node of the list.
int
size_
;
// The number of elements in the list.
int
size_
;
// The number of elements in the list.
// These fields point to the last element read via GetElement(i) or
// GetElementOr(i). They are used to speed up list traversal as
// often they allow us to find the wanted element by looking from
// the last visited one instead of the list head. This means a
// sequential traversal of the list can be done in O(N) time instead
// of O(N^2).
mutable
int
last_read_index_
;
mutable
const
ListNode
<
E
>*
last_read_
;
// We disallow copying List.
// We disallow copying List.
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
List
);
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
List
);
};
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment