学习二叉树时,如果能直观显示,测试程序的时候会方便许多。

实现树形打印的标准方法是利用队列,此处参考的是CSDN上的一篇文章:树状显示二叉树, 原程序使用C++实现,这里使用C。

算法中使用了两个队列,一个用于存储树的结点,另一个用于存储打印过程中每个结点对应的信息。

上一篇文章写了可以利用 void 指针来实现模板,这一次嫌麻烦没有用这个方法,复制粘贴了两个队列。

改天试一试能不能把 void 指针的赋值抽象成一套函数来用用。

如同上面那篇文章中介绍的,此打印程序的核心思想是利用父结点的坐标 pos, 和每一层的偏移量 offset 计算左右子结点的位置。

左结点的坐标是 pos - offset, 右结点的坐标是 pos + offset.

实现代码如下:

 1 // content of "BST.h"
 2 #include<stdio.h>
 3 #include<stdlib.h>
 4
 5 // definition of the Tree.
 6
 7 struct Node {
 8     int key;
 9     struct Node *LeftChild;
10     struct Node *RightChild;
11 };
12
13 typedef struct Node *Position;
14 typedef struct Node *SearchTree;
15
16 int GetHeight(SearchTree T);
17 SearchTree Insert(SearchTree T, int data);
18 Position Find(SearchTree T, int data);
19 SearchTree Delete(SearchTree T, int data);
20 Position FindMin(SearchTree T);
21
22 void Error1(char *s);
23
24 // Definition of the Queue of Nodes.
25
26 typedef Position ElementType;
27
28 struct Q_Item {
29     ElementType data;
30     struct Q_Item *next;
31 };
32
33 typedef struct Q_Item *PtrToItem;
34
35 struct Qrec {
36     PtrToItem front, end;
37 };
38
39 typedef struct Qrec *Queue;
40
41 Queue CreateQ(void);
42 void InQ(Queue Q, ElementType data);
43 ElementType OutQ(Queue Q);
44 void Clear(Queue Q);
45 int IsEmpty(Queue Q);
46 int Power(int x, int n);
47
48 // Definition of the Queue of the info needed in PrintDepth.
49
50 struct infoNode {
51     int pos;
52     int space;
53     int level;
54     int newline;
55     struct infoNode *next;
56 };
57
58 typedef struct infoNode *infoItem;
59
60 struct infoQrec {
61     infoItem front, end;
62 };
63
64 typedef struct infoQrec *infoQ;
65
66 infoItem MakeItem(int pos, int space, int level, int newline);
67 infoQ CreateInfoQ(void);
68 void Pushback(infoQ Q, infoItem item);
69 infoItem PopFront(infoQ Q);
70 int InfoQEmpty(infoQ Q);
71
72 // the final function is here
73 75 void PrintDepth_2(SearchTree T);

  1 #include"BST.h"
  2 #define TRUE 1
  3 #define FALSE 0
  4
  5 // the Queue of TreeNodes.
  6
  7 Queue CreateQ(void)
  8 {
  9     Queue Q = (Queue)malloc(sizeof(struct Qrec));
 10     if(!Q)
 11         Error1("out of space for Queue for TreeNode");
 12
 13     Q->front = Q->end = NULL;
 14
 15     return Q;
 16 }
 17
 18 void InQ(Queue Q, ElementType data)
 19 {
 20     PtrToItem newNode = (PtrToItem)malloc(sizeof(ElementType));
 21     if(!newNode)
 22     {
 23         printf("no space for newNode\n");
 24         exit(1);
 25     }
 26
 27     newNode->data = data;
 28     newNode->next = NULL;
 29
 30     if(!Q->end)
 31         Q->front = Q->end = newNode;
 32     else
 33     {
 34         Q->end->next = newNode;
 35         Q->end = newNode;
 36     }
 37 }
 38
 39 ElementType OutQ(Queue Q)
 40 {
 41     ElementType data;
 42     PtrToItem temp;
 43
 44     if(!Q->front)
 45     {
 46         printf("the Queue is empty\n");
 47         exit(1);
 48     }
 49
 50     temp = Q->front;
 51     data = temp->data;
 52
 53     if(temp->next == NULL)
 54         Q->front = Q->end = NULL;
 55     else
 56         Q->front = temp->next;
 57
 58     free(temp);
 59
 60     return data;
 61 }
 62
 63 void Clear(Queue Q)
 64 {
 65     PtrToItem curr, temp;
 66
 67     curr = Q->front;
 68
 69     while(curr)
 70     {
 71         temp = curr;
 72         curr = curr->next;
 73         free(temp);
 74     }
 75
 76     free(Q);
 77
 78 }
 79
 80 int IsEmpty(Queue Q)
 81 {
 82     return Q->front == NULL;
 83 }
 84
 85 int Power(int x, int n)
 86 {
 87     if(n == 0)
 88         return 1;
 89     else if( n % 2 )
 90         return Power(x*x, n/2) * x;
 91     else
 92         return Power(x*x, n/2);
 93 }
 94
 95 // the Queue for printing information.
 96
 97 infoItem MakeItem(int pos, int space, int level, int newline)
 98 {
 99     infoItem newItem = (infoItem)malloc(sizeof(struct infoNode));
100     if(!newItem)
101         Error1("out of space for infoNode");
102
103     newItem->pos = pos;
104     newItem->space = space;
105     newItem->level = level;
106     newItem->newline = newline;
107     newItem->next = NULL;
108
109     return newItem;
110 }
111
112 infoQ CreateInfoQ(void)
113 {
114     infoQ Q = (infoQ)malloc(sizeof(struct infoQrec));
115     if(!Q)
116         Error1("out of space for infoQ");
117
118     Q->front = Q->end = NULL;
119
120     return Q;
121 }
122
123 void Pushback(infoQ Q, infoItem item)
124 {
125     infoItem newItem = item;
126
127     if(!Q->end)
128         Q->front = Q->end = newItem;
129     else
130     {
131         Q->end->next = newItem;
132         Q->end = newItem;
133     }
134 }
135
136 infoItem PopFront(infoQ Q)
137 {
138     infoItem item;
139
140     if(!Q->front)
141         Error1("the Queue is empty");
142
143     item = Q->front;
144
145     if(item->next == NULL)
146         Q->front = Q->end = NULL;
147     else
148         Q->front = item->next;
149
150     return item;
151 }
152
153 void ClearInfoQ(infoQ Q)
154 {
155     infoItem curr, temp;
156
157     curr = Q->front;
158
159     while(curr)
160     {
161         temp = curr;
162         curr = curr->next;
163         free(temp);
164     }
165
166     free(Q);
167
168 }
169
170 int InfoQEmpty(infoQ Q)
171 {
172     return Q->front == NULL;
173 }
174
175
176
177 // this function also print the NULL nodes,
178 // so the tree will look better and prettier,
179 // but also acquire a larger screen because
180 // this function divides the screen into
181 // many blocks, so the space here is consuming.
182 //
183 // |  |  |  |44|  |  |  |
184 // |  |29|  |  |  |66|  |
185 // |11|  |33|  |54|  |77|
186 //
187 // the key idea of this program is:
188 // while the node is not at the bottom,
189 // no matter if there is a node in the tree,
190 // we create a infoItem with the printing information,
191 // and push a NULL into the Queue.
192 // when we pop the elements out of the Queue,
193 // if the Node it contains is a NULL, we print some
194 // blank block, otherwise we print the key in the Node.
195
196
197 void PrintDepth(SearchTree T)
198 {
199     Position currNode;
200     Queue Q = CreateQ();
201     infoQ IQ = CreateInfoQ();
202     infoItem newInfo, currInfo, preInfo;
203     int height = GetHeight(T);
204     int ScreenWidth = Power(2, height+1);
205     int pos, level, space, newline;
206     int dataWidth = 1;    // dataWidth is the width of the block.
207     int i;
208
209     InQ(Q, T);
210     level = 1;
211     pos = ScreenWidth >> level;
212     space = pos;
213     newline = TRUE;
214
215     newInfo = MakeItem(pos, space, level, newline);
216     Pushback(IQ, newInfo);
217
218     preInfo = newInfo;
219
220     while(!IsEmpty(Q))
221     {
222         currNode = OutQ(Q);
223         currInfo = PopFront(IQ);
224
225         if(currInfo->newline)
226             printf("\n");
227
228         for(i=0; i<currInfo->space; i++)
229             printf(" ");
230
231         if(currNode)
232             printf("%d",currNode->key);
233         else
234             printf(" ");
235
236         if(currInfo->level < height+1)   // if the node is not at the bottom,
237         {                    //  always create 2 child nodes.
238             level = currInfo->level + 1;
239             pos = currInfo->pos - (ScreenWidth >> level);  // the left child.
240             if(level > preInfo->level)
241             {
242                 newline = TRUE;
243                 space = pos;
244             }
245             else
246             {
247                 newline = FALSE;
248                 space = pos - preInfo->pos;
249             }
250
251             space--;       // set aside space for the data to be printed.
252             newInfo = MakeItem(pos, space, level, newline);
253
254             Pushback(IQ, newInfo);
255
256             preInfo = newInfo;
257
258             if(currNode)  // if there is a node in a tree, create the left child.
259             {
260                 if(currNode->LeftChild)
261                     InQ(Q, currNode->LeftChild);
262                 else
263                     InQ(Q, NULL);
264             }
265             else      // if there is a NULL, create the "left child" for NULL.
266                 InQ(Q, NULL);
267
268             pos = currInfo->pos + (ScreenWidth >> level); // the right child.
269             newline = FALSE;
270             space = pos - preInfo->pos;
271             space--;
272
273             newInfo = MakeItem(pos, space, level, newline);
274
275             Pushback(IQ, newInfo);
276
277             if(currNode)
278             {
279                 if(currNode->RightChild)
280                     InQ(Q, currNode->RightChild);
281                 else
282                     InQ(Q, NULL);
283             }
284             else
285                 InQ(Q, NULL);
286
287             preInfo = newInfo;
288
289         }
290
291     }
292
293     printf("\n\n");
294 }

