C++实现二叉树基本功能(有序二叉树添加、删除、显示)

二叉树的数据保存方式主要是数组和链表,如果使用完全二叉树数组更适合,负责适合使用链表保存。数据读取分为前序、中序、后序,主要以父节点来区分,前序则先父节点、左子节点、右子节点;中序则先左子节点、父节点、右子节点;后序则左子、右子、中。

#include <iostream>
#include <vector>

using namespace std;

// 定义二叉树
typedef struct CSNode {
    int data;
    CSNode* left = NULL, * right = NULL;
}CSNode, * CSTree;

class DbTree {
private:
    CSNode* lastTree = NULL;
    CSNode node;                        // 好的吧,我这里是不是应该也用指针的
    bool haveHead = false;             // 定义是否有文件,完全没有则为false
    CSNode* tree = NULL;
    vector<CSNode*> pointLink;
    vector<CSNode> vct;
    vector<CSNode> orderlyVct;

    void left(CSNode* currentTree = NULL);
    void center(CSNode* currentTree = NULL);
    void right(CSNode* currentTree = NULL);
public:
    DbTree(int x) {
        node.data = x;
        tree = &node;
        haveHead = true;
    }

    void add(int x, CSNode* currentTree = NULL);
    bool remove(int x, CSNode* currentTree = NULL);
    void removeAll(CSNode* currentTree = NULL);               // 全部删除,本来我是觉得可以用后序遍历一次全部删除的,但是我懒
    void leftShow();
    vector<CSNode> centerShow();    // 中序会是从小到大,我可以直接输出使用
    void rightShow();
    void balance();                 // 平衡二叉树,将二叉树平衡排序
};

int main()
{
    DbTree dbTree(100);
    dbTree.add(50);
    dbTree.add(122);
    dbTree.add(60);
    dbTree.add(55);
    dbTree.add(65);
    dbTree.add(70);

    cout << "left is :" << endl;
    dbTree.leftShow();
    cout << "rihgt is :" << endl;
    dbTree.rightShow();
    cout << "center is :" << endl;
    dbTree.centerShow();

    dbTree.remove(60);
    cout << "删除完成" << endl;
    dbTree.leftShow();

    dbTree.removeAll();
    cout << "全部删除后" << endl;
    dbTree.centerShow();

    int i = 1;
    int j;
    while (i)
    {
        cin >> i;
        if (i == 1) {
            cin >> j;
            dbTree.add(j);
        }
        if (i == 2) {
            cin >> j;
            dbTree.remove(j);
        }
        if (i == 3)
        {
            cout << "显示一波" << endl;
            dbTree.centerShow();
        }

    }

    return 0;
}


void DbTree::add(int x, CSNode* currentTree) {
    if (currentTree == NULL)
        currentTree = &node;

    // 如果是首次添加添加,则将设为二插树头文件
    if (!haveHead)
    {
        haveHead = true;
        node.data = x;
    }
    else {
        //tree = &node;
        // 如果比当前值小,在左边添加,负责在右边添加
        if (x < currentTree->data) {
            if (currentTree->left == NULL)
            {
                CSNode* lastTree;
                lastTree = currentTree;
                currentTree = new CSNode;
                currentTree->data = x;
                lastTree->left = currentTree;
            }
            else {
                currentTree = currentTree->left;
                add(x, currentTree);
            }
        }
        else if (x > currentTree->data)
        {
            if (currentTree->right == NULL)
            {
                CSNode* lastTree;
                lastTree = currentTree;
                currentTree = new CSNode;
                currentTree->data = x;
                lastTree->right = currentTree;
            }
            else {
                currentTree = currentTree->right;
                add(x, currentTree);
            }
        }
    }
}

bool DbTree::remove(int x, CSNode* currentTree) {
    if (haveHead) {
        if (currentTree == NULL)
        {
            lastTree = &node;
            currentTree = &node;
        }


        //tree = &node;
        CSNode* deleteTree = currentTree;
        if (x == currentTree->data) {
            // 删除当前树,并且如果有子二叉树,讲子二叉树重新排序
            if (currentTree->left != NULL && currentTree->right != NULL) {
                // 将父节点的替换的子节点方向指向子节点的右边子节点,子节点的左边子节点并到右边子节点的最左边
                if (x != node.data) {
                    if (lastTree->left == currentTree)
                        lastTree->left = currentTree->right;
                    else
                        lastTree->right = currentTree->right;
                }

                lastTree = currentTree->left;
                currentTree = currentTree->right;
                while (currentTree->left != NULL)
                {
                    currentTree = currentTree->left;
                }
                currentTree->left = lastTree;       // 将删除后的点的左下角点保存
            }
            else if (currentTree->left == NULL && currentTree->right == NULL) {
                if (x != node.data)
                    if (lastTree->left == currentTree)
                        lastTree->left = NULL;
                    else
                        lastTree->right = NULL;
                else {
                    haveHead = false;
                }
            }
            else {
                // 将父的链接指向自己的子
                if (x != node.data)
                {
                    if (lastTree->left == currentTree)
                        if (currentTree->left != NULL)
                            lastTree->left = currentTree->left;
                        else
                            lastTree->left = currentTree->right;
                    else
                        if (currentTree->left != NULL)
                            lastTree->right = currentTree->left;
                        else
                            lastTree->right = currentTree->right;
                }
            }
            // 如果删除的父节点是第一个
            if (x == node.data) {
                if (deleteTree->right != NULL) {
                    node.data = deleteTree->right->data;
                    node.left = deleteTree->right->left;
                    node.right = deleteTree->right->right;
                }
                else if (deleteTree->left != NULL) {
                    node.left = deleteTree->left->left;
                    node.right = deleteTree->left->right;
                    node.data = deleteTree->left->data;
                }
            }
            else
                delete deleteTree;

            return true;    // 返回执行成功,并且不继续一下循环
        }


        lastTree = currentTree;
        // 如果比当前值小,在左边添加,负责在右边添加
        if (x < currentTree->data) {
            if (currentTree->left == NULL)
            {
                return false;
            }
            else {
                currentTree = currentTree->left;
                remove(x, currentTree);
            }
        }
        else {
            if (currentTree->right == NULL)
            {
                return false;
            }
            else {
                currentTree = currentTree->right;
                remove(x, currentTree);
            }
        }
    }
}

