我在计算机课上遇到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实现,因为我想真正学会如何在将来做这个。
答案 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,只需使用索引在原始数据和临时数组之间来回进行合并。