The deque's RemoveAt() method now shifts the objects in the direction that produces the least amount of work

git-svn-id: file:///srv/devel/repo-conversion/nusu@161 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
Markus Ewald 2009-07-13 20:22:59 +00:00
parent 58c3254260
commit 7885e86836
2 changed files with 31 additions and 25 deletions

View File

@ -12,7 +12,9 @@ namespace Nuclex.Support.Collections {
throw new InvalidOperationException("Cannot remove items from empty deque"); throw new InvalidOperationException("Cannot remove items from empty deque");
} }
// TODO: Zero removed array entry if array is kept // This is necessary to make sure the deque doesn't hold dead objects alive
// in unreachable spaces of its memory.
this.blocks[0][this.firstBlockStartIndex] = default(ItemType);
++this.firstBlockStartIndex; ++this.firstBlockStartIndex;
if(this.firstBlockStartIndex >= this.blockSize) { // Block became empty if(this.firstBlockStartIndex >= this.blockSize) { // Block became empty
@ -33,12 +35,15 @@ namespace Nuclex.Support.Collections {
throw new InvalidOperationException("Cannot remove items from empty deque"); throw new InvalidOperationException("Cannot remove items from empty deque");
} }
// TODO: Zero removed array entry if array is kept // This is necessary to make sure the deque doesn't hold dead objects alive
// in unreachable spaces of its memory.
int lastBlock = this.blocks.Count - 1;
this.blocks[lastBlock][this.lastBlockEndIndex - 1] = default(ItemType);
--this.lastBlockEndIndex; --this.lastBlockEndIndex;
if(this.lastBlockEndIndex == 0) { // Block became empty if(this.lastBlockEndIndex == 0) { // Block became empty
if(this.count > 1) { if(this.count > 1) {
this.blocks.RemoveAt(this.blocks.Count - 1); this.blocks.RemoveAt(lastBlock);
this.lastBlockEndIndex = this.blockSize; this.lastBlockEndIndex = this.blockSize;
} else { // Last block - do not remove } else { // Last block - do not remove
this.firstBlockStartIndex = 0; this.firstBlockStartIndex = 0;
@ -65,49 +70,49 @@ namespace Nuclex.Support.Collections {
/// </summary> /// </summary>
/// <param name="index">Index of the item that will be removed</param> /// <param name="index">Index of the item that will be removed</param>
private void removeFromLeft(int index) { private void removeFromLeft(int index) {
if(index == this.count - 1) { if(index == 0) {
RemoveLast(); RemoveFirst();
} else { } else {
int blockIndex, subIndex; int blockIndex, subIndex;
findIndex(index, out blockIndex, out subIndex); findIndex(index, out blockIndex, out subIndex);
int lastBlock = this.blocks.Count - 1; int firstBlock = 0;
int startIndex; int endIndex;
if(blockIndex < lastBlock) { if(blockIndex > firstBlock) {
Array.Copy( Array.Copy(
this.blocks[blockIndex], subIndex + 1, this.blocks[blockIndex], 0,
this.blocks[blockIndex], subIndex, this.blocks[blockIndex], 1,
this.blockSize - subIndex - 1 subIndex
); );
this.blocks[blockIndex][this.blockSize - 1] = this.blocks[blockIndex + 1][0]; this.blocks[blockIndex][0] = this.blocks[blockIndex - 1][this.blockSize - 1];
for(int tempIndex = blockIndex + 1; tempIndex < lastBlock; ++tempIndex) { for(int tempIndex = blockIndex - 1; tempIndex > firstBlock; --tempIndex) {
Array.Copy( Array.Copy(
this.blocks[tempIndex], 1,
this.blocks[tempIndex], 0, this.blocks[tempIndex], 0,
this.blocks[tempIndex], 1,
this.blockSize - 1 this.blockSize - 1
); );
this.blocks[tempIndex][this.blockSize - 1] = this.blocks[tempIndex + 1][0]; this.blocks[tempIndex][0] = this.blocks[tempIndex - 1][this.blockSize - 1];
} }
startIndex = 0; endIndex = this.blockSize - 1;
} else { } else {
startIndex = subIndex; endIndex = subIndex;
} }
Array.Copy( Array.Copy(
this.blocks[lastBlock], startIndex + 1, this.blocks[firstBlock], this.firstBlockStartIndex,
this.blocks[lastBlock], startIndex, this.blocks[firstBlock], this.firstBlockStartIndex + 1,
this.lastBlockEndIndex - startIndex - 1 endIndex - this.firstBlockStartIndex
); );
if(this.lastBlockEndIndex == 1) { if(this.firstBlockStartIndex == this.blockSize - 1) {
this.blocks.RemoveAt(lastBlock); this.blocks.RemoveAt(0);
this.lastBlockEndIndex = this.blockSize; this.firstBlockStartIndex = 0;
} else { } else {
this.blocks[lastBlock][this.lastBlockEndIndex - 1] = default(ItemType); this.blocks[0][this.firstBlockStartIndex] = default(ItemType);
--this.lastBlockEndIndex; ++this.firstBlockStartIndex;
} }
--this.count; --this.count;

View File

@ -126,6 +126,7 @@ namespace Nuclex.Support.Collections {
} else { } else {
return (index - this.firstBlockStartIndex + lastBlock * this.blockSize); return (index - this.firstBlockStartIndex + lastBlock * this.blockSize);
} }
} }
} }