二叉树基本操作(二) -----显示

来源:互联网 发布:赛为智能人工智能 编辑:程序博客网 时间:2024/06/08 11:49

接上回,简单的在屏幕上面显示二叉树。

方案

显示效果设计

1、显示结构采用满二叉树的结构来显示,不管有多少节点,显示结构只和深度有关(没有的节点,显示空白)
2、显示大小、间隔,以二叉树最后一层为标准,不管二叉树多深,最后一层相邻两个节点距离不变,该距离可定制
3、不同节点之间不应当重叠

实现关键步骤

1、该二叉树的显示和层数有关,层数约大,上层的间距越大,越小,下层的间距越小,
不同层数的二叉树的最终显示,最后一层的间隔都是一样的。
实现:固定间隔,因此二叉树的总宽度近视等于:  间隔 * 最后一层的节点个数
2、坐标问题。
a、Y坐标位置: 节点的深度可以作为印时的Y坐标
b、X坐标位置:由于二叉树每个节点之间的距离都可以安排为上一层节点的1/2,而左右子节点到该节点的距离又相等。所以可以如下安排:
X坐标:       1
1-1/2                        1+1/2
     1/2-1/4     1/2+1/4     3/2-1/4      3/2+1/4
3、打印。由于打印是按行的因此需要实现按层遍历,
借助队列可以实现按层打印
伪代码:
首节点放入队列
while(队列不为空)
弹出并打印当前节点
左右孩子放入队列

实现

1、相关定义

