Print binary tree

本文介绍了一个使用队列实现的二叉树数据结构及其可视化方法。通过递归创建平衡二叉树,并采用先序遍历填充节点信息到队列中,最终实现对二叉树结构的打印。文章详细展示了如何计算节点之间的距离、确定每个节点的位置,以及如何逐层打印二叉树。
#include 
#include 

#define ARRAY_SIZE (63)
#define NODE_DISTANCE (4)
#define PRINT_OFFSET (2)

typedef enum _CHILD_DIRECTION
{
	LEFT_CHILD = 1,
	RIGHT_CHILD,
	NOT_CHILD,
}CHILD_DIRECTION;

typedef struct _Node {
	int value;
	struct _Node *left;
	struct _Node *right;
}Node;

typedef struct _NodeInfo {
	struct _Node *node;
	struct _NodeInfo *parent;
	int height;
	int offset;
	int distance_between_nodes;
	CHILD_DIRECTION direction;
}NodeInfo;

static int queue_head_idx = 0, queue_tail_idx = 0;
static NodeInfo node_queue[ARRAY_SIZE+1];

static void queue_reset()
{
	queue_head_idx = queue_tail_idx = 0;
}

static int queue_empty()
{
	return queue_head_idx == queue_tail_idx;
}

static int queue_full()
{
	return ((queue_head_idx+1)%(ARRAY_SIZE+1)) == queue_tail_idx;
}

static void queue_insert(NodeInfo node_info)
{
	if (queue_full() == 0)
	{
		node_queue[queue_head_idx] = node_info;
		queue_head_idx++;
		queue_head_idx = queue_head_idx%(ARRAY_SIZE+1);
	}
}

static NodeInfo queue_offer()
{
	NodeInfo ret_node_info = {0};
	if (queue_empty() == 0)
	{
		ret_node_info = node_queue[queue_tail_idx];
		queue_tail_idx++;
		queue_tail_idx = queue_tail_idx%(ARRAY_SIZE+1);
	}
	return ret_node_info;
}

static Node * create_sub_tree(int *src, int start, int end)
{
	Node *node;
	int mid;
	
	if (start > end) return NULL;

	mid = (start + end)/2;

	node = malloc(sizeof(Node));
	if (node)
	{
		node->value = src[mid];
		node->left = create_sub_tree(src, start, mid -1);
		node->right= create_sub_tree(src, mid+1, end);
	}

	return node;
}

static void create_binary_tree(Node** root, int *src, int size)
{
	printf("create_binary_tree begin\n");

	if (root == NULL) return;
 
	*root = create_sub_tree(src, 0, size-1);
	printf("create_binary_tree end\n");
}

static void print_node(int height, NodeInfo *node_info_ordered, int size)
{
	int i, j, node_idx = 0, last_node_level = height;
	NodeInfo *node_info;
	NodeInfo *parent_node;
	int target_offset, current_offset;
	int current_line_width, node_num_in_current_line;
	
	current_offset = 0;
	target_offset = node_info_ordered[node_idx].distance_between_nodes/2 + PRINT_OFFSET;
	node_info_ordered[node_idx].offset = target_offset;
	node_num_in_current_line = 1;

	while(current_offset < target_offset) {
		printf(" ");
		current_offset++;
	}
	
	while (node_idx < size)
	{
		node_info = &node_info_ordered[node_idx];
		
		if(node_info->height != last_node_level)
		{
			printf("\n");

			parent_node = node_info->parent;
			current_line_width = parent_node->distance_between_nodes/2;
			
			current_offset = 0;
			target_offset = parent_node->offset - (current_line_width/2);
			while(current_offset < target_offset) {
				printf(" ");
				current_offset++;
			}

			for(i=0; iheight;
			node_num_in_current_line *= 2;

			current_offset = 0;
		}
		
		parent_node = node_info->parent;
		if(parent_node != NULL)
		{
			if (node_info->direction == LEFT_CHILD)
			{
				node_info->offset = parent_node->offset - (parent_node->distance_between_nodes/4);
			}
			else
			{
				node_info->offset = parent_node->offset + (parent_node->distance_between_nodes/4);
			}
		}

		target_offset = node_info->offset;
		while(current_offset < target_offset) {
			printf(" ");
			current_offset++;
		}
		current_offset += printf("%d", node_info->node->value);

		node_idx++;
	}

	printf("\n");
}



static int preordering_traverse(int height, Node* root, NodeInfo *node_info_ordered)
{
	NodeInfo node_info = {0};
	Node* node;
	int idx = 0, h;
	int i=1, distance_between_nodes = NODE_DISTANCE;
	while(ileft)
		{
			node_info.node = node->left;
			node_info.height = h-1;
			node_info.parent = &node_info_ordered[idx-1];
			node_info.distance_between_nodes = node_info.parent->distance_between_nodes/2;
			node_info.direction = LEFT_CHILD;
			queue_insert(node_info);
		}

		if (node->right)
		{
			node_info.node = node->right;
			node_info.height = h-1;
			node_info.parent = &node_info_ordered[idx-1];;
			node_info.distance_between_nodes = node_info.parent->distance_between_nodes/2;
			node_info.direction = RIGHT_CHILD;
			queue_insert(node_info);
		}
	}
	return idx;
}

#define TREE_MAX(a,b) (((a)>(b))?(a):(b))
static int calc_tree_height(Node* root)
{
	if(root != NULL)
		return TREE_MAX(1+calc_tree_height(root->left), 1+calc_tree_height(root->right));
	else
		return 0;
}

static void print_tree(Node* root)
{
	int height, offset, size;
	Node *node = root;
	NodeInfo node_queue_ordered[ARRAY_SIZE+1];
	
	height = calc_tree_height(root);

	printf("print_tree height = %d\n", height);

	size = preordering_traverse(height, root, node_queue_ordered);

	print_node(height, node_queue_ordered, size);

	queue_reset();
}

int main()
{
	int a[ARRAY_SIZE] = {3,5,5,1,2,6,8,4,7,9, \
		3,5,5,1,2,6,8,4,7,9, \
		3,5,5,1,3,5,5,1,2,6, \
		8,4,7,9,3,5,5,1,2,6, \
		3,5,5,1,3,5,5,1,2,6, \
		8,4,7,9,3,5,5,1,8,4, \
		7,9,3};
	Node* root;

	printf("print binary tree begin\n");

	create_binary_tree(&root, a, ARRAY_SIZE);

	print_tree(root);
	
	printf("print binary tree end\n");

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值