[data structure] Java implementation of eight sorting algorithms

Posted by souravsasi123 on Thu, 17 Feb 2022 18:28:20 +0100

methodaverage timeWorst timeExtra spacestability
Bubble sortingO(n2)O(n2)O(1)stable
Select sortO(n2)O(n2)O(1)instable
Insert sortO(n2)O(n2)O(1)stable
Cardinality sortO(d(n+r))O(d(n+r))O(d+r)stable
Shell Sort O(nlogn)O(n2)O(1)instable
Quick sortO(nlogn)O(n2)O(nlogn)instable
Merge sortO(nlogn)O(nlogn)O(1)stable
Heap sortO(nlogn)O(nlogn)O(1)instable

1. Insert sort

Basic idea: the n elements to be sorted are regarded as an ordered table and an unordered table. At the beginning, the ordered table contains only one element, and the unordered table contains n-1 elements. In the sorting process, the first element is taken out from the unordered table every time, its sorting code is compared with the sorting code of the elements of the ordered table in turn, and it is inserted into the appropriate position in the ordered table, Make it a new ordered table.

public static void insertSort(int[] arr) {
    if (null == arr || arr.length < 2) {
        return;
    }
    for (int i = 1; i < arr.length; i++) {
        int insertVal = arr[i];
        int insertIndex = i - 1;
        // 1. Insertindex > = 0 ensures that the array is not out of bounds
        // 2. Insertval < arr [insertindex] indicates that a suitable position is not found and should be moved back
        // 3. Continue to compare forward
        while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
            arr[insertIndex + 1] = arr[insertIndex];
            insertIndex--;
        }
        // At this time, the insertion position has been found, that is, insertval > = arr [insertindex]
        arr[insertIndex + 1] = insertVal;
    }
}

2. Hill sort

Basic principle - the records are grouped according to a certain increment of subscript, and the direct insertion sorting algorithm is used for each group; As the increment decreases, each group contains more and more keywords. When the increment decreases to 1, the whole file is just divided into one group, and the algorithm terminates

//Exchange method
public static void shellSortSwap(int[] arr) {
    int temp = 0;
    for (int step = arr.length / 2; step > 0; step /= 2) {
        for (int i = step; i < arr.length; i++) {
            for (int j = i - step; j >= 0; j -= step) {
                if (arr[j] > arr[j + step]) {
                    temp = arr[j];
                    arr[j] = arr[j + step];
                    arr[j + step] = temp;
                }
            }
        }
    }
}

optimization

public static void shellSortMove(int[] arr) {
    for (int step = arr.length / 2; step > 0; step /= 2) {
        System.out.println("Step size" + step);
        for (int i = step; i < arr.length; i++) {
            int insertVal = arr[i];
            int insertIndex = i - step;
            while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
                arr[insertIndex + step] = arr[insertIndex];
                insertIndex -= step;
            }
            arr[insertIndex + step] = insertVal;
            System.out.println(Arrays.toString(arr));
        }
    }
}

3. Select sort

Basic idea - find the smallest in the array and exchange with the first, then find the smallest and second exchange from the remaining elements, and so on

public static void selectSort(int[] arr) {
    if (null == arr || arr.length < 2) {
        return;
    }
    for (int i = 0; i < arr.length - 1; i++) {
        int min = arr[i];
        int minIndex = i;
        for (int j = i + 1; j < arr.length; j++) {
            if (arr[j] < min) {
                min = arr[j];
                minIndex = j;
            }
        }
        if (minIndex != i) {
            arr[minIndex] = arr[i];
            arr[i] = min;
        }
    }
}

Optimization: while selecting the minimum value each time, you can also select and exchange the maximum value to reduce the number of choices

4. Heap sort

Basic idea - build the initial heap, and form the sequence to be arranged into a large top heap (or small top heap), ascending large top heap and descending small top heap; Swap the heap top element with the heap tail element and disconnect (remove from the queue) the heap tail element. Rebuild the heap. Repeat the element exchange and build the heap until there is only one element left in the queue (the top element of the heap).

