赞
踩
目录
主要用到队列操作,先入队根结点,再不断出队,判断出队结点是否有左右孩子,有则入队,直到队列空为止。
层次遍历挺简单,但是如果要输出结点序列时分清该结点所在的深度则需要稍微变化一点,思路如下:
参考代码如下:
- int TraversByLevel(BTNode<char> *T) {
- if (!T) return -1;
- BTNode<char>* p = T;
- BTNode<char>* last_one = T;
- BTNode<char>* pre_last;
- std::queue <BTNode<char>*> qu;
- qu.push(p);
- while (!qu.empty()) {
- p = qu.front();
- qu.pop();
- printf("%c ", p->value);
- if (p->rchild) {
- pre_last = (BTNode<char> *)p->rchild;
- } else if (p->lchild) {
- pre_last = (BTNode<char> *)p->lchild;
- }
- if (p == last_one) {
- printf("\n");
- if (p->rchild) {
- last_one = (BTNode<char> *)p->rchild;
- } else if (p->lchild) {
- last_one = (BTNode<char> *)p->lchild;
- } else {
- last_one = pre_last;
- }
- }
- if (p->lchild) {
- qu.push((BTNode<char> *)p->lchild);
- }
- if (p->rchild) {
- qu.push((BTNode<char> *)p->rchild);
- }
- }
- printf("\n");
- return 0;
- }

运行效果(下面是的是二叉树的打印,具体参看后文):
这个东西搞了我两天,不过最后写出来还是挺开心的,先来展示下打印一棵满二叉树的成果吧。
先讲讲思路吧:
然后就是程序编写了,一开始我是在层次遍历上改的,但是发现,只能满足打印满二叉树,因为我设置了一个变量,当结点行处理完就处理关系行,可是发现,关系行处理时出队结点固定了,无法读取之前结点的左右关系,并且当不是二叉树时,遇到空树就完全无法处理了,让后我就想了:无论什么二叉树都是一棵满二叉删删减减变的,那我就按照满二叉处理任何二叉树。然后就设计如下思路:
参考代码如下(upToInt为向上取整,fillWith为向字符串中填写指定个数的字符,返回值为buffer行数):
- int BTreePrintToStrArr(BTNode<char> *T, char buffer[][STR_MAX], int size) {
- if (!T || !buffer) return -1;
- BTNode<char>* p = T;
- int height;
- int tatolCol;
- int spaces[3];
- int gap[2];
- int count;
- int i, j, k;
- std::queue <BTNode<char>*> qu_travers;
- std::queue <BTNode<char>*> qu_print;
- // init
- memset(buffer, 0, size*sizeof(char));
- height = getBTreeDepth(T);
- tatolCol = upToInt(pow(2, height - 2)*6 - 1);
- gap[0] = (int)
- (0.0417*pow(height,5)
- - 0.6667*pow(height,4)
- + 4.4583*pow(height,3)
- - 13.333*pow(height,2)
- + 18.5*height - 9);
- spaces[0] = upToInt(tatolCol/2.0);
- count = i = j = k = 0;
- qu_travers.push(p);
- while (!qu_travers.empty() && i < height*2) {
- switch (i%2) {
- case 0: // process node
- p = qu_travers.front();
- qu_travers.pop();
- qu_print.push(p);
- if (count == 0) {
- fillWith(&buffer[i][j], ' ', spaces[0] - 1);
- j += spaces[0] - 1;
- } else if ((count+1)%2 == 0) {
- fillWith(&buffer[i][j], ' ', spaces[1]);
- j += spaces[1];
- } else {
- fillWith(&buffer[i][j], ' ', spaces[2]);
- j += spaces[2];
- }
- count++;
- buffer[i][j++] = p?(p->value):' ';
- qu_travers.push(p?(BTNode<char> *)p->lchild:NULL);
- qu_travers.push(p?(BTNode<char> *)p->rchild:NULL);
- if (count == (int)pow(2,(i+1)/2)) {// new line
- buffer[i][j] = '\0';
- i++;
- j = 0;
- k = 0;
- spaces[0] /= 2;
- gap[0] = (int)
- (0.0417*pow(height - i/2,5)
- - 0.6667*pow(height - i/2,4)
- + 4.4583*pow(height - i/2,3)
- - 13.333*pow(height - i/2,2)
- + 18.5*(height - i/2) - 9);
- if (count > 1) {
- gap[1] = (tatolCol - spaces[0]*2 - gap[0]*count - count*2)/(count - 1);
- } else {
- gap[1] = 0;
- }
- }
- break;
- case 1: // process link
- p = qu_print.front();
- qu_print.pop();
- // left
- if (k == 0) {
- fillWith(buffer[i] + j, ' ', spaces[0]);
- j += spaces[0];
- } else {
- fillWith(buffer[i] + j, ' ', gap[1]);
- j += gap[1];
- }
- if (p && p->lchild) {
- buffer[i][j++] = '/';
- } else {
- buffer[i][j++] = ' ';
- }
- k++;
- // right
- fillWith(buffer[i] + j, ' ', gap[0]);
- j += gap[0];
- if (p && p->rchild) {
- buffer[i][j++] = '\\';
- } else {
- buffer[i][j++] = ' ';
- }
- k++;
- if (k >= count*2 || qu_print.empty()) {
- buffer[i][j] = '\0'; j = 0;
- i++;
- spaces[1] = gap[0] + 2;
- if (count > 1) {
- spaces[2] = (tatolCol - (spaces[0]-1)*2 - count*2 - spaces[1]*count)/(count - 1);
- } else {
- spaces[2] = 0;
- }
- count = 0;
- }
- break;
- }
- }
- return i - 1;
- }

满二叉图效果图如下:
其他二叉图效果图如下:
最后还是觉得自己的方法有些冗杂,而且画出来效果不是特别好,至于深度大于6的还未试过,不知道会不会有问题。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。