考研数据结构--树的遍历,逆置,是否是完全二叉树,找第k个节点,子节点 以及各类代码题(一)

1. 树的基本结构

1.1、树的基本概念

  1. 树的定义 树是n(n>=0)个结点的有限集。当n = 0时,称为空树。在任意一棵非空树中应满足:
  • 有且仅有一个特定的称为根的结点。
  • 当n>1时,其余节点可分为m(m>0)个互不相交的有限集T1,T2,...,Tm,其中每个集合本身又是一棵树,并且称为根的子树。
  1. 树的定义是递归的,即在树的定义中又用到了自身,树是一种递归的数据结构。树作为一种逻辑结构,同时也是一种分层结构,具有以下两个特点:
  • 树的根结点没有前驱,除根结点外的所有结点有且只有一个前驱。
  • 树中所有结点可以有零个或多个后继,因此n个结点的树中有n-1条边。

1.2 树的结构体

c++ 复制代码
typedef struct BiTNode {
    char data;
    struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;

这个结构体它定义了一个叫做BiTNode的结构体,以及一个指向该结构体的指针类型BiTree

具体来说,BiTNode结构体包含以下三个成员:

  1. data:一个字符类型的数据成员。
  2. lchild:一个指向BiTNode类型的左子树的指针。
  3. rchild:一个指向BiTNode类型的右子树的指针。

lchildrchild分别表示指向左子树和右子树的指针,而data则存储每个节点的数据。通过这种方式,可以构建出一个具有左右子树结构的二叉树。

此外,该定义还使用了typedef关键字来为结构体BiTNode定义了一个别名BiTree,表示指向该结构体的指针类型。这样,我们就可以使用BiTree来声明指向BiTNode结构体的指针变量。

2. 树的创建和前序遍历

  1. 现在要创建一棵如下的树ABD##E##C##,#表示空节点。
bash 复制代码
            A
         B    C
       D  E  # #
     # # # #
  1. 递归创建树
c++ 复制代码
void createtree(BiTree& t) {  // 先序构造二叉树。
    char ch;
    // ABD##E##C##
    ch = getchar();  // 输入字符。
    if (ch == '#')
        t = NULL;
    else {
        t = (BiTNode*)malloc(sizeof(BiTNode));
        t->data = ch;
        t->lchild = NULL;
        t->rchild = NULL;
        createtree(t->lchild);
        createtree(t->rchild);
    }
};
  1. 前序遍历打印树的节点
c++ 复制代码
void PreOrder(BiTree T) {
    if (T != NULL) {
        cout << ' ' << T->data;
        PreOrder(T->lchild);  // 递归遍历左子树
        PreOrder(T->rchild);  // 递归遍历右子树
    }
};

3. 递归遍历二叉树

前中后序遍历二叉树的完整可执行代码

c++ 复制代码
#include <bits/stdc++.h>
using namespace std;
typedef struct BiTNode {
    char data;
    struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
// 递归边界,递归式
/*
BiTNode *p 和BiTree
p,在代码的角度上来讲是等价的,都是定义一个指针变量p,来指向二叉树的节点 BiTree
p:侧重于表示p指向的节点为根的一棵树 BiTNode *p 侧重表示一个树的节点
*/
//  PreOrder 先序遍历 根左右
//  InOder 中序低估遍历名称
//  PostOrder 后序递归遍历
/**
            A
         B    C
       D  E  # #
     # # # #
 */
void createtree(BiTree& t) {  // 先序构造二叉树。
    char ch;
    // ABD##E##C##
    ch = getchar();  // 输入字符。
    if (ch == '#')
        t = NULL;
    else {
     // t = new Node;  // 创建一个新的 Node 对象,并将其地址赋值给根节点。
     //也可以这样写 t = (BiTNode*)malloc(sizeof(BiTNode));
  
        t = (BiTNode*)malloc(sizeof(BiTNode));
        t->data = ch;
        t->lchild = NULL;
        t->rchild = NULL;
        createtree(t->lchild);
        createtree(t->rchild);
    }
};
// 递归-前序遍历二叉树
void PreOrder(BiTree T) {
    if (T != NULL) {
        cout << " " << T->data;
        PreOrder(T->lchild);  // 递归遍历左子树
        PreOrder(T->rchild);  // 递归遍历右子树
    }
};
// 递归-中序遍历二叉树
void InOder(BiTree T) {
    if (T != NULL) {
        InOder(T->lchild);  // 递归遍历左子树
        cout << " " << T->data;
        InOder(T->rchild);  // 递归遍历右子树
    }
};
// 递归-后序遍历二叉树
void PostOrder(BiTree T) {
    if (T != NULL) {
        PostOrder(T->lchild);  // 递归遍历左子树
        cout << " " << T->data;
        PostOrder(T->rchild);  // 递归遍历右子树
    }
};
int main() {
    BiTree t;
    // 输入创建ABD##E##C##
    createtree(t);

    cout << "递归-前序遍历二叉树:";
    PreOrder(t);
    cout << endl;

    cout << "递归-中序遍历二叉树:";
    InOder(t);
    cout << endl;

    cout << "递归-后序遍历二叉树:";
    PostOrder(t);
    cout << endl;
    return 0;
}

4. 非递归遍历二叉树

树结构,代码结合图理解,非常重要!!!

tips:栈的基本使用

用栈来保存数据

在C++中,你可以使用STL库中的stack类来创建一个堆栈。除了stack.size()之外,stack类还提供了以下几种常见的操作:

  1. stack.empty():检查堆栈是否为空。如果堆栈为空,则返回true;否则返回false。
  2. stack.top():返回堆栈顶部的元素,但不将其从堆栈中移除。
  3. stack.push(x):将元素x推入堆栈的顶部。
  4. stack.pop():移除并返回堆栈顶部的元素。
  5. stack.data():返回一个表示堆栈的容器。这个容器是一个后进先出(LIFO)的容器。

stack.size() != 0,栈不为空,结果就是 true;stack.size() == 0如果堆栈为空,那么结果就为 false。

4.1 前序遍历

c++ 复制代码
// 非递归-前序遍历
/*
思想:用栈来实现。首先访问根节点,然后将根节点入栈,接着访问当前节点的左节点,然后入栈,当左节点访问完后,
出栈,并依次访问右节点
*/
void un_preTraversal(Node* root) {
    stack<Node*>
        stack;  // 名为 stack 的堆栈(stack),名为 stack 的堆栈(stack)
    // 当前节点
    Node* p = root;
    // 因此,stack.size() != 0
    // 的含义是检查堆栈中是否有元素,也就是检查堆栈是否为空。如果堆栈不为空,那么
    // stack.size() != 0 的结果就为 true;如果堆栈为空,那么结果就为 false。
    while (p != NULL || stack.size() != 0) {
        if (p != NULL) {
            visit(p);       // 访问p之前一定要保证p不为空
            stack.push(p);  // 入栈
            p = p->lchild;
        } else {
            p = stack.top();
            stack.pop();
            p = p->rchild;
        }
    }
}

4.2 中序遍历

c++ 复制代码
// 非递归-中序遍历
/*
思想:用栈来实现。从根节点开始依次遍历当前节点的左节点,并依次入栈,当左节点遍历完成后,获取
栈顶元素并出栈,然后访问该节点,并依次遍历其右节点
*/
void un_midTraversal(Node* root) {
    stack<Node*> stack;
    Node* p = root;
    while (p != NULL || stack.size() != 0) {
        if (p != NULL) {
            stack.push(p);
            p = p->lchild;
        } else {
            p = stack.top();
            stack.pop();
            visit(p);
            p = p->rchild;
        }
    }
}

4.3. 后序遍历

c++ 复制代码
#include <bits\stdc++.h>
typedef struct treenode {
    char data;
    struct treenode *lchild, *rchild;
    int tag;
} treenode, *tree;
void createtree(tree& t) {  // 先序构造二叉树。
    char ch;
  //  ABD##E##C##
    ch = getchar();  // 输入字符。
    if (ch == '#')
        t = NULL;
    else {
        t = (treenode*)malloc(sizeof(treenode));
        t->data = ch;
        t->tag = 0;
        t->lchild = NULL;
        t->rchild = NULL;
        createtree(t->lchild);
        createtree(t->rchild);
    }
}

void back(tree t) {
    struct treenode* stack[100];  // 直接利用结构体建立一个栈。
    int top = -1;
    treenode* p = t;        // 建立指针指向这棵树。
    treenode* x;            // 保存出栈的结点。
    while (p || top != -1)  // p和栈不能为空。
    {
        if (p)  // p不为空时进栈。
        {
            top++;
            stack[top] = p;
            p = p->lchild;
        } else  // 为空的时候。
        {
            p = stack[top];                        // 访问栈顶。
            if (p->rchild && p->rchild->tag == 0)  // 判断右孩子。
            {                   // 没有被访问,指向它的右孩子。
                p = p->rchild;  // p有值要进行栈
            } else              // 已经访问过了。
            {
                p = stack[top];
                top--;
                printf("%2c", p->data);
                p->tag = 1;
                p = NULL;//这里p为空之后,访问栈顶
            }
        }
    }
}
int main() {
    tree t;
    createtree(t);
    back(t);
    return 0;
}

5. 树的层次遍历

5.1 从上至下,从左至右

tips:队列的基本使用

首先需要理解队列的使用:

  1. 在C++中,queue<Node*> q;是一个声明一个名为q的队列(queue)的语句,其中Node*是存储在队列中的元素的类型。在这种情况下,队列将存储指向Node对象的指针。
  2. 在C++的STL库中,queue容器提供了以下几种操作:
  • push(x):将元素x插入队列的尾部。
  • pop():删除队列头部的元素。
  • front():返回指向队列头部的元素。
  • back():返回指向队列尾部的元素。
  • size():返回队列中元素的个数。
  • empty():判断队列是否为空。

q.empty() == false,队列不为空

c++ 复制代码
// 树的层次遍历
// 思想:使用队列queue。先将根节点入队列,循环判断当前队列不为空时,将头元素出队列并访问头元素,然后在将它的左节点和右节点入队列
void levelTraversal(Node* root) {
    queue<Node*> q;
    Node* p = root;
    q.push(p);  // 将元素p插入队列的尾部
    // 判断条件,false队列不为空
    while (q.empty() == false) {
        p = q.front();  // 返回指向队列头部的元素
        q.pop();        // 删除队列头部的元素
        visit(p);
        if (p->lchild != NULL)
            q.push(p->lchild);//左子树继续入队
        if (p->rchild != NULL)
            q.push(p->rchild);//右子树入队
    }
}

5.2 逆置层次遍历,从下至上,从左至右

思路:将正常层次遍历的结果,存入栈中,再取出来。

c++ 复制代码
// 层次遍历
void leveltraversal(tree* root) {
    stack<tree*> stack;
    queue<tree*> q;
    tree* p = root;
    q.push(p);
    while (q.empty() == false) {
        p = q.front();
        q.pop();
        cout << p->data;
        stack.push(p);
        if (p->lchild != NULL) {
            q.push(p->lchild);
        };
        if (p->rchild != NULL) {
            q.push(p->rchild);
        };
    }
    cout << endl;
    cout << "层次遍历,逆序:";

    // 不等于0说明栈不为空
    while (stack.size() != 0) {
        tree* p = stack.top();
        stack.pop();
        cout << p->data;
    }
}

6. 找二叉树的公共祖先节点

找i,j的公共祖先节点

顺序存储,将二叉树转换,空的地方,赋值为-1

  1. i,j节点均存在,treep[i]!=-1,tree[j]!=-1
  2. 如果不存在更新ij的值,如果i>j,寻找i的父节点(i/2),更新i。如果i<j,寻找j的父节点(j/2),更新j;
  3. i=j时,返回i的值。
c++ 复制代码
#include <bits/stdc++.h>
// 找i,j的公共祖先节点
struct tree {
    // 不存在的数值为-1
    int data[12] = {-1, 1, 2, 3, -1, 4, -1, 5, -1, -1, -6, -1};
};
/*
i节点的父亲节点为2i,
左孩子是2i
右孩子是2i+1
*/
int comon(tree t, int i, int j) {
    if (t.data[i] != -1 && t.data[j] != -1)  // 说明存在值
    {
        while (i != j)  // 更新i和j的值。
        {
            if (i > j)
                i /= 2;  // 寻找大的父节点。更新i的值
            else
                j /= 2;
        }
        return t.data[i];  // 相同时返回公共祖先。
    }
    return -1;
};
int main() {
    tree t;
    int a = comon(t, 7, 10);  // 找7号和10号节点的公共祖先。
    printf("%d", a);
    return 0;
}

7. 判断是否为完全二叉树

不满足下面任何一条就不是完全二叉树

  1. 节点无左孩子,必无右孩子。
  2. 节点缺孩子,所有后继必无孩子。

第一个if判断情况

否则的情况

树结构

写法一:

c++ 复制代码
// 判断是否是完全二叉树
#include <bits/stdc++.h>
using namespace std;
#define Max 15
typedef struct treenode {
    char data;
    struct treenode *lchild, *rchild;
} treenode, *tree;
void buildtree(tree& t) {
    char ch;
    ch = getchar();
    if (ch == '#')
        t = NULL;
    else {
        t = (treenode*)malloc(sizeof(treenode));
        t->data = ch;
        t->lchild = NULL;
        t->rchild = NULL;
        buildtree(t->lchild);
        buildtree(t->rchild);
    }
}
struct squeue {
    struct treenode* data[Max];
    int f, r, tag;
};
bool isempty(squeue s) {
    if (s.f == s.r && s.tag == 0)
        return true;
    return false;
}
bool isfull(squeue s) {
    if (s.f == s.r && s.tag == 1)
        return true;
    return false;
}
bool enters(squeue& s, treenode* p) {
    if (isfull(s))
        return false;
    s.data[s.r] = p;
    s.r = (s.r + 1) % Max;
    s.tag = 1;
    return true;
}
bool outs(squeue& s, treenode*& p) {
    if (s.f == s.r && s.tag == 0)
        return false;
    p = s.data[s.f];
    s.f = (s.f + 1) % Max;
    s.tag = 0;
    return true;
}
bool isok(tree t) {
    squeue s;
    s.f = s.r = s.tag = 0;
    // flag 为true标志都有左右孩子,ans结果标志
    bool flag = true, ans = true;
    if (t == NULL)  // 判断是否为空树,空树也是完全二叉树。
        ans = true;
    if (!t->lchild && !t->rchild)  // 存在节点,左右孩子为空,也是完全二叉树
        ans = true;
    enters(s, t);  // 根节点入队
    treenode* p;
    while (!isempty(s)) {  // 遍历队
        outs(s, p);        // 先出队
        if (!p->lchild) {  // 出队元素,没有左孩子
            flag = false;
            if (p->rchild)  // 在缺孩子的情况下,还有右孩子,那么结果直接为false,不是完全二叉树。
                ans = false;
        } else  // 有左孩子
        {
            if (flag)  // 之前不存在缺孩子的节点
            {
                enters(s, p->lchild);  // 左孩子进队
                if (p->rchild)         // 右孩子存在继续进队
                    enters(s, p->rchild);
                else  // 没有右孩子的情况下,就是缺孩子将flag设置成false;
                    flag = false;
            } else  // 之前存在缺孩子的节点,的后继又有孩子,结果变量直接为false,不是完全二叉树
                ans = false;  //
        }
    }
    if (ans)
        return true;
    return false;
}
int main() {
    tree t;
    buildtree(t);
    if (isok(t))
        cout << "yes" << endl;
    else
        cout << "no" << endl;
    return 0;
}
// ABD##E##CF##G##  完全
// ABD###CE##F##  非完全

写法二(推荐)

c++ 复制代码
#include <bits/stdc++.h>
using namespace std;
// ABD##E##CF##G##  完全
// ABD###CE##F##  非完全
typedef struct tree {
    char data;
    struct tree *lchild, *rchild;
} tree;

void createTree(tree*& root) {
    char a;
    a = getchar();
    if (a == '#') {
        root = NULL;
    } else {
        root = new tree();
        root->data = a;
        root->lchild = NULL;
        root->rchild = NULL;
        createTree(root->lchild);
        createTree(root->rchild);
    }
}
void preOrder(tree* root) {
    if (root != NULL) {
        cout << root->data;
        preOrder(root->lchild);
        preOrder(root->rchild);
    }
}
bool isok(tree* root) {
    queue<tree*> q;
    tree* p;
    bool flag = true, ans = true;
    if (root == NULL) {
        ans = true;
    }
    if (!root->rchild && !root->rchild) {
        ans = true;
    }
    q.push(root);
    // 判断条件,false队列不为空
    while (q.empty() == false) {
        p = q.front();
        q.pop();
        if (!p->lchild) {     // 判断出队元素没有左孩子
            flag = false;     // 设置标记
            if (p->rchild) {  // 在没有左孩子的情况下,还没有右孩子,直接不是完全二叉树,设置false。
                ans = false;
            }
        } else {  // 有左孩子
            if (flag) {
                q.push(p->lchild);
                if (p->rchild) {
                    q.push(p->rchild);
                } else {
                    flag = false;
                }
            } else {
                ans = false;
            }
        }
    }
    if (ans)
        return true;
    return false;
}
int main() {
    tree* p;
    createTree(p);
    // ABD##E##CF##G##  完全
    // ABD###CE##F##  非完全
    // AB#D##CE##F##
    cout << "前序遍历二叉树:";
    preOrder(p);
    cout << endl;
    cout << "是否是完全二叉树:";

    if (isok(p))
        cout << "yes" << endl;
    else
        cout << "no" << endl;
    return 0;
}

8 .查找第k个节点的值

假设二叉树采用二叉链存储结构存储,设计一个算法,求先序遍历序列中第k(1 <k<二叉树中结点个数)个结点的值。

c++ 复制代码
#include <bits/stdc++.h>
using namespace std;
typedef struct tree {
    char data;
    struct tree *lchild, *rchild;
} tree;
/*
  假设二叉树采用二叉链存储结构存储,设计一个算法,求先序遍历序列中第k(1
  <k<二叉树中结点个数)个结点的值
ABD##E##C##

//                    A1
//                B2      C
//              D3   E4   F  #
//            #  # # # # #
 */
// 创建树
void createTre(tree*& root) {
    char a;
    cin >> a;
    if (a == '#') {
        root = NULL;
    } else {
        root = new tree();
        root->data = a;
        root->lchild = NULL;
        root->rchild = NULL;
        createTre(root->lchild);
        createTre(root->rchild);
    }
};

void preorder(tree* root, int k, char& temp, int& index) {
    // cout << index;
    if (root != NULL) {
        index++;
        if (index == k) {
            temp = root->data;
        };
        cout << root->data << " ";
        preorder(root->lchild, k, temp, index);
        preorder(root->rchild, k, temp, index);
    }
};

int main() {
    tree* root;
    createTre(root);
    char temp;
    int index = 0;
    cout << "递归前序遍历二叉树:";
    preorder(root, 5, temp, index);
    cout << endl;

    cout << "第4个节点的值:" << temp << endl;
    return 0;
}

9. 指针指向树的某个节点

在一棵以二叉链表为存储结构的二叉树中,查找数据域值等于 key 的结 点是否存在,如果存在,则将指针 q 指向该结点,假设结点数据域为 int 型

c++ 复制代码
#include <bits/stdc++.h>
using namespace std;
typedef struct tree {
    char data;
    struct tree *lchild, *rchild;
} tree;
/*
  在一棵以二叉链表为存储结构的二叉树中,查找数据域值等于 key 的结
点是否存在,如果存在,则将指针 q 指向该结点,假设结点数据域为 int 型。(二
叉树中结点值都不相同)
ABD##E##C##

//                    A1
//                B2      C
//              D3   E4   F  #
//            #  # # # # #
 */
// 创建树
void createTre(tree*& root) {
    char a;
    cin >> a;
    if (a == '#') {
        root = NULL;
    } else {
        root = new tree();
        root->data = a;
        root->lchild = NULL;
        root->rchild = NULL;
        createTre(root->lchild);
        createTre(root->rchild);
    }
};
void disp(tree* root) {
    if (root != NULL) {
        cout << root->data;
        disp(root->lchild);
        disp(root->rchild);
    }
}
// q为指向改节点为key的指针,key为节点的值
void search(tree* root, tree*& q, int key) {
    if (root != NULL) {
        if (root->data == key) {
            q = root;
        } else {
            search(root->lchild, q, key);
            search(root->rchild, q, key);
        }
    }
};

int main() {
    tree* root;
    createTre(root);
    tree* q;
    cout << "递归前序遍历二叉树:";
    disp(root);
    cout << endl;

    // cout << "查找值为E的节点的值:";
    search(root, q, 'E');
    cout << "q个节点的值:" << q->data << endl;
    return 0;
}

10. 利用递归计算二叉树中所有结点的个数。

法一:定义全局变量 n 用来计数。

c++ 复制代码
#include <bits/stdc++.h>
using namespace std;
typedef struct tree {
    char data;
    struct tree *lchild, *rchild;
} tree;
/*
  在一棵以二叉链表为存储结构的二叉树中,查找数据域值等于 key 的结
点是否存在,如果存在,则将指针 q 指向该结点,假设结点数据域为 int 型。(二
叉树中结点值都不相同)
ABD##E##C##

//                    A1
//                B2      C
//              D3   E4   F  #
//            #  # # # # #
 */
// 创建树
void createTre(tree*& root) {
    char a;
    cin >> a;
    if (a == '#') {
        root = NULL;
    } else {
        root = new tree();
        root->data = a;
        root->lchild = NULL;
        root->rchild = NULL;
        createTre(root->lchild);
        createTre(root->rchild);
    }
};
int n = 0;
void disp(tree* root) {
    if (root != NULL) {
        n++;
        cout << root->data;
        disp(root->lchild);
        disp(root->rchild);
    }
}

int main() {
    tree* root;
    createTre(root);
    tree* q;
    cout << "递归前序遍历二叉树:";
    disp(root);
    cout << endl;
    cout << "树节点的个数:" << n << endl;
    return 0;
}

法二:定义 n1 和 n2 分别用于接收左右子树结点个数。

C++ 复制代码
#include <bits/stdc++.h>
using namespace std;
typedef struct tree {
    char data;
    struct tree *lchild, *rchild;
} tree;
/*
  在一棵以二叉链表为存储结构的二叉树中,查找数据域值等于 key 的结
点是否存在,如果存在,则将指针 q 指向该结点,假设结点数据域为 int 型。(二
叉树中结点值都不相同)
ABD##E##C##

//                    A1
//                B2      C
//              D3   E4   F  #
//            #  # # # # #
 */
// 创建树
void createTre(tree*& root) {
    char a;
    cin >> a;
    if (a == '#') {
        root = NULL;
    } else {
        root = new tree();
        root->data = a;
        root->lchild = NULL;
        root->rchild = NULL;
        createTre(root->lchild);
        createTre(root->rchild);
    }
};
int n = 0;
void disp(tree* root) {
    if (root != NULL) {
        n++;
        cout << root->data;
        disp(root->lchild);
        disp(root->rchild);
    }
}
int count(tree* root) {
    int n1, n2;
    if (root == NULL) {  // 节点为空的时候,返回0
        return 0;
    } else {
        n1 = count(root->lchild);
        n2 = count(root->rchild);
        return n1 + n2 + 1;  // 这里的+1是树本身的节点。重点注意
    }
}

int main() {
    tree* root;
    createTre(root);
    tree* q;
    cout << "递归前序遍历二叉树:";
    disp(root);
    cout << endl;
    cout << "树节点的个数:" << count(root) << endl;

    return 0;
}

11. 计算二叉树所有子节点个数

1.递归

c++ 复制代码
#include <bits/stdc++.h>
using namespace std;
typedef struct tree {
    char data;
    struct tree *lchild, *rchild;
} tree;
/*
利用递归计算二叉树中所有叶子结点的个数。

ABD##E##C##

//                    A1
//                B2      C
//              D3   E4   F  #
//            #  # # # # #
 */
// 创建树
void createTre(tree*& root) {
    char a;
    cin >> a;
    if (a == '#') {
        root = NULL;
    } else {
        root = new tree();
        root->data = a;
        root->lchild = NULL;
        root->rchild = NULL;
        createTre(root->lchild);
        createTre(root->rchild);
    }
};
int n = 0;
void disp(tree* root) {
    if (root != NULL) {
        if (root->lchild == NULL && root->rchild==NULL) {
            n++;
        };
        cout << root->data;
        disp(root->lchild);
        disp(root->rchild);
    }
}

int main() {
    tree* root;
    createTre(root);
    tree* q;
    cout << "递归前序遍历二叉树:";
    disp(root);
    cout << endl;
    cout<<"子树个数:"<<n;

    return 0;
}

12 .找双分支节点

c++ 复制代码
#include <bits/stdc++.h>
using namespace std;
typedef struct tree {
    char data;
    struct tree *lchild, *rchild;
} tree;
/*
利用递归计算二叉树中所有双分支结点个数
双分支节点:既有左子树又有右子树(如下图的:A1,B2)

ABD##E##C##

//                    A1
//                B2      C
//              D3   E4   F  #
//            #  # # # # #
 */
// 创建树
void createTre(tree*& root) {
    char a;
    cin >> a;
    if (a == '#') {
        root = NULL;
    } else {
        root = new tree();
        root->data = a;
        root->lchild = NULL;
        root->rchild = NULL;
        createTre(root->lchild);
        createTre(root->rchild);
    }
};
int n = 0;
void disp(tree* root) {
    if (root != NULL) {
        if (root->lchild != NULL &&
            root->rchild != NULL) {  // 当节点左右孩子不为空时,节点个数++
            n++;
        };
        cout << root->data;
        disp(root->lchild);
        disp(root->rchild);
    }
}
int count3(tree* root) {
    int n1, n2;
    if (root == NULL) {  // 节点为空的时候,返回0
        return 0;
    } else if (root->lchild && root->rchild) {  // 双分支节点的情况
        n1 = count3(root->lchild);
        n2 = count3(root->rchild);
        return n1 + n2 + 1;  // 这里的+1是树本身的节点。重点注意
    } else {                 // 单分支和叶子节点的情况
        n1 = count3(root->lchild);
        n2 = count3(root->rchild);
        return n1 + n2;
    }
};
int main() {
    tree* root;
    createTre(root);
    tree* q;
    cout << "递归前序遍历二叉树:";
    disp(root);
    cout << endl;
    cout << "双分支节点个数:" << n;

    return 0;
}
相关推荐
爱吃生蚝的于勒1 小时前
C语言内存函数
c语言·开发语言·数据结构·c++·学习·算法
ChoSeitaku6 小时前
链表循环及差集相关算法题|判断循环双链表是否对称|两循环单链表合并成循环链表|使双向循环链表有序|单循环链表改双向循环链表|两链表的差集(C)
c语言·算法·链表
Fuxiao___6 小时前
不使用递归的决策树生成算法
算法
我爱工作&工作love我7 小时前
1435:【例题3】曲线 一本通 代替三分
c++·算法
白-胖-子7 小时前
【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-统计数字
开发语言·c++·算法·蓝桥杯·等考·13级
workflower7 小时前
数据结构练习题和答案
数据结构·算法·链表·线性回归
好睡凯7 小时前
c++写一个死锁并且自己解锁
开发语言·c++·算法
Sunyanhui17 小时前
力扣 二叉树的直径-543
算法·leetcode·职场和发展
一个不喜欢and不会代码的码农7 小时前
力扣105:从先序和中序序列构造二叉树
数据结构·算法·leetcode
前端郭德纲8 小时前
浏览器是加载ES6模块的?
javascript·算法