北邮22信通:(13)二叉树 书上重要知识点补充 例4.3 统计结点总数 深度和叶子结点数

北邮22信通一枚~   

跟随课程进度每周更新数据结构与算法的代码和文章 

持续关注作者  解锁更多邮苑信通专属代码~

上一篇文章:

下一篇文章:

目录

一.统计结点总个数

二.统计二叉树深度

三.统计叶子结点总数

四.完整代码

4.1测试int存储类型:

代码部分:

运行结果: 

4.2测试class储存类型:

代码部分:

运行结果: 


***说明***

书上例4.3的代码和思考题~

对上一篇文章的功能有了新补充~

函数主要思想:递归调用。

***说明完毕***

一.统计结点总个数

思路:二叉树结点总数等于其左子树的节点总数+右子树的结点总数+根结点。

代码部分:

template
int bintree::nodecount(binnode* r)
{
	if (r == NULL)
		return 0;
	if (r->leftchild == NULL && r->rightchild == NULL)
		return 1;
	else
	{
		int m = nodecount(r->leftchild);
		int n = nodecount(r->rightchild);
		return m + n + 1;
	}
}

二.统计二叉树深度

代码部分:

思路:保存现场截止。

template
int bintree::height(binnode* r)
{
	if (r == NULL)
		return 0;
	else
	{
		int m = height(r->leftchild);
		int n = height(r->rightchild);
		return m > n ? m + 1 : n + 1;
	}
}

三.统计叶子结点总数

        思路:判断某一处的结点是不是叶子结点,判断条件就是看它左右孩子是否没有。如果都没有,那就是叶子结点。然后调用函数递归来实现整体。

代码部分:

template
int bintree::leafcount(binnode* r)
{
	if (r == NULL)
		return 0;
	if (r->leftchild == NULL && r->rightchild == NULL)
		return 1;
	else
	{
		int m = leafcount(r->leftchild);
		int n = leafcount(r->rightchild);
		return m + n;
	}
}

四.完整代码

4.1测试int存储类型:

代码部分:

#include
#define MAXSIZE 100000
//注意:不能将上面这行宏定义写成
//#define MAXSIZE 1e5
//上面这样写会报错!!
using namespace std;

template
struct binnode
{
	temp data;
	binnode* leftchild;
	binnode* rightchild;
};

template
class bintree
{
private:
	void create(binnode*& r, temp data[], int i, int n);
	void release(binnode* r);
public:
	binnode* root;
	bintree(temp data[], int n);
	void preorder(binnode* r);
	void inorder(binnode* r);
	void postorder(binnode* r);
	void levelorder(binnode* r);

	int nodecount(binnode* r);
	int height(binnode* r);
	int leafcount(binnode* r);
	~bintree();
};

template
void bintree::create(binnode*& r, temp data[], int i, int n)
{
	if (i <= n && data[i - 1] != 0)
	{
		r = new binnode;
		r->data = data[i - 1];
		r->leftchild = r->rightchild = NULL;
		create(r->leftchild, data, 2 * i, n);/*书上代码错误1:向函数传入实参时少传入一个n*/
		create(r->rightchild, data, 2 * i + 1, n);/*书上代码错误同上*/
	}
}

template
bintree::bintree(temp data[], int n)
/*书上代码错误2:构造函数不能有返回值类型,但是书上多加了一个void*/
/*如果构造函数的声明语句写成
void bintree::bintree(temp data[], int n),
程序会报错:不能在构造函数上指定返回值类型*/
{
	create(this->root, data, 1, n);
}

template
void bintree::preorder(binnode* r)
{
	if (r != NULL)
	{
		cout << r->data;//访问结点;
		preorder(r->leftchild);//遍历左子树
		preorder(r->rightchild);//遍历右子树
	}
}

template
void bintree::inorder(binnode* r)
{
	if (r != NULL)
	{
		inorder(r->leftchild);
		cout << r->data;
		inorder(r->rightchild);
	}
}

template
void bintree::postorder(binnode* r)
{
	if (r != NULL)
	{
		postorder(r->leftchild);
		postorder(r->rightchild);
		cout << r->data;
	}
}

