《数据结构》课程设计--c++二叉树

二叉树简单介绍

二叉树是一种树形数据结构,每个节点最多有两个子节点,分别称为左子节点右子节点。二叉树常用于查找、排序等场景。

二叉树的常见类型有:

  • 完全二叉树:除了最后一层,其他层都被完全填满,且最后一层的节点从左到右排列。
  • 满二叉树:所有节点都有两个子节点,叶子节点在同一层。
  • 二叉搜索树:左子节点的值小于父节点,右子节点的值大于父节点,方便快速查找。

常用操作包括遍历(前序、中序、后序遍历)和插入、删除等。

实验题目

二叉树设计(师承图)

实验内容

任务目标

实现关于二叉树的存储、操作、显示等功能,并选用你熟悉的历史人物及其之间的关系作为操作的数据对象,国内国外、中文英文、各种关系(父母子女、师承、上下级)都可以。

任务描述

基本功能

  • 1)在教材合适的代码基础上实现,测试数据按上述要求自行构建;
  • 2)程序提供菜单,可以实现删除和新增结点;
  • 3)按自己的方式显示二叉树,同时计算并显示其高度、结点数以及四种遍历顺序;
  • 4)程序内置初始数据,根结点设置为你自己的名字,程序启动后立即显示初始二叉树;
  • 5)二叉树被修改后,立即重新显示。

进阶功能

  • 1)初始数据从文件加载,系统退出后修改的数据自动存储到文件;
  • 2)树形显示二叉树;
  • 3)实现交互式操作,结点内容可编辑,结点位置可以移动。

本文实现全部8个功能。难点+创新点:树形显示、移动节点位置。

解决方案

算法设计

在本实验中使用C++语言进行编程,实现了二叉树的各种操作,包括创建节点、添加节点、删除节点、遍历节点、根据先序和中序结果构建二叉树等。整体思路包括:通过节点类 TreeNode 定义了二叉树的节点结构,包括数据和左右子节点。通过 BinaryTree 类定义了二叉树的操作,包括获取根节点、手动输入加入尾部节点、找到父节点、插入左右子节点、遍历方法(中序、先序、后序、层序)、删除节点、计算高度、计算节点数、查找最小值结点、打印二叉树等。实现了根据先序和中序结果构建二叉树的方法,并且可以在控制台上打印二叉树的样子。代码还包括文件输出功能,可以将遍历结果输出到文件。提供了移动和替换节点的功能,可以从一个位置移动节点到另一个位置。

类和结构体 的数据成员设计

class TreeNode {//二叉树结点类
public:
    string data;
    TreeNode* left;
    TreeNode* right;
    TreeNode(string value) {
        data = value;
        left = nullptr;
        right = nullptr;
    }
};
class BinaryTree {//二叉树类
public:
    TreeNode* root;
    BinaryTree() {
        root = nullptr;
    }
    BinaryTree(const string& e)
    // 操作结果:建立以e为根的二叉树
    {
        root = new TreeNode(e);
    }
    // 获取根节点
    TreeNode* getRoot()
    {
        return root;
}
    ///其他函数见下表
};

此外,为了更好的显示二叉树,设计了一个SetColor函数,更清晰美观的展示输出内容。

SetColor函数设计

void SetColor(int fore = 7, int back = 0) // 改变控制台中输出的颜色
{
    unsigned char m_color = fore;
    m_color += (back << 4);
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), m_color);
return;
}

BinTree类中的函数设计

