数据结构——二叉树基本操作(C++实现)

前言:

本代码实现二叉树的基本操作(四种遍历,增删查,求节点数,求树高,求单层节点数,求叶子数,镜像反转,相似树,判断完全二叉树,冒泡排序…);如右错误和可优化之处,还请指点!

实现代码:

/*************************************************************************
	> File Name: Btree.cpp
	> Author: 念念
	> Mail: 2845906049@qq.com 
	> Created Time: 2021年08月21日 星期六 17时42分40秒
    > Function: 二叉树的基本操作(四种遍历,增删查,求节点数,求树高,
    求单层节点数,求叶子数,镜像反转,相似树,判断完全二叉树,冒泡排序...)
 ************************************************************************/
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <queue>

using namespace std;

struct Node  //树节点结构体
{
    int data;
    Node * left;
    Node * right;
};

class Btree
{
public:
    Btree(){root = NULL;}
    ~Btree(){freeTree(root);}
    
    Node *getRoot() const {return root;}

    //生成len个随机数并插入树
    void setRandTree(int len); 
    
    //接口,二叉树的插入,小左大右,调用私有insert函数递归
    void insert(int data);
    
    //接口,找到对应值的位置,返回其指针
    //这里有一个问题:如果没找到直接返回空,在外部程序调用了返回节点的内部元素会出现段错误。
    //所以在外部调用要先判断返回值是否为空。
    Node * search(int data) const {return search(root,data);}

    //接口,按值删除
    void delet(int data){delet(root,data);}

    //三种递归遍历,前中后序,调用对应私有成员函数递归
    void prePrint() const {cout << "前序遍历:";prePrint(root);cout << endl;}
    void midPrint() const {cout << "中序遍历:";midPrint(root);cout << endl;}
    void tailPrint() const {cout <<"后序遍历:";tailPrint(root);cout << endl;}
    
    //层序遍历
    void levelPrint();

    //获取节点数
    void showCount() const {cout << "节点数为:" << getCount(root);cout << endl;}
    int getCount() const {return getCount(root);}

    //获取树高
    void showHigh() const {cout << "树 高 为:" << getHight(root);cout << endl;} 
    int getHight() const {return getHight(root);}

    //求第level层节点数
    void showLevelCount(unsigned int level) const 
    {cout << "第" << level << "层的节点数为:" << getLevelCount(root,level) << endl;}
    int getLevelCount(unsigned int level) const {return getLevelCount(root,level);}

    //求叶子节点数
    void showLeafCount() const 
    {cout << "叶子数为:" << getLeafCount(root) << endl;}
    int getLeafCount(){return getLeafCount(root);}

    //镜像反转接口
    void mirroTree(){mirroTree(root);}

    //判断结构相似接口
    void showStructCmp(Node *other) const
    {isStructCmp(root,other) ? cout << "结构相似\n" : cout << "结构不同\n";}
    bool isStructCmp(Node *root1,Node *root2) const ;

    //判断是否为完全二叉树接口
    void showCompleteTree()
    {isCompleteTree() ? cout << "完全二叉树\n" : cout << "非完全二叉树\n";}
    bool isCompleteTree();

    //排序:中序遍历输出
    void sortPrint() const {midPrint();}
    
private:
    //创建新节点
    Node *createNode(int data);

    //递归插入函数,采用排序二叉树的方法插入(每个节点的左子树元素小于节点元素,右子树元素大于节点元素)
    //这种创建方法的中序遍历就是排序后的结果。
    void insert(Node *root,int value);

    //查询函数
    Node *search(Node *root,int data) const;

    //删除函数
    void delet(Node *root,int data);

    //三种递归遍历函数
    void prePrint(Node *root) const ;
    void midPrint(Node *root) const ;
    void tailPrint(Node *root) const ;
    
    //递归获取节点数、树高、
    int getCount(Node *root) const ;
    int getHight(Node *root) const ;

    //递归获取第k层树高
    int getLevelCount(Node *root,unsigned int k) const ;

    //求叶子数
    int getLeafCount(Node *root) const ;

    //镜像翻转函数
    Node *mirroTree(Node *root);

    //释放内存
    void freeTree(Node *root);

    Node * root;
	queue<Node *> q;//此队列用于层序遍历和判断是否为完全二叉树
};