template
void bintree::levelorder(binnode* R)
{
	binnode* queue[MAXSIZE];
	int f = 0, r = 0;
	if (R != NULL)
		queue[++r] = R;//根节点入队
	while (f != r)
	{
		binnode* p = queue[++f];//队头元素入队
		cout << p->data;//出队打印
		if (p->leftchild != NULL)
			queue[++r] = p->leftchild;//左孩子入队
		if (p->rightchild != NULL)
			queue[++r] = p->rightchild;//右孩子入队
	}
}

template 
void bintree::release(binnode* r)
{
	if (r != NULL)
	{
		release(r->leftchild);
		release(r->rightchild);
		delete r;
	}
}

/*书上代码错误3:不能在析构函数上指定返回值类型,但是书上代码多了一个void*/
template
bintree::~bintree()
{
	release(this->root);
}

template
int bintree::nodecount(binnode* r)
{
	if (r == NULL)
		return 0;
	if (r->leftchild == NULL && r->rightchild == NULL)
		return 1;
	else
	{
		int m = nodecount(r->leftchild);
		int n = nodecount(r->rightchild);
		return m + n + 1;
	}
}

template
int bintree::height(binnode* r)
{
	if (r == NULL)
		return 0;
	else
	{
		int m = height(r->leftchild);
		int n = height(r->rightchild);
		return m > n ? m + 1 : n + 1;
	}
}

template
int bintree::leafcount(binnode* r)
{
	if (r == NULL)
		return 0;
	if (r->leftchild == NULL && r->rightchild == NULL)
		return 1;
	else
	{
		int m = leafcount(r->leftchild);
		int n = leafcount(r->rightchild);
		return m + n;
	}
}

int main()
{
	system("color 0A");
	int a[5] = { 1,2,3,4,5 };
	bintreebintreee(a, 5);
	cout << "前序遍历:" << endl;
	bintreee.preorder(bintreee.root);
	cout << endl << "中序遍历:" << endl;
	bintreee.inorder(bintreee.root);
	cout << endl << "后序遍历:" << endl;
	bintreee.postorder(bintreee.root);
	cout << endl << "层序遍历:" << endl;
	bintreee.levelorder(bintreee.root);
	cout << endl << "二叉树中的节点总数为:";
	cout << bintreee.nodecount(bintreee.root);
	cout << endl << "二叉树的深度为:";
	cout << bintreee.height(bintreee.root);
	cout << endl << "二叉树的叶子结点数为:";
	cout << bintreee.leafcount(bintreee.root);
	cout << endl;
}

运行结果: 

北邮22信通:(13)二叉树 书上重要知识点补充 例4.3 统计结点总数 深度和叶子结点数_第1张图片

4.2测试class储存类型:

代码部分:

#include
#define MAXSIZE 100000
//注意:不能将上面这行宏定义写成
//#define MAXSIZE 1e5
//上面这样写会报错!!
using namespace std;
class student
{
private:
	int ID;
	string name;
public:
	int existence;
	student()
	{
		this->ID = 0;
		this->name = "unknown name";
		this->existence = 0;
	}
	student(int ID, string name)
	{
		this->ID = ID;
		this->name = name;
		this->existence = 1;
	}
	friend ostream& operator<<(ostream& output, student& s)
	{
		output << s.ID << " " << s.name << endl;
		return output;
	}
};

template
struct binnode
{
	temp data;
	binnode* leftchild;
	binnode* rightchild;
};

template
class bintree
{
private:
	void create(binnode*& r, temp data[], int i, int n);
	void release(binnode* r);
public:
	binnode* root;
	bintree(temp data[], int n);
	void preorder(binnode* r);
	void inorder(binnode* r);
	void postorder(binnode* r);
	void levelorder(binnode* r);

	int nodecount(binnode* r);
	int height(binnode* r);
	int leafcount(binnode* r);
	~bintree();
};

template
void bintree::create(binnode*& r, temp data[], int i, int n)
{
	/*书上代码的一个问题:data[i-1]!=0会报错,这是因为data的数据类型是temp,没法实现!=的运算*/
	//书上原代码
	//if (i <= n && data[i - 1] != 0)
	if (i <= n && data[i - 1].existence != 0)
	{
		r = new binnode;
		r->data = data[i - 1];
		r->leftchild = r->rightchild = NULL;
		create(r->leftchild, data, 2 * i, n);/*书上代码错误1:向函数传入实参时少传入一个n*/
		create(r->rightchild, data, 2 * i + 1, n);/*书上代码错误同上*/
	}
}

