1.二叉树

是一种树形结构,每个结点至多有那个子树,并且二叉树的子树有左右之分,次序不能颠倒。

满二叉树:

即每个节点都有俩个子节点。一个深度为k且有2的k次方-1个节点的二叉树。

完全二叉树:

深度为k的,有n个节点的二叉树,当且仅当每一个节点都与深度为k的满二叉树从1-n 一一对应时,就是完全二叉树。是满二叉树的子集。

 

储存结构:

顺序存储结构:即使用数组进行存储。第一个元素为根节点,左子树的索引为层数*2-1,左子树的索引为层数*2,用0来表示空元素。但会造成大量空间的浪费,因此适用于完全二叉树。

链式存储结构:每个节点都有指向左子树和右子树的指针。这里我们用Java实现。为了插入和删除方便,我们设置一个头结点,指向根节点。

public class BinaryTree<T> {
    public class Node {
	Node lchild;
	Node rchild;
	T data;
    }
    private Node head;
}

遍历方法:

先序遍历、中序遍历、后序遍历。其中先中后指的是根节点的遍历顺序。且 左子树 先于右子树遍历

先序遍历(即深度遍历):根 -> 左  -> 右    A->B->D->G->C->E->F

代码:

public void frontOrder(Node node){
        if(node == null){
            return ;
        }
        System.out.println(node.data);
        frontOrder(node.lchild);
        frontOrder(node.rchild);
    }

//使用栈来完成
public void frontOrder2(Node node){
        if(node == null){
            return ;
        }
        Stack<Node> stack = new Stack();
        stack.push(node);
        while (! stack.isEmpty()){

            Node parent = stack.pop();
            System.out.println(parent.data);
            if(parent.rchild != null){
                stack.push(parent.rchild);
            }
            if(parent.lchild != null){
                stack.push(parent.lchild);
            }
        }
    }

 

中序遍历:左 -> 根  -> 右    D->G->B->A->E->C->F

代码:


    public void middleOrder(Node node){
        if(node == null){
            return ;
        }

        middleOrder(node.lchild);
        System.out.println(node.data);
        middleOrder(node.rchild);
    }

后序遍历:左 -> 右  -> 中    G->D->B->E->F->C->A

代码

    public void afterOrder(Node node){
        if(node == null){
            return ;
        }

        afterOrder(node.lchild);
        afterOrder(node.rchild);
        System.out.println(node.data);
    }

按层遍历即广度遍历:

可以使用队列这种形式,先进先出 

    public void cengOrder(Node node ){
        //LinkedList 支持队列操作
        LinkedList<Node> nodes = new LinkedList<>();
        nodes.push(node);
        while (! nodes.isEmpty()){
            Node parent = nodes.poll();
            System.out.println(parent.data);
            //放入左节点
            if(parent.lchild != null){
                nodes.addLast(parent.lchild);
            }
            //放入右节点
            if(parent.rchild != null){
                nodes.addLast(parent.rchild);
            }
        }
    }

线索二叉树:

以二叉链表为存储结构时,只能找到结点的的左右孩子结点的信息,而不能获得它的前驱和后继的信息。为了获取前驱和后继,最简单的方法就是添加前驱和后继的指针,但是这样会造成空间的浪费。为了避免空间浪费,我们依旧使用左右结点来作为前驱和后继,并加上标志位。

定义如下:若结点有左子树,则令lchild指向左孩子,否则指向前驱;若结点有右孩子,则令rchild指向右孩子,否则指向后继。

public class BinaryTree<T> {
    public class Node {
	Node lchild;
	Node rchild;
	T data;
        int lTag; //为0指向左孩子,为1指向前驱
        int RTag;
    }
    private Node head;
}

森林与二叉树的转换:

1.连线:将兄弟结点连线

2.抹线:抹去除左子树的其他子树的线

3.旋转

哈夫曼树(最优二叉树):

带权路径最小的树为最优二叉树。

构建:假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为:
(1) 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点);
(2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;
(3)从森林中删除选取的两棵树,并将新树加入森林;
(4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。

哈夫曼编码:即将左0右1,即可获得编码

堆:

左子树和右子树上的元素大于父节点的元素,因此父节点的元素为最小的。或者是左子树和右子树的元素小于父节点的元素,父节点的元素为最大。

二叉排序树(二叉查找树)

1.若它的左子树不空,则左子树上的左右结点的值均小于它的根节点的值

2.若它的右子树不空,则右子树的所有结点的值均大于它的根节点的值

3.它的左右树也分别为二叉排序树。

用于查找数据。

比如想查找7的话,先要比较8,在比较3,在比较6,得到7;可见比较次数是与二叉树的深度有关。因此最坏时间复杂度是O(logn)

平衡二叉树:

1.左右树的深度只差不超过1,

2.左子树、右子树均为平衡二叉树。

我们希望二叉排序树都是平衡二叉树,显得较低一些,比较次数少。

平衡二叉树的添加与删除调整:旋转,

红黑树

根节点是黑色的;

每个叶子节点都是黑色的空节点(NIL),也就是说,叶子节点不存储数据;

任何相邻的节点都不能同时为红色,也就是说,红色节点是被黑色节点隔开的;

每个节点,从该节点到达其可达叶子节点的所有路径,都包含相同数目的黑色节点;

 

B+树:

每个节点中子节点的个数不能超过 m,也不能小于 m/2;

根节点的子节点个数可以不超过 m/2,这是一个例外;

m 叉树只存储索引,并不真正存储数据,这个有点儿类似跳表;

通过链表将叶子节点串联在一起,这样可以方便按区间查找

一般情况,根节点会被存储在内存中,其他节点存储在磁盘中

 

B树:

B+ 树中的节点不存储数据,只是索引,而 B 树中的节点存储数据;B 树中的叶子节点并不需要链表来串联。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值