编写算法求出二叉树的深度(层数)
二叉树的深度是指从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。本文将用两种方式求出二叉树的深度
第一种:无可置疑是递归
核心代码块:
/*求二叉树的深度 ,递归方式*/
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