Algorithm 05 - Analysis and Implementation of Heap Sort and Depth First Search

Algorithm 05 - Subtract and Conquer

1. Introduction

The subtraction method is that each step can reduce a certain problem size (-1, -k, -n/2, etc.), and finally becomes a smallest small problem.

Common applications of subtract-and-conquer: heap sort, depth-first search.

Second, heap sort

1. Basic idea

Heap Sort: An ascending sort based on a complete binary tree.

The process of heap sort:

  1. Sort a linear structure (such as an array) as a complete binary tree: if the subscript of an element A in the array is k, then the element with the subscript (k-1)/2 is equivalent to the parent node of A, and the subscript is 2 The element of *k+1 is equivalent to the left child node of A, and the element with subscript 2*k+2 is equivalent to the right child node of A;
  2. Sort n elements and put the minimum value at the top of the array: first put the minimum value of the left subtree of node k to the left child node of k, and then put the minimum value of the right subtree of node k first The right child node of k, and then the minimum value of node k and its left and right children is the minimum value of the array. Recursion is required here.
  3. Take the minimum value of the array and put it into the array M;
  4. Let n=n-1, repeat steps 2 and 3 until n=0, and the sorting is completed: M is the array in which the sequence is shot.

Application: Perform binary search when the data source is unordered or chained. Generally not used for sorting, the space complexity is too high.

2. Code implementation

public static <E extends Comparable<E>> E[] heapSort(E[] arr) {
    if (Tool.isEmpty(arr)) {
        return null;
    }

    //由于直接new泛型数组报错,所以使用Arrays.copyOf()
    E[] result = Arrays.copyOf(arr, arr.length);
    //缩小问题规模:每次-1
    for (int i = 0; i < arr.length; i++) {
        // 缩小后的问题规模
        int n = arr.length - i;
        // 解决小问题:对首位进行单次堆排序,将最小值放到首位
        heapSort(arr, n, 0);
        // 获取最小值
        result[i] = arr[0];
        // 将未排序的数据放到首位
        arr[0] = arr[n - 1];
    }

    return result;
}

/**
 * 单次堆排序:递归设置当前节点与其左右节点的最小值
 * @param arr:要排序的数组
 * @param n:表示数组大小,即问题的规模
 * @param k:要比较的节点下标
 */
public static <E extends Comparable<E>> void heapSort(E[] arr, int n, int k) {
    // 左节点下标
    int left = 2 * k + 1;
    // 右节点下标
    int right = 2 * k + 2;
    if (left >= n) {
        return;
    }

    // 将左子树中最小值放到左节点
    heapSort(arr, n, left);
    // 再将右子树中最小值放到右节点
    heapSort(arr, n, right);

    E data = arr[k];
    E l = arr[left];
    //右节点如果不存在,就将它的值设为MAX
    E r = right < n ? arr[right] : null;
    //如果当前节点是最小的,直接返回
    if (data.compareTo(l) <= 0 && (r == null || data.compareTo(r) <= 0)) {
        return;
    }
    //如果左节点是最小的,就将左节点与当前节点交换
    if (r == null || l.compareTo(r) < 0) {
        arr[left] = data;
        arr[k] = l;
        //如果右节点是最小的,就将右节点与当前节点交换
    } else {
        arr[right] = data;
        arr[k] = r;
    }
}

3. Depth-first search

1. Basic idea

Depth-first search is the idea of ​​searching by depth first, keep walking in one direction, go back when there is no way, and then search in another direction until you find the end point.

Steps:

  1. Use a two-dimensional array to simulate a maze. The value of the array: 0 means you can get through, 1 means you can't get through, 2 means you walked through, and 3 means a wall. and specify the start and end points;
  2. Starting from the starting point, search in the order of bottom left and top right. If you can go to the next point, mark its value as 2, then start with this point as the new starting point, and search in the order of bottom left and top right; if you can't go to the bottom A point, mark its value as 1, then go back to the previous point and search from the remaining direction;
  3. Repeat step 2 until you reach the end.

Application: Find your way in a maze

2. Code implementation

/**
 * @param arr    需要查找的数组。其中0表示走得通,1表示走不通,2表示走过,3表示墙。
 * @param startX 起点横坐标
 * @param startY 起点纵坐标
 * @param endX   终点横坐标
 * @param endY   终点纵坐标
 */
public static boolean dfsSort(int[][] arr, int startX, int startY, int endX, int endY) {
    if (startX < 0 || startY < 0 || endX < 0 || endY < 0) {
        return false;
    }
    // 到达终点
    if (arr[endX][endY] == 2) {
        return true;
    }

    //如果没有走过,就按左下右上的顺序查找
    if (arr[startX][startY] == 0) {
        //标记已走过
        arr[startX][startY] = 2;
        //从左边开始找
        if (dfsSort(arr, startX - 1, startY, endX, endY)) {
            return true;
            //从上边开始找
        } else if (dfsSort(arr, startX, startY - 1, endX, endY)) {
            return true;
            //从右边开始找
        } else if (dfsSort(arr, startX + 1, startY, endX, endY)) {
            return true;
            //从下边开始找
        } else if (dfsSort(arr, startX, startY + 1, endX, endY)) {
            return true;
            //如果没有路,就标记为1,然后返回
        } else {
            arr[startX][startY] = 1;
            return false;
        }
    }
    return false;
}

The demo has been uploaded to gitee, and students who need it can download it!

Previous: Algorithm 04 - Common Sorting Algorithms for Chess and Card Games

Next: Algorithm 06 - Dynamic Programming

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325432769&siteId=291194637