【问题标题】:Method to sort an array in JavaJava中对数组进行排序的方法
【发布时间】:2020-01-15 16:29:51
【问题描述】:

我一直在研究一种将数组从最低到最高排序的方法。 我想出了下面的代码,但正如您可能猜到的那样,它并没有达到我的预期。

我希望应用的逻辑如下:

假设我有一个数组,例如数组 {4,3,1,2,5} 例如,代码会将数组 [0](在本例中为 4)与数组中的每个元素进行比较,

array[0]>array[0] (4>4=false), 
array[0]>array[1] (4>3)= +1counter, 
array[0]>array[2] (4>1)= +1counter, 
array[0]>array[3] (4>2)= +1counter,
array[0]>array[4] (4>5=false)

counter = 3

因此,由于计数器值现在为 3,因此在新数组(array2 或 arrayOrdered)中,数字 4 将位于第三个索引中。

我应该如何解决它?任何帮助都非常感谢!

public static int[] OrderArray(int[] array)
{

    int[] array2=new int[array.length];

    for (int i=0; i<array.length; i++)
    {
        int place=0;
        for (int j=0; j<array.length;j++)
        {
            if (array[i]> array[j])
            {
                place = place+1;
            }
            array2[place] = array[i];
        }

    }
    return array2;
}

【问题讨论】:

  • 您是否有充分的理由不简单地使用Arrays.sort? (或者,IntStream.of(array).sorted().toArray(),或者许多其他选择之一)(或者,尝试实现一个众所周知的算法)
  • 您在此处尝试应用的方法是“计算小于第 i 个元素的元素数;将第 i 个元素放在第 i 个位置”。例如,如果输入中有相等的元素,这不起作用。
  • 如果数组是[4,5,1,2,3]怎么办?这个算法会给你错误的结果。所以换个方向思考吧。

标签: java arrays sorting


【解决方案1】:

我在youtube做了一个视频,看看hawaiideveloper的解决方案:

package SortingArrayFun;

导入 java.util.Arrays;

公共类 SortAnArrayAscending {

public static void main(String[] args) {
    int [] originalArray = {13, 54, 60, 33, 20, 1, 4, 2, 5, 6, 9, 10, 23}; // The original Array
    int totalOfElements = originalArray.length; // Counts the amount of elements in this array which should be 13
    System.out.println("The amount of elements in this array is: " + originalArray.length);
    

    for(int outerLoopCounter = 0; outerLoopCounter <= totalOfElements;  outerLoopCounter++) { // we need this to cycle the same amount of times
        //as the totalOfElements
            for(int leftIndexer = 0;  leftIndexer < (totalOfElements -1);  leftIndexer++) { // this does the action of moving the index to the left
                int rightIndexer = leftIndexer + 1; // this will make the index go right
                int positionA = originalArray[leftIndexer]; // store the output of each element that comes from the left pointer aka left index
                int positionB = originalArray[rightIndexer]; // store the output of each element that comes from the right pointer aka right index
                
                        //Control Flow aka Decision Maker if position B is less than position A... please swap them
                                if(positionB < positionA) { // control flow 
                                        originalArray[leftIndexer] = positionB; // then swap them and make position on the right go to position on left
                                        originalArray[rightIndexer] = positionA; // do the opposite of what position B does
                }
        }
}
    
    System.out.println(Arrays.toString(originalArray));  //prints the array on one line
    
}

}