//手动输入加入尾部节点
void addNode(string target, string value, string direction) {
    if (root == nullptr) {
        root = new TreeNode(value);
        return;
    }
    queue<TreeNode*> q;
    q.push(root);
    while (!q.empty()) {
        TreeNode* current = q.front();
        q.pop();
        if (current->data == target) {
            if (direction == "left" && current->left == nullptr) {
                current->left = new TreeNode(value);
                return;
            }
            else if (direction == "right" && current->right == nullptr) {
                current->right = new TreeNode(value);
                return;
            }
        }
        if (current->left != nullptr) {
            q.push(current->left);
        }
        if (current->right != nullptr) {
            q.push(current->right);
        }
    }
}
// 从文件中输入节点数据和位置(可随意插入任意个数节点)
void Opnefile() {
    ifstream inputFile("input.txt");
    if (inputFile.is_open()) {
        string preorderSequence, inorderSequence;
        if (getline(inputFile, preorderSequence) && getline(inputFile, inorderSequence)) {
            istringstream issPre(preorderSequence), issIn(inorderSequence);
            vector<string> pre, in;
            // 将字符串按空格分割为数组
            string temp;
            while (issPre >> temp) {
                pre.push_back(temp);
            }
            while (issIn >> temp) {
                in.push_back(temp);
            }
            // 创建二叉树
            CreateBinaryTree(pre.data(), in.data(), (int)in.size());
        }
        else {
            SetColor(10, 0);
            cout << "读取文件内容错误" << endl;
            SetColor();
        }
        inputFile.close();
    }
    else {
        SetColor(10, 0);
        cout << "无法打开文件" << endl;
        SetColor();
    }
}
// 找到父节点
TreeNode* findParentNode(TreeNode* root, const string& value, TreeNode* parent = nullptr)
{
    if (root == nullptr) {
        return nullptr;
    }
    if (root->data == value) {
        return parent;
    }
    TreeNode* leftResult = findParentNode(root->left, value, root);
    if (leftResult != nullptr) {
        return leftResult;
    }
    TreeNode* rightResult = findParentNode(root->right, value, root);
    return rightResult;
}
// 找兄弟节点
TreeNode* findBrotherNode(TreeNode* root, const string& value)
{
    TreeNode* parent = findParentNode(root, value);
    if (parent == nullptr) {
        SetColor(3, 0);
        cout << "没有双亲节点";
        SetColor();
        cout << endl;
    }
    if (parent != nullptr) {
        if ((parent->left != nullptr) && (parent->left->data == value) && (parent->right != nullptr)) {
            return parent->right;
        }
        if ((parent->right != nullptr) && (parent->right->data == value) && (parent->left != nullptr)) {
            return parent->left;
        }
        if ((parent->right != nullptr) && (parent->right->data == value) && (parent->left == nullptr)) {
        }
        if ((parent->left != nullptr) && (parent->left->data == value) && (parent->right == nullptr)) {
        }
    }
    return nullptr;
}
//插入一个节点作为上一个节点的左孩子   //插入一个节点作为上一个节点的右孩子
void insertLeftChild(TreeNode* parent, const string& value) {
    if (parent == nullptr) {
        cout << "没有双亲节点" << endl;
    }
    else {
        if (parent->left != nullptr) {
            TreeNode* a = parent->left;
            parent->left = new TreeNode(value);
            parent->left->left = a;
        }
    }
}
void insertrightChild(TreeNode* parent, const string& value) {
    if (parent == nullptr) {
        cout << "没有双亲节点" << endl;
    }
    else {
        if (parent->right != nullptr) {
            TreeNode* a = parent->right;
            parent->right = new TreeNode(value);
            parent->right->left = a;
        }
    }
}
// 前中后层序遍历并显示排列后的二叉树
void displayInOrder() {
    displayInOrderRecursive(root);  // 中序遍历二叉树
    cout << endl;
}
void displayInOrderRecursive(TreeNode* root) {
    if (root != nullptr) {
        displayInOrderRecursive(root->left);  // 先访问左子树
        cout << root->data << " ";  // 访问当前节点
        displayInOrderRecursive(root->right);  // 最后访问右子树
    }
}
void displayPreOrder() {
    displayPreOrderRecursive(root);  // 先序遍历二叉树
    cout << endl;
}
void displayPreOrderRecursive(TreeNode* root) {
    if (root != nullptr) {
        cout << root->data << " ";  // 访问当前节点
        displayPreOrderRecursive(root->left);  // 然后访问左子树
        displayPreOrderRecursive(root->right);  // 最后访问右子树
    }
}
void displayPostOrder() {
    displayPostOrderRecursive(root);  // 后序遍历二叉树
    cout << endl;
}
void displayPostOrderRecursive(TreeNode* root) {
    if (root != nullptr) {
        displayPostOrderRecursive(root->left);  // 先访问左子树
        displayPostOrderRecursive(root->right);  // 然后访问右子树
        cout << root->data << " ";  // 最后访问当前节点
    }
}
void displayLevelOrder() {
    if (root == nullptr) return;
    queue<TreeNode*> q;
    q.push(root);
    while (!q.empty()) {
        TreeNode* current = q.front();
        cout << current->data << " ";  // 逐层遍历二叉树节点
        if (current->left != nullptr) {
            q.push(current->left);  // 将左子节点加入队列
        }
        if (current->right != nullptr) {
            q.push(current->right);  // 将右子节点加入队列
        }
        q.pop();
    }
    cout << endl;
}
//根据值删除节点  //判断是否存在这个节点(是否是可删除的)  //删除结点
bool deleteNodeByValue(TreeNode*& root, string value) {
    if (root == nullptr) {
        return 0;
    }
    if (root->data == value) {
        deleteNode(root);
        root = nullptr;
        return 1;
    }
    else {
        bool deleteleft = deleteNodeByValue(root->left, value);  // 向左子树查找
        bool deleteright = deleteNodeByValue(root->right, value);  // 向右子树查找
        if ((deleteleft + deleteright) == 0) {
            return 0;
        }
        return 1;
    }
}
void deleteNode(TreeNode*& node) {
    if (node == nullptr) {
        return;
    }
    deleteNode(node->left);
    deleteNode(node->right);
    delete node;
    node = nullptr;
}
//查找指定节点在第几层
int findNodeLevel(TreeNode* root, const string& value) {
    queue<pair<TreeNode*, int>> nodesQueue;
    nodesQueue.push({ root, 1 });
    while (!nodesQueue.empty()) {
        TreeNode* current = nodesQueue.front().first;
        int level = nodesQueue.front().second;
        nodesQueue.pop();
        if (current->data == value) {
            return level;
        }
        if (current->left != nullptr) {
            nodesQueue.push({ current->left, level + 1 });
        }
        if (current->right != nullptr) {
            nodesQueue.push({ current->right, level + 1 });
        }
    }
    return -1;  // 不存在
}
//计算高度  //计算节点数
int calculateHeight(TreeNode* node) { 
        if (node == nullptr) {
            return 0;
        }
        else {
            int leftHeight = calculateHeight(node->left);
            int rightHeight = calculateHeight(node->right);

            if (leftHeight > rightHeight) {
                return leftHeight + 1;
            }
            else {
                return rightHeight + 1;
            }
        }
    }
    int calculateNodeCount(TreeNode* node) { 
        if (node == nullptr) {
            return 0;
        }
        else {
            return 1 + calculateNodeCount(node->left) + calculateNodeCount(node->right);
        }
    }
