c# -归并排序,内存不足

本文关键字:内存不足 归并排序 | 更新日期: 2023-09-27 18:02:11

我实现了用于100,000整型文件的合并排序算法。它负责排序并收集文件中的反转。它适用于小型测试数组,但一旦我插入实际文件,我就会出现内存错误。我怎么修理它?错误发生在MergeSort期间,我的aux数组中的元素数量为12,500下面是我的代码:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Assignment_1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> data = File2Array("IntegerArray.txt");
            int[] unsorted = data.ToArray();
            List<string> inversions = new List<string>();
            Sort(ref unsorted, ref inversions);
            Console.WriteLine("number of inversions is: " + inversions.Count());
            Console.ReadLine();
        }
        public static void Sort(ref int[] unsorted, ref List<string>inversions)
        {
            int size = unsorted.Length;
            if (size == 1)
                return;
            int mid = size / 2;
            int leftSize = mid;
            int rightSize = size - leftSize;
            int[] left = new int[leftSize];
            int[] right = new int[rightSize];
            Array.Copy(unsorted, 0, left, 0, leftSize);
            Array.Copy(unsorted, mid, right, 0, rightSize);
            Sort(ref left, ref inversions);
            Sort(ref right, ref inversions);
            int[] aux = new int[leftSize + rightSize];
            for (int i = 0, j = 0, k = 0; k < aux.Length; k++)
            {
                if (left[i] < right[j])
                {
                    aux[k] = left[i++];
                    // if left array is exhausted, copy the remaining right array elements over
                    if (i == leftSize)
                    {
                        Array.Copy(right, j, aux, ++k, rightSize - j);
                        unsorted = aux;
                        break;
                    }
                }
                else
                {
                    int temp = i;
                    while (temp < leftSize)
                    {
                        inversions.Add(left[temp++] + "-" + right[j]);
                    }
                    aux[k] = right[j++];
                    if (j == rightSize)
                    {
                        Array.Copy(left, i, aux, ++k, leftSize - i);
                        unsorted = aux;
                        break;
                    }
                }
            }
        }
        public static List<int> File2Array(string file)
        {
            List<int> data = new List<int>();
            using (StreamReader reader = new StreamReader(file))
            {
                int line;
                do
                {
                    int.TryParse(reader.ReadLine(), out line);
                    data.Add(line);
                }
                while (!reader.EndOfStream);
            }
            return data;
        }
    }
}

c# -归并排序,内存不足

这里有一些代码供您查看。

首先要认识到文件已经是单个元素的集合。因此,我们可以在读取文件时进行第一次分组/排序。由于数组在这部分非常不实用,所以我使用了Lists,然后将返回值强制转换为int[][]

static int[][] makearrays(string filename)
{
    List<List<int>> outval = new List<List<int>>();
    using(StreamReader sr = new StreamReader(filename))
    {
        while(!sr.EndOfStream)
        {
            int a = 0, b = 0;
            a = int.Parse(sr.ReadLine());
            if(!sr.EndOfStream)
                b = int.Parse(sr.ReadLine());
            else
            {
                outval.Add(new List<int>() { a });
                break;
            }
            if(a > b)
                outval.Add(new List<int>() { b, a });
            else
                outval.Add(new List<int>() { a, b });
        }
    }
    return outval.Select(x => x.ToArray()).ToArray();
}

有了这个数组,我们可以开始剩下的分组/排序

使用递归,但内存占用最小:

static int[][] dosort(int[][] input)
{
    if(input.Length == 1)
        return input;
    int i = 1, m = 0;
    for(; i < input.Length; i += 2)
    {
        int limit = Math.Min(input[i].Length, input[i - 1].Length);
        int[] temp = new int[input[i].Length + input[i - 1].Length];
        int j = 0, k = 0, l = 0;
        while(j < input[i].Length && k < input[i - 1].Length)
        {
            if(input[i][j] < input[i - 1][k])
            {
                temp[l++] = input[i][j++];
            }
            else
                temp[l++] = input[i - 1][k++];
        }
        while(l < temp.Length)
        {
            if(j < input[i].Length)
                temp[l++] = input[i][j++];
            if(k < input[i - 1].Length)
                temp[l++] = input[i - 1][k++];
        }
        input[m++] = temp;
    }
    if(input.Length % 2 == 1)
        input[m++] = input.Last();
    input = input.Take(m).ToArray();
    return dosort(input);
}

在我的测试中,100000元素文件在不到四分之一秒的时间内排序,包括将其读入内存。