Skip to content

Commit

Permalink
Change ArrayBasedStack to be amortized O(1) for PUSH (TheAlgorithms#150)
Browse files Browse the repository at this point in the history
  • Loading branch information
afoix authored Aug 29, 2020
1 parent ee28dac commit 6d18833
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 9 deletions.
13 changes: 13 additions & 0 deletions DataStructures.Tests/ArrayBasedStackTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,18 @@ public static void PushTest()
stack.Push(4);
Assert.IsTrue(stack.Peek() == 4);
}

[Test]
public static void AutomaticResizesTest()
{
var stack = new ArrayBasedStack<int>();
stack.Capacity = 2;
stack.Push(0);
stack.Push(1);
stack.Push(2);
stack.Push(3);
stack.Push(4);
Assert.IsTrue(stack.Capacity > 2);
}
}
}
46 changes: 37 additions & 9 deletions DataStructures/ArrayBasedStack/ArrayBasedStack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,22 @@ namespace DataStructures.ArrayBasedStack
/// <typeparam name="T">Generic Type.</typeparam>
public class ArrayBasedStack<T>
{
private const int DefaultCapacity = 10;

/// <summary>
/// <see cref="Array"/> based stack.
/// </summary>
private T[] stack;

/// <summary>
/// How many items are in the stack right now.
/// </summary>
private int count;

/// <summary>
/// Initializes a new instance of the <see cref="ArrayBasedStack{T}"/> class.
/// </summary>
public ArrayBasedStack() => stack = Array.Empty<T>();
public ArrayBasedStack() => stack = new T[DefaultCapacity];

/// <summary>
/// Initializes a new instance of the <see cref="ArrayBasedStack{T}"/> class.
Expand All @@ -42,34 +49,50 @@ public ArrayBasedStack(IEnumerable<T> items)
/// <summary>
/// Gets the number of elements on the <see cref="ArrayBasedStack{T}"/>.
/// </summary>
public int Count => stack.Length;
public int Count => count;

/// <summary>
/// Gets or sets the Capacity of the <see cref="ArrayBasedStack{T}"/>.
/// </summary>
public int Capacity
{
get
{
return stack.Length;
}

set
{
Array.Resize(ref stack, value);
}
}

/// <summary>
/// Removes all items from the <see cref="ArrayBasedStack{T}"/>.
/// </summary>
public void Clear() => Array.Resize(ref stack, 0);
public void Clear() => count = 0;

/// <summary>
/// Determines whether an element is in the <see cref="ArrayBasedStack{T}"/>.
/// </summary>
/// <param name="item">The item to locate in the <see cref="ArrayBasedStack{T}"/>.</param>
/// <returns>True, if the item is in the stack.</returns>
public bool Contains(T item) => Array.IndexOf(stack, item) > -1;
public bool Contains(T item) => Array.IndexOf(stack, item, 0, count) > -1;

/// <summary>
/// Returns the item at the top of the <see cref="ArrayBasedStack{T}"/> without removing it.
/// </summary>
/// <returns>The item at the top of the <see cref="ArrayBasedStack{T}"/>.</returns>
public T Peek() => stack[^1];
public T Peek() => stack[count - 1];

/// <summary>
/// Removes and returns the item at the top of the <see cref="ArrayBasedStack{T}"/>.
/// </summary>
/// <returns>The item removed from the top of the <see cref="ArrayBasedStack{T}"/>.</returns>
public T Pop()
{
var item = stack[^1];
Array.Resize(ref stack, stack.Length - 1);
var item = stack[count - 1];
count = count - 1;
return item;
}

Expand All @@ -79,8 +102,13 @@ public T Pop()
/// <param name="item">The item to push onto the <see cref="ArrayBasedStack{T}"/>.</param>
public void Push(T item)
{
Array.Resize(ref stack, stack.Length + 1);
stack[^1] = item;
if (count == Capacity)
{
Capacity = Capacity * 2;
}

stack[count] = item;
count = count + 1;
}
}
}

0 comments on commit 6d18833

Please sign in to comment.