MENU

求二叉树深度【递归】&【非递归】

• November 12, 2020 •

编写算法求出二叉树的深度(层数)


二叉树的深度是指从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。本文将用两种方式求出二叉树的深度

第一种:无可置疑是递归

核心代码块:

/*求二叉树的深度 ,递归方式*/
int getDepth(BiTreeNode *root)
{
    int left, right;
    if (root == NULL)    //递归出口
        return 0;
    else
    {
        left = getDepth(root->leftChild);    //递归
        right = getDepth(root->rightChild);
        return left > right ? (left+1) : (right+1);   //返回较深的一棵子树
    }
}

源文件:《main.c》

#include"BiTree.h"
#include"Domin.h"
int main()
{
    /*测试二叉树*/
    BiTreeNode *root, *p;
    initiateBiTree(&root);
    p = leftInsert(root, 'A');
    p = leftInsert(p, 'B');
    leftInsert(p, 'D');
    rightInsert(p, 'E');
    p = rightInsert(root->leftChild, 'C');
    leftInsert(p, 'F');
    rightInsert(p, 'G');
    printf("二叉树前序遍历:");
    preOrder(root->leftChild);
    printf("\n");
    printf("二叉树中序遍历:");
    midOrder(root->leftChild);
    printf("\n");
    printf("该二叉树的深度为:");
    printf("%d \n", getDepth(root->leftChild));
    system("pause");
    return 0;
}

测试结果:

上方主函数中建立的二叉树,结果如下:


测试一:深度为3


对主函数稍作修改

建立下方形状的二叉树,有


测试二:深度为2


第二种:利用队列层序遍历

思想步骤:

1. 将根结点入队,当前队列中第一层的结点数(count)为1;

2. 进行当前层结点数(count)次出队,判断每个结点的左右子树是否为空,如果不为空,则入队,下一层结点数(nextCount)++;

3. 将下一层结点数变为当前层结点数,进行下一次循环,深度+1;

4. 直到队列为空时退出循环,得到最大深度;

核心代码块:

//求二叉树的深度,非递归方式
int getDepth(BiTreeNode *root)
{
    if (root == NULL)
        return 0;
    Queue queue, *p;
    p = &queue;
    initiateQueue(p);
    int depth = 0, count = 1,nextCount = 0;    //该层中结点的个数,下一层结点的个数
    queueAppend(p, root);                     //根结点入队
    BiTreeNode *temp = (BiTreeNode*)malloc(sizeof(BiTreeNode));
    while (isNotEmpty(p))   //队列不为空时一直循环
    {
        depth++;            //每进入一次循环,就代表开始进入下一层
        for (int i = 0; i < count; i++)
        {
            queuePop(p, temp);
            if (temp->leftChild!=NULL) {    //添加非空结点
                queueAppend(p, temp->leftChild);
                nextCount++;
            }
            if (temp->rightChild!=NULL) {
                queueAppend(p, temp->rightChild);
                nextCount++;
            }
        }
        count = nextCount;   //即将进行出队下一层结点,下一层结点数成为当前层结点数
        nextCount = 0;       //将下一层结点从0开始计数
    }
    return depth;
}

完整测试代码如下:

注:实例测试由4个文件构成:《BiTree.h》《Domin.h》《Queue.h》《main.c》,第二种方式核心代码块放在《Domin.h》头文件内

《BiTree.h》

