当前位置: 首页 > article >正文

二叉树k层的叶子结点个数

文章目录

  • 1 题目
  • 2 思路
    • 2.1 思路1
    • 2.2 思路2
  • 3 代码实现
    • 3.1 思路1
    • 3.2 思路2
    • 3.3 完整的代码案例

1 题目

假设二叉树采用二叉链表存储结构,设计一个算法求其指定的第k层(k>1,跟是第1层)的叶子结点个数。

2 思路

2.1 思路1

设置一个全局变量记录某层叶子结点个数,前序遍历二叉树,并在遍历的过程中记录结点的层数。

2.2 思路2

层序遍历二叉树,记录某层的二叉树叶子结点个数。没有目标层时,让该层结点的孩子结点入队;到达目标层时,不再让该层的孩子结点入队,统计队中(该层)叶子结点的个数。

  • 具体流程
    • 设置两个指针分别指该层的最后一个结点lastNode(初始为根结点)和下一层的最后一个非叶结点newNode。
    • 每遍历到结点的左/右孩子为非叶结点时,把newNode更新为当前结点的左/右孩子;
    • 当遍历的结点为该层的最后结点时,把lastNode更新为最新的newNode。

3 代码实现

二叉树的存储结构:

template <typename T>
class BiTNode {
public:
    T data;
    BiTNode* left;
    BiTNode* right;
    BiTNode():data(NULL),left(NULL),right(NULL){};
};

template <>
class BiTNode<int> {
public:
    int data;
    BiTNode* left;
    BiTNode* right;
    BiTNode() : data(0), left(nullptr), right(nullptr) {}
    BiTNode(int x) : data(x), left(nullptr), right(nullptr) {}
    BiTNode(int x, BiTNode *left, BiTNode *right) : data(x), left(left), right(right) {}
};

template <>
class BiTNode<char> {
public:
    char data;
    BiTNode* left;
    BiTNode* right;
    BiTNode() : data('\0'), left(nullptr), right(nullptr) {}
    BiTNode(char x) : data(x), left(nullptr), right(nullptr) {}
    BiTNode(char x, BiTNode *left, BiTNode *right) : data(x), left(left), right(right) {}
};

3.1 思路1

template <typename T>
void calLevelLeaf(BiTNode<T>* root, int level, int k){
    if(level < k){
        if(root->left != nullptr) calLevelLeaf(root->left, level+1, k);
        if(root->right != nullptr) calLevelLeaf(root->right, level+1, k);
    }else if(level == k && root->left == nullptr && root->right == nullptr){
        leafNum++;
    }
} 

template <typename T>
int getLevelLeaf(BiTNode<T>* root, int k){
    calLevelLeaf(root, 1,  k);
    return leafNum;
}

3.2 思路2

template <typename T>
int getLevelLeaf2(BiTNode<T>* root, int k){
    deque<BiTNode<T>*> q;//双端队列
    BiTNode<T> *newNode = nullptr, *lastNode = root;  
    int level = 1;//层数
    int leafNum = 0;//该层的叶子结点个数
    q.push_back(root);
    while(!q.empty()){
        BiTNode<T>* p;
        if(level == k){
            while(!q.empty()){
                p = q.front();
                q.pop_front();
                if(p->left == nullptr && p->right == nullptr){
                    leafNum++;
                }
            }
            break;
        }
        else{
            p = q.front();
            q.pop_front();
            if(p->left != nullptr){
                q.push_back(p->left);
                newNode = p->left;
            }
            if(p->right != nullptr){
                q.push_back(p->right);
                newNode = p->right;
            }
            if(lastNode == p){
                lastNode = newNode;
                level += 1;
            }
        }
    }
    return leafNum;
}

3.3 完整的代码案例

#include <iostream>
#include <stack>
#include <deque>
#include <queue>
using namespace std;

template <typename T>
class BiTNode {
public:
    T data;
    BiTNode* left;
    BiTNode* right;
    BiTNode():data(NULL),left(NULL),right(NULL){};
};

template <>
class BiTNode<int> {
public:
    int data;
    BiTNode* left;
    BiTNode* right;
    BiTNode() : data(0), left(nullptr), right(nullptr) {}
    BiTNode(int x) : data(x), left(nullptr), right(nullptr) {}
    BiTNode(int x, BiTNode *left, BiTNode *right) : data(x), left(left), right(right) {}
};

template <>
class BiTNode<char> {
public:
    char data;
    BiTNode* left;
    BiTNode* right;
    BiTNode() : data('\0'), left(nullptr), right(nullptr) {}
    BiTNode(char x) : data(x), left(nullptr), right(nullptr) {}
    BiTNode(char x, BiTNode *left, BiTNode *right) : data(x), left(left), right(right) {}
};


