二叉树——创建、先序遍历、中序遍历、后序遍历、层序遍历、先序和中序序列构建二叉树、先序和后序序列构建二叉树、非递归中序遍历、非递归先序遍历、非递归后续遍历(王道版)

参考王道《2023年数据结构考研复习指导》

#include <iostream>

typedef int ElemType;

// 链式存储二叉树
typedef struct BiTNode {
	ElemType data;
	struct BiTNode* lchild, * rchild;
} BiTNode, * BiTree;

// 链式队列结点(存储二叉树结点指针)
typedef struct LinkNode {
	BiTNode* data;			// 类型为二叉树结点指针
	struct LinkNode* next;
} LinkNode;

// 链式队列
typedef struct LinkQueue {
	LinkNode* front, * rear;
} LinkQueue;

// 链栈(带头结点)
typedef struct LiStackNode {
	BiTNode* data;
	struct LiStackNode* next;
} LiStackNode, * LiStack;

bool CreateTree(BiTree& T, ElemType* datagroup, int length);
bool PreTree(BiTree& T, ElemType* datagroup, int length, int& i);
void visit(BiTNode* p);
void PreOrder(BiTree T);
void InOrder(BiTree T);
void PostOrder(BiTree T);
bool InitQueue(LinkQueue& Q);
bool IsEmpty(LinkQueue Q);
bool EnQueue(LinkQueue& Q, BiTNode* x);
bool DeQueue(LinkQueue& Q, BiTNode*& x);
void DestroyQueue(LinkQueue& Q);
void LevelOrder(BiTree T);
void BuildTreeByPreOrderAndInOrder(BiTree& T, ElemType* preOrder, ElemType* inOrder, int preb, int pree, int inb, int ine);
void BuildTreeByInOrderAndPostOrder(BiTree& T, ElemType* inOrder, ElemType* postOrder, int inb, int ine, int postb, int poste);
bool InitStack(LiStack& S);
bool StackEmpty(LiStack S);
bool Push(LiStack& S, BiTNode* p);
bool Pop(LiStack& S, BiTNode*& p);
bool GetTop(LiStack S, BiTNode*& p);
void DestroyStack(LiStack& S);
void InOrder2(BiTree T);
void PreOrder2(BiTree T);
void PostOrder2(BiTree T);

int main() {
	BiTree T;
	ElemType datagroup[] = { 1, 2, 4, -1, -1, 5, -1, -1, 3, 6, -1, 7, -1, -1, -1 };

	CreateTree(T, datagroup, sizeof(datagroup) / sizeof(datagroup[0]));
	PreOrder(T);
	std::cout << std::endl;
	InOrder(T);
	std::cout << std::endl;
	PostOrder(T);
	std::cout << std::endl;
	LevelOrder(T);
	std::cout << std::endl;

	ElemType preOrder[] = { 1, 2, 4, 5, 3, 6, 7 };
	ElemType inOrder[] = { 4, 2, 5, 1, 6, 7, 3 };
	ElemType postOrder[] = { 4, 5, 2, 7, 6, 3, 1 };

	BiTree T2;
	BuildTreeByPreOrderAndInOrder(T2, preOrder, inOrder, 0, 6, 0, 6);
	PreOrder(T2);
	std::cout << std::endl;

	BiTree T3;
	BuildTreeByInOrderAndPostOrder(T3, inOrder, postOrder, 0, 6, 0, 6);
	PreOrder(T3);
	std::cout << std::endl;

	InOrder2(T);
	std::cout << std::endl;

	PreOrder2(T);
	std::cout << std::endl;

	PostOrder2(T);
	std::cout << std::endl;

	system("pause");
	return 0;
}

// 创建二叉树
// datagroup数组的元素的值作为树中各个节点的数据,并规定如果某个元素的值为-1,表示对应的节点是NULL节点。
bool CreateTree(BiTree& T, ElemType* datagroup, int length) {
	int i = 0;		// 数组指针
	return PreTree(T, datagroup, length, i);
}

// 创建二叉树(按照先序遍历方式,组成一个棵树)
bool PreTree(BiTree& T, ElemType* datagroup, int length, int& i) {
	if (i >= length || datagroup[i] == -1) {
		T = NULL;
		i++;
		return true;
	}

	T = (BiTNode*)malloc(sizeof(BiTNode));

	if (T == NULL)
		return false;

	T->data = datagroup[i++];
	return PreTree(T->lchild, datagroup, length, i) && PreTree(T->rchild, datagroup, length, i);
}

/*==================================================================*/
// 访问二叉树结点的操作
void visit(BiTNode* p) {
	std::cout << p->data << " ";
}

