我有以下合并排序迭代实现,但不知何故,它不起作用。我调试了它,但找不到原因。
合并函数将保持与递归情况相同,只有数组除法逻辑会有所不同,如果我是正确的。
如果我的方向错误,请纠正。
答案 0 :(得分:2)
当您尝试使用相同的对象来表示不同的间隔时,我认为您遇到了问题: 在MergeSort_Iterative循环中,当您向list1添加新元素时,您使用“info”对象作为时间变量,然后将其添加到list1集合。
在Java中,所有对象变量都是引用,因此当您将对象添加到集合时,您不是要添加它的副本,而是添加一个被修改并再次插入的引用。
info.left = left;
info.right = mid;
list1.add(info);
info.left = mid + 1;
info.right = right;
list1.add(info);
要解决此问题,您应该创建两个对象,以便两个对象执行insections:
info = new MergePosInfo();
info.left = left;
info.right = mid;
list1.add(info);
info = new MergePosInfo();
info.left = mid + 1;
info.right = right;
list1.add(info);
另一方面,一旦解决了上述问题,你应该从list更短到更宽的间隔和从左到右的位置迭代list2,你的算法不会按顺序生成list2。
您需要修改MergeSort_Iterative:
public static void MergeSort_Iterative(int[] numbers, int left, int right) {
int mid;
if (right <= left)
return;
LinkedList<MergePosInfo> list1 = new LinkedList<MergePosInfo>();
LinkedList<MergePosInfo> list2 = new LinkedList<MergePosInfo>();
for(int i = left; i <= right; i+=2)
{
MergePosInfo info = new MergePosInfo();
info.left = i;
info.right = (i+1<=right)?(i+1):i;
info.mid = -1;
list1.add(info);
list2.add(info);
}
int l = right-left+1;
for(int partsSize = 2; partsSize <= l/2; partsSize*=2)
{
int ll1 = list1.size();
for(int i = 0; i < ll1; i+=2)
{
MergePosInfo info2 = new MergePosInfo();
info2.left = list1.get(0).left;
info2.right = list1.get(1).right;
info2.mid = (info2.left+info2.right)/2;
list1.remove(0);
list1.remove(0);
list1.add(info2);
list2.addLast(info2);
}
}
for (int i = 0; i < list2.size(); i++) {
System.out.println("Merge [" + Integer.toString(list2.get(i).left) + " , " + Integer.toString(list2.get(i).right) + "]" );
DoMerge(numbers, list2.get(i).left, list2.get(i).mid+1,
list2.get(i).right);
}
}
除了向DoMerge添加一些行:
public static void DoMerge(int[] numbers, int left, int mid, int right) {
int[] temp = new int[25];
int i, left_end, num_elements, tmp_pos;
left_end = (mid - 1);
tmp_pos = left;
num_elements = (right - left + 1);
if(num_elements == 2)
{
if(numbers[left]>numbers[right])
{
int buffer = numbers[left];
numbers[left] = numbers[right];
numbers[right] = buffer;
}
return;
}
...
正如您所看到的,我提供的解决方案仅在“数字”长度为2 ^ k时有效。你可以尝试自己解决它,如果你不能,我会给你最后的改变。
我离开了 System.out.println(“Merge [”+ Integer.toString(list2.get(i).left)+“,”+ Integer.toString(list2.get(i).right)+“]”);行,这样您就可以了解合并排序的工作原理。
答案 1 :(得分:1)
info.left = left;
info.right = mid;
list1.add(info);
info.left = mid + 1;
info.right = right;
list1.add(info);
您正在使用同一个对象。对每次迭代使用不同的对象,与使用info2