我的合并排序代码有什么问题?

时间:2015-12-12 00:00:14

标签: java arrays sorting arraylist merge

我在计算机课上遇到Merge Sort问题。我不断收到任何错误或返回原始的ArrayList。

我认为Merge Sort涉及将数组(列表)递归地分成两半,直到只剩下一个元素,然后,从这些单独的元素开始,按排序顺序合并它们。这将继续,直到数组(列表)已排序。至于实际的排序部分,我试图在新的ArrayList中插入两半之间的较高值,直到它们都是空的,在这种情况下,填充的ArrayList现在被排序。

这是我目前的代码:

public static ArrayList<Integer> mergesort(ArrayList<Integer> arr) {

    // Base case: if size of ArrayList is 1, return it.
    if (arr.size() < 2) {
        return arr;
    }

    // Else: Find the middle index.
    int middle = (arr.size() - 1) / 2;

    // Split into left and right halves.
    ArrayList<Integer> leftHalf = new ArrayList<Integer>();
    for (int i = 0; i < middle; i++)
        leftHalf.add(arr.get(i));

    ArrayList<Integer> rightHalf = new ArrayList<Integer>();
    for (int j = middle; j < arr.size(); j++)
        rightHalf.add(arr.get(j));

    // Recurse using the halves.
    mergesort(leftHalf);
    mergesort(rightHalf);

    // Sort and merge the two halves.
    return merge(leftHalf, rightHalf, arr);
}

// Merge two halves and sort them, and put the sorted values into the ArrayList sorted.
public static ArrayList<Integer> merge(ArrayList<Integer> arr1, ArrayList<Integer> arr2, ArrayList<Integer> sorted) {

    // While the ArrayLists are not empty, add sorted elements to ArrayList sorted.
    while (arr1.size() > 0 && arr2.size() > 0) {

        // If the first element in A is greater than the first in B, remove A and add to ArrayList sorted.
        if (arr1.get(0) >= arr2.get(0)) {
            sorted.add(arr1.get(0));
            arr1.remove(0);
        }
        // Else, remove from B and add to ArrayList sorted.
        else {
            sorted.add(arr2.get(0));
            arr2.remove(0);
        }
    }

    // If there're still elements in A due to arr being odd
    // add them to C since they will be the largest.
    if (arr1.size() > 0)
        sorted.add(arr1.get(0));

    return sorted;
}

我很感激任何帮助,但请不要给我一个完整的Merge Sort实现,因为我想真正学会如何在将来做这个。

2 个答案:

答案 0 :(得分:0)

我看到两个直接的问题。

首先,你有无限的递归。假设您传入一个4值列表并打印列表大小和中间值,您将获得:

size 4, middle 1 size 3, middle 1 size 2, middle 0 size 2, middle 0 size 2, middle 0 ... to infinity

请记住,Java在代码中执行整数除法。

其次,您将arr参数从mergesort传递给merge,没有任何内容从中删除。因此,即使你通过了无限递归,你仍然最终得到一个更大的列表,你的原始列表加上你.add()编辑的任何内容

答案 1 :(得分:0)

如MarquisDeMizzle所述,当arr.size()== 1时,中间== 1。

#include <type_traits>

template <class... T>
struct TypeList {
  static constexpr const std::size_t size = sizeof...(T);
};

/***
 * Concat metafunction
 */

template <typename A, typename B>
struct Concat;

template <class... As, class... Bs>
struct Concat<TypeList<As...>, TypeList<Bs...>> {
  typedef TypeList<As..., Bs...> type;
};

template <typename A, typename B>
using Concat_t = typename Concat<A, B>::type;

/***
 * Split metafunction
 */

template <int i, typename TL>
struct Split;

template <int k, typename... TL>
struct Split<k, TypeList<TL...>> {
private:
  typedef Split<k / 2, TypeList<TL...>> FirstSplit;
  typedef Split<k - k / 2, typename FirstSplit::R> SecondSplit;

public:
  typedef Concat_t<typename FirstSplit::L, typename SecondSplit::L> L;
  typedef typename SecondSplit::R R;
};

template <typename T, typename... TL>
struct Split<0, TypeList<T, TL...>> {
  typedef TypeList<> L;
  typedef TypeList<T, TL...> R;
};