// 复制后续遍历,将原来用于显示的地方用于删除
void DbTree::removeAll(CSNode* currentTree) {
    if (haveHead)
    {
        // 所有二叉树排序获取,可以这样暴力一波
        /*vector<CSNode> thisVct;
        thisVct = centerShow();

        for(int i = 0; i < thisVct.size(); i++){
            remove((int)thisVct[i].data);
        }/**/

        // 从起点开始
        if (currentTree == NULL)
            currentTree = &node;

        if (currentTree->left != NULL)
        {
            pointLink.push_back(currentTree);
            removeAll(currentTree->left);
        }
        else if (currentTree->right != NULL) {
            pointLink.push_back(currentTree);
            removeAll(currentTree->right);
        }
        else {
            // 如果删除的父节点是第一个
            if (currentTree->data == node.data) {
                haveHead = false;
            }
            else
                delete currentTree;

            if (pointLink.size() > 0) {
                CSNode* tree = pointLink.back(); 
                currentTree = tree;      // 返回最后一个变量
                currentTree->left = NULL;
                pointLink.pop_back();

                if (tree->right != NULL)
                {
                    CSNode* crtList = tree->right;
                    tree->right = NULL;
                    removeAll(crtList);
                }

                removeAll(currentTree);
            }
        }/* */
    }
    //haveHead = false;
}

void DbTree::left(CSNode* currentTree)
{
    cout << currentTree->data << endl;

    if (currentTree->left != NULL)
    {
        left(currentTree->left);
    }

    if (currentTree->right != NULL) {
        left(currentTree->right);
    }
}
void DbTree::leftShow() {
    if (haveHead)
        left(&node);
}

/* 中序,左中右的检测,左边有值则将当前值加入对战,左边没有则将当前输出显示并查询右边,如果有则继续将其作为起始点同样的查询
 * 上面结束后从堆栈中取出继续同样操作(但左边的不用再处理因为已经执行),直到堆栈为空
 */
void DbTree::center(CSNode* currentTree)
{
    if (currentTree->left != NULL)
    {
        vct.push_back(*currentTree);
        center(currentTree->left);
    }
    else {
        //显示或输出当前的,并添加到返回链表
        cout << currentTree->data << endl;
        orderlyVct.push_back(*currentTree);

        // 并对右边进行检测
        if (currentTree->right != NULL) {
            center(currentTree->right);
        }
        else    // 负责对堆栈进行同样操作
        {
            if (vct.size() > 0) {
                currentTree = &vct.back();      // 返回最后一个变量
                vct.pop_back();
                currentTree->left = NULL;
                center(currentTree);
            }
        }
    }
}
vector<CSNode> DbTree::centerShow()
{
    orderlyVct.clear(); // 先清空再进去全部添加
    if (haveHead)
        center(&node);
    return orderlyVct;
}

/* 输出顺序:左右中;
 */
void DbTree::right(CSNode* currentTree) {
    if (currentTree->left != NULL)
    {
        vct.push_back(*currentTree);
        right(currentTree->left);
    }
    else if (currentTree->right != NULL) {
        vct.push_back(*currentTree);
        right(currentTree->right);
    }
    else {
        cout << currentTree->data << endl;

        if (vct.size() > 0) {
            CSNode* tree = &vct.back();
            if (tree->right != NULL && tree->right->data == currentTree->data)
                tree->right = NULL;

            currentTree = tree;      // 返回最后一个变量
            vct.pop_back();
            currentTree->left = NULL;
            right(currentTree);
        }
    }
}
void DbTree::rightShow() {
    if (haveHead)
        right(&node);
}

// 将二叉树重新排序生成
void DbTree::balance()
{
    vector<CSNode> thisVct;
    thisVct = centerShow();
    // 新建二叉树,每次已对应中间值添加
    for (int i = 0; i < thisVct.size(); i++) {

    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值