我可以被认为是Java新手。我'我们教授在我们学校给了我们一个问题。我应该做一个自然的合并排序算法,每次必须找到两个排序的子数组并合并它们。(这是自下而上合并排序的一个版本)。但我被困在这里是我的代码
public class NaturalMergeMine {
private static Comparable[] aux;
public static void sort(Comparable[] a) {
aux = new Comparable[a.length];
sort(a, 0, a.length - 1);
}
public static boolean isSorted(Comparable[] a) {
for (int i = 1; i < a.length; i += 1) {
if (a[i - 1].compareTo(a[i]) < 0) {
return false;
}
}
return true;
}
private static void sort(Comparable[] a, int lo, int hi) {
int i = lo;
int j = 0;
int mid = 0;
int az = 0;
while (true) {
i = 0;
System.out.println("outter");
while (i < a.length) {
System.out.println("inner 1");
if (i == a.length - 1) {
break;
} else if (a[i].compareTo(a[i + 1]) < 0) {
break;
}
i++;
}
j = i + 1;
while (j < a.length) {
System.out.println("inner 2");
if (j == a.length - 1) {
break;
} else if (a[j].compareTo(a[j + 1]) < 0) {
break;
}
j++;
}
mid = lo + (j - lo) / 2;
Merge(a, lo, mid, j);
lo = 0;
if (isSorted(a)) {
break;
}
}
}
public static void Merge(Comparable[] a, int lo, int mid, int hi) {
int i = lo;
int j = mid + 1;
for (int k = lo; k <= hi; k++) {
aux[k] = a[k];
}
for (int k = lo; k <= hi; k++) {
if (i > mid) {
a[k] = aux[j++];
} else if (j > hi) {
a[k] = aux[i++];
} else if (aux[i].compareTo(aux[j]) < 0) {
a[k] = aux[j++];
} else {
a[k] = aux[i++];
}
}
}
public static void show(Comparable[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
}
public static void main(String[] args) {
Integer[] arr = {6, 4, 5, 7, 8, 3, 2, 1};
sort(arr);
show(arr);
}
}
发生的事情是它没有正确合并,并且它在outter循环中进入无限循环,这是因为它没有正确排序。是否有人可以建议我更好的方式,或者可以告诉我我在这里犯的错误。提前谢谢。
答案 0 :(得分:1)
问题出在中期计算中,我不太清楚为什么你这样做,但是如果mid在你的合并方法中比你少,那么你就不会遇到故障情况所以你会坚持发现它而不解决运行你需要拿起两个数组进行排序,所以你可以将i插入到合并方法中,而不是在中间,这样就可以从故障中开始合并。
public class NaturalMergeMine {
private static Comparable[] aux;
public static void sort(Comparable[] a) {
aux = new Comparable[a.length];
sort(a, 0, a.length - 1);
}
public static boolean isSorted(Comparable[] a) {
for (int i = 1; i < a.length; i += 1) {
if (a[i - 1].compareTo(a[i]) > 0) {//changed operator to greater than
return false;
}
}
return true;
}
private static void sort(Comparable[] a, int lo, int hi) {
int i = lo;
int j = 0;
int mid = 0;
int az = 0;
while (true) {
i = 0;
System.out.println("outter");
while (i < a.length) {
System.out.println("inner 1");
if (i == a.length - 1) {
break;
} else if (a[i].compareTo(a[i + 1]) > 0) {//changed operator to greater than
break;
}
i++;
}
j = i + 1;
while (j < a.length) {
System.out.println("inner 2");
if (j == a.length - 1) {
break;
} else if (a[j].compareTo(a[j + 1]) > 0) {//changed operator to greater than
break;
}
j++;
}
// mid = lo + (j - lo) / 2;
Merge(a, lo, i, j);
lo = 0;
if (isSorted(a)) {
break;
}
}
}
public static void Merge(Comparable[] a, int lo, int mid, int hi) {
int i = lo;
int j = mid + 1;
for (int k = lo; k <= hi; k++) {
aux[k] = a[k];
}
for (int k = lo; k <= hi; k++) {
if (i > mid) {
a[k] = aux[j++];
} else if (j > hi) {
a[k] = aux[i++];
} else if (aux[i].compareTo(aux[j]) > 0) {//changed the operator to greater than
a[k] = aux[j++];
} else {
a[k] = aux[i++];
}
}
}
public static void show(Comparable[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
}
public static void main(String[] args) {
Integer[] arr = {6, 4, 5, 7, 8, 3, 2, 1};
sort(arr);
show(arr);
}
}
答案 1 :(得分:0)
Amer Qarabsa的回答解决了原始代码的问题。下面是一些更优化的替代示例,扫描数组以查找成对的升序,而不是每次从头开始。如果数组被反转,则第一次传递创建2的运行,下一次传递运行4,....对于原始版本,每个循环的运行大小只会增加一个。下面的示例代码使用开放时间间隔(最后一个索引是数组的结尾而不是数组的最后一个元素)。
public class jsortns {
private static Comparable[] aux;
public static void sort(Comparable[] a) {
aux = new Comparable[a.length];
int i;
int j;
int k;
while (true) { // merge pass
i = 0;
while(true) { // find, merge pair of runs
j = i; // find left run
while (++j < a.length) {
if (a[j-1].compareTo(a[j]) > 0)
break;
}
if(j == a.length){ // if only one run left
if(i == 0) // if done return
return;
else // else end of merge pass
break;
}
k = j; // find right run
while (++k < a.length) {
if (a[k-1].compareTo(a[k]) > 0){
break;
}
}
Merge(a, i, j, k); // merge runs
i = k;
if(i == a.length) // if end of merge pass, break
break;
}
}
}
// merge left and right runs
// ll = start of left run
// rr = start of right run == end of left run
// ee = end of right run
public static void Merge(Comparable[] a, int ll, int rr, int ee) {
int i = ll;
int j = rr;
int k;
for (k = ll; k < ee; k++)
aux[k] = a[k];
k = ll;
while(true){
// if left element <= right element
if (aux[i].compareTo(aux[j]) <= 0) {
a[k++] = aux[i++]; // copy left element
if(i == rr){ // if end of left run
while(j < ee) // copy rest of right run
a[k++] = aux[j++];
return; // and return
}
} else {
a[k++] = aux[j++]; // copy right element
if(j == ee){ // if end of right run
while(i < rr){ // copy rest of left run
a[k++] = aux[i++];
}
return; // and return
}
}
}
}
没有复制版本,而是在两个数组之间来回合并,如果排序的数据最终在错误的数组中,则只在末尾复制。
public class jsortns {
private static Comparable[] b; // temp array
private static Comparable[] o; // original array reference
private static Comparable[] t; // used to swap a, b
public static void sort(Comparable[] a) {
o = a; // save ref to a
b = new Comparable[a.length]; // allocate temp array
int i;
int j;
int k;
while (true) { // merge pass
i = 0;
while(true) { // find, merge pair of runs
j = i; // find left run
while (++j < a.length) {
if (a[j-1].compareTo(a[j]) > 0)
break;
}
if(j == a.length){ // if only one run left
if(i != 0){ // if not done
while(i < j){ // copy run to b
b[i] = a[i];
i++;
}
break; // break to end merge pass
} else { // else sort done
if(a != o){ // if a not original a, copy
for(i = 0; i < a.length; i++)
b[i] = a[i];
}
return;
}
}
k = j; // find right run
while (++k < a.length) {
if (a[k-1].compareTo(a[k]) > 0){
break;
}
}
Merge(a, b, i, j, k); // merge left, right into b
i = k;
if(i == a.length) // break if end pass
break;
}
t = a; // swap a and b (references)
a = b;
b = t;
}
}
// merge left and right runs from a[] to b[]
// ll = start of left run
// rr = start of right run == end of left run
// ee = end of right run
public static void Merge(Comparable[] a, Comparable[] b, int ll, int rr, int ee) {
int i = ll;
int j = rr;
int k = ll;
while(true){
// if left element <= right element
if (a[i].compareTo(a[j]) <= 0) {
b[k++] = a[i++]; // copy left element
if(i == rr){ // if end of left run
while(j < ee) // copy rest of right run
b[k++] = a[j++];
return; // and return
}
} else {
b[k++] = a[j++]; // copy right element
if(j == ee){ // if end of right run
while(i < rr){ // copy rest of left run
b[k++] = a[i++];
}
return; // and return
}
}
}
}