二叉树打印树形

#include<iostream>
#include<cstring>
#include<stdio.h>
#include<algorithm>
#include"MyBST.h"
using namespace std;

int main()
{
    cout<<"Please enter the numbers:"<<endl;//提示用户输入
    MyBST *mybst = new MyBST( );//构造类MyBST的对象 mybst,指针类型
    while(cin.peek()!='\n')//peek 相当于偷看一眼,再放回去
    {                       //当下一个读入的不是回车时
        int temp;
        cin>>temp;//读入数值
        mybst->insertNode(temp);//插入树中
    }

   mybst->output();//打印二叉树图形

    cout<<"Please enter the number to delete:"<<endl;//提示用户输入要删除的数值
    int deletex;
    while(scanf("%d",&deletex)!=EOF)//读入以文件结尾为止。控制台下使用ctrl+z+回车
    {
        Node *temp=mybst->findByKey(deletex);//创建值为deletex的节点temp
    	if(temp==nullptr)
    		cout<<"无 "<<deletex<<endl;//没有该节点,无法删除
    	else
    		mybst->deleteNode(temp);//删除该节点temp
     mybst->output();//打印
	}


}

主函数注释很全了。。。

题目要求:输入数字,以回车结束,建立二叉搜索树,并打印树形。

输入要删除的数字,重新打印树形。

 

二叉树的定义和基本函数   搬砖:https://www.cnblogs.com/coffeeSS/p/5452719.html

打印树形那里,其实是一个中序遍历,根在左,叶子在右。深度每增加一层,前面打印的空格就越多。

#include<iostream>
#include<cstring>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<cstdlib>

using namespace std;

//节点结构
struct Node{
    Node(int k=0):key(k){}//初始化
    Node* parent = nullptr;//父节点
    Node* left = nullptr;//左孩子
    Node* right = nullptr;//右孩子
    int key;//对应的数值
};


class MyBST{
private:
    Node* root=nullptr;//根节点
    Node* findSuccessor(Node* n);//寻找后继节点
    Node* findPredecessor(Node* n);//寻找前驱节点
    void  insertNode(Node* n);//插入节点
    void output_impl(Node* n, bool left, string indent);//输出函数需要调用的函数,方便打印树形
    void output(Node* root);//遍历输出所有节点
public:
    MyBST(){};//构造函数
    Node* getRoot(){ return root; }//返回根节点
    Node* findByKey(int k);//寻找数值为k的节点
    void insertNode(int k);//插入数值为k的节点
    void output()//输出树形
    {
        output(root);
    }
    void deleteNode(Node* n);//删除节点
};



Node* MyBST::findByKey(int k){
    Node* temp = root;//获取根节点
    while (temp != nullptr){
        if (k == temp->key)//当key相等的时候返回匹配节点
           {
             return temp;
           }
        temp = k < temp->key ? temp->left : temp->right;//通过比较key的值来决定搜索向哪一棵子树进行
    }

    return nullptr;
}


Node* MyBST::findPredecessor(Node* n)//寻找前驱节点
{
    if (n->left != nullptr){//若x的左子树不为空,
        n = n->left; //则x前驱是x节点左子树里最靠右的那个节点
        while (n->right != nullptr)
            n = n->right;
        return n;
    }
    while (n->parent != nullptr&&n->parent->left == n)//如果x的左子树为空,
        n = n->parent;
    return n->parent;//那么我们就要向上找x的第一个有右孩子且左子树里没有x节点的祖先
}

Node* MyBST::findSuccessor(Node* n)//寻找后继节点
{
    if (n->right != nullptr)
	{
		//若n的右子树不为空,则n后继是x节点右子树里最靠左的那个节点
        n = n->right;
        while (n->left != nullptr)
            n = n->left;
        return n;
    }
    while (n->parent != nullptr&&n->parent->right == n)//如果n的左子树为空
        n = n->parent;//那么我们就要向上找x的第一个有右孩子且左子树里没有x节点的祖先
    return n->parent;
}



