【问题标题】:Recursive Selection Sort in JavaJava中的递归选择排序
【发布时间】:2018-11-26 05:37:40
【问题描述】:

我需要实现这个算法,在每次递归调用时创建一个新的 ArrayList 对象。

我的起始数组包含这个顺序的整数"20, 40 ,10, 30 ,50 ,5" ,排序后我有5,5,5,5,5,5。我认为问题出在递归调用和 SelectionSort 的最后一个 for cicle 中,因为删除最后一个 for 我注意到第一个元素的排序正确。

import java.util.*;

public class SelectionSort {

   //var
   public ArrayList<Integer> arr ;

   //constructor
   public SelectionSort(ArrayList<Integer> arr){
      this.arr = arr;
   }

   public ArrayList<Integer> getarraylist() {
   return arr;
   }


   public void sort(){  

     //position of the last sorted element
     int minimum =0;

     if (arr.size() <=0 )  return;

     for ( int j = 1; j < arr.size()-1; j++ ) { 

           if (arr.get(j) < arr.get(0) ) {
               minimum = j;
               //swap element 0 and minimum
               int temp = arr.get(0);
               arr.set(0, arr.get(minimum));
               arr.set(minimum, temp);
           }
     }

     //recursive call, new array without first element (already sorted)
     ArrayList<Integer> arr2 = new ArrayList<>(arr.subList(1,arr.size()));
     SelectionSort s2 = new SelectionSort(arr2);
     s2.sort();

     for(int i=0;i<s2.getarraylist().size();i++) {
         arr.set(i, s2.getarraylist().get(i));
     }
}

驱动类

public class Main {

    public static void main(String[] args) {

    ArrayList<Integer> arr = new ArrayList<Integer (Arrays.asList(20,40,10,30,50,5));


    System.out.println("\n ARRAY ELEMENTS \n ");
    for (int i: arr) {
        System.out.println(i);
    }

    System.out.println("\n SORTED ELEMENTS \n ");
    SelectionSort s = new SelectionSort(arr);
    s.sort();
    for (int i: s.getarraylist()) {
        System.out.println(i);
    }

}
}

【问题讨论】:

