我的堆性能有问题。我不知道我的代码的哪一部分会影响这种数据结构的性能。例如,插入/删除9999个元素需要12000毫秒。 Heap必须在不到100ms的时间内完成(理论上)。正常列表在20000毫秒内完成。你能指出一些我不习惯的坏习惯吗?在我的代码中使用过吗?
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();
}
}
}
答案 0 :(得分:3)
您的代码实际上存在比速度更严重的问题(这是由每个插入的数组大小调整引起的)。
看看这个
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;
}
}
}
答案 1 :(得分:1)
可能性能较低的一些事情:
Array.Resize
Your implementation of RemoveAt
Your implementation of insert
我不确定我理解您需要实现的目标,但似乎您可以使用简单的List<int>
替换您的Heap类
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)
我相信微软(和Mono编码员)为List编写代码要比我写的要好得多:我不想实现其他人已经实现的东西