树与二叉树 p162

本文详细介绍了多种二叉树的操作和遍历算法,包括根据前序和中序序列构造二叉树、计算节点数量、查找叶子节点、建立叶子节点链表、设置节点的父节点指针、先序后序转换、查找节点层数以及二叉树的双序遍历。此外,还涉及了中序线索二叉树中节点的特定操作,如寻找子树中最后一个节点、中序前驱和前序后继。这些算法都是二叉树数据结构的重要组成部分。
摘要由CSDN通过智能技术生成

1、根据前序序列和中序序列构造二叉树,假设结点数据值互不相同。

确定根节点在中序中的位置,将中序序列分为两个子序列,递归处理直到所处理的子序列只剩下一个元素

BTnode *CreateBt(char pre[],char in[],int l1,int r1,int l2,int r2){
	BTnode *s;
	int i;
	if(l1>r1) return NULL; //递归结束条件 
	s=(BTnode *)malloc(sizeof(BTnode));
	s->lchild=S->rchild=NULL;
	for(i=l2;i<=r2;i++)
		if(in[i]==pre[l1]) break;
	s->data=in[i];   //确定根节点位置 
	s->lchild=CreateBt(pre,in,l1+1,l1+i-l2,l2,i-1);
	s->rchild=CreateBt(pre,in,l1+i-l2+1,r1,i+1,r2);
	return s; 
} 

2、二叉链存储结构

(1)设计算法计算给定二叉树的所有节点

实质遍历二叉树

int n=0;    //先序遍历
void count(BTnode *p){
	if(p){
		++n;
		count(p->lchild);
		count(p->rchild);
	}
}

//后序遍历
int count(BTnode *p){
	int n1,n2;
	if(p==NULL){
		return 0;
	}
	else {
		n1=count(p->lchild);
		n2=count(p->rchild);
		return 1+n1+n2;
	}
}

(2)计算给定二叉树的所有叶子结点

int n=0;     //采用前序遍历 
void count(BTnode *p){
	if(p){
		if(p->lchild==NULL&&p->rchild==NULL) ++n;
		count(p->lchild);
		count(p->rchild);
	}
} 

//对应后序遍历 
int count(BTnode *p){
	int n1,n2;
	if(p==NULL){
		return 0;
	}else if(p->lchild==NULL&&p->rchild==NULL)   return 1;
	else {
		n1=count(p->lchild);
		n2=count(p->rchild);
		return n1+n2;
	}
}  

(3)利用节点右孩子指针将一棵二叉树的叶子结点从左向右串成单链表(题目中定义两个指针,head和tail,head指向第一个叶子结点初值为NULL,tail指向最后一个叶子结点)

遍历过程中只在遇到叶子结点的时候对其右指针进行操作

void link(BTnode *p,BTnode *&head,BTnode *&tail){
	if(p){
		if(p->lchild==NULL&&p->rchild==NULL){
			if(head==NULL){  //找到第一个叶子结点,确定链表头 
				head=p;
				tail=p;
			}
			else {         //不是第一个叶子结点,则尾插法构建链表 
				tail->rchild=p;
				tail=p;
			}
		} 
		link(p->lchild,head,tail);    //先序遍历 
		link(p->rchild,head,tail) ;
	}
} 

(4)增加一个指向双亲结点的parent指针,设计算法给这个指针赋值,并输出所有节点到根节点的路径

修改二叉链表结点数据结构,将所有结点的parent指针指向双亲结点,打印所有节点到根节点的路径。

typedef struct BTnode{
	char data;
	struct BTnode *rchild;
	struct BTnode *lchild;
	struct BTnode *parent;
}BTnode;
//给parent指针赋值 
void triBTree(BTnode *p,BTnode *q){//q始终指向当前访问结点p的双亲结点 
	if(p){
		p->parent=q;
		q=p;
		triBTree(p->lchild,q);
		triBTree(p->rchild,q);
	}	
}
//任给一个节点求其到根节点的路径 
void printPath(BTnode *p){
	while(p){
		printf("%d",p->data);
		p=p->parent;
	}
}

(6)假设满二叉树b的先序序列存在长度为n的数组中,设计算法将其转换为后序遍历序列

只需将根节点移动到整个序列的末尾,然后继续递归处理序列的前一半和后一半

void change(char pre[],int l1,int r1,char post[],int l2,int r2){
	if(l1<=r1){
		post[r2]=pre[l1];
		change(pre,l1+1,(l1+1+r1)/2,post,l2,(l2+r2-1)/2);
		change(pre,(l1+1+r1)/2+1,r1,post,(l2+r2-1)/2+1,r2-1);
	}
}

(7)二叉链表存储二叉树,设计算法求二叉树b中值为x的结点的层号

int L=1;
void high_x(BTnode *b,int x){
	if(b){
		if(p->data==x) printf("%d",L);
		++L;
		high_x(p->lchild,x);
		high_x(p->rchild,x);
		--L;	
	}
}

(10)二叉树的双序遍历:对于二叉树的每个节点,先访问这个节点,再按照双序遍历它的左子树,然后再一次访问这个节点,再双序遍历右子树。

void Double_order(BTnode *t){
	if(t){
		Visit(t); //已经定义的访问t的函数 
		Double_order(t->lchild);
		Visit(t) ;
		Double_order(t->rchild);
	}
}

(11)设中序线索二叉树类型为TBTnode *InThTree

(1)设计算法在一棵中序线索二叉树中寻找节点t的子树上中序下的最后一个节点

沿着t的右子树链一直走下去,直到遇到其右指针为右线索的节点为止

TBTnode *inLast(TBTnode *t){
	TBTnode *p=t;
	while(p&&!p->rtag)	p=p->rchild;
	return p;
}

(2)找t的中序前驱

若t有左线索,则其左线索所指结点即为中序前驱;若无左线索,则其左子树中中序最后一个节点为它的中序前驱

TBTnode *inPrior(TBTnode *t){
	TBTnode *p=t->lchild;
	if(p&&!t->ltag) p=inLast(p);
	return p;
}

(3)找t的前序后继

分三种情况:1、节点有左孩子 2、节点只有右孩子  3、节点没有孩子,此时其前序后继是此节点的右线索走到无右线索节点这个节点就是前序后继

TBTnode *preNext(TBTnode *t){
	TBTnode *p;
	if(!t->ltag) p=t->lchild;
	else if(!t->rtag) p=t->rchild;
	else{
		p=t;
		while(p&&p->rtag) p=p->rchild;
		if(p) p=p->rchild;
	}
	return p;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值