#pragma once
/*二叉树基本操作头文件*/
#include<stdio.h>
#include<stdlib.h>
typedef char DataType;   //声明数据类型
struct  BiTreeNode
{
    DataType data;
    BiTreeNode *leftChild;
    BiTreeNode *rightChild;
};
//初始化二叉树
void  initiateBiTree(BiTreeNode **root)
{
    (*root) = (BiTreeNode*)malloc(sizeof(BiTreeNode));
    (*root)->leftChild = NULL;
    (*root)->rightChild = NULL;
}
//插入左孩子结点
BiTreeNode* leftInsert(BiTreeNode *curr, DataType data)
{
    if (curr == NULL)
        return NULL;
    BiTreeNode *node = (BiTreeNode*)malloc(sizeof(BiTreeNode));
    node->data = data;
    node->rightChild = NULL;
    node->leftChild = curr->leftChild;
    curr->leftChild = node;
    return node;
}
//插入右孩子结点
BiTreeNode* rightInsert(BiTreeNode *curr, DataType data)
{
    if (curr == NULL)
        return NULL;
    BiTreeNode *node = (BiTreeNode*)malloc(sizeof(BiTreeNode));
    node->data = data;
    node->leftChild = NULL;
    node->rightChild = curr->rightChild;
    curr->rightChild = node;
    return node;
}
//前序遍历二叉树
void preOrder(BiTreeNode *root)
{
    if (root != NULL)
    {
        printf("%c ", root->data);
        preOrder(root->leftChild);
        preOrder(root->rightChild);
    }
}
//中序遍历
void midOrder(BiTreeNode *root)
{
    if (root != NULL)
    {
        midOrder(root->leftChild);
        printf("%c ", root->data);
        midOrder(root->rightChild);
    }
}

《Queue.h》

#pragma once
/*队列基本操作头文件*/
#include"BiTree.h"
typedef BiTreeNode queueDataType;
struct QueueNode
{
    queueDataType data;
    QueueNode *next;
};
struct Queue
{
    QueueNode *head;
    QueueNode *rear;
};
void initiateQueue(Queue *queue)
{
    queue->head = NULL;
    queue->rear = NULL;
}
/*判断非空*/
bool isNotEmpty(Queue* queue)
{
    if (queue->head == NULL)
        return false;
    return true;
}
/*入队函数*/
void queueAppend(Queue *queue, queueDataType *data)
{
    QueueNode *node = (QueueNode*)malloc(sizeof(QueueNode));
    if (data != NULL)
    {
        node->data.data = data->data;
        node->data.leftChild = data->leftChild;
        node->data.rightChild = data->rightChild;
    }
    else {
        node->data.data = '0';       // 用0来标记要入队的结点是空的二叉树结点
        node->data.leftChild = NULL;
        node->data.rightChild = NULL;
    }
    node->next = NULL;
    if (queue->rear == NULL)
    {
        queue->head = node;
        queue->rear = node;
    }
    else
    {
        queue->rear->next = node;
        queue->rear = node;
    }
}
/*出队函数*/
void queuePop(Queue*queue, queueDataType *data)
{
    if (!isNotEmpty(queue))
        return;
    *data = queue->head->data;
    queue->head = queue->head->next;
    if (queue->head == NULL)
        queue->rear = NULL;
}
/*取队头元素*/
void  getHead(Queue *queue,queueDataType *head)
{
    if (!isNotEmpty(queue))
        head = NULL;
    else
        *head = (queue->head->data);
}

《main.c》

#include"BiTree.h"
#include"Domin.h"
int main()
{
    /*测试二叉树*/
    BiTreeNode *root, *p;
    initiateBiTree(&root);
    p = leftInsert(root, 'A');
    p = leftInsert(p, 'B');
    leftInsert(p, 'D');
    rightInsert(p, 'E');
    p = rightInsert(root->leftChild, 'C');
    leftInsert(p, 'F');
    p = rightInsert(p, 'G');
    rightInsert(p, 'H');
    printf("二叉树前序遍历:");
    preOrder(root->leftChild);
    printf("\n");
    printf("二叉树中序遍历:");
    midOrder(root->leftChild);
    printf("\n");
    printf("该二叉树的深度为:");
    printf("%d \n", getDepth(root->leftChild));
    system("pause");
    return 0;
}

测试结果:

测试一:深度为4


将主函数稍作改变:

测试结果如下:


测试二:深度为3



代码编译器:Visual Studio 2017
ok

Archives QR Code Tip
QR Code for this page
Tipping QR Code