个人学习所记笔记,如有错误请见谅
内容为二叉树的结点插入操作,先序中序后序层次遍历操作
代码所展示的为大体框架,可根据题目对相应代码部分进行修改
求树的高度以及宽度
求WPL
求高度
- 时间复杂度:
O(n)
,因为每个节点被访问一次。 - 空间复杂度:
O(h)
,其中h
是树的高度,这由递归栈深度决定。
求宽度
- 时间复杂度:
O(n)
,其中n
是树中的节点数。每个节点会被入队和出队一次。 - 空间复杂度:
O(w)
,其中w
是树的最大宽度。队列的空间使用与当前层的节点数量有关。
求WPL
- 时间复杂度: (O(n)),其中,(n) 是树中节点的总数。因为每个节点最多被访问一次,不管它是叶子节点还是内部节点。
- 空间复杂度: (O(h)),其中 (h) 是树的高度,最坏情况下为 (O(n))(对于完全不平衡的树)。
这些复杂度分析表明,CalculateWPL
方法在实际应用中对大多数树的处理是高效的,但在处理高度不平衡的树时,空间复杂度可能会较高。
代码如下
#include <iostream>
#include <queue>
using namespace std;
//二叉树的链式存储结构
typedef struct BiTNode {
int data;
struct BiTNode* lchild, * rchild;
}BiTNode,*BiTree;
// 初始化二叉树
void InitTree(BiTree& T) {
T = nullptr; // 初始化为空树
}
// 插入节点
void InsertNode(BiTree& T, int value) {
if (T == nullptr) {
// 如果树为空,创建根节点
T = new BiTNode;
T->data = value;
T->lchild = nullptr;
T->rchild = nullptr;
return;
}
// 使用层序遍历找到第一个没有两个孩子的节点
queue<BiTNode*> q;
q.push(T);
while (!q.empty()) {
BiTNode* node = q.front();
q.pop();
// 如果左孩子为空,插入到左孩子
if (node->lchild == nullptr) {
node->lchild = new BiTNode;
node->lchild->data = value;
node->lchild->lchild = nullptr;
node->lchild->rchild = nullptr;
return;
}
else {
q.push(node->lchild);//将现有左子节点加入队列
}
// 如果右孩子为空,插入到右孩子
if (node->rchild == nullptr) {
node->rchild = new BiTNode;
node->rchild->data = value;
node->rchild->lchild = nullptr;
node->rchild->rchild = nullptr;
return;
}
else {
q.push(node->rchild);
}
}
}
//先序遍历显示
void visit(BiTree root) {
cout << root->data << " ";
}
void PreOrder(BiTree root) {
if (root != nullptr) {
visit(root);
// cout << root->data << " ";
PreOrder(root->lchild);
PreOrder(root->rchild);
}
}
//中序遍历显示
void inorderTraversal(BiTree root) {
if (root != nullptr) {
inorderTraversal(root->lchild);
cout << root->data << " ";
inorderTraversal(root->rchild);
}
}
//后序遍历
void PostOrder(BiTree root) {
if (root != nullptr) {
PostOrder(root->lchild);
PostOrder(root->rchild);
cout << root->data << " ";
}
}
//层序遍历
// 层序遍历显示
void LevelOrder(BiTree root) {
if (root == nullptr) return;
queue<BiTNode*> q;
q.push(root);
while (!q.empty()) {
BiTNode* node = q.front();
q.pop();
cout << node->data << " ";
// 将左右孩子节点加入队列
if (node->lchild != nullptr) {
q.push(node->lchild);
}
if (node->rchild != nullptr) {
q.push(node->rchild);
}
}
}
// 计算树的高度
//这段代码适用于所有类型的二叉树,包括普通二叉树。
// 它通过递归计算每个子树的高度,并返回左右子树中较大的高度加上 1,代表当前节点的高度。
// 无论树是否完全二叉,这种方法都能正确地计算出树的高度。
int TreeHeight(BiTree root) {
if (root == nullptr) return 0;
int leftHeight = TreeHeight(root->lchild);
int rightHeight = TreeHeight(root->rchild);
return max(leftHeight, rightHeight) + 1;
}
// 计算树的宽度
int TreeWidth(BiTree root) {
if (root == nullptr) return 0;
int maxWidth = 0;
queue<BiTree> q;
q.push(root);
while (!q.empty()) {
int levelSize = q.size(); // 当前层的节点数
maxWidth = max(maxWidth, levelSize);
// 处理当前层的所有节点
for (int i = 0; i < levelSize; ++i) {
BiTree node = q.front();
q.pop();
if (node->lchild != nullptr) q.push(node->lchild);
if (node->rchild != nullptr) q.push(node->rchild);
}
}
return maxWidth;
}
// 计算树的 WPL
void CalculateWPL(BiTree root, int depth, int& wpl) {
if (root == nullptr) return;
// 如果是叶子节点
if (root->lchild == nullptr && root->rchild == nullptr) {
wpl += root->data * depth;
}
else {
// 递归计算左右子树
CalculateWPL(root->lchild, depth + 1, wpl);
CalculateWPL(root->rchild, depth + 1, wpl);
}
}
int main()
{
BiTree T;
InitTree(T);
InsertNode(T, 1);
InsertNode(T, 2);
InsertNode(T, 3);
InsertNode(T, 4);
InsertNode(T, 5);
InsertNode(T, 6);
InsertNode(T, 7);
cout << "先序: ";
PreOrder(T);
cout << endl;
cout << "中序: ";
inorderTraversal(T);
cout << endl;
cout << "后序: ";
PostOrder(T);
cout << endl;
cout << "层序: ";
LevelOrder(T);
cout << endl;
cout << "树的高度为:" << TreeHeight(T)<<endl;
cout << "树的宽度为:" << TreeWidth(T) << endl;
int wpl = 0;
CalculateWPL(T, 0, wpl);
cout << "树的 WPL 为: " << wpl << endl;
return 0;
}
运行结果如下