//释放内存
void Btree::freeTree(Node *root)
{
    if(NULL == root)return;
    freeTree(root->left);
    freeTree(root->right);
    delete root;
}

//新建节点
Node * Btree::createNode(int data)
{
    Node *newnode = new(Node);
    newnode->left = NULL;
    newnode->right = NULL;
    newnode->data = data;
    return newnode;
}

//随机生成树
void Btree::setRandTree(int len)
{
    cout << "插入随机数:";
    srand((unsigned)time(NULL));
    for(int i = 0;i < len; i++)
    {
        int num = rand()%99 + 1;
        cout << num << " ";
        insert(num);
    }
    cout << endl;
}

//插入接口
void Btree::insert(int data)
{
    if(NULL == root)  //空树插入在根节点
    {
        root = createNode(data);
        return;
    }
    insert(root,data);
}

//递归插入
void Btree::insert(Node *root,int data)
{
    if(NULL == root)
    {
        return;
    }
    if(NULL == root->left && data < root->data)
    {
        root->left = createNode(data);
        root->left->data = data;
        return;
    }
    if(NULL == root->right && data >= root->data)
    {
        root->right = createNode(data);
        root->right->data = data;
        return;
    }
    if(data < root->data)
    {
        insert(root->left,data);
    }
    else
    {
        insert(root->right,data);
    }
}

//按值查找
Node *Btree::search(Node *root,int data) const
{
    if(NULL == root)return NULL; //危险做法,如果在外部直接调用其返回结构体的内部成员会出现段错误
    if(data == root->data) return root;
    return data > root->data ? search(root->right,data) : search (root->left,data);
}

//按值删除
void Btree::delet(Node *root,int data)
{
    Node *temp = search(root,data);
	if(temp == NULL)
	{
		cout << "cannt find value!\n";
	}
	else
	{
        if(NULL == temp->left && NULL == temp->right)
        {
            delete temp;
        }
		if(NULL == temp->right)  //右子树为空,左孩子替换根节点
		{
			Node *p = temp->left; 
            temp->data = p->data;
			temp->left = p->left;
			delete p;
		}
		else if(NULL == temp->left)  //左子树为空,右孩子替换
		{
			Node *p = temp->right;
            temp->data = p->data;
			temp->right = p->right;
			delete p;
		}
		else  //左右子树都不为空,用右子树中最小的元素替换(也可以用左子树最大元素替换)
		{
			Node *min = temp->right;
			while(min->left)  //此插入法右子树最小元素一定是最左下方的一个
			{
				min = min->left;
            }
            temp->data = min->data;  //将最小的元素数据赋给该节点
            if(min == temp->right)  //右子树最小为右孩子
            {
                temp->right = min->right;
            }
            else
            {
			    if(NULL != min->right)  
                {
                    Node *p = min->right;
                    min = min->right; //由其右子树顶替最小位置
                    delete p;
                }
            }
            delete min;
		}	
	}
}

//前序遍历
void Btree::prePrint(Node *root) const 
{
    if(NULL == root)return;
    cout << root->data << " ";
    prePrint(root->left);
    prePrint(root->right);
}

//中序遍历
void Btree::midPrint(Node *root) const 
{
    if(NULL == root)return;
    midPrint(root->left);
    cout << root->data << " ";
    midPrint(root->right);
}

//后序遍历
void Btree::tailPrint(Node *root) const 
{
    if(NULL == root)return;   
    tailPrint(root->left);
    tailPrint(root->right);
    cout << root->data << " ";
}

//层序遍历
void Btree::levelPrint()
{
    cout << "层序遍历:";
    if(NULL == root)return;
    q.push(root);
    while(1)
    {
        int count = q.size();
        if(count == 0)break;
        while(count--)
        {
            Node * temp = q.front();
            q.pop();
            cout << temp->data << " ";
            if(NULL != temp->left)q.push(temp->left);
            if(NULL != temp->right)q.push(temp->right);
        }
    }
    cout << endl;
}

//获取节点数
int Btree::getCount(Node *root) const 
{
    if(NULL == root)return 0;

    return 1 + getCount(root->left) + getCount(root->right); 
}

//获取层高
int Btree::getHight(Node *root) const 
{
    if(NULL == root)return 0; //空树0层

    int lefthight = getHight(root->left);
    int righthight = getHight(root->right);

    return lefthight > righthight ? lefthight + 1 : righthight + 1;
}

