计算完全二叉树节点个数(递归、层次遍历、二叉搜索)

一、递归遍历O(n)

二、层次遍历O(n)

三、二叉搜索O(logn*logn)

 参考网址:Count Number of Nodes in a Complete Binary Tree (Leetcode Problem Solution) (includehelp.com)

#include<iostream>
#include<vector>
#include<queue>
#include<stack>
#include<ctime>
#include<iomanip>
using namespace std;

struct TreeNode {
    int val = 0;
    TreeNode *left = NULL;
    TreeNode *right = NULL;
};

//利用队列,生成的完全二叉树
void CreateTreeNode(TreeNode *root, int Num) {
    queue<TreeNode *> Q;
    Q.push(root);//根结点入队
    int data = 1;//根的值为1
    while (data < Num) {
        TreeNode *curr_node = Q.front();//取队首元素
        Q.pop();//队首出队
        curr_node->left = new TreeNode;
        curr_node->left->val = data++;
        Q.push(curr_node->left);//左子树入队尾

        curr_node->right = new TreeNode;
        curr_node->right->val = data++;
        Q.push(curr_node->right);//右子树入队尾
    }
}

//利用队列,层次遍历二叉树,计数
int LevelOrderTraversal(TreeNode *root) {
    queue<TreeNode *> Q;
    int count = 0;
    Q.push(root);//根节点入队
    while (!Q.empty()) {//队不为空,则一直遍历
        TreeNode *curr_node = Q.front();//取队首元素
        cout << setw(4) << curr_node->val;//输出当前元素的值
        Q.pop();//队首出队
        count++;
        if (curr_node->left) {//左子树不为空
            Q.push(curr_node->left);//左子树入队尾
        }

        if (curr_node->right) {//同上
            Q.push(curr_node->right);
        }
    }
    return count;
}

//递归实现的遍历
//flag 1 2 3 对应于先序 中序 后序遍历
int RecursiveTraversal(const TreeNode *root) {
    if (!root)
        return 0;
    return 1 + RecursiveTraversal(root->left) + RecursiveTraversal(root->right);
}

bool is_exists(TreeNode *root, int h, int no_of_nodes) {
    TreeNode *cur = root;

    int left = 1, right = pow(2, h);
    //loop runs for h=O(logn) time
    //binary search to find the 
    //no_of_nodes th node exist or not
    for (int i = 0; i < h; ++i) {//一定要走完h层,到根节点
        int mid = left + (right - left) / 2;
        if (no_of_nodes <= mid) {
            cur = cur->left;
            right = mid;
        } else {
            cur = cur->right;
            left = mid + 1;
        }
    }
    //if no_of_nodes at last level exists 
    //then cur will point to that no_of_nodes th node
    //else NULL
    //指向最后一层,cur为空,不存在,不为空,则存在
    return cur != NULL;
}

//since it's a complete tree we can traverse 
//towards the left child always
//since the last level nodes will be as 
//left as far possible,
// while循环直到最右边为空,即为树高
int height(TreeNode *root) {
    if (!root)
        return 0;
    TreeNode *cur = root;
    int count = 0;
    while (cur) {
        count++;
        cur = cur->left;
    }
    return count;
}

//calculate number of nodes in 
//the complete tree efficiently
int binary_search_countNodes(TreeNode *root) {
    if (!root)
        return 0;
    else if (!root->left && !root->right)
        return 1;

    int h_except_last_level = height(root) - 1;
    //number of nodes except the last level 
    //is calculated as follow
    // 前h - 1 层节点都是满的,
    int no_of_nodes_except_last_level = pow(2, h_except_last_level) - 1;
    //number of possible nodes at the last level
    //最后一层,数量在1 到 前面数量 + 1
    int left = 1, right = no_of_nodes_except_last_level + 1;

    //do binary search to check 
    //if predicted number of node exists or not
    while (left <= right) {
        int mid = left + (right - left) / 2;

        //finds if last level has mid number of nodes or not
        if (is_exists(root, h_except_last_level, mid)) {
            left = mid + 1;
        } else
            right = mid - 1;
    }//left 与right 相等后,再查找,left++,因此真实数量为right
    return no_of_nodes_except_last_level + right;
}

// 所有的代码都需要写在 Algo 类内,自行定义其他需要的变量或函数
class Algo {
public:
    Algo() {
        cout << "algo ok" << endl;
    }

    int run(TreeNode *head) {
        //在此写入你的代码
        cout << "\n层次遍历计数:\t" << LevelOrderTraversal(head)
            << "\n递归遍历计数:\t" << RecursiveTraversal(head)
            << "\n二叉搜索计数:\t" << binary_search_countNodes(head)
            << '\n';

        return 0; //修改为返回正确的结果
    }
};

int main() {
    Algo algo;
    TreeNode head;
    CreateTreeNode(&head, 100);    //10 为生成的二叉树结点的数量,生成的二叉树为完全二叉树
    time_t start = clock();
    algo.run(&head);
    time_t end = clock();
    cout << "程序耗时: " << double(end - start) / CLOCKS_PER_SEC << " ms" << endl;
    cout << "占用内存:" << sizeof(algo) << " byte" << endl;
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 二叉树的递归遍历: 二叉树的递归遍历是指通过递归方法遍历二叉树的各个节点,按照某种次序访问每个节点。常见的二叉树遍历方式有前序遍历、中序遍历和后序遍历。 2. 二叉树的非递归遍历: 二叉树的非递归遍历是指通过循环等非递归方法遍历二叉树的各个节点,按照某种次序访问每个节点。非递归遍历需要借助栈来实现,常见的二叉树遍历方式有前序遍历、中序遍历和后序遍历。 3. 二叉树的层次遍历二叉树的层次遍历是指按照从上到下、从左到右的顺序遍历每一层节点。常用的方法是使用队列来实现,首先将根节点入队列,然后依次出队列,并将其左右子节点入队列,直到队列为空。 4. 输出二叉树上所有叶节点二叉树上的叶节点是指没有子节点节点。可以通过递归方式,对每个节点进行判断,如果该节点没有左右子节点,则将该节点输出。 5. 求二叉树的高度: 二叉树的高度是指从根节点到叶节点最长路径上经过的边数。可以通过递归方式求解,从左右子树中选取较大的一个加上根节点即可。 6. 二叉树层序生成算法二叉树层序生成算法是指按照从上到下、从左到右的顺序依次生成每个节点。可以使用队列来实现,首先将根节点入队列,然后依次出队列,并根据当前节点生成其左右子节点,将其入队列,直到生成完所有节点
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值