算法——树(二叉树、二叉堆、优先队列)

在这里插入图片描述

二叉树

package tree_tree;/**
 * Copyright (C), 2019-2020
 * author  candy_chen
 * date   2020/6/23 9:38
 * version 1.0
 * Description: 测试
 */

import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

/**
 *
 */
public class MyBinaryTree {
    
    

    /**
     * 二叉树节点
     */

    private static class TreeNode{
    
    
        int data;
        TreeNode leftChild;
        TreeNode rightChild;

        TreeNode(int data){
    
    
            this.data = data;
        }

    }
    public static TreeNode creatBinaryTree(LinkedList<Integer> inputList){
    
    
        TreeNode node = null;
        if (inputList ==null || inputList.isEmpty()){
    
    
            return null;
        }
        Integer data = inputList.removeFirst();
        if (data != null){
    
    
            node = new TreeNode(data);
            node.leftChild = creatBinaryTree(inputList);
            node.rightChild = creatBinaryTree(inputList);
        }
        return node;
    }

    /**
     * 二叉树前序遍历
     * @param node 二叉树节点
     */
    public static void preOrderTraveral(TreeNode node){
    
    
        if (node == null){
    
    
            return;
        }
        System.out.println(node.data);
        preOrderTraveral(node.leftChild);
        preOrderTraveral(node.rightChild);
    }

    /**
     * 二叉树中序遍历
     * @param node 二叉树节点
     */
    public static void inOrderTraveral(TreeNode node){
    
    
        if (node == null){
    
    
            return;
        }
        inOrderTraveral(node.leftChild);
        System.out.println(node.data);
        inOrderTraveral(node.rightChild);
    }

    /**
     * 二叉树后序遍历
     * @param node  二叉树节点
     */

    public static void postOrderTraveral(TreeNode node){
    
    
        if (node == null){
    
    
            return;
        }
        postOrderTraveral(node.leftChild);
        postOrderTraveral(node.rightChild);
        System.out.println(node.data);
    }

    /**
     * 二叉树非递归前序遍历
     * @param root 二叉树根节点
     */
    public static void preOrderTraveralWithStack(TreeNode root){
    
    
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode treeNode = root;
        while (treeNode != null || !stack.isEmpty()){
    
    
            //迭代访问节点的左孩子,并入栈
            while (treeNode != null){
    
    
                System.out.println(treeNode.data);
                stack.push(treeNode);
                treeNode = treeNode.leftChild;
            }
            //如果节点没有左孩子,则弹出栈顶节点,访问右孩子
            if (!stack.isEmpty()){
    
    
                treeNode = stack.pop();
                treeNode = treeNode.rightChild;
            }
        }
    }

    /**
     * 二叉树层序遍历
     * @param root 二叉树层序遍历
     */
    public static void levelOrderTraversal(TreeNode root){
    
    
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        //将指定的元素插入此队列(如果立即可行且不会违反容量限制),当使用有容量限制的队列时,此方法通常要优于 add(E),后者可能无法插入元素,而只是抛出一个异常。
        queue.offer(root);
        while (!queue.isEmpty()){
    
    
            // poll()获取并移除此队列的头,如果此队列为空,则返回 null。
            // remove()获取并移除此队列的头。此方法与 poll 唯一的不同在于:此队列为空时将抛出一个异常。
            TreeNode node = queue.poll();
            System.out.println(node.data);
            if (node.leftChild != null){
    
    
                queue.offer(node.leftChild);
            }
            if (node.rightChild != null){
    
    
                queue.offer(node.rightChild);
            }
        }
    }

    public static void main(String[] args) {
    
    
        LinkedList<Integer> inputList = new LinkedList<Integer>(Arrays.asList(new Integer[]{
    
    3,2,9,null,null,10,null,null,8,null,4}));
        TreeNode treeNode =creatBinaryTree(inputList);
        System.out.println("前序遍历: ");
        preOrderTraveral(treeNode);
        System.out.println("**************************************");
        preOrderTraveralWithStack(treeNode);
        System.out.println("中序遍历: ");
        inOrderTraveral(treeNode);
        System.out.println("后序遍历: ");
        postOrderTraveral(treeNode);
        System.out.println("层序遍历: ");
        levelOrderTraversal(treeNode);
    }
}

二叉堆

package tree_tree;/**
 * Copyright (C), 2019-2020
 * author  candy_chen
 * date   2020/6/23 17:07
 * version 1.0
 * Description: 测试
 */

import java.util.Arrays;

/**
 *
 */
public class test {
    
    

    public static void upAdjust(int[] array){
    
    
        int childIndex = array.length-1;
        int parentIndex = (childIndex -1)/2;
        //temp保存插入的叶子节点值,用于最后的赋值
        int temp = array[childIndex];
        while (childIndex >0 && temp < array[parentIndex]){
    
    
            //无序真正交换,只需要单向赋值即可
            array[childIndex] = array[parentIndex];
            childIndex = parentIndex;
            parentIndex = (parentIndex -1)/2;
        }
        array[childIndex] = temp;
    }

