简体   繁体   中英

How to optimize the sorting algorithm?

I need to sort an array. I write code, i use insertion sort, but for big n this code work so slow. How optimize my code. May be there is another algorithm.

 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);
    }

You can use counting sort instead of insertion sort. Because counting sort takes a linear time, but insertion sort at worst takes О(n^2) Here is example of using counting sort:

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);
    }
}

You should look into QuickSort or MergeSort if you want faster sorting algorithms. Unlike InsertionSort (and SelectionSort), they are recursive, but still fairly easy to implement. You can find many examples if you look around on the internet.

As Anna stated above, counting sort can be a really good algorithm, considering you don't have a really large data set and the data is not sparse.

For example, an array of size 10k with 100 elements duplicated will have much better space efficiency than an array of size 10k with all unique elements and spread in a sparse fashion.

For example, the following array -> [5,5,4,...,2,2,1,1,5,6,7,8] will need a space of an array of size 8 (1 being the minimum and 8 being the maximum) while, This array -> [5,100,6004,3248,45890,2384,128,8659,...,3892,128] will need a space of an array at least of size 45886 (5 being the minimum and 45890 being the maximum).

So, I'll suggest you use this algorithm when you know that the data set you have is evenly distributed within an acceptable range which won't make your program run out of memory. Otherwise you can go with something like quicksort or mergesort. That gets the work done just fine.

That being said, Anna's implementation of counting sort seemed a little over coded to me personally, so here's me sharing my implementation.

    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;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM