创建后序线索二叉树并进行后续遍历【C语言代码实现】

后序线索二叉树的创建算法思想:后续遍历树中每一个结点,访问每一对前驱和后继,如果当前结点左孩子为空,则将左孩子指针指向前驱结点,将左指针标记域设置为真;如果前驱结点右孩子指针为空,则将右孩子指针域指向后继结点,将右指针标记域设置为真。

后序遍历后续线索二叉树算法思想:不同于先序与中序遍历寻找当前结点的后继结点,后序遍历是寻找当前结点的前驱结点,并压入栈中,直到遍历完树中所有结点,最后将栈中元素弹出即实现后序遍历二叉树。

寻找当前结点的前驱结点算法思想:如果当前结点左指针标记域为真,即当前结点不存在左孩子,则左指针指向当前孩子的前驱结点;如果当前结点左指针标记域为假,查看当前结点右指针域,如果当前结点右指针域为假,则当前结点存在右孩子,根据后续遍历规则,当前结点的前驱结点为右指针指向的结点;如果如果当前结点左指针标记域为假,且结点右指针域为真,则当前结点不存在右孩子,只存在左孩子,则前驱结点为左孩子指向的结点。

 (1)fun.c

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//树相关数据结构
typedef char ElemType;
typedef struct BSTNode {
	ElemType data;
	struct BSTNode* lchild, * rchild;
	int ltag, rtag;
}BSTNode, * BSTree;
//先序创建树
void creatTree(BSTree& T);
//访问结点
void visit1(BSTNode* pnode);
//后序遍历树,检验建树与遍历是否成功
void postOrder(BSTree T);
//初始化标记位
void initial(BSTree& T);
//后续线索二叉树
//算法思想:后续遍历树中每一个结点,并进行线索化
void postThrTree(BSTNode* pcurnode);
void creatPostBSTree(BSTree T);
//得到当前结点前驱结点
BSTNode* getPreNode(BSTNode* pcurnode);
//通过线索后续遍历线索二叉树;
void postOrderBSTree(BSTree T);

//链栈相关数据结构
typedef char SElemType;
typedef struct LinkNode {
	SElemType data;
	struct LinkNode* next;
}LinkNode, * LinkStack;
//初始化栈
void initial(LinkStack& S);
//判栈空
int isEmpty(LinkStack S);
// 入栈(头部插入)
void push(LinkStack & S, SElemType x);
//出栈(头部删除)
void pop(LinkStack& S, SElemType& x);

(2)Stack.app

#include"func.h"
//初始化栈
void initial(LinkStack& S) {
	S = (LinkNode*)malloc(sizeof(LinkNode));
	S->next = NULL;
}
//判栈空
int isEmpty(LinkStack S) {
	if (S->next == NULL) {
		return 1;
	}
	else {
		return 0;
	}
}
//入栈(头部插入)
void push(LinkStack &S, SElemType x) {
	LinkNode* pnode = (LinkNode*)malloc(sizeof(LinkNode));
	pnode->data = x;
	pnode->next = S->next;
	S->next = pnode;
}
//出栈(头部删除)
void pop(LinkStack& S, SElemType& x) {
	LinkNode* pnode = S->next;
	x = pnode->data;
	S->next = pnode->next;
}

(3)BSTree.cpp