    /**
     * "下沉操作"
     * @param array 待调整的堆
     * @param parentIndex  要“下沉”的父节点
     * @param length    堆的有效大小
     */
    public static void downAdjust(int[] array, int parentIndex, int length){
    
    
        //temp保存父节点值,用于最后的赋值
        int temp = array[parentIndex];
        int childIndex = 2 * parentIndex + 1;
        while (childIndex < length){
    
    
            //如果有右孩子,且右孩子小于左孩子的值,则定位到右孩子
            if (childIndex + 1 < length && array[childIndex + 1] < array[childIndex]){
    
    
                childIndex++;
            }
            //如果父节点小于任何一个孩子的值,则直接跳出
            if (temp <= array[childIndex])
                break;
            //无须整整交换,单向赋值即可
            array[parentIndex] = array[childIndex];
            parentIndex = childIndex;
            childIndex = 2 * childIndex + 1;
        }
        array[parentIndex] =temp;
    }


    /**
     * 构建堆
     * @param array 待调整的堆
     */
    public static void buildHeap(int[] array){
    
    
        //从最后一个非叶子节点开始,依次做“下沉”操作
        for (int i = (array.length -2)/2; i>= 0; i--){
    
    
            downAdjust(array,i,array.length);
        }
    }
    public static void main(String[] args) {
    
    
        int[] array = new int[] {
    
    1,3,2,6,5,7,8,9,0};
        upAdjust(array);
        System.out.println(Arrays.toString(array));

        array = new int[]{
    
    7,1,3,10,5,2,8,9,6};
        buildHeap(array);
        System.out.println(Arrays.toString(array));

    }
}

优先队列

package tree_tree;/**
 * Copyright (C), 2019-2020
 * author  candy_chen
 * date   2020/6/24 15:54
 * version 1.0
 * Description: 测试
 */

import java.util.Arrays;

/**
 *
 */
public class PriorityQueue {
    
    
    private int[] array;
    private int size;
    public PriorityQueue(){
    
    
        //队列初始长度为32
        array = new int[32];
    }

    /**
     * 入队
     * @param key 入队元素
     */
    public void enQueue(int key){
    
    
        //队列长度超出范围,扩容
        if (size >= array.length){
    
    
            resize();
        }
        array[size++] = key;
        upAdjust();
    }
    /**
     * 出队
     */
    public int deQueue() throws Exception{
    
    
        if (size <= 0){
    
    
            throw new Exception("the queue is empty!");
        }
        //获取堆顶元素
        int head = array[0];
        //让最后一个元素移动到堆顶
        array[0] = array[--size];
        downAdjust();
        return head;
    }

    /**
     * 下沉调整
     */
    private void downAdjust() {
    
    
        //temp保存父节点的值,用于最后的赋值
        int parentIndex = 0;
        int temp = array[parentIndex];
        int childIndex = 1;
        while (childIndex <size){
    
    
            //如果有右孩子,且右孩子小于左孩子的值,则定位到右孩子
            if (childIndex + 1 < size && array[childIndex + 1] < array[childIndex]){
    
    
                childIndex++;
            }
            //如果父节点小于任何一个孩子的值,则直接跳出
            if (temp <= array[childIndex])
                break;
            //无须整整交换,单向赋值即可
            array[parentIndex] = array[childIndex];
            parentIndex = childIndex;
            childIndex = 2 * childIndex + 1;
        }
        array[parentIndex] =temp;

    }

    /**
     * "上浮调整"
     */
    private void upAdjust() {
    
    
        int childIndex = size - 1;
        int parentIndex = (childIndex - 1)/2;
        //temp保存插入的叶子节点值,用于最后的赋值
        int temp = array[childIndex];
        while (childIndex > 0 && temp > array[parentIndex]){
    
    
            //无须真正交换,单向赋值即可
            array[childIndex] = array[parentIndex];
            childIndex = parentIndex;
            parentIndex = (parentIndex - 1 )/ 2;
        }
        array[childIndex] = temp;
    }

    /**
     * 队列扩容
     */
    private void resize() {
    
    
        //队列容量翻倍
        int newSize = this.size *2;
        this.array = Arrays.copyOf(this.array,newSize);
    }

    public static void main(String[] args) throws Exception {
    
    
        PriorityQueue priorityQueue = new PriorityQueue();
        priorityQueue.enQueue(3);
        priorityQueue.enQueue(5);
        priorityQueue.enQueue(10);
        priorityQueue.enQueue(2);
        priorityQueue.enQueue(7);
        System.out.println("出队元素: " + priorityQueue.deQueue());
        System.out.println("出队元素: " + priorityQueue.deQueue());
    }
}

说明:根据网络资料进行搜索学习理解整理 若有侵权联系作者

  • 参考书籍:漫画算法-小灰的算法之旅

猜你喜欢

转载自blog.csdn.net/qq_35655602/article/details/106989873