template <typename T>
void createBiTNode(BiTNode<T>** treeNode, deque<T>dataDeq) {//层序遍历建立二叉树
    //特殊处理根结点
    T data;
    data = dataDeq.front();
    dataDeq.pop_front();
    BiTNode<T> * node = new BiTNode<T>();
    *treeNode = node;
    (*treeNode)->data = data;

    deque<BiTNode<T>**> nodeDeq;//用于层序建立树时访问双亲节点
    nodeDeq.push_back(treeNode);

    int index = 2;//用于判定左右孩子(左偶,右奇)
    while (!dataDeq.empty()){//当数据节点非空时,进行建树

        BiTNode<T>** nodeParent = nodeDeq.front();
       nodeDeq.pop_front();

       for(int i = 0; i < 2;i++){
           data = dataDeq.front();
           dataDeq.pop_front();
           if(data == '#'){//适用于char
           //if(data == -1){//适用于int
               if(index%2 == 0) (*nodeParent)->left = nullptr;
               else (*nodeParent)->right = nullptr;
           }else{
               BiTNode<T> * node = new BiTNode<T>();
               node->data = data;
               if(index%2 == 0){
                   (*nodeParent)->left = node;
                   nodeDeq.push_back(&(*nodeParent)->left);
               }else{
                   (*nodeParent)->right = node;
                   nodeDeq.push_back(&(*nodeParent)->right);
               }
           }
           index++;
       }
    }
}


template <>
void createBiTNode<char>(BiTNode<char>** treeNode, deque<char>dataDeq) {//层序遍历建立二叉树
    //特殊处理根结点
    char data;
    data = dataDeq.front();
    dataDeq.pop_front();
    BiTNode<char> * node = new BiTNode<char>();
    *treeNode = node;
    (*treeNode)->data = data;

    deque<BiTNode<char>**> nodeDeq;//用于层序建立树时访问双亲节点
    nodeDeq.push_back(treeNode);

    int index = 2;//用于判定左右孩子(左偶,右奇)
    while (!dataDeq.empty()){//当数据节点非空时,进行建树

        BiTNode<char>** nodeParent = nodeDeq.front();
        nodeDeq.pop_front();

        for(int i = 0; i < 2;i++){
            data = dataDeq.front();
            dataDeq.pop_front();
            if(data == '#'){
                if(index%2 == 0) (*nodeParent)->left = nullptr;
                else (*nodeParent)->right = nullptr;
            }else{
                BiTNode<char> * node = new BiTNode<char>();
                node->data = data;
                if(index%2 == 0){
                    (*nodeParent)->left = node;
                    nodeDeq.push_back(&(*nodeParent)->left);
                }else{
                    (*nodeParent)->right = node;
                    nodeDeq.push_back(&(*nodeParent)->right);
                }
            }
            index++;
        }
    }
}

template <>
void createBiTNode<int>(BiTNode<int>** treeNode, deque<int>dataDeq) {//层序遍历建立二叉树
    //特殊处理根结点
    char data;
    data = dataDeq.front();
    dataDeq.pop_front();
    BiTNode<int> * node = new BiTNode<int>();
    *treeNode = node;
    (*treeNode)->data = data;

    deque<BiTNode<int>**> nodeDeq;//用于层序建立树时访问双亲节点
    nodeDeq.push_back(treeNode);

    int index = 2;//用于判定左右孩子(左偶,右奇)
    while (!dataDeq.empty()){//当数据节点非空时,进行建树

        BiTNode<int>** nodeParent = nodeDeq.front();
        nodeDeq.pop_front();

        for(int i = 0; i < 2;i++){
            data = dataDeq.front();
            dataDeq.pop_front();
            if(data == -1){
                if(index%2 == 0) (*nodeParent)->left = nullptr;
                else (*nodeParent)->right = nullptr;
            }else{
                BiTNode<int> * node = new BiTNode<int>();
                node->data = data;
                if(index%2 == 0){
                    (*nodeParent)->left = node;
                    nodeDeq.push_back(&(*nodeParent)->left);
                }else{
                    (*nodeParent)->right = node;
                    nodeDeq.push_back(&(*nodeParent)->right);
                }
            }
            index++;
        }
    }
}

template <typename T>
void inOrder(BiTNode<T>* treeNode){
    if(treeNode){
        inOrder(treeNode->left);
        cout<<treeNode->data<<" ";
        inOrder(treeNode->right);
    }
}

template <typename T>
void preOrder(BiTNode<T>* treeNode){
    if(treeNode){
        cout<<treeNode->data<<" ";
        preOrder(treeNode->left);
        preOrder(treeNode->right);
    }
}

template <typename T>
void postOrder(BiTNode<T>* treeNode){
    if(treeNode){
        postOrder(treeNode->left);
        postOrder(treeNode->right);
        cout<<treeNode->data<<" ";
    }
}

template <typename T>
void preOrder2(BiTNode<T>* treeNode){
    stack<BiTNode<T>*> s;
    BiTNode<T>* p = treeNode;
    while(p || !s.empty()){
        if(p){
            cout<<p->data<<" ";
            s.push(p);
            p = p->left;
        }else{
            p = s.top();
            s.pop();
            p = p->right;
        }
    }
}

