I have a problem with a performance of the heap. I don't know which part of my code effects the performance of this data structure. For instance inserting/deleting 9999 elements took 12000 ms. Heap has to do it in less than 100ms (in theory). And normal list did it in 20000 ms. Can you point some bad habits that I' ve used in my code ?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Heap
{
int[] items;
int size = 1;
public Heap()
{
items = new int[size];
}
public Heap(int size)
{
items = new int[size];
}
public void AddOnLast(int value)
{
int i = items.Length + 1;
Array.Resize(ref items, i);
items[items.Length-1] = value;
}
// Deleting item of specific index from the array/ using LINQ
public void RemoveAt(int indexToRemove)
{
items = items.Where((source, indexOfElements) => indexOfElements != indexToRemove).ToArray();
}
/*Method which push up the elment after adding it on the last place
k - last index/ when k=0, element is on the top of the heap
p - parent index/ item - value of element/ parent - value of parent */
private void PushUp()
{
int k = items.Length - 1;
while (k > 0)
{
int p = (k - 1) / 2;
int item = items[k];
int parent = items[p];
if (item > parent)
{
//Swap of elements
items[k] = parent;
items[p] = item;
k = p;
}
else
{
break;
}
}
}
// Method which put element in correct place of the heap
public void insert(int value)
{
AddOnLast(value);
PushUp();
}
/* After deleting item from the heap we have to push down element to check if heap structure is correct
k - index of first element, top of the heap/ l - left "child" index / r - right child index
max is max value - either right or left child */
private void PushDown()
{
int k = 0;
int l = 2 * k + 1;
while (l < items.Length)
{
int max = 1;
int r = l + 1;
if (r < items.Length)
{
if (items[r] > items[l])
{
//max become right child
max++;
}
}
if (items[k] < items[max])
{
//swap of 2 values, prevous element and next element are swapped
int temp = items[k];
items[k] = items[max];
items[max] = temp;
}
else
{
break;
}
}
}
//Deleting item from the top of the heap
public void delete()
{
if (items.Length == 0)
{
Console.Write("No elements to delete");
}
else if (items.Length == 1)
{
RemoveAt(0);
}
else
{
int hold = items[0];// we hold the first element
items[0] = items[items.Length - 1]; // last element become first
RemoveAt(items.Length - 1); // we delete last element, and check if last element which is now on the top of the heap is on the right place
PushDown();
}
}
}
Your code actually have more serious problems than just speed (that is caused by the resizing of array on every insert).
Have a look at this
class Heap
{
int[] items;
int size = 0;
public Heap() : this(16)
{
}
public Heap(int initSize)
{
if (initSize < 1)
{
throw new ArgumentException("Size must be greater than 0");
}
items = new int[initSize];
}
/*Method which push up the elment after adding it on the last place
k - last index/ when k=0, element is on the top of the heap
p - parent index/ item - value of element/ parent - value of parent */
private void PushUp()
{
int k = size - 1;
while (k > 0)
{
int p = (k - 1) / 2;
int item = items[k];
int parent = items[p];
if (item > parent)
{
//Swap of elements
items[k] = parent;
items[p] = item;
k = p;
}
else
{
break;
}
}
}
// Method which put element in correct place of the heap
public void Insert(int value)
{
if (items.Length <= size)
{
Array.Resize(ref items, items.Length * 2);
}
items[size++] = value;
PushUp();
}
public bool IsEmpty()
{
return size == 0;
}
/* After deleting item from the heap we have to push down element to check if heap structure is correct
k - index of first element, top of the heap/ l - left "child" index / r - right child index
max is max value - either right or left child */
private void PushDown(int k)
{
int l = 2 * k + 1;
while (l < size)
{
int max = l;
int r = l + 1;
if (r < size)
{
if (items[r] > items[l])
{
//max become right child
max = r;
}
}
if (items[k] < items[max])
{
//swap of 2 values, prevous element and next element are swapped
int temp = items[k];
items[k] = items[max];
items[max] = temp;
}
else
{
break;
}
k = max;
l = 2 * k + 1;
}
}
//Deleting item from the top of the heap
public int Pop()
{
if (size == 0)
{
throw new DataException("No elements to delete");
}
else if (size == 1)
{
return items[--size];
}
else
{
int ret = items[0];
items[0] = items[--size];
PushDown(0);
return ret;
}
}
}
A few things that maybe have low performance:
Array.Resize
Your implementation of RemoveAt
Your implementation of insert
Not sure I understand what you need to achieve, but it seems you can replace your Heap class with a simple List<int>
RemoveAt -> List.RemoveAt
AddOnLast -> List.Add
Insert-> List.Insert(0, yourValue) //(If I understand correctly what you need)
delete -> List.removeAt(0) // or maybe List.removeAt(list.Length - 1)
And i trust Microsoft(and Mono coders) writing code for a List much better than I could write: I don't want to implement something that someone else has already implemented
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.