Sorting array by divide and conquer strategy (bisection sorting algorithm)

Keywords: Java

Today, I'm going to be familiar with consolidating the divide and conquer algorithm to sort the array. The divide and conquer problem is to divide the complex big problem into simple small problems, and then solve the small problems in turn. Suppose we want to sort and output the following array:

[ 32, 11, 22, 17, 222, 42, 162, 82, 1, 1231, 12, 2 ]

If we use the divide and conquer strategy, we need to first decompose the big problem into small problems. We can first decompose the array of length 12 into two arrays of length 6, and then decompose them as follows

[ 32, 11, 22, 17, 222, 42 ]
[ 162, 82, 1, 1231, 12, 2 ]

Is it possible to sort directly after decomposition? It seems that it's still not OK, so we can continue to decompose until we can directly compare.

//Second decomposition
[ 32, 11, 22 ] 
[ 17, 222, 42 ] 

[ 162, 82, 1 ] 
[ 1231, 12, 2 ]

//Third decomposition

[ 32, 11 ]
[ 22 ]

[ 17, 222 ]
[ 42 ]

[ 162, 82 ]
[ 1 ]

[ 1231, 12 ]
[ 2 ]

//Fourth decomposition

[ 32 ]
[ 11 ]

[ 22 ]

[ 17 ]
[ 222 ]

[ 42 ]

[ 162 ]
[ 82 ]

[ 1 ]

[ 1231 ]
[ 12 ]

[ 2 ]

Our ultimate goal is to decompose a complex array into a small array with a length of 1, so that we can directly compare two arrays, such as [32] and [11]. At this time, we should enter a cycle to compare the first elements of the two arrays, and then merge them to get [11, 32], and then use [11, 32] and [22] to compare the size of the first element of the array. After the comparison is completed, merge to get [11, 22, 32], and so on, and the final result will be a sorting.

When we divide the above analysis into steps, we should realize two functions:

  • The complex array is divided into simple array at atomic level.
  • After comparing the atomic level arrays, they are merged in turn to form a sorted complex array.

Let's implement the code now. First, we create an interface to describe the sorting algorithm class.

public interface Sort {
    public int[] sort(int[] arr);
}

Then we will edit the implementation of this class. The final call effect should be as follows:

import java.util.Arrays;

public class DivisionSort implements Sort {
  @Override
  public int[] sort(int[] arr) {
      //...
      return arr;
  }
  public static void main(String[] args) {
    int[] arr = new int[] { 32, 11, 22, 17, 222, 42, 162, 82, 1, 1231, 12, 2 };
    Sort divisionSort = new DivisionSort();
    int[] sortedArr = divisionSort.sort(arr);
    System.out.println(Arrays.toString(sortedArr));
  }
}

Let's first decompose the complex array into simple arrays:

private void splitArr(int[] arr, int start, int end) {
  // Only when the start position of the array is equal to the end position can the division stop (at this time, the array length is 1)
  if (end != start) {
    // Take the midpoint position, and divide the array into two parts by recursive call
    int mid = (end + start) / 2;
    splitArr(arr, start, mid);
    splitArr(arr, mid + 1, end);
  }
}

The decomposed function is a recursive call, which divides the array into atomic level recursively. For the merged function, we can think about how to compare [11, 32] and [22], take out the first element of the two arrays in turn, and push the smaller one into the merged array after comparison.

So here we should compare the size of 11 and 22, then push 11 into the merged array, then compare 32 and 22, and then push 22 into the merged array. The final comparison will judge that an array has no elements to compare. Then the remaining numbers of another array are all large numbers. Just push directly into the merged array, and then we can realize it. After that:

private void mergeArr(int[] arr, int start, int end) {
  // Divide the array into left and right sides for comparison
  // For example, {11 32 22} will be divided into {11 32} and {22} arrays
  int mid = (start + end) / 2;
  int[] leftArr = Arrays.copyOfRange(arr, start, mid + 1);
  int[] rightArr = Arrays.copyOfRange(arr, mid + 1, end + 1);
  int i = 0, j = 0;
  for (int k = start; k <= end; k++) {
      // Determine whether the array has no extra elements
      if (i == leftArr.length) {
          arr[k] = rightArr[j];
          j++;
          continue;
      }

      if (j == rightArr.length) {
          arr[k] = leftArr[i];
          i++;
          continue;
      }

      if (leftArr[i] < rightArr[j]) {
          arr[k] = leftArr[i];
          i++;
      } else {
          arr[k] = rightArr[j];
          j++;
      }
  }
}

The final DivisionSort class is like this:

import java.util.Arrays;

public class DivisionSort implements Sort {
    @Override
    public int[] sort(int[] arr) {
        this.splitArr(arr, 0, arr.length - 1);
        return arr;
    }

    private void splitArr(int[] arr, int start, int end) {
        if (end != start) {
            int mid = (end + start) / 2;
            splitArr(arr, start, mid);
            splitArr(arr, mid + 1, end);
            mergeArr(arr, start, end);
        }
    }

    private void mergeArr(int[] arr, int start, int end) {
        int mid = (start + end) / 2;
        int[] leftArr = Arrays.copyOfRange(arr, start, mid + 1);
        int[] rightArr = Arrays.copyOfRange(arr, mid + 1, end + 1);
        int i = 0, j = 0;
        for (int k = start; k <= end; k++) {
            if (i == leftArr.length) {
                arr[k] = rightArr[j];
                j++;
                continue;
            }

            if (j == rightArr.length) {
                arr[k] = leftArr[i];
                i++;
                continue;
            }

            if (leftArr[i] < rightArr[j]) {
                arr[k] = leftArr[i];
                i++;
            } else {
                arr[k] = rightArr[j];
                j++;
            }
        }
    }

    public static void main(String[] args) {
        int[] arr = new int[] { 32, 11, 22, 17, 222, 42, 162, 82, 1, 1231, 12, 2 };
        Sort divisionSort = new DivisionSort();
        int[] sortedArr = divisionSort.sort(arr);
        System.out.println(Arrays.toString(sortedArr));
    }
}

The final output is [1, 2, 11, 12, 17, 22, 32, 42, 82, 162, 222, 1231], and the sorting is completed.

Posted by tmswenson on Sun, 27 Oct 2019 21:29:09 -0700