// 打印最终的二叉树
    void printBinaryTree(TreeNode* root, string prefix = "", bool isLeft = true) {
        if (root) {
            if (root->right) {
                printBinaryTree(root->right, prefix + (isLeft ? "┇     " : "      "), false);
            }
            SetColor(6, 0);
            cout << prefix;
            SetColor();
            SetColor(6, 0);
            cout << (isLeft ? "┗━━━" : "┏━━━");
            SetColor();
            SetColor(2, 0);
            cout << root->data << endl;
            SetColor();
            if (root->left) {
                printBinaryTree(root->left, prefix + (isLeft ? "      " : "┇     "), true);
            }
        }
    }
//构建二叉树  //根据先序和中序结果构建二叉树
    void CreateBinaryTree(TreeNode*& r, string* pre, string* in, int preLeft, int preRight, int inLeft, int inRight)
    {
        if (inLeft > inRight)
            r = nullptr;
        else
        {
            r = new TreeNode(pre[preLeft]);
            int mid = inLeft;
            while (in[mid] != pre[preLeft])
                mid++;
            CreateBinaryTree(r->left, pre, in, preLeft + 1, preLeft + mid - inLeft, inLeft, mid - 1);
            CreateBinaryTree(r->right, pre, in, preLeft + mid - inLeft + 1, preRight, mid + 1, inRight);
        }
    }
    void CreateBinaryTree(string* pre, string* in, int n)
    {
        CreateBinaryTree(root, pre, in, 0, n - 1, 0, n - 1);
    }
//将先序中序排列的二叉树输出到文件中
void displayPreOrderRecursive(TreeNode* root, ofstream& outputFile) {
        if (root != nullptr) {
            outputFile << root->data << " ";  // 输出当前节点的数值到文件
            displayPreOrderRecursive(root->left, outputFile);  // 探索左子树
            displayPreOrderRecursive(root->right, outputFile);  // 探索右子树
        }
    }
    void displayInOrderRecursive(TreeNode* root, ofstream& outputFile) {
        if (root != nullptr) {
            displayInOrderRecursive(root->left, outputFile);  // 探索左子树
            outputFile << root->data << " ";  // 输出当前节点的数值到文件
            displayInOrderRecursive(root->right, outputFile);  // 探索右子树
        }
    }