#include"func.h";
//先序创建树
void creatTree(BSTree& T) {
	ElemType ch;
	scanf("%c", &ch);
	if (ch == '#') {
		T = NULL;
	}
	else {
		T = (BSTNode*)malloc(sizeof(BSTNode));
		T->data = ch;
		creatTree(T->lchild);
		creatTree(T->rchild);
	}
}
//访问结点
void visit1(BSTNode* pnode) {
	printf("%c", pnode->data);
}
//后序遍历树,检验建树与遍历是否成功
void postOrder(BSTree T) {
	if (T != NULL) {
		postOrder(T->lchild);
		postOrder(T->rchild);
		visit1(T);
	}
}
//初始化标记位
void initial(BSTree& T) {
	if (T != NULL) {
		T->ltag = 0;
		T->rtag = 0;
		initial(T->lchild);
		initial(T->rchild);
	}
}
//后续线索二叉树
//算法思想:后续遍历树中每一个结点,并进行线索化
BSTNode* prenode = NULL;
void visit2(BSTNode* pcurnode) {
	if (pcurnode->lchild == NULL) {
		pcurnode->lchild = prenode;
		pcurnode->ltag = 1;
	}
	if (prenode != NULL&& prenode->rchild == NULL) {//注意需要先判空,再判右孩子为空,否则会报错
		prenode->rchild = pcurnode;
		prenode->rtag = 1;
	}
	prenode = pcurnode;//更新前驱结点
}
void creatBSTree(BSTree T) {
	if (T != NULL) {
		creatBSTree(T->lchild);
		creatBSTree(T->rchild);
		visit2(T);
	}
}
//后序建树主过程,注意最后一个结点的处理
void creatPostBSTree(BSTree T) {
	prenode = NULL;
	if (T != NULL) {
		creatBSTree(T);
		if (prenode->rchild == NULL) {//处理最后一个结点
			prenode->rtag = 1;
		}
	}
}
//得到当前结点前驱结点
BSTNode* getPreNode(BSTNode* pcurnode) {
	if (pcurnode->ltag == 1) {//如果当前结点左标记为1,则左孩子为前驱结点
		return pcurnode->lchild;
	}//左右根
	else {//否则,当前结点左标记为0,当前结点存在左孩子
		if (pcurnode->rtag == 0) {//如果当前结点右标记为真,根据后续遍历规则,则右孩子为前驱结点
			return pcurnode->rchild;
		}
		else {//否则,当前结点没有右孩子,根据后续遍历规则,当前结点不存在右孩子,存在左孩子,则左孩子为前驱
			return pcurnode->lchild;
		}
	}
}
LinkStack S = NULL;//利用栈存储遍历序列
//通过线索后续遍历线索二叉树
void postOrderBSTree(BSTree T) {
	initial(S);//初始化栈
	for (BSTNode* pcurnode = T; pcurnode != NULL; pcurnode = getPreNode(pcurnode)) {
		push(S, pcurnode->data);//将当前结点数值插入栈中
	}
}
//AB#D##CE###
int main() {
	BSTree Thr = NULL;
	creatTree(Thr);
	postOrder(Thr);
	printf("\n");
	initial(Thr);
	creatPostBSTree(Thr);//后续线索化二叉树
	postOrderBSTree(Thr);//遍历后续线索二叉树
	while (!isEmpty(S)) {
		ElemType x;
		pop(S, x);
		printf("%c", x);
	}
	printf("\n");
}

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个关于C语言和二叉树的问题。 首先,我们需要定义二叉树的数据结构: ```c struct TreeNode { int val; struct TreeNode* left; struct TreeNode* right; }; ``` 接下来,我们可以编写一个函数来根据先和中创建叉树: ```c struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize) { if (preorderSize == 0 || inorderSize == 0) { return NULL; } int rootVal = preorder[0]; struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode)); root->val = rootVal; int rootIndex = 0; for (int i = 0; i < inorderSize; i++) { if (inorder[i] == rootVal) { rootIndex = i; break; } } root->left = buildTree(preorder + 1, rootIndex, inorder, rootIndex); root->right = buildTree(preorder + rootIndex + 1, preorderSize - rootIndex - 1, inorder + rootIndex + 1, inorderSize - rootIndex - 1); return root; } ``` 上述代码中,我们使用递归的方式来根据先和中创建叉树。先列的第一个元素为根节点,通过在中列中找到根节点的位置,可以将中列分为左子树和右子树两部分。然后,递归地调用 buildTree 函数来分别构建左子树和右子树。 接下来,我们可以编写一个函数来进行: ```c void postorderTraversal(struct TreeNode* root) { if (root != NULL) { postorderTraversal(root->left); postorderTraversal(root->right); printf("%d ", root->val); } } ``` 上述代码中,我们使用递归的方式来进行。先遍左子树,再遍右子树,最后访问根节点。 最终的代码如下所示: ```c #include <stdio.h> #include <stdlib.h> struct TreeNode { int val; struct TreeNode* left; struct TreeNode* right; }; struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize) { if (preorderSize == 0 || inorderSize == 0) { return NULL; } int rootVal = preorder[0]; struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode)); root->val = rootVal; int rootIndex = 0; for (int i = 0; i < inorderSize; i++) { if (inorder[i] == rootVal) { rootIndex = i; break; } } root->left = buildTree(preorder + 1, rootIndex, inorder, rootIndex); root->right = buildTree(preorder + rootIndex + 1, preorderSize - rootIndex - 1, inorder + rootIndex + 1, inorderSize - rootIndex - 1); return root; } void postorderTraversal(struct TreeNode* root) { if (root != NULL) { postorderTraversal(root->left); postorderTraversal(root->right); printf("%d ", root->val); } } int main() { int preorder[] = {1, 2, 4, 5, 3}; int inorder[] = {4, 2, 5, 1, 3}; int size = sizeof(preorder) / sizeof(int); struct TreeNode* root = buildTree(preorder, size, inorder, size); postorderTraversal(root); printf("\n"); return 0; } ``` 运行结果如下所示: ``` 4 5 2 3 1 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值