//基于栈的递归消除(后序遍历)
void PostOrder2(BiTree root){
BiTNode *p,*q;
Stack S;
InitStack(&S);
p=root;
while(p!=NULL||IsEmpty(S)){
if(p!=NULL){
Push(&S,p);
p=p->LChild;
}
GetTop(&S,&p);
if(p->Rchild==NULL||p->Rchild==q){
visit(p->data);
q=p;
Pop(&S,&p);
p=NULL;
}else
p=p->Rchild;
}
}
//交换二叉树的左右子树(后序)
void swap(BiTree *root){
if(bt!=NULL){
swap(root->LChild);
swap(root->Rchild);
temp=root->LChild;
root->LChild=root->Rchild;
root->Rchild=temp;
}
}
//层序遍历二叉树
void LevelOrder(BiTree root){
LinkQueue Q;
InitQueue(Q);
BiTNode *p;
EnQueue(&Q,root);
while(IsEmpty(Q)){
DeQueue(&Q,&p);
visit(p->data);
if(p->LChild!=NULL)
EnQueue(&Q,p->LChild);
if(p->RChild!=NULL)
EnQueue(&Q,p->RChild);
}
}
//后序遍历二叉树,一边遍历一边线索化
void PostThread(ThreadTree root){
if(root!=NULL){
PostThread(T->lchild);
PostThread(T->rchild);
visit(T);
}
}
void visit(ThreadNode *q){
if(q->LChild==NULL){//左子树为空,建立前驱线索
q->LChild=pre;
q->Ltag=1;
}
if(pre!=NULL&&pre->RChild==NULL){
pre->RChild=q;
pre->Rtag=1;
}
pre=q;
}
//后序线索化二叉树
void CreatePostThread(Thread T){
if(T!=NULL){
PostThread(T);
if(pre->rchild == NULL) //处理最后一个结点
pre->rtag=1;
}
}
ThreadNode *pre = NULL; //全局变量pre,指向当前访问结点的前驱
void PreOrder(BiTree root,int k,char *e){
int i = 0;
if(root!=NULL){
Visit(root->data);
i++;
if(i==k){
*e = root->data;
}
PreOrder(root->LChild);
PreOrder(root->Rchild);
}
}
//先序线索二叉树中找先序后继
ThreadNode * PrePost(ThreadNode *p){
BiTNode *next,*q;
if(p->LChild!=NULL){
next=p->LChild;
}else{
next=p->Rchild;
}
return next;
}
//后序线索二叉树中找后序前驱
ThreadNode * PostPre(ThreadNode *p){
BiTNode *pre,*q;
if(p->RChild!=NULL){
pre=p->RChild;
}else{
pre=p->Lchild;
}
return pre;
}
//二叉树的自下而上,从右到左的层次遍历算法
void LevelOrder(BiTree root){
SeqStack S;
InitStack(&S);
LinkQueue Q;
InitQueue(&Q);
BiTNode *p;
EnQueue(&Q,root);
Push(&S,root);
while(QueueIsEmpty(Q)){
DeQueue(&Q,&p);
visit(p->data);
if(p->LChild!=NULL){
EnQueue(&Q,p->LChild);
Push(&S,p->LChild);
}
if(p->RChild!=NULL){
EnQueue(&Q,p->RChild);
Push(&S,p->RChild);
}
}//退出while循环 元素以全部放入栈中
//出栈
while(StackIsEmpty(S)==0){ //将栈中结点弹出
BiTNode *temp;
temp = Pop(&S);
printf("%c",temp->data);
}
}
算法的执行步骤:
1、如果树为空,则直接返回错。
2、如果树不为空:层次遍历二叉树 ;
区别不同于单纯的层序遍历
//非递归算法求二叉树的高度
int findTreeHight(BiTree root){
Queue Q; //创建队列
InitQueue(*Q);
BiTree t;
t = root;
EnterQueue(&Q,t);
int h = 0; //记录高度 初始从1开始
int child = 0;
while(!IsEmptyQueue(Q)){
if(t->LChild){
EnterQueue(&Q,t->LChild); //左孩子入队
child++;
}
if(t->RChild){
EnterQueue(&Q,t->RChild); //右孩子入队
child++;
}
DeleteQueue(&Q,&t); //队头出队
if(child == Q.len){ //len为队列中元素个数
h++;
child = 0;
}
}
return h;
}
//求二叉树的高度(后序)
int PostTreeDepth(BiTree bt){
int hl,hr,max;
if(bt!=NULL){
hl=PostTreeDepth(bt->LChild); //求左子树的深度
hr=PostTreeDepth(bt->Rchild); //求右子树的深度
max=hl>hr?hl+1:hr+1;
return max;
}
else return 0;
}
//求二叉树的高度(前序)
int PreTreeDepth(BiTree bt,int h){ //h为bt指向结点的所在层次 初值为1
//可以通过遍历计算二叉树中每个结点的层次
//最大值为二叉树的高度
if(bt!=NULL){
if(h>depth)
depth=h; //depth是全局变量 初始为0
PreTreeDepth(bt->LChild,h+1);
PreTreeDepth(bt->RChild,h+1);
}
return depth;
}
算法的执行步骤:
1、如果树为空,则直接返回错。
2、如果树不为空:层次遍历二叉树 ;
2.1、如果遇到一个结点,左孩子为空,右孩子不为空,则该树一定不是完全二叉树;
2.2、如果一个结点左右孩子都不为空,则pop该节点,将其左右孩子入队列;
2.3、如果遇到一个结点,左孩子不为空,右孩子为空;或者左右孩子都为空;则该节点之后的队列中的结点都为叶子节点; 该树才是完全二叉树,否则就不是完全二叉树。
//判断二叉树是否为完全二叉树
int Judge_Complete(BiTree boot)
{
BiTree t;
LinkQueue Q;//创建一个空队列
InitQueue(Q);
EnQueue(Q,root); //将T的头结点入队
t = root;//给t赋初值T根节点
if(root==NULL)
return 0;
while(IsEmpty(Q))
{
if(t->lchild==NULL && t->rchild!=NULL)//如果左孩子为空右孩子不为空,说明一定不是完全二叉树
return false;
if(t->lchild!=NULL && t->rchild!=NULL)//左右孩子都不为空
{
DeQueue(Q,t);//删除该双亲节点
EnQueue(Q,t->lchild); //将左孩子入队
EnQueue(Q,t->rchild); //将右孩子入队
}
//如果左孩子不为空右孩子为空,或者左右孩子都为空(该节点为叶子结点)
//则该节点之后的所有节点都应该是叶子结点
if((t->lchild!=NULL && t->rchild==NULL) || (t->lchild==NULL && t->rchild==NULL))
{
DeQueue(Q,t); //从刚才判断的节点的下一个节点一次判断剩下队列中的节点是否左右子树都为空
while(IsEmpty(Q))
{
if(t->lchild==NULL && t->rchild==NULL)
DeQueue(Q,t);
else
return false;
}
return true;
}
}
return true;
}
所谓二叉树t1与t2相似,指的是t1与t2都是空二叉树;或者 t1的左子树与t2的左子树相似,同时t1的右子树与t2的右子树相似。
算法的执行步骤:
//二叉树相似性判断
int like(BiTree t1,BiTree t2){
int like1,like2;
if(t1==NULL && t2==NULL){ //t1和t2均为空树 相似,返回1
return 1;
}
else if(t1==NULL || t2==NULL){ //t1和t2其中之一为空树,不相似 ,返回0
return 0;
}
else{
like1 = like(t1->LChild,t2->LChild); //判断t1和t2的左子树是否相似
like2 = like(t1->Rchild,t2->Rchild); //判断t1和t2的右子树是否相似
return (like1&&like2);
}
}
int leafnum; //全局变量 统计叶子结点数目
//对一棵以孩子兄弟链表表示的树统计其叶子结点的数目(左子树为空则为叶子结点)
int getLeafNum(CSTree tree){
if(tree!=NULL){
if(tree->FirstChild!=NULL){
leafnum++; //全局变量 统计叶子结点数目
}
getLeafNum(tree->FirstChild);
getLeafNum(tree->Nextsibling);
}
}
int max=0; //全局变量
//以孩子兄弟表示法存储的树的高度
int getHeight(CSTree tree,int layer){
if(tree!=NULL){
if(layer>max){
max=layer;
}
getHeight(tree->FirstChild,layer+1);
getHeight(tree->Nextsibling,layer);
}
return max;
}
算法的执行步骤:
1、如果树为空,则直接返回错。
2、如果树不为空:遍历二叉树找到值为X的结点
2.1、while循环输出该结点的右结点,直到右结点为NULL
CSNode * PreOrder(CSTree root,char x){
CSNode *temp;
if(root!=NULL){
if(root->data==x){
temp=root;
}
PreOrder(root->LChild);
PreOrder(root->Rchild);
}
return temp;
}
//采用孩子—兄弟表示法存储, 编写算法输出该树中值为X的结点的所有兄弟结点
void BroNodeX(CSTree root,char x,CSNode[] *bro){
int i=0;
CSNode *p;
p=PreOrder(root,x);
p=p->Nextsibling;
while(p!=NULL){
bro[i++]=p;
p=p->Nextsibling;
}
}
算法的执行步骤:
1、如果树为空,则直接返回错。
2、如果树不为空:层次遍历二叉树 ;
//二叉链表存储,求二叉树的宽度
int findTreeWidtht(BiTree root){
Queue Q; //创建队列
InitQueue(*Q);
BiTree t;
t = root;
EnterQueue(&Q,t);
int h = 1; //记录高度 初始高度为1
int num = 0;
int max = 0;
while(!IsEmptyQueue(Q)){
if(t->LChild){
EnterQueue(&Q,t->LChild); //左孩子入队
num++;
}
if(t->RChild){
EnterQueue(&Q,t->RChild); //右孩子入队
num++;
}
DeleteQueue(&Q,&t); //队头出队
if(num == Q.len){ //len为队列中元素个数
if(max<num){
max=num;
}
h++;
num = 0;
}
}
return max;
}
//二叉链表存储,求二叉树根结点到r结点之间的路径
void path(BiTree root,BiTNode *r){
BiTNode *p,*q;
int i,top=0;
BiTree s[Stack_Size];
q=NULL;
p=root;
while(p!=NULL||top!=0){
while(p!=NULL){
top++;
if(top>=Stack_Size)
overFlow(); //栈溢出
s[top]=p;
p=p->LChild; //遍历左子树
}
if(top>0){
p=s[top];
if(p->Rchild==NULL||p->Rchild=q){
if(p==r){ //找到r所指结点,显示从根结点到r结点之间的路径
for(i=1;i<=top;i++)
printf("%d",s[i]->data);
return;
}
else{
q=p; //用q保留刚遍历过的结点
top--;
p=NULL; //跳过前面左遍历,继续退栈
}
}
else p=p->Rchild; //遍历右子树
}
}
}
int find_public(BiTNode T[],int i,int j)//注意这里不是BiTNode* &T
{
if(T[i].data!='#'&&T[j].data!='#')//还要判断结点是否存在
{
while(i!=j)
{
if(i>j)
i=i/2;
else
j=j/2;
}
return i;
}
else
return 0;
}
算法步骤:
参考16题,相当于利用两个栈 保存从根结点分别到结点p,q路径上的所有结点。之后比较两个栈中元素,最先相等的就i是最近的共同祖先
//二叉链表存储,求二叉树结点p q的最近公共祖先
BiTNode * PostOrder2(BiTree root,BiTNode *p,BiTNode *q){
BiTNode *bt,*pre;
int i,j,top1,top=-1;
BiTree S[Stack_Size],S1[Stack_Size];
pre=NULL;
bt=root;
while(bt!=NULL||top!=0){
while(bt!=NULL){
top++;
if(top>=Stack_Size)
overFlow(); //栈溢出
S[top]=bt;
p=p->LChild; //遍历左子树
}
if(top>-1){
bt=S[top];
if(bt->Rchild==NULL||bt->Rchild=pre){
if(bt==p){
for(i=0;i<top;i++){
S1[i]=S[i];
top1=top;
}
}
if(bt==q){
for(i=top;i>-1;i--)
for(j=top1;j>-1;j--){
if(S[i]==S1[j])
return S[i];
}
}
pre=bt; //用pre保留刚遍历过的结点
top--;
bt=NULL; //跳过前面左遍历,继续退栈
}
else bt=bt->Rchild; //遍历右子树
}
}
return NULL;
}
算法分析:删除以元素值为x根的子树,只要能删除其左、右子树,就可以释放值为x的根结点,因此采用后序遍历算法。
算法步骤:
1、遍历二叉树找到值为x的结点
2、调用删除函数,进行删除并释放空间
:因为题中要求删除树中每个元素值为x的结点的子树,因此要遍历完整整棵二叉树
//对于二叉树中每一个值为x的结点,删去以它为根的子树,并释放相应的空间
void DeleteXTree(BiTree *bt){ //删除以bt为根的子树
DeleteXTree(bt->LChild);
DeleteXTree(bt->Rchild);
free(bt);
}
//在二叉树上查找所有以x为元素值的结点,并删除
void SearchX(BiTree bt,char x){
LinkQueue Q;
InitQueue(Q);
BiTNode *p;
EnQueue(&Q,bt);
while(IsEmpty(Q)){
DeQueue(&Q,&p);
if(p->LChild!=NULL){
if(p->LChild->data==x)
DeleteXTree(&(p->LChild));
p->LChild=NULL;
else
EnQueue(&Q,p->LChild);
}
if(p->RChild!=NULL){
if(p->RChild->data==x)
DeleteXTree(&(p->RChild));
p->RChild=NULL;
else
EnQueue(&Q,p->RChild);
}
}
}
算法思路:
同15题、9题,求出第几层 以及每层结点个数累加即可。
//求取一棵二叉树的路径长度
int findTreeWidtht(BiTree root){
Queue Q; //创建队列
InitQueue(*Q);
BiTree t;
t = root;
EnterQueue(&Q,t);
int h = 0; //记录高度
int num = 0;
int wpl = 0;
while(!IsEmptyQueue(Q)){
if(t->LChild){
EnterQueue(&Q,t->LChild); //左孩子入队
num++;
}
if(t->RChild){
EnterQueue(&Q,t->RChild); //右孩子入队
num++;
}
DeleteQueue(&Q,&t); //队头出队
if(num == Q.len){ //len为队列中元素个数
h++;
wpl+=h*num;
num = 0;
}
}
return wpl;
}
//已知先序 中序遍历序列 建立二叉链表
int pos=0;//全局变量
tree build(char pre[],char in[],int begin,int end)
{
if(s<=e)
{
BiTNode *root=(BiTNode *)malloc(sizeof(BiTNode));
root->data=pre[pos];
int i;
for(i=begin;i<=end;i++)
if(in[i]==root->data)
break;
pos++;
root->lchild=build(pre,in,begin,i-1);
root->rchild=build(pre,in,i+1,end);
return root;
}
return NULL;
}