天天看点

打印二叉树的边界节点(c++实现)

       这段代码是根据别人的代码修改而来,网上关于这个题目的代码很多,但是很多代码都没有注释,甚至有相当一部分人的代码都是错误 。这段代码在vs2013已经跑通,特别是二叉树的建立需要花费一点时间去分析。由于要准备秋招,才开始准备学习结构与算法,如果有更好的解法麻烦留言!

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

struct Tree {
	int data;
	Tree *left;
	Tree *right;
	Tree(int data) :data(data), left(NULL), right(NULL){}
};

Tree* T;
Tree* edgeMap[100 + 5][5]; //此数组是用来接纳树两边边界点,数组的大小需要根据实际的需要进行分析,个人能力有限,尚没有优化,应该利用容器能够实现大小动态规划

void createBtiTree(Tree* &tree)  //创建二叉树
{
	int data;
	cin >> data;
	if (data == -1)
	{
		tree = NULL;
	}
	else
	{
		tree = new Tree(0);
		tree->data = data;
		createBtiTree(tree->left);
		createBtiTree(tree->right);
	}
}

int getHeight(Tree* tree, int l)  //求树的高度,l代表树高
{
	if (tree == NULL)
		return l;

	return max(getHeight(tree->left, l + 1), getHeight(tree->right, l + 1));  //得出树的最大高度
}

void setEdgeMap(Tree* tree, int l) //将二叉树中最左边数和最有边数赋值给edgeMap数组
{
	if (tree == NULL)
		return;
	
	if (edgeMap[l][0] == NULL)
		edgeMap[l][0] = tree;

	edgeMap[l][1] = tree;
	setEdgeMap(tree->left, l + 1); 
	setEdgeMap(tree->right, l + 1);
}

void printleafNotInMap(Tree* h, int l) //打印叶节点,打印出的叶节点不包括edgeMap数组中元素,这是为了防止节点被重复打印
{
	if (h == NULL)
		return;
	if (h->left == NULL && h->right == NULL && edgeMap[l][0] != h && edgeMap[l][1] != h)
		cout << h->data << " ";

	printleafNotInMap(h->left, l + 1);
	printleafNotInMap(h->right, l + 1);
}

void printEdge(Tree* tree)
{
	int height = getHeight(tree, 0);
	setEdgeMap(tree, 0);

	for (int i = 0; i < height; i++)   //左边元素从上至下打印
		cout << edgeMap[i][0]->data << " ";

	printleafNotInMap(tree, 0);    //底部叶节点从左至右打印

	while ((--height) >= 0)
		if (edgeMap[height][0] != edgeMap[height][1])  //右边的元素从下至上打印,至此,正好实现了题目要求(逆时针打印)
			cout << edgeMap[height][1]->data << " ";

	cout << endl;
}

int main()
{
	createBtiTree(T);  //创建数的过程比较复杂,需要认真分析,一个反复递归的过程,特别需要注意,创建树的结束条件是-1,所以最好在草稿纸上面演算
	printEdge(T);
	return 0;
}