public static void heapSort(int[] arr) {
    // Construction of large top reactor
    for (int i = arr.length / 2 - 1; i >= 0; i--) {
        // From the first non leaf node, from bottom to top, from left to right
        adjustHeap(arr, i, arr.length);
    }
    // Adjust structure + swap top and end elements
    int temp = 0;
    for (int i = arr.length - 1; i > 0; i--) {
        // exchange
        temp = arr[i];
        arr[i] = arr[0];
        arr[0] = temp;
        adjustHeap(arr, 0, i);
    }

}


/**
     * Adjust an array (binary tree) to a large top heap
     * Complete the adjustment of the tree with non leaf nodes corresponding to i into a large top heap
     *
     * @param arr    Array to be adjusted
     * @param i      Represents the index of non leaf nodes in the array
     * @param length Indicates how many elements are adjusted
     */
private static void adjustHeap(int arr[], int i, int length) {
    // Save current variable
    int temp = arr[i];
    // Start to adjust that k is the left child of node i
    for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {
        // If the value of the left child node is less than that of the right child node
        if (k + 1 < length && arr[k] < arr[k + 1]) {
            // Let k point to the right node
            k++;
        }
        // If the child node is larger than the parent node
        if (arr[k] > temp) {
            arr[i] = arr[k];// Assign a larger value to the current node
            i = k;// Let i point to k and continue the comparison
        } else {
            break;
        }
    }
    // When the for loop ends, the maximum value of the tree with i as the parent node has been adjusted
    arr[i] = temp;//Put the temp value in the adjusted position
}

5. Bubble sorting

Basic idea - by comparing the values of adjacent elements from front to back in the sequence to be sorted, the reverse order found is exchanged, so as to move the larger elements from front to back to complete the sorting

