二叉树的后序非递归及使用后序获取两个接点的第一个共同祖先

//2020-04-30
//注意c的结构体赋值并非是传递结构体的引用(指针)
//js和Java写多了容易漏掉这个东西
/**
* 后序遍历:当返回根结点时需要判断是左孩子还是右孩子返回,两种实现方式:
* 1.使用变量记录上一次访问的结点
* 2.创建新的结构,添加tag字段标识结点的左右孩子是否访问,当进入根节点的左右孩子时,无论此时左右是否被访问,
* 都应该设置相应的标志,因为当左右孩子返回根结点时,返回的孩子分支树一定已经被访问过了, 当访问了右孩子时其左孩子一定被访问
*/
#include<stdio.h>
#include<stdlib.h>
#define MAX 100
#define LEFT 0
#define RIGHT 1

typedef int Elem;

typedef struct BTNode {
	Elem e;
	struct BTNode * lChild;
	struct BTNode * rChild;
} * BTNode;

typedef struct {
	BTNode node;
	//标识当前节点是否被访问
	int tag;
} TNode;

BTNode ancestor(BTNode root, Elem p, Elem q);

BTNode buildTree(Elem [], int , int , Elem [], int , int );
void preOrder(BTNode);
void inOrder(BTNode);
void postOrder(BTNode);

int i = 1;

int main(void) {
	Elem A[] = {1,2,4,5,3,6,7};
	Elem B[] = {4,2,5,1,6,3,7};
	
	BTNode obj = buildTree(A, 0, 6, B, 0, 6);
	postOrder(obj);
	//printf("%d", ancestor(obj, 4, 6)->e);

	
	return 0; 
} 

BTNode ancestor(BTNode root, Elem p, Elem q) {
	TNode stack[MAX], ancestor[MAX];
	int top = -1, top_a = -1;
	while(root != NULL || top > -1) {
		if(root) {
			stack[++top] = (TNode){root, LEFT};
			root = root->lChild;
		} else {
			TNode t = stack[top];
			if(t.node->rChild && t.tag == LEFT) {
				t.tag = RIGHT;
				root = root->rChild;
			} else {
				--top;
				if(t.node->e == p) {
					while(top_a < top) {
						top_a++;
						ancestor[top_a] = stack[top_a];
					}
				} else if(t.node->e == q) {
					break;
				}
				root = NULL;				
			}
		}
	}
	int i = 0;
	while(stack[i].node == ancestor[i].node) ++i;
	return stack[--i].node;
	
}

BTNode buildTree(Elem A[], int sa, int ea, Elem B[], int sb, int eb) {
	BTNode node = (BTNode)malloc(sizeof(struct BTNode) * 1);
	node->e = A[sa]; 
	int i = sb;
	for(i; A[sa] != B[i]; ++i);
	int ll = i - sb;
	int rr = eb - i;
	if(ll > 0) {
		node->lChild = buildTree(A, sa + 1, sa + ll, B, sb, sb + ll - 1);
	} else {
		node->lChild = NULL;
	}
	if(rr > 0) {
		node->rChild = buildTree(A, sa + ll + 1, ea, B, sb + ll + 1, eb);
	} else {
		node->rChild = NULL;
	}
	return node;
}

void preOrder(BTNode T) {
	if(T == NULL) return;
	printf("%d ", T -> e);
	preOrder(T->lChild);
	preOrder(T->rChild);
}

void inOrder(BTNode T) {
	if(T == NULL) return;
	inOrder(T->lChild);
	printf("%d ", T -> e);
	inOrder(T->rChild);
}

void postOrder(BTNode T) {
	TNode * stack[MAX];
	BTNode root = T;
	int top = -1;
	while(root != NULL || top > -1) {
		if(root ) {
			TNode * t = (TNode *)malloc(sizeof(TNode));
			t->node = root;
			t->tag = LEFT;
			stack[++top] = t;
			root = root->lChild;
		} else {
			TNode * t = stack[top];
			if(t->node->rChild != NULL && t->tag == LEFT) {
				t->tag = RIGHT;
				root = t->node->rChild;
			} else {
				--top;
				printf("%d ", t->node->e);
				root = NULL;				
			}
		}
	}
	
	
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值