二叉树生成与打印显示 c语言实现

3 篇文章 1 订阅
3 篇文章 0 订阅

程序效果

刷题时有个二叉树可视化的程序就好了,于是乎自己写了一个。将"__Tree codes.cpp"及"__Tree codes.h"导入即可使用。 一个 bt_print(root) 函数即可完成二叉树可视化。
先上二叉树打印效果图:
![二叉树打印效果](https://img-blog.csdnimg.cn/20190512104111921.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzUxMjY2Mw==,size_16,color_FFFFFF,t_7

接口

从数组生成二叉树的函数以及打印二叉树的函数为:

// 从nums数组生成二叉树。数组元素须为小于等与999的正整数,空节点以宏定义numMeansNull表示。
struct TreeNode *createTreeFromArray(int *nums, int numsSize);
// 打印二叉树bt
void bt_print(TreeNode *bt);

使用举例

上图的二叉树是由如下数组生成的:

int nums[] = { 15,54,87,1,45,20,4,88,452,10,20,13,2,150,5, 6,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 };
struct TreeNode* root = createTreeFromArray(nums, sizeof(nums) / sizeof(nums[0]));
bt_print(root);

如果有部分节点为空,则数组中对应位置的元素应设置成与 numMeansNull 相等的值,numMeansNull被宏定义为-1.
如下代码

int nums[] = { 15,54,87,1,45,20,4,88,452,-1,-1,13,-1,150,5, 6,-1,3,4,5,6,7,8,9,-1,11,12,13,14,15,16 };
struct TreeNode* root = createTreeFromArray(nums, sizeof(nums) / sizeof(nums[0]));
bt_print(root);

生成的二叉树如下
在这里插入图片描述

完整的程序

可从我的代码库 https://github.com/zqxl/leetcode 下载。
完整代码如下:

“__Tree codes.h”

/*二叉树生成与打印程序*/
#pragma once
#include<stdio.h>
#include<vector>
#include<math.h>
#include<malloc.h>

// 数组中数值等与此值的元素将被视为二叉树中的空节点
#define numMeansNull -1

// Definition for a binary tree node.
struct TreeNode {
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

// 从nums数组生成二叉树。数组元素须为小于等与999的正整数,空节点以宏定义numMeansNull表示。
struct TreeNode *createTreeFromArray(int *nums, int numsSize);
// 打印二叉树bt
void bt_print(TreeNode *bt);

“__Tree codes.cpp”

#include"__Tree codes.h"

void calTreeDepth(TreeNode *t);
void setPrintBuffer(TreeNode *t);

// 由二维数组生成二叉树
struct TreeNode *createTreeFromArray(int *nums, int numsSize) {
	struct TreeNode *nodes = (struct TreeNode*)calloc(numsSize, sizeof(struct TreeNode));
	for (int i = 0; i < numsSize; i++) {
		nodes[i].val = nums[i];
		int child = i * 2 + 1;
		nodes[i].left = (child < numsSize && nums[child] != numMeansNull) ? &nodes[child] : NULL;
		child = i * 2 + 2;
		nodes[i].right = (child < numsSize && nums[child] != numMeansNull) ? &nodes[child] : NULL;
	}
	return &nodes[0];
}

// 当前节点的深度
int depth = 0;
// 该树的深度,如果只有根节点则深度为1
int depthMax = 0;
// 打印缓冲区的宽度,当前应打印的列数,上次打印位置的列数
int width = 0, column = 0, lastColumn = 0;
char **printBuffer = NULL;

void bt_print(TreeNode *bt) {
	depth = 0;
	column = 0;
	lastColumn = 0;
	depthMax = 0;
	// 根据树的大小申请内存
	calTreeDepth(bt);
	width = 3 * ((1 << (depthMax - 1)) * 2 - 1);
	int height = 1 + (depthMax - 1) * 3;
	printBuffer = (char**)malloc(height *sizeof(char*));
	for (int i = 0; i < height; i++) {
		printBuffer[i] = (char*)malloc(width * sizeof(char));
		memset(printBuffer[i],' ',width);
		printBuffer[i][width - 1] = '\0';
	}

	depth = 0;
	column = width / 2;
	lastColumn = column;
	setPrintBuffer(bt);
	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width; j++) {
			printf("%c", printBuffer[i][j]);
		}
		printf("\n");
	}

}

// 递归找到该树的最大深度
void calTreeDepth(TreeNode *t) {
	if (t) {
		depth++;
		depthMax = depthMax < depth ? depth : depthMax;
		calTreeDepth(t->left);
		calTreeDepth(t->right);
		depth--;
	}
}

