算法——树(二叉树、二叉堆、优先队列)
二叉树
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());
}
}
说明:根据网络资料进行搜索学习理解整理 若有侵权联系作者
- 参考书籍:漫画算法-小灰的算法之旅