优化冒泡排序(Java)

时间:2013-04-24 14:49:00

标签: java optimization recursion bubble-sort

我想知道如何优化冒泡排序,以便它忽略已经排序的元素,即使在第一次传递之后也是如此。

Eg. [4, 2, 3, 1, 5, 6] --> [2, 3, 1, **4, 5, 6**]

我们观察到[4,5,6]已经按排序顺序,如何修改我的代码以便它在下一遍中忽略这3个元素? (这意味着排序会更有效率?) 你建议使用递归方法吗?

public static void bubblesort(int[] a) {
  for(int i=1; i<a.length; i++) {
    boolean is_sorted = true;

    for(int j=0; j<a.length; j++) {
      if(a[j] > a[j+1]) {
         int temp = a[j];
         a[j] = a[j+1];
         a[j+1] = temp;
         is_sorted = false;
      }
    }

    if(is_sorted) return;
  }
}

谢谢你的时间!

9 个答案:

答案 0 :(得分:16)

首先,您有一个越界访问:

    for(int j=0; j<a.length; j++) {
      if(a[j] > a[j+1]) {

表示j == a.length-1,因此循环条件应该是j < a.length-1

但是,在冒泡排序中,您知道在k通过后,最大的k元素在数组的k最后条目处排序,因此传统的冒号排序使用< / p>

public static void bubblesort(int[] a) {
  for(int i=1; i<a.length; i++) {
    boolean is_sorted = true;

    for(int j=0; j < a.length - i; j++) { // skip the already sorted largest elements
      if(a[j] > a[j+1]) {
         int temp = a[j];
         a[j] = a[j+1];
         a[j+1] = temp;
         is_sorted = false;
      }
    }

    if(is_sorted) return;
  }
}

现在,当数组具有较长的最大元素尾部时,仍然会进行大量不必要的迭代,比如你有k,k-1,...,1作为第一个k元素和k+1到在此之后依次100000000。标准冒泡排序将通过(几乎)整个阵列k次。

但是如果你还记得上次交换的位置,你知道在那个索引之后,顺序中有最大的元素,所以

public static void bubblesort(int[] a) {
  int lastSwap = a.length-1;
  for(int i=1; i<a.length; i++) {
    boolean is_sorted = true;
    int currentSwap = -1;

    for(int j=0; j < lastSwap; j++) {
      if(a[j] > a[j+1]) {
         int temp = a[j];
         a[j] = a[j+1];
         a[j+1] = temp;
         is_sorted = false;
         currentSwap = j;
      }
    }

    if(is_sorted) return;
    lastSwap = currentSwap;
  }
}

将对上面的示例进行排序,只有一次遍历整个数组,其余的只通过(短)前缀。

当然,总的来说,这不会给你带来太大的收益,但是无论如何优化冒泡排序都是徒劳的。

答案 1 :(得分:1)

(unsigned)0 - 1

答案 2 :(得分:0)

你应该使用变量&#34; size&#34;对于内部循环,并将其更改为每个循环中最新的交换元素。这样,您的内部循环将上升到最新的&#34;交换&#34;元素并传递未被破坏的其余部分(也就是在正确的位置)。即

do {
        int newsize =0;
        for (int i = 1; i < size; i++) {
            if (a[i - 1] > a[i]) {
                int temp;
                temp = a[i - 1];
                a[i - 1] = a[i];
                a[i] = temp;
                newsize =i;
            }
        }
        size = newsize;
   } while (size > 0);

答案 3 :(得分:0)

    public static void BubbleSorter(params int[] input){
        int newSize = input.Length-1, size = 0;
        bool swap;
        do
        {
            swap = false;
            for (int j = 0; j < newSize; j++)
            {
                if (input[j] > input[j + 1])
                {
                    int temp = input[j + 1];
                    input[j + 1] = input[j];
                    input[j] = temp;
                    swap = true;
                    size = j;
                }
            } newSize = size;
        } while (swap);

        DisplayArrayElements(input);
    }

答案 4 :(得分:0)

我设计了一种方法,通过排除在先前循环中已经排序的数组的开头和结尾处的部分来减少迭代次数。

static int[] BubbleSortOptimized(int arr[]) {
    int start = 0, stop = arr.length - 1, control = 0;
    boolean ordered, nsCaught;
    while (true){
        ordered = true;
        nsCaught = false;
        for (int i = start; i < stop; i++) {
            if (i > 1) {
                if (!nsCaught && arr[i-2] > arr[i-1]){
                    ordered = false;
                    start = i-2;
                    nsCaught = true;
                }
            }
            if (arr[i] > arr[i+1]){
                int hold = arr[i];
                arr[i] = arr[i+1];
                arr[i+1] = hold;
                control = i;
            }
        }
        System.out.println(Arrays.toString(arr));
        if (ordered) return arr;
        stop = control;
    }
}

但正如@Daniel Fischer在之前的回答中所说,it doesn't do a lot with larger arrays.

答案 5 :(得分:0)

public class Tester {
    static boolean bubbleFlag = true;

    public static void main(String[] args) {
        int array[] = new int[] {
            1,
            9,
            2,
            3,
            4,
            5,
            6
        };
        bubbleSort(array);
    }

    private static void bubbleSort(int...array) {
        System.out.println("Before Sorting: " + Arrays.toString(array));

        for (int i = 0; i < array.length - 1; i++) {
            if (i > 0) if (bubbleFlag) break;

            for (int j = 0; j < array.length - i - 1; j++) {
                if (array[j] > array[j + 1]) array = swap(j, j + 1, array);
                System.out.println("Iteration " + i + " :" + Arrays.toString(array));
            }
            bubbleFlag = true;
        }
    }

    private static int[] swap(int i1, int i2, int...is) {
        bubbleFlag = false;
        is[i1] = is[i1] + is[i2];
        is[i2] = is[i1] - is[i2];
        is[i1] = is[i1] - is[i2];
        return is;
    }
}

答案 6 :(得分:0)

我认为这就是您所需要的。关键是要考虑 仅在发生最后一次交换的索引处(新)排列数组。

public static void bubblesort(int[] a) {
  int i, n, newn;
  n = a.length;

  while (n > 0) {
      newn = 0;
      for (i = 1; i < n; i++) {
          if (a[i - 1] > a[i]) {
              temp = a[i];
              a[i] = a[i - 1];
              a[i - 1] = temp;
              newn = i;
          }
      }
      n = newn;
    }

    return a;
}

答案 7 :(得分:0)

您可以使用单个 do-while-loop 而不是两个嵌套的 for-loop 并将逻辑移动到内部 if 语句 em>。后续通过的通过指数更短。

public static void bubbleSort(int[] arr) {
    boolean swapped = false;
    int i = 0, pass = 0;
    do {
        if (i < arr.length - 1 - pass) {
            if (arr[i] > arr[i + 1]) {
                int temp = arr[i];
                arr[i] = arr[i + 1];
                arr[i + 1] = temp;
                swapped = true;
            }
            i++;
        } else {
            i = 0;
            pass++;
            swapped = false;
        }
    } while (i < arr.length - 1 - pass || swapped);
}
public static void main(String[] args) {
    int[] arr = {6, 1, 5, 8, 4, 3, 9, 2, 0, 7};
    System.out.println(Arrays.toString(arr));
    bubbleSort(arr);
    System.out.println(Arrays.toString(arr));
}

输出:

[6, 1, 5, 8, 4, 3, 9, 2, 0, 7]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

另见:Bubble sort output is incorrect

答案 8 :(得分:-1)

优化的气泡排序,其中只有1个用于循环

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>

  <table>
    <tr>
      <th>QTY</th>
      <th>UNIT PRICE</th>
      <th>LINE TOTAL</th>
    </tr>
    <tr>
      <td><input type="text" class="qty"></td>
      <td><input type="text" class="unit"></td>
      <td>
        <input type='text' class='amount' style="width: 190px"></td>
    </tr>
    <tr>
      <td><input type="text" class="qty"></td>
      <td><input type="text" class="unit"></td>
      <td>
        <input type='text' class='amount' style="width: 190px"></td>
    </tr>
    <tr>
      <td><input type="text" class="qty"></td>
      <td><input type="text" class="unit"></td>
      <td>
        <input type='text' class='amount' style="width: 190px"></td>
    </tr>
    <tr>
      <td><input type="text" class="qty"></td>
      <td><input type="text" class="unit"></td>
      <td>
        <input type='text' class='amount' style="width: 190px"></td>
    </tr>
    <tr>
      <td><input type="text" class="qty"></td>
      <td><input type="text" class="unit"></td>
      <td>
        <input type='text' class='amount' style="width: 190px"></td>
    </tr>
    <tr>
      <td><input type="text" class="qty"></td>
      <td><input type="text" class="unit"></td>
      <td>
        <input type='text' class='amount' style="width: 190px"></td>
    </tr>
    <tr>
      <td><input type="text" class="qty"></td>
      <td><input type="text" class="unit"></td>
      <td>
        <input type='text' class='amount' style="width: 190px"></td>
    </tr>
    <tr>
      <td><input type="text" class="qty"></td>
      <td><input type="text" class="unit"></td>
      <td>
        <input type='text' class='amount' style="width: 190px"></td>
    </tr>
    <tr>
      <td><input type="text" class="qty"></td>
      <td><input type="text" class="unit"></td>
      <td>
        <input type='text' class='amount' style="width: 190px"></td>
    </tr>
    <tr>
      <td><input type="text" class="qty"></td>
      <td><input type="text" class="unit"></td>
      <td>
        <input type='text' class='amount' style="width: 190px"></td>
    </tr>
    <tr>
      <td><input type="text" class="qty"></td>
      <td><input type="text" class="unit"></td>
      <td>
        <input type='text' class='amount' style="width: 190px"></td>
    </tr>
    <tr>
      <td></td>
      <td class="auto-style1">Sub Total</td>
      <td>
        <input type="text" class="result" style="width: 190px">
      </td>
    </tr>
  </table>