1.二叉树概念
二叉树:任何一个节点的子节点不超过2
满二叉树:节点总数为:2∧n-1 (n是树的高度)
完全二叉树:如果二叉树中除去最后一层节点为满二叉树,且最后一层的结点依次从左到右分布,则此二叉树被称为完全二叉树。
2.二叉树的遍历
二叉树节点:
class Node{
private Node leftNode;
private Node rightNode;
private int value;
public Node(int value) {
this.value = value;
}
public Node getLeftNode() {
return leftNode;
}
public void setLeftNode(int n) {
this.leftNode = new Node(n);
}
public Node getRightNode() {
return rightNode;
}
public void setRightNode(int n) {
this.rightNode = new Node(n);
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
前序遍历:
public void Preorder() {
System.out.println(this.getValue());
if(this.leftNode!=null){
this.leftNode.Preorder();
}
if(this.rightNode!=null){
this.rightNode.Preorder();
}
}
中序遍历:
public void Middle_order(){
if(this.leftNode!=null){
this.leftNode.Middle_order();
}
System.out.println(this.getValue());
if(this.rightNode!=null){
this.rightNode.Middle_order();
}
}
后序遍历:
public void Post_order(){
if(this.leftNode!=null){
this.leftNode.Post_order();
}
if(this.rightNode!=null){
this.rightNode.Post_order();
}
System.out.println(this.getValue());
}
前序查找:(省略中序查找与后序查找)
public Node search(int i) {
if(this.value==i){return this;}
Node result=null;
if(this.leftNode!=null){
result=leftNode.search(i);
}
if(result!=null){return result;}
if(this.rightNode!=null){
result=rightNode.search(i);
}
return result;
}
3.顺序存储二叉树
顺序二叉树特点:
(1)顺序二叉树只考虑完全二叉树
(2)第n个元素的左子节点为 2n+1
(3)第n个元素的右子节点为 2n+2
(4)第n个元素的父节点为(n-1)/2
n从0开始编号
✏遍历顺序存储的二叉树:
/*顺序存储二叉树*/
public class ArrBinarytreeDemo {
public static void main(String[] args) {
int[] arr=new int[]{1,2,3,4,5,6,7};
ArrBinarytree a=new ArrBinarytree(arr);
a.Preorder();
}
}
class ArrBinarytree{
private int[] arr;
public ArrBinarytree(int[] arr){
this.arr=arr;
}
public void Preorder(){
this.Preorder(0);
}
public void Preorder(int index) {
if(arr==null||arr.length<0){
System.out.println("数组为空,无法遍历");
return;
}
System.out.println(arr[index]);
if((index*2+1)<arr.length){
Preorder(2*index+1);
}
if((index*2+2)<arr.length){
Preorder(2*index+2);
}
}
}
4.线索二叉树
线索二叉树节点类:
class Node {
private Node leftNode;
private Node rightNode;
private int value;
//Leftflag=0 时LeftNode指向左儿子;Leftflag=1 时LeftNode指向前驱节点。
public int Leftflag = 0;
//Rightflag=0 时RightNode指向左儿子;Rightflag=1 时RightNode指向前驱节点。
public int Rightflag =0;
public Node(int value) {
this.value = value;
}
public Node getLeftNode() {
return leftNode;
}
public void setLeftNode(Node node) {
this.leftNode = node;
}
public Node getRightNode() {
return rightNode;
}
public void setRightNode(Node node) {
this.rightNode = node;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
class ThreadedBinaryTree{
Node pre=null; // 存储当前当前节点的父节点
public static void ThreadNode(Node node){//中序线索化二叉树
if(node==null){return;}
//递归左子节点
ThreadNode(node.getLeftNode());
if(node.getLeftNode()==null){
node.setLeftNode(pre);
node.Leftflag=1;
}
if(pre!=null&&pre.getRightNode()==null){
pre.setRightNode(node);
pre.Rightflag=1;
}
pre=node;
//递归右子节点
ThreadNode(node.getRightNode());
}
}
遍历线索二叉树:
public static void threadIterate(Node node){//输入树的根节点进行遍历
//打印输出,直到节点都遍历完
while(node!=null){
while(node.Leftflag!=1){
//找到左下角的首节点
node=node.getLeftNode();
}
//打印当前节点
System.out.println(node.getValue());
while (node.Rightflag==1){
node=node.getRightNode();
System.out.println(node.getValue());
}
node=node.getRightNode();
}
}
哈夫曼树:
叶子节点的带权路径:叶子节点的权值*(叶子节点与根节点的路径长度)
WPL:所有叶子节点的带权路径之和
🦁贪心法构造哈夫曼树:
1.对于数组[3,7,8,29,5,11,23,14]
2.将数组内的所以元素变为一个叶子节点,用List存放
3.排序List,得到最小的两个节点
4.将取出的两个节点连成一棵树,根节点的权值为两颗节点权值之和
5.删除取出的两个小节点,将合并后的根节点存入List中
6.循环3~5步,直到List内只有唯一一个根节点,就是哈夫曼树
🖥代码实现
先定义一个树的节点类
public class Node implements Comparable<Node>{
int value;
Node left;
Node right;
public Node(int value){
this.value=value;
}
public void setLeft(Node left) {
this.left = left;
}
public void setRight(Node right) {
this.right = right;
}
@Override
public int compareTo(Node o) {
return this.value-o.value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
}
实现哈夫曼树构建:
public class HaffmanTree {
public static void main(String[] args) {
int[] arr={3,7,8,29,5,11,23,14};
Node HuffmanRoot=createHuffmanTree(arr);
System.out.println(HuffmanRoot);
}
public static Node createHuffmanTree(int[] arr){
//使用数组中的元素创建若干个只有一个节点的二叉树。
List<Node> Nodes=new ArrayList<Node>();
for(int value:arr){
Nodes.add(new Node(value));
}
//循环处理,直到数组内只有一个节点为止
while(Nodes.size()>1){
//对树节点数组进行排序
Collections.sort(Nodes);
//取出两个最小的节点
Node left=Nodes.get(Nodes.size()-1);
Node right=Nodes.get(Nodes.size()-2);
Node newNode=new Node(left.value+right.value);
newNode.setLeft(left);
newNode.setRight(right);
Nodes.remove(left);
Nodes.remove(right);
Nodes.add(newNode);
}
return Nodes.get(0);
}
}