template <typename T>
void inOrder2(BiTNode<T>* treeNode){
    stack<BiTNode<T>*> s;
    BiTNode<T>* p = treeNode;
    while(p || !s.empty()){
        if(p){
            s.push(p);
            p = p->left;
        }else{
            p = s.top();
            cout<<p->data<<" ";
            s.pop();
            p = p->right;
        }
    }
}

template <typename T>
void postOrder2(BiTNode<T>* treeNode){
    stack<BiTNode<T>*> s;
    BiTNode<T> *p = treeNode, *r = nullptr;
    while(p || !s.empty()){
        if(p){
            s.push(p);
            p = p->left;
        }else{
            p = s.top();
            if(p->right && p->right != r){//有右孩子且没有访问过
                p = p->right;
            }else{
                cout<<p->data<<" ";
                s.pop();
                r = p;
                p = nullptr;
            }
        }
    }
}

template <typename T>
void levelOrder(BiTNode<T>* treeNode) {
    queue<BiTNode<T>*> nodeQue;
    BiTNode<T>* p = treeNode;
    nodeQue.push(p);
    while(!nodeQue.empty()){
        p = nodeQue.front();
        nodeQue.pop();
        cout<<p->data<<" ";
        if(p->left) nodeQue.push(p->left);
        if(p->right) nodeQue.push(p->right);
    }
}

int leafNum = 0;

template <typename T>
void calLevelLeaf(BiTNode<T>* root, int level, int k){
    if(level < k){
        if(root->left != nullptr) calLevelLeaf(root->left, level+1, k);
        if(root->right != nullptr) calLevelLeaf(root->right, level+1, k);
    }else if(level == k && root->left == nullptr && root->right == nullptr){
        leafNum++;
    }
} 

template <typename T>
int getLevelLeaf(BiTNode<T>* root, int k){
    calLevelLeaf(root, 1,  k);
    return leafNum;
}

template <typename T>
int getLevelLeaf2(BiTNode<T>* root, int k){
    deque<BiTNode<T>*> q;//双端队列
    BiTNode<T> *newNode = nullptr, *lastNode = root;  
    int level = 1;//层数
    int leafNum = 0;//该层的叶子结点个数
    q.push_back(root);
    while(!q.empty()){
        BiTNode<T>* p;
        if(level == k){
            while(!q.empty()){
                p = q.front();
                q.pop_front();
                if(p->left == nullptr && p->right == nullptr){
                    leafNum++;
                }
            }
            break;
        }
        else{
            p = q.front();
            q.pop_front();
            if(p->left != nullptr){
                q.push_back(p->left);
                newNode = p->left;
            }
            if(p->right != nullptr){
                q.push_back(p->right);
                newNode = p->right;
            }
            if(lastNode == p){
                lastNode = newNode;
                level += 1;
            }
        }
    }
    return leafNum;
}

int main() {
    //使用字符串
    //deque<char> treeVec{'a', 'b', 'c', 'd', 'e', '#', '#'};
    //deque<char> treeVec{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '#', '#','i','#','#','k','l'};
    deque<char> treeVec{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '#', 'i', 'j','#','#','k','l','m','n','#','#','o','#','#','p','#','#'};
    BiTNode<char>* tree = new BiTNode<char>();
    createBiTNode(&tree, treeVec);
    //使用数值
//    deque<int> treeVec{1, 2, 3, 4, 5, -1, -1};
//    BiTNode<int>* tree = new BiTNode<int>();
//    createBiTNode(&tree, treeVec);
    //遍历树
    //inOrder(tree);
    //cout<<endl;
    
    printf("%d", getLevelLeaf2(tree, 5));//tree,4
    

	return 0;    
}


http://www.kler.cn/a/155980.html

相关文章:

  • 某app最新版 vmp算法分析一
  • 车-路-站-网”信息耦合的汽车有序充电
  • (干货)Jenkins使用kubernetes插件连接k8s的认证方式
  • 2024年11月13日
  • 【QT】QSS
  • matlab建模入门指导
  • 【Qt开发流程】之自定义语法高亮和使用HTML语法
  • Proteus仿真--基于ADC0832设计的两路电压表
  • Mongodb安装及其使用
  • Linux 基本语句_14_信号灯实验
  • Hdoop学习笔记(HDP)-Part.06 安装OracleJDK
  • 【Java基础系列】BigDecimal入门
  • GB/T 37380-2019抗污易洁涂膜玻璃检测
  • Paxos 算法
  • 算法通关村第十六关-白银挑战滑动窗口经典题目
  • 第十七章 其他-rpc、rabbitmq(如何对消息做持久化、如何控制消息被消费的顺序)、celery(应用场景、运行机制、如何实现定时任务)
  • postgres在docker中使用
  • LeetCode刷题---反转链表
  • SCAU:链表创建与插入结点(填空)
  • word表格图片批处理参考程序
  • Linux-usb触摸板去除鼠标箭头
  • Ubuntu20.24 安装ecCodes,包括 tar.gz 和 python(笔记)
  • [网络安全]dos命令
  • Sakila数据库和World数据库
  • Vue+ElementUI+C#前后端分离:监控长耗时任务的实践
  • [足式机器人]Part4 南科大高等机器人控制课 Ch00 课程简介