树状打印任意形式二叉树

树状打印任意形式二叉树

高度为8的二叉树打印最终效果:
在这里插入图片描述树状打印任意形式二叉树_第1张图片
二叉树高度大概为6、7时,宽度就超过了控制台的最大宽度,所以没有用cout输出,而是输出为一个文件,所以声明了一个ofstream(out_file)。
注:输出后用记事本和sublime都没有预期的显示效果,需要用Notepad打开。

为了压缩显示面积,每个节点(节点宽度最好是奇数)之间相隔为1,原本树的三角形表示用_、/、\代替。

因为有些二叉树不是完全二叉树,没有子节点的时候不需要打印连接的线,为了方便判断以及层次遍历,先用一个string类型的数组list保存一下要打印的节点内容。
下方代码中code是HFNode的一个成员变量,保存节点的顺序,比如根节点的左孩子是0,右孩子是1,根节点左孩子的右孩子就是01(即Huffman树的译码规则)。另一个成员变量id就是要打印的节点内容。
默认数组最大长度为1024,足够打印10层的二叉树。(试着打过一次17层的树,文件有20M,Notepad加载相当缓慢。)

之后比较麻烦的地方就是空格、下划线的计数,可以自己画一个方格布数格子。

部分源代码如下:

template <class T>
void Huffman<T>::PrintTree(string out_file_name)
{
	ofstream out_file(out_file_name);
	int height = 0;
	int i, j, k ,l , pos;
	string str;
	string list[1024];
	//初始化
	for (i = 0; i < 1024; i++)
		list[i] = "   ";
	list[1] = "XXX";

	//层次遍历,但不能遍历root,因为root的code为空
	if (root == NULL)
		return;
	queue<HFNode<T>*> q;
	q.push(root->LeftChild);
	q.push(root->RightChild);
	while (!q.empty())
	{
		for (i = 0; i < q.size(); i++)
		{
			HFNode<T>* p = q.front();
			q.pop();
			if (p->LeftChild)
				q.push(p->LeftChild);
			if (p->RightChild)
				q.push(p->RightChild);
			if (!p)
				break;
			if (p->code.length() > height)
				height = p->code.length();

			//先利用code找到对应的数组位置
			pos = 1;
			str = p->code;
			for (j = 0; j < str.length(); j++)
			{
				pos *= 2;
				if (str[j] == '1')
					pos++;
			}
			//进行赋值
			if (p->id != -1)
				list[pos] = std::to_string(p->id);
			else
				list[pos] = "XXX";
		}
	}
	height++;

	//先打印节点
	int s = pow(2, height) - 1;	
	int h = height;
	for (i = 1; i <= s; i++)
	{
		for (j = 0; j < pow(2, h - 1) - 1; j++)
			out_file << "  ";
		out_file << setw(3) << setfill('0') << list[i];
		for (j = 0; j < pow(2, h - 1) - 1; j++)
			out_file << "  ";
		out_file << ' ';
		//打印完节点后,下一行打印连接线条
		if (i == pow(2, height - h + 1) - 1)
		{
			out_file << endl;
			if (i == s)
				break;
			for (k = i+1; k <= 2 * i + 1; k++)
			{
				if (list[k] == "   ")
					for (l = 0; l < pow(2, h) - 1; l++)
						out_file << ' ';
				else
				{
					if (k % 2 == 0)
					{
						for (l = 0; l < pow(2, h - 1); l++)
							out_file << ' ';
						for (l = 0; l < pow(2, h - 1) - 2; l++)
							out_file << '_';
						out_file << '/';
					}
					else
					{
						out_file << '\\';
						for (l = 0; l < pow(2, h - 1) - 2; l++)
							out_file << '_';
						for (l = 0; l < pow(2, h - 1); l++)
							out_file << ' ';
					}
				}
				out_file << ' ';
			}

			out_file << endl;
			
			//连接线第二行的\和/
			for (k = i + 1; k <= 2 * i + 1; k++)
			{
				if (list[k] == "   ")
					for (l = 0; l < pow(2, h) - 1; l++)
						out_file << ' ';
				else
				{
					if (k % 2 == 0)
					{
						for (l = 0; l < pow(2, h - 1) - 1; l++)
							out_file << ' ';
						out_file << '/';
						for (l = 0; l < pow(2, h - 1) - 1; l++)
							out_file << ' ';
					}
					else
					{
						for (l = 0; l < pow(2, h - 1) - 1; l++)
							out_file << ' ';
						out_file << '\\';
						for (l = 0; l < pow(2, h - 1) - 1; l++)
							out_file << ' ';
					}
				}
				out_file << ' ';
			}
			out_file << endl;
			h--;
		}
	}
}

你可能感兴趣的:(小技巧)