在算法实现方面要求,熟练掌握二叉树的递归和非递归遍历,并能够用之解决实际问题,如:计算树的层数、度,查找满足条件的节点等。
1,假设二叉树采用二叉链存储结构存储,设计一个算法,求先序遍历序列中第k(1≤k≤二叉树中节点个数)个节点的值
递归模型
f(b,k)=' ' 当b=NULL时返回特殊字符' '
f(b,k)=b->data 当k=n
f(b,k)=((ch=f(b->lchild,k))==' '?f(b->rchild,k):ch) 其他情况
对应的递归算法
int n=1; //全局变量
ElemType PreNode(BTNode *b,int k)
{ ElemType ch;
if (b==NULL)
return ' ';
if (n==k)
return(b->data);
n++;
ch=PreNode(b->lchild,k); //遍历左子树
if (ch!=' ')
return(ch); //在左子树中找到后返回
ch=PreNode(b->rchild,k); //遍历右子树
return(ch); //返回右子树中的遍历结果
}
非递归算法,先序遍历对应的算法
ElemType PreNode1(BTNode *b,int k) //先序遍历的非递归算法
{ BTNode *St[MaxSize],*p;
int top=-1,n=0;
if (b!=NULL)
{ top++; //根节点进栈
St[top]=b;
while (top>-1) //栈不为空时循环
{ p=St[top]; //退栈并访问该节点
top--;
n++;
if (n==k) return(p->data);
if (p->rchild!=NULL) //右孩子节点进栈
{ top++;
St[top]=p->rchild;
}
if (p->lchild!=NULL) //左孩子节点进栈
{ top++;
St[top]=p->lchild;
}
}
printf("\n");
}
return(' ');
}
2,假设二叉树采用二叉链存储结构存储,设计一个算法,求中序遍历序列中第k(1≤k≤二叉树中节点个数)个节点的值。
递归算法
int n=1; //全局变量
ElemType InNode(BTNode *b,int k)
{ ElemType ch;
if (b==NULL)
return ' ';
ch=InNode(b->lchild,k); //遍历左子树
if (ch!=' ') //在左子树找到了便返回ch
return ch;
else
{ if (n==k)
return b->data;
n++;
return InNode(b->rchild,k); //返回在右子树中查找的结果
}
}
非递归算法
ElemType InNode1(BTNode *b,int k) //中序遍历的非递归算法
{ BTNode *St[MaxSize],*p;
int top=-1,n=0;
if (b!=NULL)
{ p=b;
while (top>-1 || p!=NULL)
{ while (p!=NULL) //扫描*p的所有左节点并进栈
{ top++;
St[top]=p;
p=p->lchild;
}
if (top>-1)
{ p=St[top]; //出栈*p节点
top--;
n++;
if (n==k) return(p->data);
p=p->rchild; //扫描*p的右孩子节点
}
}
printf("\n");
}
return(' ');
}
3,假设二叉树采用二叉链存储结构存储,设计一个算法,求后序遍历序列中第k(1≤k≤二叉树中节点个数)个节点的值。
递归算法
int n=1; //全局变量
ElemType PostNode(BTNode *b,int k)
{ ElemType ch;
if (b==NULL)
return ' ';
ch=PostNode(b->lchild,k); //遍历左子树
if (ch!=' ') //在左子树找到了便返回ch
return ch;
else
{ ch=PostNode(b->rchild,k); //遍历右子树
if (ch!=' ') //在右子树找到了便返回ch
return ch;
if (n==k)
return b->data;
n++;
}
}
非递归算法
ElemType PostNode1(BTNode *b,int k) //后序遍历的非递归算法
{ BTNode *St[MaxSize];
BTNode *p;
int flag,top=-1,n=0; //栈顶指针置初值
if (b!=NULL)
{ do
{ while (b!=NULL) //将*b的所有左节点进栈
{ top++;
St[top]=b;
b=b->lchild;
}
p=NULL; //p指向栈顶节点的前一个已访问的节点
flag=1; //设置b的访问标记为已访问过
while (top!=-1 && flag)
{ b=St[top]; //取出当前的栈顶元素
if (b->rchild==p) //右孩子不存在或右孩子已被访问,访问之
{ n++;
if (n==k) return(b->data);
top--;
p=b; //p指向则被访问的节点
}
else
{ b=b->rchild; //b指向右孩子节点
flag=0; //设置未被访问的标记
}
}
} while (top!=-1);
printf("\n");
}
return(' ');
}
4,假设二叉树采用二叉链存储结构存储,设计一个算法,求中序遍历序列中第一个节点的值。
ElemType FirstNode(BTNode *b)
{ if (b==NULL)
return(' ');
while (b->lchild!=NULL)
b=b->lchild;
return(b->data);
}
5,假设二叉树采用二叉链存储结构存储,试设计一个算法,计算一棵给定二叉树的所有节点数。
递归算法如下
int Nodes(BTNode *b)
{ int num1,num2;
if (b==NULL)
return 0;
else
{ num1=Nodes(b->lchild);
num2=Nodes(b->rchild);
return (num1+num2+1);
}
}
6,假设二叉树采用二叉链存储结构存储,设计一个算法计算一棵给定二叉树的所有叶子节点个数。
递归算法如下
int LeafNodes(BTNode *b)
{ int num1,num2;
if (b==NULL)
return 0;
else if (b->lchild==NULL && b->rchild==NULL)
return 1;
else
{ num1=LeafNodes(b->lchild);
num2=LeafNodes(b->rchild);
return (num1+num2);
}
}
7,假设二叉树采用二叉链存储结构存储,设计一个算法求其中最小值的节点值。
递归算法如下
void FindMinNode(BTNode *b,ElemType &min)
{ if (b->data<min)
min=b->data;
FindMinNode(b->lchild,min); //在左子树中找最小节点值
FindMinNode(b->rchild,min); //在右子树中找最小节点值
}
void MinNode(BTNode *b)
{ if (b!=NULL)
{ ElemType min=b->data;
FindMinNode(b,min);
printf("Min=%d\n",min);
}
}
8,假设二叉树采用二叉链存储结构存储,设计一个算法求其中节点值为x的节点个数。
对应的递归算法:
int FindCount(BTNode *b,ElemType x)
{ if (b==NULL)
return 0;
else if (b->data==x)
return(1+FindCount(b->lchild,x)+FindCount(b->rchild,x));
else
return(FindCount(b->lchild,x)+FindCount(b->rchild,x));
}
9,假设二叉树采用链接存储结构进行存储,设计一个算法,求二叉树b的宽度(即具有节点数最多的那一层上的节点个数)并输出各节点的层次。
int BTWidth(BTNode *b)
{ struct
{ int lno; //节点的层次编号
BTNode *p; //节点指针
} Qu[MaxSize]; //定义非循环队列
int front,rear; //定义队首和队尾指针
int lnum,max,i,n;
front=rear=0; //置队列为空队
if (b!=NULL)
{ rear++;
Qu[rear].p=b; //根节点指针进队
Qu[rear].lno=1; //根节点的层次编号为1
while (rear!=front) //队列不为空
{ front++;
b=Qu[front].p; //队头出队
lnum=Qu[front].lno;
if (b->lchild!=NULL) //左孩子进队
{ rear++;
Qu[rear].p=b->lchild;
Qu[rear].lno=lnum+1;
}
if (b->rchild!=NULL) //右孩子进队
{ rear++;
Qu[rear].p=b->rchild;
Qu[rear].lno=lnum+1;
}
}
printf("各节点的层编号:\n");
for (i=1;i<=rear;i++)
printf(" %c,%d\n",Qu[i].p->data,Qu[i].lnlno);
max=0;lnum=1;i=1;
while (i<=rear)
{ n=0;
while (i<=rear && Qu[i].lno==lnum)
{ n++;
i++;
}
lnum=Qu[i].lno;
if (n>max) max=n;
}
return max;
}
else
return 0;
}
10,假设二叉树以二叉链存储,设计一个算法,求其指定的某一层k(k>1)的叶子节点个数。
int LeafKLevel(BTNode *b,int k)
{ BTNode *Qu[MaxSize]; //定义循环队列
int front,rear; //定义队首,队尾指针
int leaf=0; //leaf累计叶子节点个数
int last; //定义当前层中最右节点在队列中的位置
int level; //定义当前节点的层号
front=rear=0; //置队列为空队列
if (b==NULL || k<=1) //条件错误返回0
return(0);
rear++; //节点指针进队
last=rear;level=1; //第1层的最右节点在队列中的位置为1
Qu[rear]=b;
while (rear!=front) //队列不为空时循环
{ front=(front+1)%MaxSize;
b=Qu[front]; //队头出队列
if (level==k && b->lchild==NULL && b->rchild==NULL)
leaf++;
if (b->lchild!=NULL) //左孩子进队
{ rear=(rear+1)%MaxSize;
Qu[rear]=b->lchild;
}
if (b->rchild!=NULL) //右孩子进队
{ rear=(rear+1)%MaxSize;
Qu[rear]=b->rchild;
}
if (front==last) //同层的最右节点处理完毕,层数增1
{ level++;
last=rear; //让last指向下一层的最右节点在队列中的位置
}
if (level>k) //当层号大于k时返回leaf,不再继续
return(leaf);
}
}