【讨论】:

    【解决方案2】:

    请注意,堆排序、合并排序或快速排序比问题中使用的排序类型要快。

    我用第三个数组更新了 vmarinescu 的代码,用于处理重复项。请注意,这是一种缓慢的方法。

    public static int[] OrderArray(int[] array){
        int[] array2=new int[array.length];
        int[] stored=new int[array.length];     // used to handle duplicates
        for (int i=0; i<array.length; i++)
        {
            int place=0;
            for (int j=0; j<array.length;j++)
            {
                if (array[i]> array[j])
                    place = place+1;
            }
            while(stored[place] != 0)           // skip duplicates
                place += 1;
            array2[place] = array[i];
            stored[place] = 1;
        }
        return array2;
    }
    

    作为替代方案,循环排序与此类似,但在原地排序(它不需要第二个数组)。

    https://en.wikipedia.org/wiki/Cycle_sort

    public static void cyclesort(int a[])
    {
    int n = a.length;
    int i, j, p;                            // used for indexing
    int e, t;                               // used to hold array elements
        for (j = 0; j < n - 1; j++) {
            e = a[j];                       // e = 1st element of a cycle
            p = j;                          // p = position to store e
            for(i = j+1; i < n; i++){       // advance p to 1st element >= e
                if(a[i] < e)
                    p += 1;
            }
            if(p == j)                      // if p not changed, e is in place
                continue;                   //   continue with next element
            while(e == a[p])                // skip any duplicates
                p += 1;
            t = a[p];                       // swap(e, a[p])
            a[p] = e;
            e = t;                          //   e = next element in this cycle
            while(p != j){                  // continue this cycle
                p = j;
                for(i = j+1; i < n; i++){   //   advance p to 1st element >= e
                    if(a[i] < e)
                        p += 1;
                }
                while(e == a[p])            //   skip any duplicates
                    p += 1;
                t = a[p];                   //   swap(e, a[p])
                a[p] = e;
                e = t;                      //     e = next element in this cycle
            }
        }
    }  
    

    【讨论】:

    • 哦,我没有考虑过重复!谢谢,该代码非常有用
    【解决方案3】:

    您要执行的操作称为排序,您可以使用许多具有不同特征的已知排序算法来完成您想要的操作。

    您可以在此处阅读许多不同的排序算法:https://en.wikipedia.org/wiki/Sorting_algorithm

    Java 本身具有内置排序功能,您可以使用 Arrays.sort 方法对数组进行排序,该方法使用非常快速且众所周知的 Quicksort 算法来处理整数数组。

    正如其他评论员所讨论的那样,您的排序算法似乎存在缺陷,并且总体上似乎最接近 插入排序 算法,您可能需要查看一些想法:https://en.wikipedia.org/wiki/Insertion_sort

    插入排序迭代,每次重复消耗一个输入元素, 并增长一个排序的输出列表。每次迭代,插入排序 从输入数据中删除一个元素,找到它所属的位置 在排序列表中,并将其插入那里。它重复直到没有 输入元素保留。

    来自上述链接的伪代码:

    i ← 1
    while i < length(A)
        j ← i
        while j > 0 and A[j-1] > A[j]
            swap A[j] and A[j-1]
            j ← j - 1
        end while
        i ← i + 1
    end while
    

    【讨论】:

    • 我一定会看看的!这是一项家庭作业,因此部分限制是不使用 java 方法或递归等,但在完成此工作后,我发现它有多么有用!谢谢!!!
    【解决方案4】:

    当您准备好决定将其放置在何处时。您应该在它确定元素位置的循环之外执行此操作

    public static int[] OrderArray(int[] array)
    {
    
        int[] array2=new int[array.length];
    
        for (int i=0; i<array.length; i++)
        {
            int place=0;
            for (int j=0; j<array.length;j++)
            {
                if (array[i]> array[j])
                {
                    place = place+1;
                }
            }
          array2[place] = array[i];
        }
        return array2;
    }
    
    

    我为您的算法做了一个简单的测试,它在 100 个测试用例中有 1\3 个失败。主要是因为测试用例有
    1) 重复
    2) 零

       public static void main(String[] args) {
            int failed = 0;
            int succeeded = 0;
            for (int i = 0; i < 100; i++) {
                //"Unordered array"
                int[] unOrdArr = new int[10];
                for (int j = 0; j < unOrdArr.length; j++) {
                    int val = (int) Math.ceil(Math.random() * 100);
                    unOrdArr[j] = val;
                }
                //Sorted by suggested algorithm
                int [] ordArr = orderArray(unOrdArr);
                //Sorted by internal lib
                int [] intrnSortArr = Arrays.copyOf(unOrdArr, unOrdArr.length);
                Arrays.sort(intrnSortArr);
                if(Arrays.equals(ordArr, intrnSortArr)) {
                    succeeded++;
                } else {
                    failed++;
                    System.out.println("Failed");
                    System.out.println(Arrays.toString(unOrdArr));
                    System.out.println(Arrays.toString(ordArr));
                    System.out.println("---------");
                };
            }
            System.out.println("Successfully sorted: " + succeeded);
            System.out.println("Failed to sort: " + failed);
        }
    

    【讨论】:

      【解决方案5】:

      使用 Java 8。

      import java.util.Arrays;
      
      public class Test {
          public static void main( String[] args ) {
              int[] array = { 2, 1, 3, 5, 4 };
              System.out.println( Arrays.toString( array ) );
      
              int[] orderedArray = Arrays.stream( array )
                  .sorted()
                  .toArray();
              System.out.println( Arrays.toString( orderedArray ) );
          }
      }
      

      【讨论】:

        【解决方案6】:

        我没有检查所有极端情况以确保您的逻辑是正确的,但可以肯定的是:

        array2[place] = array[i];
        

        应该在第二个 for 块之外。您的代码当前会覆盖 array2 中的所有良好插入。

        工作实施:

        public static int[] OrderArray(int[] array){
        
          int[] array2=new int[array.length];
          for (int i=0; i<array.length; i++)
          {
              int place=0;
              for (int j=0; j<array.length;j++)
              {
                  if (array[i]> array[j])
                  {
                      place = place+1;
                  }
              }
              array2[place] = array[i];
          }
          return array2;
        }
        

        【讨论】:

        • “正确的实现:”这是不正确的。见我的comment
        • 你真的能说一个坏掉的算法有一个有效的实现吗?
        • 其实不知道。如果不工作,你会怎么称呼它?我试图通过指出逻辑中最大的缺陷来回答“如何解决”的问题。
        • "如果不工作,你会怎么称呼它?"不工作、损坏、不正确、有缺陷等。
        【解决方案7】:
        int place=0;
                for (int j=0; j<array.length;j++)
                {
                    if (array[i]> array[j])
                    {
                        place = place+1;
                    }
                    array2[place] = array[i];
                }
        

        您每次都更新了 array2[place],而它应该在您遍历数组后更新。 因此 array2[place] = array[i]; 这应该在第二个 for 循环之外

        int place=0;
                for (int j=0; j<array.length;j++)
                {
                    if (array[i]> array[j])
                    {
                        place = place+1;
                    }
        
                }
        array2[place] = array[i];
        

        【讨论】:

          最近更新 更多