合并排序创建内存堆

时间:2018-05-05 09:29:13

标签: java algorithm methods merge heap

我编写了这个Merge Sort,它允许用户通过只传递两个参数(一个ArrayList和一个Comparator)来调用它:

public static < T > void mergeSort(ArrayList < T > array, Comparator < T > c) {
    int high = array.size()-1;
    sort(array, c, 0, high, new ArrayList < T > (high/2));
  }  

  protected static < T > void sort(ArrayList < T > array, Comparator < T > c, int low, int high, ArrayList < T > tmp) {
    if (low < high) {
      int mid = low + (high - low) / 2;
      sort(array, c, low, mid, tmp);
      sort(array, c, mid + 1, high, tmp);
      merge(array, c, low, mid, high, tmp);
    }
  } 

  protected static < T > void merge(ArrayList < T > array, Comparator < T > c, int p, int mid, int q, ArrayList < T > tmp) {
    tmp.clear();
    int i = p;
    int j = mid + 1;
    int k = 0;
    for (; i <= mid && j <= q; k++) {
      if (c.compare(array.get(i), array.get(j)) < 0)
        tmp.add(k, array.get(i++));
      else
        tmp.add(k, array.get(j++));
    }
    if (i <= mid && j > q) {
      while (i <= mid)
        tmp.add(k++, array.get(i++));
    } else {
      while (j <= q)
        tmp.add(k++, array.get(j++));
    }
    for (k = 0; k < tmp.size()-p; k++)
      array.set(k + p, tmp.get(k));

  }
}

在调用之后我试图打印其内容(我应该订购):

Sorting.mergeSort(arrayA, new LongComparator());
System.out.println(Arrays.toString(arrayA.toArray()));

但我收到了这个错误:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3332)
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448)
    at java.lang.StringBuilder.append(StringBuilder.java:136)
    at java.util.Arrays.toString(Arrays.java:4574)

如何改善合并排序?临时ArrayList是错误的主要原因吗?因为当我尝试订购数百万个数据时会发生此错误。它有2-3个元素。 编辑:这是我的第一个算法版本,它没有支持方法,只需要我需要做的两个参数

public static < T > void sort(ArrayList < T > array, Comparator < T > c, int low, int high) {
    if (low < high) {
      int mid = low + (high - low) / 2;
      sort(array, c, low, mid);
      sort(array, c, mid + 1, high);
      merge(array, c, low, mid, high);
    }
  } 

@SuppressWarnings("unchecked")
  public static <T> void merge(ArrayList<T> array, Comparator<T> c, int p, int mid, int q) {
    Object[] tmp = new Object[q-p+1]; 
    int i = p;
    int j = mid+1;
    int k = 0;
    while (i <= mid && j <= q) {
        if (c.compare(array.get(i), array.get(j))<0)
          tmp[k] = array.get(i++);
        else
          tmp[k] = array.get(j++);
        k++;
    }
    if (i <= mid && j > q) {
        while (i <= mid) 
          tmp[k++] = array.get(i++);
    } else {
        while (j <= q)
          tmp[k++] = array.get(j++);
    }
    for (k = 0; k < tmp.length; k++)
      array.set(k+p, (T)tmp[k]);
  }

1 个答案:

答案 0 :(得分:0)

解决问题的两种方法:

增加可用内存:正如Turing85所提到的,使用VM选项运行带有更多内存的java,例如-Xmx2048m分配2GB。

减少使用的内存:使用像Long和Double这样的基本类型的ArrayList使用4次(在我的简单实验中)和使用基本类型long / double的等效数组一样多的内存。 / p>

TraverseProps(person);
// ..................................................
static void TraverseProps(object obj, int level = 0)
{
    string indent = new string(' ', level * 2);
    if (obj == null)
    {
        Console.WriteLine(indent + "<NULL>");
        return;
    }
    var properties = obj.GetType().GetProperties();
    foreach (var property in properties)
    {
        var value = property.GetValue(obj);
        Console.Write(indent + property.Name + ": ");
        if (property.PropertyType.IsArray)
        {
            Console.WriteLine(indent + "[");
            int i = 0;
            foreach (var item in (Array)value)
            {
                Console.WriteLine(indent + "item " + i + ":");
                TraverseProps(item, level + 1);
                i++;
            }
            Console.WriteLine(indent + "]");
        }
        else
        {
            Console.WriteLine(value);
        }
    }
}
由于多种原因,

还会使代码运行速度明显变慢(如果您的目标是使用非基本类型的合并排序,您可能会看到性能提升,但内存增益不会那么显着)