//(判断)移动二叉树结点
    bool moveAndReplaceNode(TreeNode* root, const string& targetValue, const string& destinationValue)
{
    if(findNodeLevel(root,targetValue)<findNodeLevel(root,destinationValue))
                {
                    SetColor(3, 0);
                    cout << "无法向后移动 ";
                    SetColor();
                    cout << endl;
                    return 0;
                }
        TreeNode* find1 = findParentNode(root, targetValue);
        if (find1 == nullptr)
        {
            SetColor(11, 0);
            cout << "被移动的不在其中" << endl;
            SetColor();
            return 0;
        }
        TreeNode* find2 = findParentNode(root, destinationValue);
        if (find2 == nullptr)
        {
            SetColor(11, 0);
            cout << "目标位置不在其中" << endl;
            SetColor();
            return 0;
        }
        TreeNode* val = nullptr;
        if (find1->left != nullptr && find1->left->data == targetValue) {
            val = find1->left;
            find1->left = nullptr;
        }
        if (find1->right != nullptr && find1->right->data == targetValue) {
            val = find1->right;
            find1->right = nullptr;
        }
        if (find2->left != nullptr && find2->left->data == destinationValue) {
            find2->left = val;
        }
        if (find2->right != nullptr && find2->right->data == destinationValue) {
            find2->right = val;
        }
        return 1;
    }

源程序代码 Mytree.cpp