template
bintree::bintree(temp data[], int n)
/*书上代码错误2:构造函数不能有返回值类型,但是书上多加了一个void*/
/*如果构造函数的声明语句写成
void bintree::bintree(temp data[], int n),
程序会报错:不能在构造函数上指定返回值类型*/
{
	create(this->root, data, 1, n);
}

template
void bintree::preorder(binnode* r)
{
	if (r != NULL)
	{
		cout << r->data;//访问结点;
		preorder(r->leftchild);//遍历左子树
		preorder(r->rightchild);//遍历右子树
	}
}

template
void bintree::inorder(binnode* r)
{
	if (r != NULL)
	{
		inorder(r->leftchild);
		cout << r->data;
		inorder(r->rightchild);
	}
}

template
void bintree::postorder(binnode* r)
{
	if (r != NULL)
	{
		postorder(r->leftchild);
		postorder(r->rightchild);
		cout << r->data;
	}
}

template
void bintree::levelorder(binnode* R)
{
	binnode* queue[MAXSIZE];
	int f = 0, r = 0;
	if (R != NULL)
		queue[++r] = R;//根节点入队
	while (f != r)
	{
		binnode* p = queue[++f];//队头元素入队
		cout << p->data;//出队打印
		if (p->leftchild != NULL)
			queue[++r] = p->leftchild;//左孩子入队
		if (p->rightchild != NULL)
			queue[++r] = p->rightchild;//右孩子入队
	}
}

template 
void bintree::release(binnode* r)
{
	if (r != NULL)
	{
		release(r->leftchild);
		release(r->rightchild);
		delete r;
	}
}

/*书上代码错误3:不能在析构函数上指定返回值类型,但是书上代码多了一个void*/
template
bintree::~bintree()
{
	release(this->root);
}

template
int bintree::nodecount(binnode* r)
{
	if (r == NULL)
		return 0;
	if (r->leftchild == NULL && r->rightchild == NULL)
		return 1;
	else
	{
		int m = nodecount(r->leftchild);
		int n = nodecount(r->rightchild);
		return m + n + 1;
	}
}

template
int bintree::height(binnode* r)
{
	if (r == NULL)
		return 0;
	else
	{
		int m = height(r->leftchild);
		int n = height(r->rightchild);
		return m > n ? m + 1 : n + 1;
	}
}

template
int bintree::leafcount(binnode* r)
{
	if (r == NULL)
		return 0;
	if (r->leftchild == NULL && r->rightchild == NULL)
		return 1;
	else
	{
		int m = leafcount(r->leftchild);
		int n = leafcount(r->rightchild);
		return m + n;
	}
}

int main()
{
	system("color 0A");
	student stu[5] = { {1,"zhang"},{2,"wang"},{3,"li"},{4,"zhao"},{5,"liu"} };
	bintreebintreee(stu, 5);
	cout << "前序遍历:" << endl;
	bintreee.preorder(bintreee.root);
	/*说明:这里体现了将根节点定义为public类型的好处,
	不然需要通过一个成员函数来实现这个功能,
	从数据保密性来看,这样做也是可以的:
	外部如果不通过调用成员函数,就只能访问根节点一个节点内的数据,
	但是其他任意节点内的数据都无法访问,安全性也相对较高。
	*/
	cout << endl << "中序遍历:" << endl;
	bintreee.inorder(bintreee.root);
	cout << endl << "后序遍历:" << endl;
	bintreee.postorder(bintreee.root);
	cout << endl << "层序遍历:" << endl;
	bintreee.levelorder(bintreee.root);
	cout << endl << "二叉树中的节点总数为:";
	cout << bintreee.nodecount(bintreee.root);
	cout << endl << "二叉树的深度为:";
	cout << bintreee.height(bintreee.root);
	cout << endl << "二叉树的叶子结点数为:";
	cout << bintreee.leafcount(bintreee.root);
	cout << endl;
	return 0;
}

运行结果: 

北邮22信通:(13)二叉树 书上重要知识点补充 例4.3 统计结点总数 深度和叶子结点数_第2张图片

北邮22信通:(13)二叉树 书上重要知识点补充 例4.3 统计结点总数 深度和叶子结点数_第3张图片

你可能感兴趣的:(数据结构,北邮22信通,算法)