  • 您能否举一个输入/输出示例来说明它是如何错误排序的?
  • 谢谢@GBlodgett 我的起始数组按此顺序包含整数"20, 40 ,10, 30 ,50 ,5" ,排序后我有 "5,5,5,5,5,5 " 我认为问题出在“SelectionSort”类的 cicle 的最后一个
  • edit您的问题并添加此信息。
  • @Turing85 我不知道为什么您关于“set”方法的最后回复似乎消失了。无论如何 Eclipse 报告了这个方法:“用指定的元素替换这个列表中指定位置的元素”

标签: java sorting recursion arraylist selection-sort


【解决方案1】:

您的算法中实际上有两个错误,它们共同导致观察到的输出。


第一个错误在确定最小元素的for-loop 中:

for ( int j = 1; j < arr.size()-1; j++ ) { ...

您过早终止一个元素,即永远不会考虑最后一个元素。因此,在第一次迭代之后,5ArrayList 中的最后一个元素。事实上,它是您ArrayLists 中每个 中的最后一个元素。解决方法是不要在for-条件中减去1

for ( int j = 1; j < arr.size(); j++ ) { ...

第二个错误是在最后一个for-loop 中,您将索引is2 的值复制到索引iarr。您忽略了s2arr 短一个元素这一事实。因此,唯一未被覆盖的元素是最后一个元素。解决方法是从s2 中获取i-th 元素,但将其写入arri + 1-th 索引处:

arr.set(i + 1, s2.getarraylist().get(i));

现在让我们看看这两个错误如何导致观察到的输出。自从

  • ArrayList 中的最后一个元素永远不会被覆盖并且
  • 最后一个元素总是相同的,

所有元素都具有相同的值(在您的测试用例中:5)。


对您的代码的一些评论:

【讨论】:

  • 是的!非常感谢您的帮助!接下来我要做的就是对插入排序做同样的事情(我希望避免错误 XD)也谢谢你的评论,下次我会尝试更准确:)
【解决方案2】:

我不确定我是否理解这个问题,但我创建了一个递归(和迭代) selectionSort 和 InsertionSort 只是为了好玩,希望对您有所帮助。

public class Sorts {
    public static void swap(Comparable[] a, int i, int j) {
        Comparable temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

    public static void selectionSortItr(Comparable[] a, int n) {
        for (int i = 0; i < n - 1; i++) {
            int f = i;
            for (int j = i + 1; j < n; j++) {
                if (a[j].compareTo(a[f]) < 0)
                    f = j;
            }
            swap(a, i, f);
        }
    }

    public static int select(Comparable[] a, int n, int j, int f) {
        if (j >= n) 
            return f;
        if (a[j].compareTo(a[f]) < 0)
            f = j;
        return select(a, n, j + 1, f);
    }

    public static void selectionSort(Comparable[] a, int n, int i) {
        if (i < n - 1) {
            swap(a, i, select(a, n, i + 1, i));
            selectionSort(a, n, i + 1);
        }
    }

    public static void insertionSortItr(Comparable[] a) {
        for (int i = 1; i < a.length; i++) {
            int j;
            Comparable cur = a[i];
            for (j = i; j > 0 && cur.compareTo(a[j - 1]) < 0; j--) {
                a[j] = a[j - 1];
            }
            a[j] = cur;
        }
    }

    public static void insertionSortInner(Comparable[] a, Comparable cur, int j) {
        if (j > 0 && cur.compareTo(a[j - 1]) < 0) {
            a[j] = a[j - 1];
            insertionSortInner(a, cur, j - 1);
        } else {
            a[j] = cur;
        }
    }

    public static void insertionSort(Comparable[] a, int i, int n) {
        if (i < n) {
            insertionSortInner(a, a[i], i);
            insertionSort(a, i + 1, n);
        }
    }

    public static void main(String[] args) {
        Integer[] a = new Integer[10];
        for (int i = 0; i < 10; i++) 
            a[i] = (int) (Math.random()*100);
        selectionSort(a, 10, 0);
        for (int i = 0; i < 10; i++) 
            System.out.println(a[i]);
    }
}

【讨论】:

  • 我刚刚意识到这是插入排序,而不是选择排序。我为此道歉...... ;)
【解决方案3】:

最后一个循环:

for(int i=0;i<s2.getarraylist().size();i++) {
     arr.set(i, s2.getarraylist().get(i));
 }

这会覆盖具有相同编号的每个元素。 (为什么你的结果全是 5)这是因为你只迭代到倒数第二个元素(arr.size()-1)。然后复制该行中的元素:

 ArrayList<Integer> arr2 = new ArrayList<>(arr.subList(1,arr.size()));

最终,您只是复制 (5) 上的最后一个元素,然后将其复制到最终的 ArrayList arr

此外,您每次调用 sort 方法时都会创建另一个 SelectionSort 对象。这不好。

这是我写的代码:

 public void sort(List<Integer> list){  

     //position of the last ordered element
     int minimum =0;
     if (list.size() <=0 )  return;

     for ( int j = 1; j < list.size(); j++ ) { 

           if (list.get(j) < list.get(0) ) {
               minimum = j;
               //swap element 0 and minimum
               int temp = list.get(0);
               list.set(0, list.get(minimum));
               list.set(minimum, temp);

           }

     }


     sort(list.subList(1,list.size()));
}

我将其更改为接受List&lt;Integer&gt; 的参数(因为subList() 方法返回List),然后摆脱了最后一个循环以及您创建新对象的位置。

你也必须改变

s.sort();

到:

s.sort(s.getarraylist());

输出:

 ARRAY ELEMENTS 

20
40
10
30
50
5

 SORTED ELEMENTS 

5
10
20
30
40
50

【讨论】:

  • "这会覆盖具有相同编号的每个元素。" - 你能详细说明一下吗?由于 OP 将 i 用于 get(...)set(...) (arr.set(i, s2.getarraylist().get(i));),因此这种说法并不明显。
  • @Turing85 我编辑了我的问题,但我为你的更好解释 +1
  • 一点:不要将ArrayList 设为静态。这可能会导致令人讨厌的错误,并且很难测试/模拟。
  • @GBlodgett 感谢您的代码。我也以与您提出的算法类似的方式制作了算法(而不是使用整数作为排序方法的参数而不是数组列表,它可以工作)无论如何我想特别找到解决这个问题的方法。我删除了最后一个“for”,我注意到它的第一个元素已正确排序,所以问题出在递归调用和最后一个“for”中
  • @Turing85 嗯,没有考虑到这一点。感谢您指出!
猜你喜欢
  • 2019-03-09
  • 2015-02-13
  • 2015-08-13
  • 2019-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 2013-12-27
相关资源
最近更新 更多