完全二叉树操作大全

1.二叉树的定义

二叉树( binary tree)t 是有限个元素的集合(可以为空)。当二叉树非空时,其中有一个称为根(root)的元素,余下的元素(如果有的话)被组成2个二叉树,分别称为t的左子树和右子树.
你会发现二叉树的定义都含有递归的思想,没错二叉树的很多操作都要依赖递归完成。
完全二叉树:
从满二叉树上删除有限个元素产生的二叉树。比较规则。

二叉树的遍历

遍历是二叉树中最常用的操作:
前序遍历:是先访问父节点并输出,前序遍历左子树,前序遍历右子树。
代码如下:

template <class T>
void linkedBinaryTree<T>::preOrder(binaryTreeNode<T> *t){

    if (t != NULL){

        visit(t);
        preOrder(t->leftChild);
        preOrder(t->rightChild);

    }
}

中序遍历:
先中序遍历左子树,在输出父节点,在中序遍历右子树。

template <class T>
void linkedBinaryTree<T>::inOrder(binaryTreeNode<T> *t){
    if (t!=NULL){
        inOrder(t->leftChild);
        visit(t);
        inOrder(t->rightChild);
    }
}

后序遍历:
先后序遍历左子树,在后序遍历右子树,在输出父节点。

template <class T>
void linkedBinaryTree<T>::postOrder(binaryTreeNode<T> *t){
    if (t!=NULL){
        postOrder(t->leftChild);
        postOrder(t->rightChild);
        visit(t);
    }
}

层次遍历:
按从顶层到底层的次序访问树中元素,在同一层中,从左到右进行访问。依赖队列实现

template <class T>
//队列实现层次遍历
void linkedBinaryTree<T>::levelOrder(binaryTreeNode<T> *t){

    arrayQueue<binaryTreeNode<T>*> q;
    while (t!=NULL){

        visit(t);


        //将节点的孩子们放到队列中
        if (t->leftChild!=NULL){
            q.push(t->leftChild);
        }
        if (t->rightChild!=NULL){
            q.push(t->rightChild);
        }

        //提取下一个访问节点
        try {
            t = q.front();
        }catch (int e){ return;}

        q.pop();

    }


}

可以看到前三种遍历方式都要依赖递归实现。

3.二叉树的创建

1)利用层次遍历结构直接创建:
层次遍历是按从顶层到底层的次序访问树中元素,在同一层中,从左到右进行访问。
实现代码:

template<class T>
//按层次遍历的顺序创建树
void linkedBinaryTree<T>::LevelCreateTree(int nodeSize,char* string) {

    treeSize = nodeSize;

    //层次遍历有关的都要结合队列来做
    arrayQueue<binaryTreeNode<T>*> *queues = new    arrayQueue<binaryTreeNode<T>*>;

    int count = 1;

    binaryTreeNode<T> *node = new binaryTreeNode<T>();//用来移动的节点Node
    root = new binaryTreeNode<T>();
    node = root;
    root->element = string[count-1];//头结点

    //只有一个元素时
    if (count == nodeSize){
        return;
    }

    queues->push(node);
    while (!queues->empty()) {
        node = queues->front();
        queues->pop();
        if (node->leftChild == NULL) {
            binaryTreeNode<T> *left = new binaryTreeNode<T>();
            left->element = string[count];
            node->leftChild = left;
            queues->push(left);
            count++;
            if (count == nodeSize)//这时候中止并不会有数组越界的bug
                break;
        }
        if (node->rightChild == NULL) {
            binaryTreeNode<T> *right = new binaryTreeNode<T>;
            right->element = string[count];
            node->rightChild = right;
            queues->push(right);
            count++;
            if (count == nodeSize)
                break;
        }
    }
}

由于层次遍历的特性,需要用到的结构应该是队列,arrayQueue就是用数组实现的队列。通过队列就实现了通过层次遍历的结构创建完全二叉树。思路比较简单,就是不断进入队列和出队列的过程。
2)通过前序遍历和中序遍历结果创建二叉树
代码:
也是要用到递归理解的难点在于:通过父节点(在前序遍历中确定)在中序中的位置确定父节点的左右子树。

//利用前序遍历和中序遍历创建二叉树
template <class T>
binaryTreeNode<T>* linkedBinaryTree<T>::CreateByPreIn(T *VLR, T *LVR, int n) {

    if (n == 0)
        return NULL;
    int k = 0;
    while (VLR[0] != LVR[k])
        k++;
    binaryTreeNode<T> *t = new binaryTreeNode<T>();
    t->element = VLR[0];//父节点创建

    t->leftChild = CreateByPreIn(VLR + 1, LVR, k);
    t->rightChild = CreateByPreIn(VLR + k + 1, LVR + k + 1, n - k - 1);

    return t;

}

2)通过后序遍历和中序遍历结果创建二叉树
代码:
也是要用到递归理解的难点在于:通过父节点(在后序遍历中确定)在中序中的位置确定父节点的左右子树的长度,通过长度递归寻找

//利用后序遍历和中序遍历产生结果
template <class T>
binaryTreeNode<T>* linkedBinaryTree<T>::CreateByPostIn(T *LRV, T *LVR, int n) {//n为序列长度


    if (n == 0){
        return NULL;
    }
    int k =0;
    while (LRV[n-1]!=LVR[k])
        k++;

    //创建父节点
    binaryTreeNode<T> *t = new binaryTreeNode<T>();
    t->element = LRV[n-1];

    t->leftChild = CreateByPostIn(LRV,LVR,k);
    t->rightChild = CreateByPostIn(LRV+k,LVR+k+1,n-k-1);

    return t;

}

注意后两种创建完全二叉树的方法都是返回的二叉树节点,所以要让完全二叉树的根等于该方法。

4.二叉树的常用方法

1)计算二叉树的节点数目:
基本思路还是递归:
基本情况:如果节点是空返回是0.
否则返回:1+以左孩子为根的二叉树的节点数目+以右孩子为根的二叉树的节点数目。
实现代码:

template <class T>
int linkedBinaryTree<T>::getNodesNum(binaryTreeNode<T> *node) {
    if (node==NULL){
        return 0;
    }

    return 1+getNodesNum(node->leftChild)+getNodesNum(node->rightChild);

}

2)计算二叉树的高度:
基本思路还是递归,你会发现二叉树的操作离不开递归。
**基本情况:**如果节点为空,返回0.
否则返回:1+max(以左孩子为根的二叉树的高度,以右孩子为根的二叉树的高度)。
实现代码:

template <class T>
//计算树的高度
int linkedBinaryTree<T>::height_tree(binaryTreeNode<T> *node) {
    if (node==NULL){
        return 0;
    }

    return 1+max(height_tree(node->leftChild),height_tree(node->rightChild));

}

关于二叉树的应用我们下次再聊。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值