剑指offer面试题32:从上到下打印二叉树

题目一:不分行从上到下打印二叉树。从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。二叉树节点定义如下:

struct BinaryTreeNode
{
    int                          m_nValue;
    BinaryTreeNode*  m_pLeft;
    BinaryTreeNode*  m_pRight;
};

思路:相当于二叉树的层次遍历,我们可以通过队列辅助打印:每次打印一个节点的时候,如果该节点有子节点,则把该节点的子节点放入队列的尾部。接下来到队列的头部取出最早进入队列的节点,重复前面的操作,直至队列中所有的节点都被打印出来。

*以下代码未经验证

#define QUEUE_SIZE 1024
typedef struct queue {
	int head;
	int tail;
	BinaryTreeNode *data[QUEUE_SIZE];  // 暂不考虑溢出情况
}my_queue;


void queue_push(my_queue *queue, BinaryTreeNode * val) {
	queue->data[queue->tail] = val;
	queue->tail++;
}

BinaryTreeNode * queue_pop(my_queue *queue) {
	BinaryTreeNode * val = queue->data[queue->head];
	queue->head++;
	return val;
}

int queue_size(my_queue *queue) {
	return queue->tail - queue->head;
}

my_queue *tree_help_queue;
void PrintFromTopToBottom(BinaryTreeNode *pTreeRoot) {
	if (NULL == pTreeRoot) {
		return;
	}
	queue_push(tree_help_queue, pTreeRoot); // 根入队列
	while (0 != queue_size(tree_help_queue)) {
		BinaryTreeNode *tmp = queue_pop(tree_help_queue);
		printf(" %d ", tmp->m_nValue);

		if (pTreeRoot->m_pLeft != NULL) { // 如果该节点有子节点,则把该节点的子节点放入队列的尾部
			queue_push(tree_help_queue, pTreeRoot->m_pLeft);
		}
		if (pTreeRoot->m_pRight != NULL) { // 如果该节点有子节点,则把该节点的子节点放入队列的尾部
			queue_push(tree_help_queue, pTreeRoot->m_pRight);
		}
	}
}

题目二:分行从上到下打印二叉树。从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印,每一层打印到一行。

思路:为了把二叉树的每一行单独打印到一行中,我们需要两个变量,一个变量表示在当前层中还没有打印的节点数;另一个变量表示下一层节点数。

void PrintFromTopToBottomLINE(BinaryTreeNode *pTreeRoot) {
	if (NULL == pTreeRoot) {
		return;
	}
	queue_push(tree_help_queue, pTreeRoot); // 根入队列

	int nextlevelnum = 0;
	int nowlevelneedp = 1;

	while (0 != queue_size(tree_help_queue)) {
		if (pTreeRoot->m_pLeft != NULL) { // 如果该节点有子节点,则把该节点的子节点放入队列的尾部
			queue_push(tree_help_queue, pTreeRoot->m_pLeft);
			nextlevelnum++;

		}
		if (pTreeRoot->m_pRight != NULL) { // 如果该节点有子节点,则把该节点的子节点放入队列的尾部
			queue_push(tree_help_queue, pTreeRoot->m_pRight);
			nextlevelnum++;
		}

		BinaryTreeNode *tmp = queue_pop(tree_help_queue);
		printf(" %d ", tmp->m_nValue);
		nowlevelneedp--;
		if (0 == nowlevelneedp) {
			printf("\n");
			nowlevelneedp = nextlevelnum;
			nextlevelnum = 0;
		}
	}
}

题目三:之字形打印二叉树。请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二行按照从右到左的顺序打印,其他行以此类推。

思路:之字形顺序打印二叉树需要两个栈,在打印某一层的时候,将下一层的节点保存到栈中。如果当前打印的是奇数层,则先保存左子叶节点;如果当前打印的层数是偶数层,则先保存右子叶节点再保存左子叶节点到第二个栈中。为什么需要两个栈,因为一个栈要打印,一个栈保存下一层子叶节点。

#define STACK_SIZE 1024
typedef struct stack {
	int base;
	int top;
	BinaryTreeNode *data[STACK_SIZE];  // 暂不考虑溢出情况
}my_stack;

BinaryTreeNode *stack_top(my_stack *stack) {
	BinaryTreeNode *val = stack->data[stack->top];
	return val;
}

void stack_push(my_stack *stack, BinaryTreeNode *pTreeRoot) {
	stack->data[stack->top] = pTreeRoot;
	stack->top++;
}

BinaryTreeNode *stack_pop(my_stack *stack) {
	stack->top--;
	BinaryTreeNode *val = stack->data[stack->top];
	return val;
}

int stack_size(my_stack *stack) {
	int size = stack->top - stack->base;
	return size;
}

my_stack *tree_help_stack[2];  // need init 
void zhiPrintFromTopToBottom(BinaryTreeNode *pTreeRoot) {
	if (NULL == pTreeRoot) {
		return;
	}

	int current = 0;
	int next = 1;
	stack_push(tree_help_stack[current], pTreeRoot); // 根入栈0

	while (0 != stack_size(tree_help_stack[current]) || 0 != stack_size(tree_help_stack[next])) {
		BinaryTreeNode *tmp = stack_pop(tree_help_stack[current]);
		printf(" %d ", tmp->m_nValue);

		if (0 == current) {
			if (pTreeRoot->m_pLeft != NULL) { // 如果该节点有子节点,该层为从右向左打印,栈先放左子节点
				stack_push(tree_help_stack[next], pTreeRoot->m_pLeft);

			}
			if (pTreeRoot->m_pRight != NULL) { 
				stack_push(tree_help_stack[next], pTreeRoot->m_pLeft);
			}
		}
		else {
			if (pTreeRoot->m_pRight != NULL) {  // 如果该节点有子节点,该层为从左向右打印,栈先放右子节点
				stack_push(tree_help_stack[next], pTreeRoot->m_pLeft);
			}
			if (pTreeRoot->m_pLeft != NULL) { 
				stack_push(tree_help_stack[next], pTreeRoot->m_pLeft);
			}
		}
		// 交换两个栈
		if (0 == stack_size(tree_help_stack[current])) {
			printf("\n");
			current = 1 - current;
			next = 1 - next;
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值