int main() {
    BinaryTree tree;
    tree.Openfile();

SetColor(3, 0);
cout << "第一次打开从input.txt中读取数据" << endl << endl;
SetColor(8, 0);
cout << "中国古代书法家师徒关系表(部分)(左师右徒)" << endl;
SetColor();
tree.printBinaryTree(tree.root);
SetColor(3, 0);
cout << "输出先序遍历结果: ";
SetColor();
tree.displayPreOrder();  // 输出先序遍历结果
SetColor(3, 0);
cout << "输出中序遍历结果: ";
SetColor();
tree.displayInOrder();  // 输出中序遍历结果
SetColor(3, 0);
cout << "输出后序遍历结果: ";
SetColor();
tree.displayPostOrder();  // 输出后序遍历结果
SetColor(3, 0);
cout << "输出层序遍历结果: ";
SetColor();
tree.displayLevelOrder();  // 输出层序遍历结果
SetColor(3, 0);
cout << "高度是: ";
SetColor();
cout << tree.calculateHeight(tree.root);
SetColor(8, 0);
cout << " (列\"┇\"线)";
SetColor();
cout << endl; // 计算并显示二叉树的高度
SetColor(3, 0);
cout << "节点数: ";
SetColor();
cout << tree.calculateNodeCount(tree.root) << endl; // 计算并显示二叉树的节点数
SetColor(0, 15);
cout << "1:删除某个节点  2:增加一个节点  3:修改节点内容  4:移动某个节点  5:查询某个节点  6:退出并保存至文件";
SetColor();
cout << endl;
while (1) {
    int swi = 0;
    bool flag = 0;
    cin >> swi;
    switch (swi) {
    case(1): {
        SetColor(0, 15);
        cout << "谁被逐出师门了:";
        SetColor();
        cout << endl;
        string edit;
        cin >> edit;
        if (tree.deleteNodeByValue(tree.root, edit) == 0)
        {
            SetColor(11, 0);
            cout << "该人不在其中";
            SetColor();
            cout << endl;
            break;
        }
        SetColor(8, 0);
        cout << endl
            << "中国古代书法家师徒关系表(部分)(左师右徒)" << endl;
        SetColor();
        tree.printBinaryTree(tree.root);
        SetColor(3, 0);
        cout << "输出先序遍历结果: ";
        SetColor();
        tree.displayPreOrder();  // 输出先序遍历结果
        SetColor(3, 0);
        cout << "输出中序遍历结果: ";
        SetColor();
        tree.displayInOrder();  // 输出中序遍历结果
        SetColor(3, 0);
        cout << "输出后序遍历结果: ";
        SetColor();
        tree.displayPostOrder();  // 输出后序遍历结果
        SetColor(3, 0);
        cout << "输出层序遍历结果: ";
        SetColor();
        tree.displayLevelOrder();  // 输出层序遍历结果
        SetColor(3, 0);
        cout << "高度是: ";
        SetColor();
        cout << tree.calculateHeight(tree.root);
        SetColor(8, 0);
        cout << " (列\"┇\"线)";
        SetColor();
        cout << endl; // 计算并显示二叉树的高度
        SetColor(3, 0);
        cout << "节点数: ";
        SetColor();
        cout << tree.calculateNodeCount(tree.root) << endl; // 计算并显示二叉树的节点数
        break;
    }
           case(2): {
    int choose = 0;
    if (tree.calculateHeight(tree.root) == 2 && tree.root->right == nullptr) {
        SetColor(0, 15);
        cout << "谁起家了?";
        SetColor();
        cout << endl;
        string add;
        cin >> add;
        tree.addNode(tree.root->data, add, "right");
        SetColor(8, 0);
        cout << endl
            << "中国古代书法家师徒关系表(部分)(左师右徒)" << endl;
        SetColor();
        tree.printBinaryTree(tree.root);
        SetColor(3, 0);
        cout << "输出先序遍历结果: ";
        SetColor();
        tree.displayPreOrder();  // 输出先序遍历结果
        SetColor(3, 0);
        cout << "输出中序遍历结果: ";
        SetColor();
        tree.displayInOrder();  // 输出中序遍历结果
        SetColor(3, 0);
        cout << "输出后序遍历结果: ";
        SetColor();
        tree.displayPostOrder();  // 输出后序遍历结果
        SetColor(3, 0);
        cout << "输出层序遍历结果: ";
        SetColor();
        tree.displayLevelOrder();  // 输出层序遍历结果
        SetColor(3, 0);
        cout << "高度是: ";
        SetColor();
        cout << tree.calculateHeight(tree.root);
        SetColor(8, 0);
        cout << " (列\"┇\"线)";
        SetColor();
        cout << endl; // 计算并显示二叉树的高度
        SetColor(3, 0);
        cout << "节点数: ";
        SetColor();
        cout << tree.calculateNodeCount(tree.root) << endl; // 计算并显示二叉树的节点数
    }
    if (tree.calculateHeight(tree.root) != 0 && tree.calculateHeight(tree.root) != 1) {
        SetColor(0, 15);
        cout << "1:找到了师傅(在二叉树中根据徒弟节点插入师傅节点)  2:找到了徒弟(在二叉树中根据师傅节点插入徒弟节点)";
        SetColor();
        cout << endl;
        cin >> choose;
        if (choose == 1)
        {
            SetColor(0, 15);
            cout << "谁的师傅重出江湖了?";
            SetColor();
            cout << endl;
            string add;
            cin >> add;
            TreeNode* parent = tree.findParentNode(tree.root, add);
            if (parent == nullptr) {
                SetColor(11, 0);
                cout << "该人不在其中" << endl;
                SetColor();
                break;
            }
            if ((tree.calculateHeight(tree.root) == 1) || (tree.calculateHeight(tree.root) == 2))
            {
                SetColor(11, 0);
                cout << "他已经是大掌门啦" << endl;
                SetColor();
                break;
            }
            if (parent != nullptr) {
                SetColor(0, 15);
                cout << "他的师傅叫?";
                SetColor();
                cout << endl;
                string teacher;
                cin >> teacher;
                if ((parent->left != nullptr) && (parent->left->data == add)) {
                    tree.insertLeftChild(parent, teacher);  // 将他作为父节点的左孩子插入
                }
                else if ((parent->right != nullptr) && (parent->right->data == add)) {
                    tree.insertrightChild(parent, teacher);  // 将他作为父节点的右孩子插入
                }
                SetColor(8, 0);
                cout << endl
                    << "中国古代书法家师徒关系表(部分)(左师右徒)" << endl;
                SetColor();
                tree.printBinaryTree(tree.root);
                SetColor(3, 0);
                cout << "输出先序遍历结果: ";
                SetColor();
                tree.displayPreOrder();  // 输出先序遍历结果
                SetColor(3, 0);
                cout << "输出中序遍历结果: ";
                SetColor();
                tree.displayInOrder();  // 输出中序遍历结果
                SetColor(3, 0);
                cout << "输出后序遍历结果: ";
                SetColor();
                tree.displayPostOrder();  // 输出后序遍历结果
                SetColor(3, 0);
                cout << "输出层序遍历结果: ";
                SetColor();
                tree.displayLevelOrder();  // 输出层序遍历结果
                SetColor(3, 0);
                cout << "高度是: ";
                SetColor();
                cout << tree.calculateHeight(tree.root);
                SetColor(8, 0);
                cout << " (列\"┇\"线)";
                SetColor();
                cout << endl; // 计算并显示二叉树的高度
                SetColor(3, 0);
                cout << "节点数: ";
                SetColor();
                cout << tree.calculateNodeCount(tree.root) << endl; // 计算并显示二叉树的节点数
            }
            else {
                SetColor(11, 0);
                cout << "该人不在其中" << endl;
                SetColor();
            }
        }
        if (choose == 2)
        {
            SetColor(0, 15);
            cout << "谁新找到了徒弟?";
            SetColor();
            cout << endl;
            string teacher;
            cin >> teacher;
            TreeNode* target = tree.findParentNode(tree.root, teacher);
            if (target == nullptr) {
                SetColor(11, 0);
                cout << "该人不在其中" << endl;
                SetColor();
                break;
            }
            SetColor(0, 15);
            cout << "他的徒弟叫?";
            SetColor();
            cout << endl;
            string student;
            cin >> student;
            if (target != nullptr)
            {
                if ((target->left != nullptr) && (target->left->data == teacher)) {
                    if ((target->left->left != nullptr) && (target->left->right != nullptr)) {
                        SetColor(11, 0);
                        cout << "他已经收了两个徒弟了,无法再收" << endl;
                        SetColor();
                    }
                    if ((target->left->left != nullptr) && (target->left->right == nullptr)) {
                        tree.addNode(teacher, student, "right");
                    }
                    if (target->left->left == nullptr) {
                        tree.addNode(teacher, student, "left");
                    }
                }
                else if ((target->right != nullptr) && (target->right->data == teacher)) {
                    if ((target->right->left != nullptr) && (target->right->right != nullptr)) {
                        SetColor(11, 0);
                        cout << "他已经收了两个徒弟了,无法再收" << endl;
                        SetColor();
                    }
                    if ((target->right->left != nullptr) && (target->right->right == nullptr)) {
                        tree.addNode(teacher, student, "right");
                    }
                    if (target->right->left == nullptr) {
                        tree.addNode(teacher, student, "left");
                    }
                }
            }
        }
    }
    if (tree.calculateHeight(tree.root) == 1 && tree.root->left != nullptr) {
        SetColor(0, 15);
        cout << "谁起家了?";
        SetColor();
        cout << endl;
        string add;
        cin >> add;
        tree.addNode(tree.root->data, add, "right");
    }
    if (tree.calculateHeight(tree.root) == 1 && tree.root->left == nullptr) {
        SetColor(0, 15);
        cout << "谁起家了?";
        SetColor();
        cout << endl;
        string add;
        cin >> add;
        tree.addNode(tree.root->data, add, "left");
    }
    if (tree.calculateHeight(tree.root) == 0) {
        SetColor(0, 15);
        cout << "谁起家了?";
        SetColor();
        cout << endl;
        string add;
        cin >> add;
        tree.addNode("", add, "");//手动创建根节点
    }
    SetColor(8, 0);
    cout << endl
        << "中国古代书法家师徒关系表(部分)(左师右徒)" << endl;
    SetColor();
    tree.printBinaryTree(tree.root);
    SetColor(3, 0);
    cout << "输出先序遍历结果: ";
    SetColor();
    tree.displayPreOrder();  // 输出先序遍历结果
    SetColor(3, 0);
    cout << "输出中序遍历结果: ";
    SetColor();
    tree.displayInOrder();  // 输出中序遍历结果
    SetColor(3, 0);
    cout << "输出后序遍历结果: ";
    SetColor();
    tree.displayPostOrder();  // 输出后序遍历结果
    SetColor(3, 0);
    cout << "输出层序遍历结果: ";
    SetColor();
    tree.displayLevelOrder();  // 输出层序遍历结果
    SetColor(3, 0);
    cout << "高度是: ";
    SetColor();
    cout << tree.calculateHeight(tree.root);
    SetColor(8, 0);
    cout << " (列\"┇\"线)";
    SetColor();
    cout << endl; // 计算并显示二叉树的高度
    SetColor(3, 0);
    cout << "节点数: ";
    SetColor();
    cout << tree.calculateNodeCount(tree.root) << endl; // 计算并显示二叉树的节点数
    break;
}
        case(3): {
            SetColor(0, 15);
            cout << "想要修改哪个节点的值";
            SetColor();
            cout << endl;
            string findstr;
            cin >> findstr;
            TreeNode* find = tree.findParentNode(tree.root, findstr);
            if (find == nullptr) {
                SetColor(11, 0);
                cout << "该人不在其中" << endl;
                SetColor();
                break;
            }
            SetColor(0, 15);
            cout << "想要修改为?";
            SetColor();
            cout << endl;
            string setstr;
            cin >> setstr;
            if (find->left->data == findstr) {
                find->left->data = setstr;
            }
            if (find->right->data == findstr) {
                find->right->data = setstr;
            }
            SetColor(8, 0);
            cout << endl
                << "中国古代书法家师徒关系表(部分)(左师右徒)" << endl;
            SetColor();
            tree.printBinaryTree(tree.root);
            SetColor(3, 0);
            cout << "输出先序遍历结果: ";
            SetColor();
            tree.displayPreOrder();  // 输出先序遍历结果
            SetColor(3, 0);
            cout << "输出中序遍历结果: ";
            SetColor();
            tree.displayInOrder();  // 输出中序遍历结果
            SetColor(3, 0);
            cout << "输出后序遍历结果: ";
            SetColor();
            tree.displayPostOrder();  // 输出后序遍历结果
            SetColor(3, 0);
            cout << "输出层序遍历结果: ";
            SetColor();
            tree.displayLevelOrder();  // 输出层序遍历结果
            SetColor(3, 0);
            cout << "高度是: ";
            SetColor();
            cout << tree.calculateHeight(tree.root);
            SetColor(8, 0);
            cout << " (列\"┇\"线)";
            SetColor();
            cout << endl; // 计算并显示二叉树的高度
            SetColor(3, 0);
            cout << "节点数: ";
            SetColor();
            cout << tree.calculateNodeCount(tree.root) << endl; // 计算并显示二叉树的节点数
            break;
        }
        case(4): {
            SetColor(0, 15);
            cout << "想要移动哪个节点";
            SetColor();
            cout << endl;
            string move;
            cin >> move;
            SetColor(0, 15);
            cout << "移动至哪个节点的位置";
            SetColor();
            cout << endl;
            string end;
            cin >> end;
            if ((tree.moveAndReplaceNode(tree.root, move, end)) == 1)
            {
                SetColor(8, 0);
                cout << endl
                    << "中国古代书法家师徒关系表(部分)(左师右徒)" << endl;
                SetColor();
                tree.printBinaryTree(tree.root);
                SetColor(3, 0);
                cout << "输出先序遍历结果: ";
                SetColor();
                tree.displayPreOrder();  // 输出先序遍历结果
                SetColor(3, 0);
                cout << "输出中序遍历结果: ";
                SetColor();
                tree.displayInOrder();  // 输出中序遍历结果
                SetColor(3, 0);
                cout << "输出后序遍历结果: ";
                SetColor();
                tree.displayPostOrder();  // 输出后序遍历结果
                SetColor(3, 0);
                cout << "输出层序遍历结果: ";
                SetColor();
                tree.displayLevelOrder();  // 输出层序遍历结果
                SetColor(3, 0);
                cout << "高度是: ";
                SetColor();
                cout << tree.calculateHeight(tree.root);
                SetColor(8, 0);
                cout << " (列\"┇\"线)";
                SetColor();
                cout << endl; // 计算并显示二叉树的高度
                SetColor(3, 0);
                cout << "节点数: ";
                SetColor();
                cout << tree.calculateNodeCount(tree.root) << endl; // 计算并显示二叉树的节点数
            }
            break;
        }
        case(5): {
            SetColor(0, 15);
            cout << "想要查找哪个节点";
            SetColor();
            cout << endl;
            string value;
            cin >> value;
            int level = tree.findNodeLevel(tree.root, value);
            if (level == -1) {
                SetColor(3, 0);
                cout << "该人不在其中";
                SetColor();
                cout << endl;
            }
            else {
                TreeNode* find = tree.findParentNode(tree.root, value);
                cout << "在第";
                SetColor(3, 0);
                cout << level;
                SetColor();
                cout << "层";
                if (tree.calculateHeight(tree.root)==2) {
                    SetColor(3, 0);
                    cout << ",已经是大掌门了";
                    SetColor();
                    cout << endl;
                    break;
                }
                if (tree.calculateHeight(tree.root)!=1) {
                   cout << ",他的师傅为";
                   SetColor(3, 0);
                   cout << find->data;
                   SetColor();
                   cout << ",他的同门为";
                   SetColor(3, 0);
                   if (tree.findBrotherNode(tree.root, value) != nullptr) {
                       cout << tree.findBrotherNode(tree.root, value)->data;
                   }
                   if (tree.findBrotherNode(tree.root, value) == nullptr) {
                       cout << "空";
                   }
                   cout << endl;
                }
               if (tree.calculateHeight(tree.root)==1) {
                    SetColor(3, 0);
                    cout << ",已经是root了";
                    SetColor();
                    cout << endl;
                }
            }
            break;
        }
        case(6): {
            flag = 1;
            break;
        }
        default: {
            SetColor(0, 4);
            cout << "输入有误";
            SetColor();
            cout << endl;
        }
        }
        if (flag == 1) {
            break;
        }
        SetColor(0, 15);
        cout << "1:删除某个节点  2:增加一个节点  3:修改节点内容  4:移动某个节点  5:查询某个节点  6:退出并保存至文件";
        SetColor();
        cout << endl;
    }
    // 将二叉树保存至txt文件
    ofstream outputFile("output.txt");
    // 将树的先序遍历结果输出到文件
    outputFile << "先序遍历结果: ";
    tree.displayPreOrderRecursive(tree.root, outputFile);
    outputFile << endl;
    outputFile << "中序遍历结果: ";
    tree.displayInOrderRecursive(tree.root, outputFile);
    outputFile << endl;
    outputFile.close();
    cout << endl
        << "已保存至output.txt中" << endl;
    system("pause");
    return 0;
}