typedef struct BinNodetag{BinNodetag* P;//父节点BinNodetag* L;//左孩子节点BinNodetag* R;//右孩子节点unsigned int index; //节点索引void * data;//节点数据}BinNode;/*****************************************************************打印二叉树使用的数据结构,用于保存二叉树节点数据和位置信息,depth:表示深度位置信息,根节点为1,往下一层为2,按层+1增长local:标示x轴位置信息,根节点为单位1,其左孩子为1-1/2,右孩子为1+1/2。每层的loacl为其父节点的local +/- 0.5^deptheg:  node->L->local = node->local - (1 << depth)*****************************************************************/typedef struct PaintNodetag //{unsigned int depth;//Y轴信息 float local;//X轴信息BinNode *node;//当前节点}PaintNode;
void PaintTree(BinNode *head); //显示打印二叉树
打印时按节点打印,借助打印节点来保存打印信息,用于分层打印

2、获取深度信息

void InWalk_info(BinNode *head, unsigned int *depth, unsigned int *num, unsigned int *max_depth){if (head == NULL){return;}(*num)++;(*depth)++;*max_depth = *max_depth < *depth ? *depth : *max_depth;InWalk_info(head->L, depth, num, max_depth);InWalk_info(head->R, depth, num, max_depth);(*depth)--;return;}void Info(BinNode *head, unsigned int *depth, unsigned int *num){unsigned int temp_depth = 0;*num = 0;InWalk_info(head, &temp_depth, num, depth);return;}

3、定义单个节点打印函数

#define PAINTGAP 2   //length for single word for painting in screen/*************************单个节点打印函数************************************local:x坐标key:在该x出打印的数字finishline:true表示换行访问该函数类似于写日志,local只能递增,没有loacl的地方显示空白,该函数有记忆性,finishline换行时,内部x坐标清零*****************************************************************************/void Paint(unsigned int local, unsigned int key, bool finishline){static unsigned int index = 0;char DotNum[4] = "%xu";char DotSpace[4] = "%xs";DotNum[1] = PAINTGAP + '0';DotSpace[1] = PAINTGAP + '0';while (index < local){printf_s(DotSpace, " ");index++;}if (finishline != true){printf_s(DotNum, key);index++;}else{printf_s(DotSpace, "\n");index = 0;}return;}

4、主函数

void PaintTree(BinNode *head){unsigned int depth = 0;unsigned int num = 0;unsigned int gap;PaintNode paint_node;//save for paint formatPaintNode *paint_dot;BinNode *node;if (head == NULL){return;}Info(head, &depth, &num);_ASSERT(depth < 32);gap = (1 << (depth - 1)); //最大宽度(最后一个层的宽度)paint_node.depth = 1;paint_node.local = 1;paint_node.node = head;queue<PaintNode> paint_queue;paint_queue.push(paint_node);while (!paint_queue.empty()){paint_dot = &paint_queue.front();if (paint_dot->depth != paint_node.depth){Paint(gap, 0, true);}Paint(paint_dot->local * gap, paint_dot->node->index, false);if (paint_dot->node->L != NULL){paint_node.depth = paint_dot->depth + 1;paint_node.local = paint_dot->local - 1.0 / (1 << paint_dot->depth);paint_node.node = paint_dot->node->L;paint_queue.push(paint_node);}if (paint_dot->node->R != NULL){paint_node.depth = paint_dot->depth + 1;paint_node.local = paint_dot->local + 1.0 / (1 << paint_dot->depth);paint_node.node = paint_dot->node->R;paint_queue.push(paint_node);}paint_node.depth = paint_dot->depth;paint_queue.pop();}Paint(gap, 0, true);}

使用上面设计提到的方法得到每个节点的坐标值,再使用总长度*坐标值将其离散化,就可以得到离散的位置,然后按照节点为单位进行打印即可。
其中遍历使用分层遍历的方式。

5、结果展示

a、不同深度的二叉树

b、删除二叉树节点验证

6、附录

测试用例搬运
#include "Factory_BinTree.h"void test1(){BinNode  *head = NULL;BinNode  *node;node = Creat(16);Insert(&head, node);node = Creat(8);Insert(&head, node);node = Creat(24);Insert(&head, node);node = Creat(4);Insert(&head, node);node = Creat(12);Insert(&head, node);node = Creat(16);Insert(&head, node);node = Creat(32);Insert(&head, node);node = Creat(28);Insert(&head, node);node = Creat(2);Insert(&head, node);node = Creat(6);Insert(&head, node);node = Creat(10);Insert(&head, node);node = Creat(14);Insert(&head, node);node = Creat(15);Insert(&head, node);node = Creat(13);Insert(&head, node);node = Creat(11);Insert(&head, node);node = Creat(9);Insert(&head, node);node = Creat(7);Insert(&head, node);node = Creat(5);Insert(&head, node);node = Creat(1);Insert(&head, node);PaintTree(head);Destory(head);return;}void test2(){BinNode  *head = NULL;BinNode  *node;BinNode  *nodeDelet;node = Creat(16);Insert(&head, node);node = Creat(8);Insert(&head, node);//delet nodenodeDelet = node;node = Creat(24);Insert(&head, node);node = Creat(4);Insert(&head, node);node = Creat(12);Insert(&head, node);node = Creat(16);Insert(&head, node);node = Creat(32);Insert(&head, node);node = Creat(28);Insert(&head, node);node = Creat(2);Insert(&head, node);node = Creat(6);Insert(&head, node);node = Creat(10);Insert(&head, node);node = Creat(14);Insert(&head, node);node = Creat(15);Insert(&head, node);node = Creat(13);Insert(&head, node);node = Creat(11);Insert(&head, node);node = Creat(9);Insert(&head, node);node = Creat(7);Insert(&head, node);node = Creat(5);Insert(&head, node);node = Creat(1);Insert(&head, node);Delete(head, nodeDelet);PaintTree(head);Destory(head);}void test3(){BinNode  *head = NULL;BinNode  *node;node = Creat(16);Insert(&head, node);node = Creat(8);Insert(&head, node);node = Creat(24);Insert(&head, node);node = Creat(4);Insert(&head, node);node = Creat(12);Insert(&head, node);node = Creat(16);Insert(&head, node);node = Creat(32);Insert(&head, node);PaintTree(head);Destory(head);return;}void main(){printf("******************************************************\n""这是三层完整结构\n""******************************************************\n");test3();printf("******************************************************\n""这是五层不完整结构\n""******************************************************\n");test1();//删除二叉树节点/*printf("******************************************************\n""删除节点前\n""******************************************************\n");test1();printf("******************************************************\n""删除节点8\n""******************************************************\n");test2();*/return;}


0 0
原创粉丝点击