void MyBST::output_impl(Node* n, bool left, string  indent)//输出树形
{
    if (n->right)
    {
       output_impl(n->right, false, indent + "      " );//右孩子则将left置为false,进入下一层时字符串增加空格
    }
    cout << indent;//输出字符串
    cout << (left ? '\\' : '/');//打印“树枝”的方向
    cout << "-----";//打印树枝
    cout << n->key << endl;//打印数值
    if (n->left)
    {
      output_impl(n->left, true, indent + "      " );//左孩子则将left置为true,进入下一层时字符串增加空格
    }
}

void MyBST::output(Node* n)//中序遍历
{
    if (n->right)
    {
        output_impl(n->right, false, "");
    }
    cout << n->key << endl;
    if (n->left)
    {
        output_impl(n->left, true, "");
    }
}



void MyBST::insertNode(int k)//公有函数中的插入数值为k的节点
{
    Node* n = new Node(k);//生成节点
    insertNode(n);//调用私有函数,插入节点
}

void MyBST::insertNode(Node* n)//私有函数中,插入节点
{
    Node* temp = root;
    if (temp==nullptr){//树为空就设置根节点
        root = n;
        return;
    }
    while (true){//这个循环里有一个大的if-else结构,用来决定插入到左子树还是右子树
        if (temp->key > n->key){//进入左子树
            if (temp->left != nullptr)//if-else结构判断是否已经到达要插入的地方
                temp = temp->left;//到达则替换,没有则深入
            else{
                temp->left = n;
                n->parent = temp;
                return;
            }
        }
        else{
            if (temp->right != nullptr)//进入右子树
                temp = temp->right;
            else{
                temp->right = n;
                n->parent = temp;
                return;
            }
        }
    }
}

void MyBST::deleteNode(Node* n)//删除节点
{
    Node* temp;//用来存取代n节点位置的节点,下面的if分三种情况确定取代n节点位置的节点temp的取值

    if (n->left == nullptr&&n->right == nullptr)//情况一:n没有孩子节点
        temp = nullptr;

    else if (n->left == nullptr || n->right == nullptr)
	{
		//情况二:n有一个孩子节点
        temp = (n->left == nullptr) ? n->right : n->left;//我们用这个孩子节点当做取代n的节点
        temp->parent = n->parent;//因为temp要取代n,所以要用temp复制n的属性,因为temp就是n的孩子节点之一,
    }                           //且另一个孩子节点是nullptr,所以n的孩子节点的信息不用复制
    else
	{
		//情况三:n有两个孩子节点,双支节点   y--temp
        temp = findSuccessor(n);//我们用n节点的后继y当做取代n的节点
        Node* successor_right;//y只可能有一个右孩子或者没有孩子,我们先要让y的右孩子取代y,再让y取代n
        if (temp->right == nullptr)//如果y没有孩子,则用nullptr取代y
            successor_right = nullptr;
        else{
            successor_right = temp->right;
            successor_right->parent = temp->parent;//y有右孩子的时候要处理右孩子的父节点
        }

        if (temp->parent->left == temp)//这个if用来让y的父节点指向取代y的节点
            temp->parent->left = successor_right;
        else
            temp->parent->right = successor_right;
        //接下来要让y取代n了,其实我们只需要把y的key值给n就行了,然后直接退出,不需要再修改其他的部分了
        n->key = temp->key;
        delete temp;
        return;
    }
    //情况一和情况二到此为止取代n节点的temp已经确定,而且当temp不是nullptr的时候,
    //temp也已经复制了必要的n的属性,剩下的就是让n的父节点指向temp了
    //注意被删除的节点有可能是根节点,所以当我们发现被删除的是根节点时,不需要让n的父节点指向temp,
    //因为n没有父节点了,但是这个时候必须修改root指针的指向
    if (n->parent != nullptr){
        if (n->parent->left == n)
            n->parent->left = temp;
        else
            n->parent->right = temp;
    }
    else
        root = temp;//修改root指针的指向
    delete n;
}

实验周的代码。

反正排名很低,没人看哈哈哈。

结果大概酱紫:

成绩出来了才敢放出来

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值