First exercise:构建前序遍历输入的二叉树

题目要求:根据键盘输入的二叉树前序遍历序列构建相应的二叉树,并计算该二叉树的叶子结点个数。

#include<iostream>
int num = 0;

//二叉树节点的固定格式
struct TreeNode
{
	char val;
	TreeNode* left;
	TreeNode* right;
};
class Tree 
{
public:
	Tree();
	~Tree();
	TreeNode* Getroot() { return root; }//为了使root为private
	void CountLeaf(TreeNode* root);
private:
	TreeNode* root;
	TreeNode* CreateTree();
	void DestoryTree(TreeNode* root);	
};
/*Tree::Tree(int x)
{
	root->val = x;
	root->right = NULL;
	root->left = NULL;
}*/
//曾错误地写成上述内容,上述内容无法和CreateTree()构建联系
Tree::Tree()
{
	root = CreateTree();//一定要给root赋值呀!!!!在此处犯过错:曾错误地只调用CreateTree()函数,未赋值给root,报错0xcccccccc。
}
Tree::~Tree() 
{
	DestoryTree(root);
}
TreeNode* Tree::CreatTree()//注意返回类型、类限定的前后顺序,注意指针*的位置,踩过坑
{
	TreeNode* root;
	char a;
	std::cin >> a;

	if (a == '#')
		return NULL;
	else 
	{
		root = new TreeNode;//new函数知识点不牢固,容易忘记
		root->val = a;
		root->left = CreateTree();//一定要递归调用呀!!
		root->right = CreateTree();
	}
	return root;
}
void Tree::CountLeaf(TreeNode* root)
{
	if (root != NULL)//非常重要,不然root为空再找子节点时,会报错
	{
		std::cout << root->val << ' ';
		if (root->left == NULL && root->right == NULL)
			num++;
		else
		{
			CountLeaf(root->left);
			CountLeaf(root->right);
		}
	}
}   
void Tree::DestoryTree(TreeNode* root)
{
	if (root != NULL)//先释放叶子子树,再释放根(注意顺序,踩过坑)
	{
		DestoryTree(root->left);
		DestoryTree(root->right);
		delete root;
	}	
}
void main()
{
	std::cout << "根据键盘输入创建一棵二叉树" << std::endl;
	Tree tree;
	std::cout << "前序遍历结果是" << std::endl;
	tree.CountLeaf(tree.Getroot());
	std::cout << std::endl;
	std::cout << "二叉树的叶子结点数为" << num << std::endl;	
}

查看理解参考程序之后,自己动手半独立实现,这个过程中发现了以下未被重视的小问题(犯过的部分错误,已在程序中注释)。因此,一定要自己动手,尽可能独立完成,千万不能眼高手低

  1. 由于忘记在构造函数中给root赋值,导致报错0xcccccccc。
    对于0xcccccccc和0xcdcdcdcd,在 Debug模式下,VC会把未初始化的栈内存上的指针全部填成 0xcccccccc,当字符串看就是 “烫烫烫烫……”;会把未初始化的堆内存上的指针全部填成 0xcdcdcdcd,当字符串看就是 “屯屯屯屯……”;对于0xfeeefeee,是用来标记堆上已经释放掉的内存。
    下面两篇文章有对此的具体解释。
    内存中常见异常值的解释(比如0xcccccccc异常值)
    关于C++中野指针的说明
  2. new与delete知识点掌握不牢固
    总是忘记使用new,如在CreatTree()函数中;
    程序执行完之后,自动跳到了析构函数,执行DestoryTree();
    关于new和delete的使用,可参考文章new和delete用法
  3. 析构函数
    C++ 析构函数中提到的下面内容目前不是特别理解:

如果我们写了析构函数,就必须要注意三法则:同时编写:析构函数、赋值构造函数、赋值运算符。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值