转载于:https://www.cnblogs.com/jeffo/p/print_binary_tree.html

C语言树形打印二叉树相关推荐

  1. C语言简单直观打印二叉树

    最直观的打印二叉树,只能用队列记录二叉树的层次遍历,并记录每个节点的层数及这层里的列数,最后再调整位置打印输出.这样的方法实现起来非常麻烦,所以大多打印二叉树的方法都是采用逆90度输出的方法. 如有二 ...

  2. C#刷剑指Offer | 从上到下打印二叉树

    [C#刷题]| 作者 / Edison Zhou 这是EdisonTalk的第288篇原创内容 我们来用之前学到的数据结构知识来刷<剑指Offer>的一些核心题目(精选了其中30+道题目) ...

  3. C语言手写二叉树(链式存储结构)

    C语言手写二叉树(链式存储结构) 二叉树结构 二叉树基本运算 代码 图例(main函数执行过程如下:) 阶段I 阶段II 阶段III 阶段IV 阶段V 先序遍历输出过程 二叉树结构 二叉树可以用顺序存 ...

  4. 横向打印二叉树 java_按树状横向打印二叉树

    问题 假设以二叉链表存储的二叉树中,每个结点所含数据元素均为单字母. 要求实 现二叉树的横向显示问题,如下图所示打印结果. 问题分析 (1) 二叉树的横向显示应是二叉树竖向显示的90°旋转.分析上图可 ...

  5. 分享一个横向打印二叉树图形的方法

    最近想起之前大二学数据结构时测试B树时写了一个打印二叉树的C语言函数,现在突然想把它记录一下,改成打印二叉树的Java实现 效果 上图的二叉树打印效果如下 解释一下这个图,将图顺时针旋转90°,看见有 ...

  6. 二叉树的基本运算实验报告C语言,实验三 二叉树基本操作与应用实验

    实验三 二叉树基本操作与应用实验 第三次实验主要包括两部分内容:1.二叉树基本操作实验:2.二叉树应用-赫夫曼树与赫夫曼编码实验.基本操作包括存储结构建立和遍历算法,本文只给出部分参考程序,请大家尽量 ...

  7. 数据结构c语言版二叉树的顺序存储表示,数据结构(十一) -- C语言版 -- 树 - 二叉树基本概念...

    内容预览 零.读前说明一.二叉树相关概念1.1.定义1.2.性质1.3.满二叉树与完全二叉树1.3.1.满二叉树1.3.2.完全二叉树1.3.3.特点延伸 二.二叉树储存结构2.1.顺序结构存储2.2 ...

  8. C语言数据结构之二叉树的层次建树及遍历方法(前序,中序,后序,层次遍历)

    C语言数据结构之二叉树的层次建树及遍历方法(前序,中序,后序,层次遍历) tips:前些天学习了C语言数据结构链表,栈,队列.今天来学习一下C语言数据结构之二叉树的各种操作. 注意:二叉树的层次建树是 ...

  9. 【剑指Offer】个人学习笔记_32_从上到下打印二叉树 IIIIII

    目录 I 题目: [剑指 Offer 32 - I. 从上到下打印二叉树](https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er- ...

最新文章

  1. R语言使用ggplot2包使用geom_density()函数绘制密度图(填充色、线性设置)实战(density plot)
  2. numpy 修改数据类型
  3. Java 8 - 06 Lambda 和方法引用实战
  4. fileinput 时间_JavaScript_Bootstrap Fileinput文件上传组件用法详解,最近时间空余,总结了一些关...
  5. python怎么打不开图片_为什么pygame打不开图片 各种格式的都试过了
  6. 10 个超炫酷后台控制面板(附 GitHub下载链接)
  7. java学习(37):二维数组
  8. 共享充电宝还在打仗,支付宝已经笑了
  9. spring mvc controller间跳转 重定向 传参
  10. 《Python游戏趣味编程》 第7章 飞机大战
  11. 从外部导入数据进MySQL
  12. neo4j中心度算法(Centrality algorithm)-3.Closeness Centrality algorithm
  13. cdd matlab 算法,求翻译 CDD修复算法
  14. 基于PC的工业控制系统的优缺点分析
  15. VSCode正则表达式搜索
  16. 海康2017校招C++开发岗位笔试题
  17. python批量检索文献pubmed_如何使用PubMed高效检索文献
  18. android 电池续航时间,如何提高安卓手机电池续航能力 这份省电指南拿好
  19. MIT计算机科学录取分数线,美国麻省理工学院分数录取线
  20. C语言实现鼠标连点器

热门文章

  1. hdu3177 贪心
  2. 计算机网络第一章:计算机网络概述
  3. 【Android FFMPEG 开发】FFMPEG 视频播放进度控制 ( 显示播放进度 | 拖动进度条播放 )
  4. 【Android 系统开发】Android框架 与 源码结构
  5. LeetCode 312. Burst Balloons
  6. 2019年六月刷题列表
  7. PHP HashTable总结
  8. NHibernate 状态的概念 以及 小测试
  9. 第22条:理解NSCopying 协议
  10. 02 - Unit010:关联映射