template <typename T, typename... TL>
struct Split<1, TypeList<T, TL...>> {
  typedef TypeList<T> L;
  typedef TypeList<TL...> R;
};

template <int k>
struct Split<k, TypeList<>> {
  typedef TypeList<> L;
  typedef TypeList<> R;
};

// Metafunction Subdivide: Split a typelist into two roughly equal typelists
template <typename TL>
struct Subdivide : Split<TL::size / 2, TL> {};

/***
 * Ordered tuple
 */

template <int X>
using int_t = std::integral_constant<int, X>;

template <class... T>
struct Ordered_List : TypeList<T...> {};

template <class... As, class... Bs>
struct Concat<Ordered_List<As...>, Ordered_List<Bs...>> {
  typedef Ordered_List<As..., Bs...> type;
};

/***
 * Merge metafunction
 */

template <typename A, typename B>
struct Merge;

template <typename B>
struct Merge<Ordered_List<>, B> {
  typedef B type;
};

template <int a, class... As>
struct Merge<Ordered_List<int_t<a>, As...>, Ordered_List<>> {
  typedef Ordered_List<int_t<a>, As...> type;
};

template <int a, class... As, int b, class... Bs>
struct Merge<Ordered_List<int_t<a>, As...>, Ordered_List<int_t<b>, Bs...>> {
  typedef Ordered_List<int_t<a>, As...> A;
  typedef Ordered_List<int_t<b>, Bs...> B;

  typedef typename std::conditional<a <= b,
                                    Concat_t<Ordered_List<int_t<a>>, typename Merge<Ordered_List<As...>, B>::type>,
                                    Concat_t<Ordered_List<int_t<b>>, typename Merge<A, Ordered_List<Bs...>>::type>
                                   >::type type;
};

template <typename A, typename B>
using Merge_t = typename Merge<A, B>::type;

/***
 * Mergesort metafunction
 */

template <typename TL>
struct MergeSort;

// Boilerplate base-cases
template <>
struct MergeSort<TypeList<>> {
  typedef Ordered_List<> type;
};

template <int X>
struct MergeSort<TypeList<int_t<X>>> {
  typedef Ordered_List<int_t<X>> type;
};

// Inductive step
template <int X, class... Xs>
struct MergeSort<TypeList<int_t<X>, Xs...>> {
  typedef TypeList<int_t<X>, Xs...> input_t;
  typedef Subdivide<input_t> subdivide_t;
  typedef typename MergeSort<typename subdivide_t::L>::type left_sort_t;
  typedef typename MergeSort<typename subdivide_t::R>::type right_sort_t;
  typedef Merge_t<left_sort_t, right_sort_t> type;
};

template <typename T>
using MergeSort_t = typename MergeSort<T>::type;

/***
 * Make ordered tuple impl
 */

#include <tuple>

template <typename T>
struct MakeStdTuple;

template <class... Ts>
struct MakeStdTuple<Ordered_List<Ts...>> {
  typedef std::tuple<Ts...> type;
};

template <typename T>
using MakeStdTuple_t = typename MakeStdTuple<T>::type;

template <class... T>
constexpr MakeStdTuple_t<MergeSort_t<TypeList<T...>>> make_ordered_tuple(T&&...) {
  return {};
}

static_assert(std::is_same<Ordered_List<int_t<1>, int_t<2>, int_t<3>>,
                           MergeSort_t<TypeList<int_t<1>, int_t<2>, int_t<3>>>>::value, "Failed a unit test");

static_assert(std::is_same<Ordered_List<int_t<1>, int_t<2>, int_t<3>>,
                           MergeSort_t<TypeList<int_t<2>, int_t<1>, int_t<3>>>>::value, "Failed a unit test");

static_assert(std::is_same<Ordered_List<int_t<1>, int_t<2>, int_t<3>>,
                           MergeSort_t<TypeList<int_t<3>, int_t<2>, int_t<1>>>>::value, "Failed a unit test");

int main() {}

在主合并循环后复制任何剩余的元素,并且由于您不知道arr1或arr2是否先变为空,请同时检查两者:

    int middle = arr.size() / 2;

如果有兴趣,您可能想要了解自下而上的合并排序。它会跳过所有的递归,并开始假设一个包含n个元素的数组是n次运行的大小为1,只需使用索引在原始数据和临时数组之间来回进行合并。

相关问题