数据结构——二叉树面试题(2)

#pragma once

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

typedef struct BSTreeNode {
	struct BSTreeNode * pLeft;	// prev
	struct BSTreeNode * pRight;	// next
	int data;
}	BSTreeNode;

BSTreeNode * CreateNode(int data)
{
	BSTreeNode *pNode = (BSTreeNode *)malloc(sizeof(BSTreeNode));
	assert(pNode);
	pNode->data = data;
	pNode->pLeft = pNode->pRight = NULL;
	return pNode;
}

// 如果存在,插入失败返回 -1, 否则插入成功,返回 0
int Insert(BSTreeNode **pRoot, int data)
{
	// 递归
	// 1. 空树处理
	// 2. 相等处理
	// 3. 小于根
	// 4. 大于根
	assert(pRoot != NULL);
	if (*pRoot == NULL) {
		// 空树
		*pRoot = CreateNode(data);
		// 记得返回
		return 0;
	}

	if ((*pRoot)->data == data) {
		return -1;
	}

	if (data < (*pRoot)->data) {
		// 1. 记得返回
		// 2. 取地址(字段)
		return Insert(&((*pRoot)->pLeft), data);
	}
	else {
		return Insert(&((*pRoot)->pRight), data);
	}
}

BSTreeNode *pPrev = NULL;	// 留个作业,不要全局变量

// 1. 中序
// 2. 有了结点,怎么构造双向链表
//	1)前驱 + 当前结点
//	2)当前结点 + 后继

void HandleNode(BSTreeNode *pRoot)
{
	// 1. 中序过来了
	// 2. pLeft 是可以更改的
	//printf("%d ", pRoot->data);

	if (pPrev != NULL) {
		pPrev->pRight = pRoot;
	}
	pRoot->pLeft = pPrev;

	// 不断记录 prev
	pPrev = pRoot;
}









void InOrderLoop(BSTreeNode *pRoot)
{
	BSTreeNode *pCur = pRoot;
	BSTreeNode *pTop;

	BSTreeNode *stack[100];
	int top = 0;

	while (pCur != NULL || top > 0) {
		while (pCur) {
			stack[top++] = pCur;
			pCur = pCur->pLeft;
		}

		// 后序的区别
		// 不能直接出栈,需要右子树也遍历完
		// 判断右子树遍历完的方式
		// 1. 右孩子为 NULL
		// 2. 通过一个遍历(pLast)记录上次遍历完的子树
		// 当 pTop->pRight == pLast
		pTop = stack[top - 1];
		top--;

		printf("%d ", pTop->data);

		pCur = pTop->pRight;
	}
}


void PostOrderLoop(BSTreeNode *pRoot)
{
	BSTreeNode *pCur = pRoot;
	BSTreeNode *pTop;
	BSTreeNode *pLast = NULL;

	BSTreeNode *stack[100];
	int top = 0;

	while (pCur != NULL || top > 0) {
		while (pCur) {
			stack[top++] = pCur;
			pCur = pCur->pLeft;
		}

		// 后序的区别
		// 不能直接出栈,需要右子树也遍历完
		// 判断右子树遍历完的方式
		// 1. 右孩子为 NULL
		// 2. 通过一个遍历(pLast)记录上次遍历完的子树
		// 当 pTop->pRight == pLast
		pTop = stack[top - 1];
		if (pTop->pRight == NULL || pTop->pRight == pLast) {
			printf("%d ", pTop->data);
			top--;
			pLast = pTop;
			continue;
		}

		pCur = pTop->pRight;
	}
}




void InOrder(BSTreeNode *pRoot)
{
	if (pRoot == NULL) {
		return;
	}

	InOrder(pRoot->pLeft);
	HandleNode(pRoot);
	InOrder(pRoot->pRight);
}

void Test()
{
	BSTreeNode *pRoot = NULL;
	Insert(&pRoot, 5);
	Insert(&pRoot, 1);
	Insert(&pRoot, 3);
	Insert(&pRoot, 4);
	Insert(&pRoot, 2);
	Insert(&pRoot, 8);
	Insert(&pRoot, 6);
	Insert(&pRoot, 7);
	Insert(&pRoot, 9);

	PostOrderLoop(pRoot);
	printf("\n");
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值