二叉树解析

一、二叉树介绍
二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。
二、顺序二叉树
利用数组实现顺序二叉树,数组的一个元素不参与二叉树,依此将数组元素摆放到左右子树上。
三、顺序二叉树实现堆排序
1.堆排序介绍
堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子节点的键值或索引总是小于(或者大于)它的父节点。
2.过程
1)初始化一个总长度变量。
2)只要这个变量大于2,就是至少一个父节点的情况(这里数字第一个元素不参与二叉树排列)
3)从最后一个父节点开始遍历每个父节点,比较它和自己最大的孩子,如果最大孩子大于自己,跟自己交换
4)根节点和最后一个节点交换位置
5)重复3-4,每次重复第一步的总长度变量减一
3. 实现

public class HeapSort {
    //    数组实现顺序二叉树
//      数组第一个元素不参与二叉树,第二个元素作为二叉树的根节点
//     父节点个数为(数组长度-1)/2
//    父节点下标 1~父节点个数
//        子节点下标
//            左子树为父节点下标*2
//            右子树为左子树下标+1
//    利用二叉树实现堆排序
//    1.从下到上比较,从右到左比较
//    2.比较左右孩子,最大的孩子跟父节点比较,如果最大孩子大于父节点,最大孩子跟父节点交换位置
    public static void main(String[] args) {
        int[] ints = {0, 6, 2, 8, 1, 5, 4, 9, 3};
//        这里通过一个变量来记录最后的节点数
        int end = ints.length;
        //这里考虑数组大于2的情况,就表示有父节点。只有2个元素,就是只有一个根节点了。
        while (end > 2) {
            //父节点个数=(数组长度-1)/2;父节点索引=1到父节点个数
            //循环遍历所有的父节点(从最后一个父节点开始遍历),
            for (int i = (end - 1) / 2; i >= 1; i--) {
                //左儿子索引=父节点索引*2,右儿子索引=左儿子+1
                //根据父节点索引计算2个儿子的索引,找到2个儿子中最大的儿子
                int maxIndex = 2 * i;
                //只有右孩子下标小于数组长度 并且右孩子大于左节点,最大孩子下标为右孩子
                if ((maxIndex + 1) < end && ints[maxIndex + 1] > ints[maxIndex]) {
                    maxIndex++;
                }
                //如果最大孩子大于父节点,两者交换位置
                if (ints[maxIndex] > ints[i]) {
                    ints[maxIndex] = ints[maxIndex] ^ ints[i];
                    ints[i] = ints[maxIndex] ^ ints[i];
                    ints[maxIndex] = ints[maxIndex] ^ ints[i];
                }
            }
            //将根节点和最后一个节点交换位置
            ints[1] = ints[1] ^ ints[end - 1];
            ints[end - 1] = ints[1] ^ ints[end - 1];
            ints[1] = ints[1] ^ ints[end - 1];
            //每循环一次,最后一个数的位置向前移动一位
            end--;
        }
        for (int i : ints) {
            System.out.println(i);
        }
    }
}

4.时间复杂度
平均时间复杂度为:O(nlogn)
5.空间复杂度:
平均时间复杂度为:O(1)
6.稳定性
不稳定
四、链式二叉树及三种遍历方式
0.节点定义

public class Node {
    //节点值
    int value;
    //左子树
    Node left;
    //右子树
    Node right;
    public Node(int value){
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public Node getLeft() {
        return left;
    }

    public void setLeft(Node left) {
        this.left = left;
    }

    public Node getRight() {
        return right;
    }

    public void setRight(Node right) {
        this.right = right;
    }
}

1.新增节点

 //定义根节点
    Node root;

    //增加节点
    public void add(int value) {
        Node newNode = new Node(value);
        //如果根节点为空,则根节点等于该新节点
        if (root == null) {
            root = newNode;
        } else {
//            复制根节点
            Node tmp = root;
            //否则判定根节点与新节点的值比较,小于插入左边,大于插入右边
            while (true) {
                //小的在左边
                if (value < tmp.getValue()) {
                    if (tmp.getLeft() == null) {
                        tmp.setLeft(newNode);
                        break;
                    } else {
                        tmp = tmp.getLeft();
                    }
                }else {
                    //大的在右边
                    if(tmp.getRight() == null){
                        tmp.setRight(newNode);
                        break;
                    }else{
                        tmp = tmp.getRight();
                    }
                }
            }
        }
    }

2.遍历节点

 //查找某个节点
    public void show(){
        showNode(root);
    }

    private void showNode(Node node){
        //前序遍历
//        System.out.println(node.getValue());
        if(node.getLeft() != null){
            showNode(node.getLeft());
        }
        //中序遍历
//        System.out.println(node.getValue());
        if(node.getRight() != null){
            showNode(node.getRight());
        }
        //后续遍历
        System.out.println(node.getValue());
    }

参考:
二叉树百科

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值