// 先序遍历,将数据设置到打印缓冲区
void setPrintBuffer(TreeNode *t) {
	if (t) {
		depth++;

		int val = t->val;
		for (int i = 0; i < 3; i++) {
			printBuffer[(depth - 1) * 3][column+1-i] = val%10 + 0x30;
			val /= 10;
		}
		if (depth > 1) {
			int linkLineInterval =  (column- lastColumn)/3;
			char linkChar = linkLineInterval > 0 ? '\\' : '/';
			printBuffer[(depth - 1) * 3 - 1][column - linkLineInterval] = linkChar;
			printBuffer[(depth - 1) * 3 - 2][column - 2*linkLineInterval] = linkChar;
		}
		
		int step = (1<<(depthMax-depth-1))*3;

		lastColumn = column;
		column -= step;
		setPrintBuffer(t->left);
		column += step;

		lastColumn = column;
		column += step;
		setPrintBuffer(t->right);
		column -= step;
		depth--;
	}
}

测试程序:

#include"__Tree codes.h"

int main() {
	int nums[] = { 15,54,87,1,45,20,4,88,452,-1,-1,13,-1,150,5, 6,-1,3,4,5,6,7,8,9,-1,11,12,13,14,15,16 };
	struct TreeNode* root = createTreeFromArray(nums, sizeof(nums) / sizeof(nums[0]));
	bt_print(root);
	getchar();
	return 0;
}
  • 15
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
二叉树的顺序存储是将二叉树的节点按照从上到下、从左到右的顺序依次存放在一个数组中,这样可以方便地进行节点的访问和操作。其中,对于第 i 个节点,它的左子节点和右子节点分别存放在数组中的第 2*i 和 2*i+1 个位置上。 下面是c语言实现二叉树顺序存储以及基本操作的代码: ```c #include <stdio.h> #include <stdlib.h> #define MAXSIZE 100 // 定义二叉树节点结构体 typedef struct TreeNode { char data; // 节点数据 } TreeNode; // 定义二叉树结构体 typedef struct BinaryTree { TreeNode nodes[MAXSIZE]; // 存储节点的数组 int size; // 当前节点数 } BinaryTree; // 初始化二叉树 void init(BinaryTree *tree) { tree->size = 0; } // 生成新节点 TreeNode* newNode(char data) { TreeNode *node = (TreeNode*)malloc(sizeof(TreeNode)); node->data = data; return node; } // 在二叉树中插入新节点 void insert(BinaryTree *tree, char data) { if (tree->size >= MAXSIZE) { printf("Error: the binary tree is full!\n"); return; } TreeNode *node = newNode(data); tree->nodes[++tree->size] = *node; } // 获取指定节点的左子节点 TreeNode* getLeftChild(BinaryTree *tree, int index) { int leftChildIndex = 2 * index; if (leftChildIndex > tree->size) { printf("Error: the node does not have left child!\n"); return NULL; } return &tree->nodes[leftChildIndex]; } // 获取指定节点的右子节点 TreeNode* getRightChild(BinaryTree *tree, int index) { int rightChildIndex = 2 * index + 1; if (rightChildIndex > tree->size) { printf("Error: the node does not have right child!\n"); return NULL; } return &tree->nodes[rightChildIndex]; } // 获取指定节点的父节点 TreeNode* getParent(BinaryTree *tree, int index) { if (index <= 1 || index > tree->size) { printf("Error: the node does not have parent!\n"); return NULL; } return &tree->nodes[index/2]; } // 打印节点的数据 void printNode(TreeNode *node) { printf("%c ", node->data); } // 先序遍历二叉树 void preOrderTraversal(BinaryTree *tree, int index) { if (index > tree->size) { return; } printNode(&tree->nodes[index]); preOrderTraversal(tree, 2*index); preOrderTraversal(tree, 2*index+1); } // 中序遍历二叉树 void inOrderTraversal(BinaryTree *tree, int index) { if (index > tree->size) { return; } inOrderTraversal(tree, 2*index); printNode(&tree->nodes[index]); inOrderTraversal(tree, 2*index+1); } // 后序遍历二叉树 void postOrderTraversal(BinaryTree *tree, int index) { if (index > tree->size) { return; } postOrderTraversal(tree, 2*index); postOrderTraversal(tree, 2*index+1); printNode(&tree->nodes[index]); } int main() { BinaryTree tree; init(&tree); insert(&tree, 'A'); insert(&tree, 'B'); insert(&tree, 'C'); insert(&tree, 'D'); insert(&tree, 'E'); printf("preOrderTraversal: "); preOrderTraversal(&tree, 1); printf("\n"); printf("inOrderTraversal: "); inOrderTraversal(&tree, 1); printf("\n"); printf("postOrderTraversal: "); postOrderTraversal(&tree, 1); printf("\n"); return 0; } ``` 在上面的代码中,我们定义了一个 `BinaryTree` 结构体,其中包含了一个 `TreeNode` 类型的数组 `nodes` 来存储节点,还有一个 `size` 变量来记录当前节点数。同时,我们还定义了几个函数来实现二叉树的基本操作,例如插入新节点、获取子节点和父节点、遍历等等。最后,在 `main` 函数中,我们向二叉树中插入了 5 个节点,并分别进行了先序、中序和后序遍历。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值