美文网首页
二叉搜索树的创建

二叉搜索树的创建

作者: 随时学丫 | 来源:发表于2018-01-19 09:45 被阅读12次

    快速排序

    递归

    1. 从数组中选取一个基准值,最开始默认选择数组第一个。
    2. 重新排列数组,所有比基准值小的放在基准值左边,所有比基准值大的放在基准值右边。
    3. 不断递归重复以上步骤直到数组排序完成。

    非递归

    借助栈(先进后出)来存储每次迭代的下标,用于计算基准值

    先将left和right入栈,以栈为空为循环终止条件,将right和left弹栈,根据left和tight来计算当前基准值,再根据快速排序的思想,比基准值大的放在基准值右边,比基准值小的放在基准值左边,使用 if 判断,并将当前的下标存入栈,不断的进行入栈弹栈和基准值的计算,达到数组快速排序的目的。

    时间复杂度

    最坏情况:每次选取的基准值都是最小或者最大值,那么每次都需要排序,需要比较n(n-1)/2次,为 O(n2)

    平均情况:每次都基准值都是中间值,n不断进行二分,只能二分log2n次,最终需要计较nlogn次,为O(nlogn)

    空间复杂度

    需要借助一个栈来实现递归,若每次划分均匀,递归的高度是O(logn),故递归后需要的栈空间为O(logn)。最坏的情况下,递归的高度是O(n),需要的空间为O(n)。

    稳定性

    快速排序是不稳定的

    快速排序有两个方向,左边的下标left一直往右走,条件是a[left]<=a[pivot](pivot为中枢元素数组下标),一般取数组第0个元素。右边的下标right一直往左走,条件是a[right]>=a[pivot]。当left<=right,重复上面的过程,直到left>right。在中枢元素a[pivot]和a[j]交换时,有可能把前面元素的稳定性打乱,比如序列为{5,3,3,4,3,8,9,10,11},现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素 3 的稳定性打乱,所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素a[pivot]和a[right] 交换的时候。

    二叉查找树

    定义

    二叉查找树是一棵有序树,具有下列性质:

    1. 若任意节点的左子树不空,则左子树上所有节点的值均小雨它的根节点的值。
    2. 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值。
    3. 任意节点的左、右子树也为二叉查找树。
    4. 没有键值相等的节点。

    构建二叉查找树

    递归

    二叉查找树构建要先计算中间值,也就是根节点在数组中的值,创建根节点之后,在递归遍历左子树和右子树进行构建。

    非递归

    借助两个栈,一个存储数组中的左、右子树的数据下标以及根节点的下标,一个用于存储二叉树的当前节点,循环条件是存储下标的栈不为空,将左右子树的下标进行弹栈,并计算根节点下标,根据根节点下标创建根节点,然后分别存储左子树的左右下标,创建左子树,存储右子树左右下标,创建右子树,将下标和左右子树分别存储到对应的栈,栈是先进后出,存入顺序和获取数据的顺序相反。接着一直循环重复上面的步骤,直到二叉查找树被创建完成。

    package dali;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Stack;
    
    public class Sort {
    
        public static void main(String[] args) {
            int[] arr = { 12, 3, 5, 15, 9, 8, 6, 2, 7 };
            // quickSort(arr, 0, arr.length-1);
            nonRecrutQuickSort(arr);
            System.out.println("快速排序");
            printArr(arr);
            Node root = null;
            Node node = null;
    //      System.out.println("递归构造二叉查找树");
    //      node = retrutSortedArrayToBST(root, arr, 0, arr.length - 1);
            System.out.println("非递归构造二叉查找树");
            node = nonRetrutSortedArrayToBST(arr);
            System.out.println("前序递归遍历");
            printTree(recrutPreorderTraversal(node));
            System.out.println("前序非递归遍历");
            printTree(nonRecrutPreorderTraversal(node));
            System.out.println("中序递归遍历");
            printTree(recrutInorderTraversal(node));
            System.out.println("中序非递归遍历");
            printTree(nonRecrutInorderTraversal(node));
            System.out.println("后序递归遍历");
            printTree(recrutPostorderTraversal(node));
            System.out.println("后序非递归遍历");
            printTree(nonRecrutPostorderTraversal(node));
        }
    
        //递归快速排序
        public static void quickSort(int[] arr, int left, int right) {
            if (left > right)
                return;
            int mid = partition(arr, left, right);
            quickSort(arr, left, mid - 1);
            quickSort(arr, mid + 1, right);
        }
    
        //非递归快速排序
        public static void nonRecrutQuickSort(int[] arr) {
            if (arr.length == 0)
                return;
            int left = 0;
            int right = arr.length - 1;
            int pivotPos;
            Stack<Integer> stack = new Stack<>();
            stack.push(left);
            stack.push(right);
            while (!stack.isEmpty()) {
                right = stack.pop();
                left = stack.pop();
                pivotPos = partition(arr, left, right);
                if (left < pivotPos - 1) {
                    stack.push(left);
                    stack.push(pivotPos - 1);
                }
                if (right > pivotPos + 1) {
                    stack.push(pivotPos + 1);
                    stack.push(right);
                }
            }
        }
    
        //计算基准值
        public static int partition(int[] arr, int left, int right) {
            if (arr.length == 0)
                return 0;
            int pivot = arr[left];
            while (left < right) {
                while (left < right && arr[right] >= pivot)
                    right--;
                arr[left] = arr[right];
                while (left < right && arr[left] <= pivot)
                    left++;
                arr[right] = arr[left];
            }
            arr[left] = pivot;
            return left;
        }
    
        //打印数组
        public static void printArr(int[] arr) {
            for (int i = 0; i < arr.length; i++) {
                System.out.print(arr[i] + " ");
            }
            System.out.println();
        }
    
        //打印二叉树
        public static void printTree(List<Integer> queue) {
            for (Integer val : queue) {
                System.out.print(val + " ");
            }
            System.out.println();
        }
    
        // 非递归后序遍历
        public static List<Integer> nonRecrutPostorderTraversal(Node root) {
            LinkedList<Integer> queue = new LinkedList<>();
            if (root == null)
                return queue;
            LinkedList<Node> stack = new LinkedList<>();
            Node pre = null;
            while (root != null || !stack.isEmpty()) {
                if (root != null) {
                    stack.push(root);
                    root = root.left;
                } else {
                    Node peekNode = stack.peek();
                    //根节点被访问的前提:无右子树或右子树已被访问过
                    if (peekNode.right != null && pre != peekNode.right) {
                        root = peekNode.right;
                    } else {
                        stack.poll();
                        queue.add(peekNode.val);
                        pre = peekNode;
                    }
                }
            }
            return queue;
        }
    
        // 递归后序遍历
        public static List<Integer> recrutPostorderTraversal(Node root) {
            LinkedList<Integer> queue = new LinkedList<>();
            if (root == null)
                return queue;
            recrutPostorderTraversal(root, queue);
            return queue;
        }
    
        private static void recrutPostorderTraversal(Node root, LinkedList<Integer> queue)     {
            if (root == null)
                return;
            if (root.left != null)
                recrutPostorderTraversal(root.left, queue);
            if (root.right != null)
                recrutPostorderTraversal(root.right, queue);
            queue.add(root.val);
        }
    
        // 非递归中序遍历
        public static List<Integer> nonRecrutInorderTraversal(Node root) {
            LinkedList<Integer> queue = new LinkedList<>();
            if (root == null)
                return queue;
            LinkedList<Node> stack = new LinkedList<>();
            while (root != null || !stack.isEmpty()) {
                if (root != null) {
                    stack.push(root);
                    root = root.left;
                } else {
                    root = stack.pop();
                    queue.add(root.val);
                    root = root.right;
                }
            }
            return queue;
        }
    
        // 递归中序遍历
        public static List<Integer> recrutInorderTraversal(Node root) {
            LinkedList<Integer> queue = new LinkedList<>();
            if (root == null)
                return queue;
            recrutInorderTraversal(root, queue);
            return queue;
        }
    
        private static void recrutInorderTraversal(Node root, LinkedList<Integer> queue) {
            if (root == null)
                return;
            if (root.left != null)
                recrutInorderTraversal(root.left, queue);
            queue.add(root.val);
            if (root.right != null)
                recrutInorderTraversal(root.right, queue);
        }
    
        // 非递归前序遍历
        public static List<Integer> nonRecrutPreorderTraversal(Node root) {
            LinkedList<Integer> queue = new LinkedList<>();
            if (root == null)
                return queue;
            LinkedList<Node> stack = new LinkedList<>();
            while (root != null || !stack.isEmpty()) {
                if (root != null) {
                    stack.push(root);
                    queue.add(root.val);
                    root = root.left;
                } else {
                    root = stack.pop();
                    root = root.right;
                }
            }
            return queue;
        }
    
        // 递归前序遍历
        public static List<Integer> recrutPreorderTraversal(Node root) {
            LinkedList<Integer> queue = new LinkedList<>();
            if (root == null)
                return queue;
            recrutPreorderTraversal(root, queue);
            return queue;
        }
    
        private static void recrutPreorderTraversal(Node root, LinkedList<Integer> queue) {
            if (root == null)
                return;
            queue.add(root.val);
            if (root.left != null)
                recrutPreorderTraversal(root.left, queue);
            if (root.right != null)
                recrutPreorderTraversal(root.right, queue);
        }
    
        // 递归构建二叉查找树
        public static Node retrutSortedArrayToBST(Node root, int[] nums, int start, int end) {
            if (start > end) {
                return null;
            } else {
                int mid = (start + end) / 2;
                root = new Node(nums[mid]);
                root.left = retrutSortedArrayToBST(root.left, nums, start, mid - 1);
                root.right = retrutSortedArrayToBST(root.right, nums, mid + 1, end);
            }
            return root;
        }
    
        // 非递归构建二叉查找树
        public static Node nonRetrutSortedArrayToBST(int[] nums) {
            if (nums == null || nums.length == 0)
                return null;
            Stack<Integer> stack = new Stack<Integer>();
            Stack<Node> tree = new Stack<Node>();
            stack.add(nums.length - 1);
            stack.add(0);
            Node root = new Node(0);
            tree.add(root);
            while (!stack.isEmpty()) {
                int left = stack.pop();
                int right = stack.pop();
                int mid = left + (right - left) / 2;
                Node node = tree.pop();
                node.val = nums[mid];
                int r = mid - 1, l = left;
                if (l <= r) {
                    node.left = new Node(0);
                    tree.add(node.left);
                    stack.push(r);
                    stack.push(l);
                }
                l = mid + 1;
                r = right;
                if (l <= r) {
                    node.right = new Node(0);
                    tree.add(node.right);
                    stack.push(r);
                    stack.push(l);
                }
            }
            return root;
        }
    
        static class Node {
            int val;
            Node left;
            Node right;
    
            public Node(int val) {
                this.val = val;
            }
        }
    }
    
    //--------------------运行结果-------------------------
    快速排序
    2 3 5 6 7 8 9 12 15 
    非递归构造二叉查找树
    前序递归遍历
    7 3 2 5 6 9 8 12 15 
    前序非递归遍历
    7 3 2 5 6 9 8 12 15 
    中序递归遍历
    2 3 5 6 7 8 9 12 15 
    中序非递归遍历
    2 3 5 6 7 8 9 12 15 
    后序递归遍历
    2 6 5 3 8 15 12 9 7 
    后序非递归遍历
    2 6 5 3 8 15 12 9 7 
    

    生成的二叉树

    二叉树.png

    相关文章

      网友评论

          本文标题:二叉搜索树的创建

          本文链接:https://www.haomeiwen.com/subject/snfooxtx.html