//求level层节点数
int Btree::getLevelCount(Node *root,unsigned int level) const 
{
    if(NULL == root || level)return 0; //空树,level为0无节点 
    if(level == 1)return 1;  //一层一个根节点
    int leftcount = getLevelCount(root->left,level - 1); //递归遍历左右子树,直到其遍历到指定层,返回1
    int rightcount = getLevelCount(root->right,level - 1);
    return leftcount + rightcount;
}

//求叶子数
int Btree::getLeafCount(Node *root) const 
{
    if(NULL == root)return 0;//空树无叶
    if(NULL == root->left && NULL == root->right)return 1;//叶子节点判断条件
    int leftcount = getLeafCount(root->left);  //非叶子节点递归求其左右子树叶子数
    int rightcount = getLeafCount(root->right);
    return leftcount + rightcount; 
}

//镜像翻转
Node * Btree::mirroTree(Node *root) 
{
    if(NULL == root)return NULL;
    Node *leftNode = mirroTree(root->left);
    Node *rightNode = mirroTree(root->right);
    root->left = rightNode;
    root->right = leftNode;
    return root;
}

//判断结构相似树
bool Btree::isStructCmp(Node *root1,Node *root2) const 
{
    if(root1 == NULL && root2 == NULL)
	{
		return 1;
	}
	else if(root1 == NULL || root2 == NULL)
	{
		return 0;
	}
	int leftcmp = isStructCmp(root1->left,root2->left);
	int rightcmp = isStructCmp(root1->right,root2->right);
	return leftcmp && rightcmp;
}

//判断是否为完全二叉树
bool Btree::isCompleteTree() 
{
    if(root == NULL)return 0;
	q.push(root);  //根节点入队列
	int leaf = 0;  //叶子结点标志位
	while(q.size() != 0)  //队列结束条件
	{
        Node *temp = q.front();  //弹出队列里的根节点
        q.pop();
		if(leaf == 0)  //已经出现叶子结点
		{
			if(temp->left != NULL || temp->right != NULL)
			{
				return 0;
				break;
			}
			if(temp->left != NULL && temp->right != NULL)
			{
				q.push(temp->left);
				q.push(temp->right);
			}
			else if(temp->left != NULL && temp->right == NULL)
			{
				leaf = 1;
				q.push(temp->left);
			}
			else if(temp->left == NULL && temp->right != NULL)
			{
				return 0;
				break;
			}
		}
	}
	return 1;    
}

int main()
{
    Btree bt;
    bt.setRandTree(10);
    cout << "插入35~39\n";
    for(int i = 35; i < 40; i++) bt.insert(i);
    if(Node *node = bt.search(35))
    {
        cout << "search(6)返回指针读出的数据:" << node->data << endl; 
    }
    bt.prePrint();
    bt.midPrint();
    bt.tailPrint();
    bt.levelPrint();
    cout << "删除37后:\n";
    bt.delet(37);
    bt.levelPrint();
#if 1  
    bt.showCount();
    bt.showHigh();
    bt.getLevelCount(3);
    bt.mirroTree();
    bt.levelPrint();
    Btree bt1;
    bt1.setRandTree(10);
    //由于两个树随机生成,极大概率非完全二叉树和结构不同
    bt.showStructCmp(bt1.getRoot());  
    bt.showStructCmp(bt.getRoot());//跟自己的结构比较结果相同
    bt.showCompleteTree();
#endif

}

运行结果:

插入随机数:43 88 85 95 8 60 37 53 72 25 
插入35~39
search(6)返回指针读出的数据:35
前序遍历:43 8 37 25 35 36 37 38 39 88 85 60 53 72 95 
中序遍历:8 25 35 36 37 37 38 39 43 53 60 72 85 88 95 
后序遍历:36 35 25 39 38 37 37 8 53 72 60 85 95 88 43 
层序遍历:43 8 88 37 85 95 25 37 60 35 38 53 72 36 39 
删除37后:
层序遍历:43 8 88 37 85 95 25 38 60 35 39 53 72 36 
节点数为:14
树 高 为:6
层序遍历:43 88 8 95 85 37 60 38 25 72 53 39 35 36 
插入随机数:43 88 85 95 8 60 37 53 72 25 
结构不同
结构相似
非完全二叉树
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

念念⁡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值