算法分析

  • addNode: 时间复杂度为O(n),其中n为树中的节点数,因为最坏情况下需要访问所有节点来找到目标位置。
  • findParentNode: 时间复杂度为O(n),因为最坏情况下需要访问整个树来找到目标节点的父节点。
  • insertLeftChildinsertRightChild: 时间复杂度为O(1),因为它们仅执行常数次操作。
  • displayInOrderdisplayPreOrderdisplayPostOrderdisplayLevelOrder: 时间复杂度均为O(n),其中n为树中的节点数,因为在最坏情况下需要访问所有节点。
  • deleteNode: 最坏情况下的时间复杂度为O(n),因为需要遍历树来查找目标节点,不过在平均情况下可以达到O(log n)。
  • deleteNodeByValue: 最坏情况下的时间复杂度为O(n^2),因为在最坏情况下可能需要删除所有节点。
  • findNodeLevel: 最坏情况下的时间复杂度为O(n),因为需要遍历整个树以找到目标节点。
  • calculateHeightcalculateNodeCount: 最坏情况下的时间复杂度为O(n),因为在最坏情况下需要访问所有节点。
  • minValueNode: 最坏情况下的时间复杂度为O(log n),因为在平衡二叉树中,查找最小值的节点所需的时间为O(log n)。
  • printBinaryTreeCreateBinaryTree: 时间复杂度均为O(n),其中n为树中的节点数,因为需要访问所有节点。

