1.二叉树
public class BinaryTreeDao<E> {
private Node root;
public BinaryTreeDao (Node node){
this.root = node;
}
public boolean add(Node node){
//定义一个辅助变量,获取根结点
Node temp = root;
//进行遍历二叉树,找到合适的位置插入
while (true) {
//如果添加的数和树中的数相同,则不插入
if (temp.num == node.num){
return false;
}
//左子树
//如果根节点大于要插入的数,就说明插入的数是二叉树的左子树
if (temp.num > node.num){
//如果当前结点的左节点为空,就将这个数插入
if (temp.left == null){
temp.left = node;
return true;
//否则,进入下一个结点
}else {
temp = temp.left;
}
//右子树
}else {
//当前结点的右节点为空,则插入
if (temp.right == null){
temp.right = node;
return true;
}else {
temp = temp.right;
}
}
}
}
//判断树是否为空
public boolean isEmpty(){
return root == null;
}
//先序遍历
List<Integer> list = new ArrayList<>();
//将根结点传入
public List<Integer> get(){
return getAll(root);
}
public List<Integer> getAll(Node node){
//就当前结点插入到集合中
list.add(node.num);
//如果左节点不为空,则进行递归
if (node.left != null) {
getAll(node.left);
//这里涉及到递归的原理,当左节点循环结束后,就会从树的最低开始向根节点遍历
}if (node.right != null){
getAll(node.right);
}
return list;
}
//中序遍历
public List<Integer> getIn(){
return getInOrder(root);
}
public List<Integer> getInOrder(Node node){
if (node.left != null){
getInOrder(node.left);
}
list.add(node.num);
if (node.right != null){
getInOrder(node.right);
}
return list;
}
//后序遍历
public List<Integer> getNext(){
return getNextOrder(root);
}
public List<Integer> getNextOrder(Node node){
if (node.left != null){
getNextOrder(node.left);
}
if (node.right != null){
getNextOrder(node.right);
}
list.add(node.num);
return list;
}
}
2.顺序存储二叉树
public class Test4 {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7};
ArrBinaryTree arrBinaryTree = new ArrBinaryTree(arr);
arrBinaryTree.preOrder();
System.out.println();
arrBinaryTree.inOrder();
System.out.println();
arrBinaryTree.nextOrder();
}
}
//顺序存储二叉树
class ArrBinaryTree{
private int[] arr;
public ArrBinaryTree(int[] arr){
this.arr = arr;
}
public void preOrder(){
this.preOrder(0);
}
public void inOrder(){
this.inOrder(0);
}
public void nextOrder(){
this.nextOrder(0);
}
//先序遍历
public void preOrder(int index){
if (arr == null || arr.length == 0){
System.out.println("数组为空!");
}
System.out.print(arr[index]+" ");
//左子树(下一个结点的下标为:index*2+1),index为当前下标
if ((index*2)+1 <arr.length){
preOrder(index*2+1);
}
//右子树
if ((index*2)+2 <arr.length){
preOrder(index*2+2);
}
}
//中序遍历
public void inOrder(int index){
if (arr.length == 0 || arr == null){
System.out.println("数组为空");
}
if ((index*2+1) < arr.length) {
inOrder(index*2+1);
}
System.out.print(arr[index]+" ");
if ((index*2+2) < arr.length) {
inOrder(index*2+2);
}
}
//后序遍历
public void nextOrder(int index){
if (arr.length == 0 || arr == null){
System.out.println("数组为空");
}
if ((index*2+1) < arr.length){
nextOrder(index*2+1);
}
if ((index*2+2) < arr.length){
nextOrder(index*2+2);
}
System.out.print(arr[index]+" ");
}
}
3.赫夫曼树
给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
若初始森林中共有n棵二叉树,最终求得的哈夫曼树共有2n-1个结点
哈夫曼树中没有度数为1的分支结点
若初始森林中共有n棵二叉树,进行n-1次合并后才能剩下一棵最终的哈夫曼树
构成赫夫曼树的步骤
(1)从小到大进行排序,将每一个数据,每个数据都是一个节点,每个节点可以看做是一颗最简单的二叉树
(2)取出根节点权值最小的两颗二叉树
(3)组成一颗新的二叉树,该新的二叉树的根节点的权值是前面两颗二叉树根节点权值的和
(4)再将这颗新的二叉树,以根节点的权值大小再次排序,不断重复1-2-3-4的步骤,知道数列中的所有数据处理完毕,就得到一个赫夫曼树
public class HaffManTree {
public static void main(String[] args) {
int arr[] = {13,7,8,3,29,6,1};
Node root = createHaffManTree(arr);
preOrder(root);
}
public static void preOrder(Node node){
if (node != null){
node.preOrder();
}else {
System.out.println("是空树,不能遍历!");
}
}
//创建赫夫曼树的方法
public static Node createHaffManTree(int[] arr){
//1.遍历arr数组
//2.将arr中每个元素构成一个Node
//3.将Node放到ArrayList中
List<Node> list = new ArrayList<>();
for (int value:arr
) {
list.add(new Node(value));
}
while (list.size() > 1){
//从小到大排序
Collections.sort(list);
System.out.println(list);
//取出权值最小的两颗二叉树
Node left = list.get(0);
Node right = list.get(1);
//构成新的二叉树
Node parent = new Node(left.value+right.value);
parent.left = left;
parent.right = right;
//从集合中删除处理过的二叉树
list.remove(left);
list.remove(right);
//将新的二叉树加入到集合中
list.add(parent);
}
//返回赫夫曼树的root头结点
return list.get(0);
}
}
//创建结点类
class Node implements Comparable<Node>{
int value;//结点权值
Node left;//左子节点
Node right;//右子节点
public Node (int value){
this.value = value;
}
public void preOrder(){
System.out.println(this);
if (this.left != null){
this.left.preOrder();
}
if (this.right != null){
this.right.preOrder();
}
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
@Override
public int compareTo(Node o) {
//从小到大排序
return this.value - o.value;
}
}