簡體   English   中英

如何優化排序算法?

[英]How to optimize the sorting algorithm?

我需要對數組進行排序。 我寫代碼,我使用插入排序,但是對於大n ,這個代碼工作得非常慢。 如何優化我的代碼。 可能還有另一種算法。

 public void insertionSort(ArrayList<Integer> arrayList) {
        int n = arrayList.size();
        int in, out;
        for(out = 1; out < n; out++)
        {
            int temp = arrayList.get(out);
            in = out;
            while (in > 0 && arrayList.get(in-1) > temp)
            {
                arrayList.set(in, arrayList.get(in-1));
                in--;
            }
            arrayList.set(in,temp);
        }
        print(arrayList);
    }

您可以使用計數排序代替插入排序。 因為計數排序需要一個線性時間,但插入排序最壞需要О(n ^ 2),這是使用計數排序的示例:

import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
public class Main {
    public static void print(int []a){
        System.out.println(Arrays.toString(a));
    }
    public static void countingSort(int []a, int []b, int n, int k){
        int []c = new int [k];
        for(int i=0; i<k; i++)
            c[i] = 0;
        for(int j=0; j<n; j++){
            c[a[j]] = c[a[j]]+1;
        }
        for(int i=1; i<k; i++){
            c[i] = c[i]+c[i-1];
        }
        for(int j=n-1; j>=0; j--){
            c[a[j]] = c[a[j]]-1;
            b[c[a[j]]] = a[j];
        }
        for(int i=0; i<n; i++)
            a[i] = b[i];
    }
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        Random ran = new Random();
        int n = Integer.parseInt(in.nextLine());
        int []a = new int[n];
        int []b = new int[n];
        int k = 5; // max value on the array
        for(int i=0; i<n; i++)
            a[i] = ran.nextInt(k);
        print(a);
        countingSort(a,b,n,k);
        print(a);
    }
}

如果需要更快的排序算法,則應研究QuickSort或MergeSort。 與InsertionSort(和SelectionSort)不同,它們是遞歸的,但仍然相當容易實現。 如果您在Internet上四處看看,可以找到許多示例。

正如 Anna 上面所說,考慮到您沒有非常大的數據集並且數據並不稀疏,計數排序可能是一個非常好的算法。

例如,一個包含 100 個重復元素的大小為 10k 的數組比包含所有唯一元素並以稀疏方式分布的大小為 10k 的數組具有更好的空間效率。

例如,以下數組 -> [5,5,4,...,2,2,1,1,5,6,7,8] 將需要一個大小為 8 的數組的空間(1 是最小值並且 8 是最大值)而這個數組 -> [5,100,6004,3248,45890,2384,128,8659,...,3892,128] 將需要一個至少大小為 45886 的數組空間(5 是最小值和 45890 是最大值)。

因此,當您知道您擁有的數據集均勻分布在一個不會使您的程序內存不足的可接受范圍內時,我建議您使用此算法。 否則,您可以使用快速排序或合並排序之類的方法。 這樣就可以很好地完成工作。

話雖這么說,Anna 的計數排序實現對我個人來說似乎有點過度編碼,所以我在這里分享我的實現。

    public int[] countSort(int[] nums) {
        int min = nums[0], max = nums[0], counterLength, start = 0;
        int[] counter;
        
        // To dynamically allocate size to the counter.
        // Also an essential step if there are negative elements in the input array.
        // You can actively avoid this step if you know:
        // 1. That the elements are not going to be negative.
        // 2. The upper bound of the elements in the array.
        for (int i : nums) {
            if (i > max)
                max = i;
            else if (i < min)
                min = i;
        }
        
        counterLength = max - min + 1;
        counter = new int[counterLength];
        
        for (int i : nums)
            counter[i - min]++;
        
        for (int i = 0; i < counterLength; i++) {
            if (counter[i] > 0) {
                int end = start + counter[i];
                Arrays.fill(nums, start, end, i + min);
                start = end;
            }
        }

        return nums;
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM