合并排序删除重复项

时间:2013-05-08 06:15:58

标签: java sorting mergesort

我正在尝试通过合并排序对数组进行排序,并在排序时删除我认为相同的元素。我递归地调用合并排序然后合并。

我达到了这一点,发现ac 重复

a b | c d

我根据某些标准确定我想要哪一个,然后选择c。我增加右手计数器和左手计数器并比较b和d。说我选择d,然后我选择b。我希望我的最终列表只有元素

c d b  

但是,正在发生的事情是在下一次递归调用时,startend为0和3,因此在下一次调用时,d将在数组中列出两次。合并过程使用的数组是:

c d b d

这是代码。提前谢谢。

private static void merge(int[] data, int start, int mid, int end)
{
    int firstCopied=0;
    int secondCopied=0;
    int index=0;
    int length=end-start+1;

    int[] temp = new int[end-start+1];
    int firstSize=mid-start+1;
    int secondSize=end-mid;

    while(firstCopied < firstSize && secondCopied < secondSize)
    {
        if(data[start+firstCopied] < data[mid+1+secondCopied])
        {
            temp[index++] = data[start+firstCopied];
            firstCopied++;
        }

        else if(data[start+firstCopied] > data[mid+1+secondCopied])
        {
            temp[index++] = data[mid+1+secondCopied];
            secondCopied++;
        }

        else if(data[start+firstCopied]==data[mid+1+secondCopied])
        {
            boolean result = PickOne();

            if(result)
            {
                temp[index++] = data[start+firstCopied];
            }
            else
            {
                temp[index++] = data[mid+1+secondCopied];
            }

            firstCopied++;
            secondCopied++;
            length--;
        }
    }
    while(firstCopied < firstSize)
    {
        temp[index++] = data[start+firstCopied];
        firstCopied++;
    }

    while(secondCopied < secondSize)
    {
        temp[index++] = data[mid+1+secondCopied];
        secondCopied++;
    }

    for(int i=0; i<length; i++)
    {
        data[start+i]=temp[i];
    }

}

3 个答案:

答案 0 :(得分:1)

C ++标准库的理念是使用一件事的算法。最好遵循这种方法,因为它将导致更多可重用的代码。

E.g。这是一个mergesort草图,然后调用std::unique

template<typename BiDirIt>
void merge_sort(BiDirIt first, BiDirIt last)
{
    auto const N = std::distance(first, last);
    if (N < 2) return;

    // sort each part individually, then merge back in-place
    auto middle = first + N / 2;
    merge_sort(first, middle);
    merge_sort(middle, last);
    std::inplace_merge(first, middle, last);
}    

int data[] = { /* your data */ };
merge_sort(std::begin(data), std::end(data));

auto it = std::unique(std::begin(data), std::end(data));
for (auto ut = std::begin(data); ut != it; ++ut) {
    // process unique data
}

如果您的数据位于std::vector而不是C阵列,则可以调用v.erase(v.begin(), it);来实际删除非唯一数据。

答案 1 :(得分:0)

您的merge在概念上会更改数组的长度。但是没有代码可以实际截断data。我建议你返回length(而不是void)并使用一些最终的后处理步骤将数据截断到最终长度,或者至少避免打印那些过去的结束元素。

答案 2 :(得分:0)

首先确保[start,mid]和[mid + 1,end]中的元素排序且唯一。 否则,代码运行后将存在重复项。