// 先序遍历
void PreOrder(BiTree T) {
	if (T != NULL) {
		visit(T);
		PreOrder(T->lchild);
		PreOrder(T->rchild);
	}
}

// 中序遍历
void InOrder(BiTree T) {
	if (T != NULL) {
		InOrder(T->lchild);
		visit(T);
		InOrder(T->rchild);
	}
}

// 后序遍历
void PostOrder(BiTree T) {
	if (T != NULL) {
		PostOrder(T->lchild);
		PostOrder(T->rchild);
		visit(T);
	}
}

/*==================================================================*/
// 初始化队列(带头结点)
bool InitQueue(LinkQueue& Q) {
	Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
	if (Q.front == NULL)
		return false;

	Q.front->next = NULL;
	return true;
}

// 判断队列是否为空
bool IsEmpty(LinkQueue Q) {
	if (Q.front == Q.rear)
		return true;
	else
		return false;
}

// 入队(带头结点)
bool EnQueue(LinkQueue& Q, BiTNode* x) {
	LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
	if (s == NULL)
		return false;
	s->data = x;
	s->next = NULL;
	Q.rear->next = s;
	Q.rear = s;
	return true;
}

// 出队(带头结点)
bool DeQueue(LinkQueue& Q, BiTNode*& x) {
	if (IsEmpty(Q))
		return false;

	LinkNode* p = Q.front->next;
	x = p->data;
	Q.front->next = p->next;
	if (p == Q.rear)			// 若此时是最后一个结点出队
		Q.rear = Q.front;
	free(p);
	return true;
}

void DestroyQueue(LinkQueue& Q) {
	LinkNode* p = Q.front->next;
	LinkNode* q;
	while (p != NULL) {
		q = p;
		p = p->next;
		free(q);
	}
	free(Q.front);
	Q.front = Q.rear = NULL;
}

/*==================================================================*/
// 层序遍历
void LevelOrder(BiTree T) {
	LinkQueue Q;
	InitQueue(Q);
	EnQueue(Q, T);
	BiTNode* p;
	while (!IsEmpty(Q)) {
		DeQueue(Q, p);
		visit(p);
		if (p->lchild != NULL)
			EnQueue(Q, p->lchild);
		if (p->rchild != NULL)
			EnQueue(Q, p->rchild);
	}
	DestroyQueue(Q);
}

/*==================================================================*/
// 根据先序序列和中序序列构造二叉树
// preb和pree分别指示了这个树的先序序列在preOrder中的起始和终止位置
// inb和ine分别指示了这个树的中序序列在inOrder中的起始和终止位置
void BuildTreeByPreOrderAndInOrder(BiTree& T, ElemType* preOrder, ElemType* inOrder, int preb, int pree, int inb, int ine) {
	T = (BiTNode*)malloc(sizeof(BiTNode));
	if (T == NULL)
		return;
	T->data = preOrder[preb];

	int i = inb, k;
	while (inOrder[i] != preOrder[preb] && i <= ine)		// 找到根节点在中序序列中的位置
		i++;
	k = i - inb;		// 左子树中结点个数

	if (i == inb)		// 说明没有左子树
		T->lchild = NULL;
	else
		BuildTreeByPreOrderAndInOrder(T->lchild, preOrder, inOrder, preb + 1, k + preb, inb, i - 1);	// 构造左子树
	if (i == ine)		// 说明没有右子树
		T->rchild = NULL;
	else
		BuildTreeByPreOrderAndInOrder(T->rchild, preOrder, inOrder, k + preb + 1, pree, i + 1, ine);	// 构造右子树
}

/*==================================================================*/
// 根据先序序列和后序序列构造二叉树
// inb和ine分别指示了这个树的中序序列在inOrder中的起始和终止位置
// postb和poste分别指示了这个树的后序序列在postOrder中的起始和终止位置
void BuildTreeByInOrderAndPostOrder(BiTree& T, ElemType* inOrder, ElemType* postOrder, int inb, int ine, int postb, int poste) {
	T = (BiTNode*)malloc(sizeof(BiTNode));
	if (T == NULL)
		return;
	T->data = postOrder[poste];

	int i = inb, k;
	while (inOrder[i] != postOrder[poste] && i <= ine)		// 找到根节点在中序序列中的位置
		i++;
	k = i - inb;		// 左子树中结点个数

	if (i == inb)		// 说明没有左子树
		T->lchild = NULL;
	else
		BuildTreeByInOrderAndPostOrder(T->lchild, inOrder, postOrder, inb, i - 1, postb, postb + k - 1);	// 构造左子树
	if (i == ine)		// 说明没有右子树
		T->rchild = NULL;
	else
		BuildTreeByInOrderAndPostOrder(T->rchild, inOrder, postOrder, i + 1, ine, postb + k, poste - 1);	// 构造右子树
}
/*==================================================================*/
// 初始化链栈(带头结点)
bool InitStack(LiStack& S) {
	S = (LiStackNode*)malloc(sizeof(LiStackNode));
	if (S == NULL)				// 内存分配失败
		return false;

	S->next = NULL;
	return true;
}