注意:对于二叉树的使用我们必须清楚每个指针具体指向的空间及其中的数据,如在我的main函数中的case2,我使用到了寻找父节点函数,再用parent->right或left定位元素,但有可能这个二叉树已经进行过了一次删除操作,我所需要寻找的元素的兄弟元素可能已经被删除了,是空指针,所以我就需要在if语句中加入(!=nullptr)的指令避免在比较时出现报错,同样这个问题也出在修改节点的值、移动节点和查询节点处。

实验结果演示

测试用例(input.txt)

(朱俊枫) 蔡邕 蔡文姬 钟繇 卫夫人 王羲之 王献之 王僧虔 萧子云 阮研 虞世南 欧阳询 张旭 颜真卿 柳公权 李白 薛稷 孔琳之 谢月出 钟会 魏相国 崔瑗

阮研 萧子云 欧阳询 柳公权 颜真卿 张旭 李白 虞世南 薛稷 王僧虔 孔琳之 王献之 王羲之 谢月出 卫夫人 钟繇 钟会 蔡文姬 魏相国 蔡邕 崔瑗 (朱俊枫)
测试输出

功能1:树形显示,菜单,计算并显示其高度、结点数及四种遍历顺序,从文件中读取数据

功能2:删除和分别在前、后新增结点,修改后立即显示二叉树
功能3:修改节点内容
功能4:查询节点信息
功能5:退出并保存至output.txt文件中
功能6:异常输入检测

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值