二叉树的基本功能实现
一.二叉树的结构及实现
1.二叉树的结构
在之前的章节中已经介绍过,二叉树是一种特殊的树,其最大度为2,及最多有左,右两个孩子,结构图如下
在此之前已经讨论过一些特殊的二叉树,这里讨论一般的二叉树
2.二叉树的实现
由以上结构我们用这样的代码来表示二叉树
typedef int BTDataType;
typedef struct BinaryTreeNode
{BTDataType data;//节点数据struct BinaryTreeNode* left;//左孩子struct BinaryTreeNode* right;//右孩子
}BTNode;
由于搜索二叉树红黑树等涉及到C++中STL模板的知识,这里直接手搓出一颗二叉树
//创建一个二叉树节点
BTNode* BuyNode(int x){BTNode* node = (BTNode*)malloc(sizeof(BTNode));if (node == NULL){perror("malloc fail");return NULL;}node->data = x;node->left = NULL;node->right = NULL;return node;
}BTNode* CreatBinaryTree()
{
//创建一系列二叉树节点BTNode* node1 = BuyNode(1);BTNode* node2 = BuyNode(2);BTNode* node3 = BuyNode(3);BTNode* node4 = BuyNode(4);BTNode* node5 = BuyNode(5);BTNode* node6 = BuyNode(6);BTNode* node7 = BuyNode(6);//通过节点内部指针手动调整为树的结构node1->left = node2;node1->right = node4;node2->left = node3;node4->left = node5;node4->right = node6;node5->right = node7;return node1;
}
根据以上创建二叉树的步骤,其结构如下:
之后定义的操作将基于此结构进行
二.二叉树的基本操作
1.前中后序遍历
前中后序遍历均为二叉树深度遍历的方法,其区别在于遍历根的时机不同。如前序遍历的顺序为根,左子树,右子树,以此类推
前序遍历
void PrevOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}printf("%d ", root->data);PrevOrder(root->left);PrevOrder(root->right);
}
若考虑将空节点的值打印为N,上图的二叉树进行前序遍历的结果为:1 2 3 N N 4 5 N 6 6
这里的前序遍历利用了二叉树的递归定义,以及函数栈帧的创建与销毁。
这里仅展示部分函数栈帧的创建与销毁。需要注意的是,若第n层栈帧return时,并非直接return到main函数,而是返回到第n-1层调用该栈帧的栈帧。等PrevOrder函数所有栈帧均返回值后将函数的返回值返回main函数。
中序遍历
原理与前序遍历类似,不过需要修改根的遍历时机。
void InOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}InOrder(root->left);printf("%d ", root->data);InOrder(root->right);
}
后序遍历
void RearOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}RearOrder(root->left);RearOrder(root->right);printf("%d ", root->data);}
2.求树的节点总数
在这里我们使用分治的思想(本质上还是递归)处理这个问题
int TreeSize(BTNode* root)
{return root == NULL ? 0 :TreeSize(root->left) + TreeSize(root->right) + 1;
}
当节点为空时返回0,将左子树与右子树的总结点相加再+1(根节点)即为树的节点总数
3.求叶子节点总数
int TreeLeafSize(BTNode* root)
{if (root == NULL)return 0;if (root->left == NULL && root->right == NULL)return 1;return TreeLeafSize(root->left)+ TreeLeafSize(root->right);
}
当是空树,返回0;当一个节点没有左右孩子时,即为叶子节点。依旧采用分治的思想,将左右子树的叶子节点加起来即为总叶子节点数
4.求树的高度
int TreeHeight(BTNode* root)
{if (root == NULL)return 0;int leftHeight = TreeHeight(root->left);int rightHeight = TreeHeight(root->right);return leftHeight > rightHeight ?leftHeight + 1 : rightHeight + 1;
}
依旧采用分治思想,一棵树的高度为左右子树中较高的那颗再+1
注意每层计算的高度最好将其返回存储(即这里的leftHeight和rightHeight),否则会存在时间效率问题