// 判断栈空
bool StackEmpty(LiStack S) {
	if (S->next == NULL)
		return true;
	else
		return false;
}

// 进栈操作——新元素入栈
bool Push(LiStack& S, BiTNode* p) {
	LiStackNode* q = (LiStackNode*)malloc(sizeof(LiStackNode));
	if (q == NULL)				// 内存分配失败
		return false;

	q->data = p;
	q->next = S->next;
	S->next = q;
	return true;
}

// 出栈操作
bool Pop(LiStack& S, BiTNode*& p) {
	if (S->next == NULL)		// 栈空,报错
		return false;

	LiStackNode* q = S->next;
	p = q->data;
	S->next = q->next;
	free(q);
	return true;
}

// 读栈顶操作
bool GetTop(LiStack S, BiTNode*& p) {
	if (S->next == NULL)		// 栈空,报错
		return false;

	p = S->next->data;
	return true;
}

// 销毁链栈
void DestroyStack(LiStack& S) {
	LiStackNode* p = S->next;
	LiStackNode* q;
	while (p != NULL) {
		q = p;
		p = p->next;
		free(q);
	}
	free(S);
	S = NULL;
}

/*==================================================================*/
// 中序遍历的非递归算法
void InOrder2(BiTree T) {
	LiStack S;
	InitStack(S);
	BiTNode* p = T;
	while (p || !StackEmpty(S)) {	// 栈不空或p不空时循环
		if (p) {					// 一路向左
			Push(S, p);				// 当前节点入栈
			p = p->lchild;			// 左孩子不空,一直向左走
		}
		else {						// 出栈,并转向出栈结点的右子树
			Pop(S, p);				// 栈顶元素出栈
			visit(p);				// 访问出栈结点
			p = p->rchild;			// 向右子树走,下一步找右子树第一个访问的结点(最左下角第一个结点)
		}
	}
	DestroyStack(S);
}

// 先序遍历的非递归算法
void PreOrder2(BiTree T) {
	LiStack S;
	InitStack(S);
	BiTNode* p = T;
	while (p || !StackEmpty(S)) {	// 栈不空或p不空时循环
		if (p) {					// 一路向左
			visit(p);				// 访问当前结点(根节点)
			Push(S, p);				// 当前节点入栈(当左孩子访问完后,访问右孩子)
			p = p->lchild;			// 左孩子不空,一直向左走(先序遍历左子树)
		}
		else {						// 出栈,并转向出栈结点的右子树
			Pop(S, p);				// 栈顶元素出栈
			p = p->rchild;			// 向右子树走,p赋值为当前结点的右孩子
		}
	}
	DestroyStack(S);
}

// 后序遍历的非递归算法
void PostOrder2(BiTree T) {
	LiStack S;
	InitStack(S);
	BiTNode* p = T;
	BiTNode* pre = NULL;			// 记录前驱结点
	while (p || !StackEmpty(S)) {	// 栈不空或p不空时循环
		if (p) {					// 一路向左
			Push(S, p);				// 当前节点入栈(当左孩子访问完后,访问右孩子)
			p = p->lchild;			// 左孩子不空,一直向左走(后序遍历左子树)
		}
		else {						// 向右
			GetTop(S, p);			// 读栈顶元素(因为根节点最后访问,当右子树还未访问时,根节点不能出栈)
			if (p->rchild && p->rchild != pre)	// 当右子树存在,且未被访问过(根节点的前驱为它的右孩子,pre记录上一个访问的结点)
				p = p->rchild;		// 转向右子树,后序遍历右子树
			else {					// 当右子树不存在,或者右子树被访问过
				Pop(S, p);			// 将根节点弹出
				visit(p);			// 访问根节点
				pre = p;			// 更新前驱结点
				p = NULL;			// 结点访问完后,重置p指针(因为根节点左右子树都被访问过了,下一个访问的结点是该根节点的父节点或右兄弟子树)
			}
		}
	}
	DestroyStack(S);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈阿土i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值