public static void bubbleSort(int[] arr) {
    if (null == arr || arr.length < 2) {
        return;
    }
    int temp;
    int count = 0;
    for (int i = 0; i < arr.length - 1; i++) {
        for (int j = 0; j < arr.length - 1 - i; j++) {
            count++;
            if (arr[j] > arr[j + 1]) {
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
    System.out.println("Compared" + count + "second");
}

Optimization: if there is no element exchange after a comparison, it indicates that the sequence is orderly and the cycle should be ended

public static void bubbleSort1(int[] arr) {
    if (null == arr || arr.length < 2) {
        return;
    }
    int temp;
    int count = 0;
    boolean flag = false;
    for (int i = 0; i < arr.length - 1; i++) {
        for (int j = 0; j < arr.length - 1 - i; j++) {
            count++;
            if (arr[j] > arr[j + 1]) {
                flag = true;
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
        if (flag) {
            flag = false;
        } else {
            break;
        }
    }
    System.out.println("Compared" + count + "second");
}

6. Quick sort

Basic idea - it is an improvement of bubble sorting. The basic idea is: divide the data to be sorted into two independent parts through one-time sorting. All the data in one part is smaller than all the data in the other part, and then quickly sort the two parts of data according to this method. The whole sorting process can be carried out recursively, so as to turn the whole data into an ordered sequence

public static void quickSort(int[] arr, int left, int right) {
    int l = left;
    int r = right;
    int pivot = arr[(left + right) / 2];
    int temp = 0;
    while (l < r) {
        // Find the element on the left that is greater than or equal to the central axis value
        while (arr[l] < pivot) {
            l++;
        }
        // Find the element on the right that is less than or equal to the central axis value
        while (arr[r] > pivot) {
            r--;
        }
        // It indicates that the left side is less than or equal to the central axis value, and the right side is greater than or equal to the central axis value
        if (l >= r) {
            break;
        }
        // exchange
        temp = arr[l];
        arr[l] = arr[r];
        arr[r] = temp;
        // If after exchange, arr[l] == pivot let r--
        if (arr[l] == pivot) {
            r--;
        }
        // If after exchange, arr[r] == pivot let l++
        if (arr[r] == pivot) {
            l++;
        }
    }
    if (l == r) {
        l++;
        r--;
    }
    // Left recursion
    if (left < r) {
        quickSort(arr, left, r);
    }
    // Recursive right
    if (l < right) {
        quickSort(arr, l, right);
    }
}

7. Merge sort

Basic idea - merge sort is a sort method based on the idea of merging. The algorithm adopts the classical divide and conquer strategy (divide and conquer divides the problem into some small problems and then solves them recursively, while the conquer stage "fixes" the answers obtained in different stages, that is, divide and conquer).

// Opening + closing
public static void mergeSort(int[] arr, int left, int right, int[] temp) {
    if (left < right) {
        int mid = (left + right) / 2;
        // Left recursion
        mergeSort(arr, left, mid, temp);
        // Recursive right
        mergeSort(arr, mid + 1, right, temp);
        merge(arr, left, mid, right, temp);
    }
}

/**
     * merge
     *
     * @param arr   Array to be sorted
     * @param left  Left ordered sequence initial index
     * @param mid   Intermediate index
     * @param right Right index
     * @param temp  Transit array
     */
public static void merge(int[] arr, int left, int mid, int right, int[] temp) {
    // Initialization i, the initial index of the left ordered sequence
    int i = left;
    // Initialization j, initial index of ordered sequence on the right
    int j = mid + 1;
    // Points to the current index of the temp array
    int t = 0;
    // 1. First fill the left and right (ordered) data into temp according to the rules to know the ordered sequence on the left and right
    // Until one side is handled
    while (i <= mid && j <= right) {
        // If the current element of the ordered sequence on the left is smaller than the element of the ordered sequence on the right
        // Copy the current element on the left to the temp array
        // Move back
        if (arr[i] < arr[j]) {
            temp[t] = arr[i];
            t++;
            i++;
        } else {
            temp[t] = arr[j];
            t++;
            j++;
        }
    }

    // 2. Fill all the remaining data into temp
    while (i <= mid) {
        temp[t] = arr[i];
        i++;
        t++;
    }

    while (j <= right) {
        temp[t] = arr[j];
        j++;
        t++;
    }

    // 3. Copy all elements in temp to arr
    // Not all elements are copied every time
    t = 0;
    int tempLeft = left;
    while (tempLeft <= right) {
        arr[tempLeft] = temp[t];
        t++;
        tempLeft++;
    }

}

8. Cardinality sort (bucket sort)

Basic idea - unify all values to be compared into the same digit length, and fill zero in front of the shorter digit. Then, start from the lowest order and sort once in turn. In this way, the sequence will become an ordered sequence from the lowest order to the highest order.

public static void radixSort(int[] arr) {
    // Get the maximum number of digits in the array
    int max = arr[0];
    for (int i = 0; i < arr.length; i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
    }
    int maxLength = (max + "").length();

    // Define a two-dimensional array, representing 10 buckets, and each bucket is a one-dimensional array
    int[][] bucket = new int[10][arr.length];

    // Define a one-dimensional array to record how many data are put in the corresponding bucket
    int[] bucketElementCounts = new int[10];

    for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
        for (int j = 0; j < arr.length; j++) {
            // Take out the bit value corresponding to each element and sort it
            int digitOfElement = arr[j] / n % 10;
            // Put it into the corresponding bucket
            bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
            bucketElementCounts[digitOfElement]++;
        }

        // Traverse each bucket and put the elements in the bucket into the original array
        int index = 0;
        for (int k = 0; k < 10; k++) {
            // If there is data in the bucket, put it into the original array
            if (bucketElementCounts[k] > 0) {
                for (int l = 0; l < bucketElementCounts[k]; l++) {
                    arr[index++] = bucket[k][l];
                }
            }
            // Set the corresponding position of the count array to 0
            bucketElementCounts[k] = 0;
        }
    }
}

Topics: Java Algorithm data structure