遍历
先序遍历
//递归
void PreOrder(BiTree T){
if(T!=NULL){
visit(T);
PreOrder(T->lchild);
PreOrder(T->rchild);
}
}
//非递归,用栈
void PreOrder(BiTNode *bt){
if(bt!=NULL){
BiTNode *Stack[maxsize];//手动模拟栈
int top=-1;
BiTNode *p;
Stack[++top]=bt;//根结点入栈
while(top!=-1){
p=Stack[top--];
visit(p);
if(p->rchild!=NULL)//应该让右孩子先入栈
Stack[++top]=p->rchild;
if(p->lchild!=NULL)
Stack[++top]=p->lchild;
}//while
}
}
中序遍历
//递归
void InOrder(BiTree T){
if(T!=NULL){
InOrder(T->lchild);
visit(T);
InOrder(T->rchild);
}
}
//非递归
void InOrder(BiTNode *bt){
if(bt!=NULL){
BiTNode *Stack[maxsize];
int top=-1;
BiTNode *p=bt;
while(top!=-1||p!=NULL){
if(p){
Stack[++top]=p;
p=p->lchild;
}
else{
p=Stack[top--];
visit(p);
p=p->rchild;
}
}
}
后序遍历
//递归
void PostOrder(BiTree T){
if(T!=NULL){
PostOrder(T->lchild);
PostOrder(T->rchild);
visit(T);
}
}
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild,*rchild;
int tag;//访问位,0表示未访问,1表示已访问
}BiTNode,*BiTree;
//非递归
void PostOrder(BiTNode *bt){
if(T!=NULL){
BiTNode *Stack[maxsize];
int top=-1;
BiTNode *p=T;
while(top!=-1||p!=NULL){
if(p){
Stack[++top]=p;
p=p->lchild;
}
else{
p=Stack[top--];
if(p->lchild&&(p->lchild->tag==0)){
Stack[++top]=p;
p=p->rchild;
}
else{
visit(p);
p->tag=1;
p=NULL;
}
}
}
}
层序遍历
typedef struct Queue{
BiTNode *data[maxsize];
int front,rear;
}Queue;
//借助队列
void LevelOrder(BiTNode *bt){
Queue Q;
InitStack(Q);
EnQueue(Q,bt);
BiTNode *P;
while(isEmpty(Q)){
DeQueue(Q,p);
visit(p);
if(p->lchild!=NULL)
EnQueue(Q,p->lchild);
if(p->rchild!=NULL)
EnQueue(Q,p->rchild);
}
}
//手动模拟队列
void LevelOrder(BiTNode *bt){
BiTNode *Q[maxsize];
int front=rear=0;
BiTNode *p;
if(bt!=NULL){
rear=(rear+1)%maxsize;
Q[rear]=bt;
while(front!=rear){
front=(front+1)%maxsize;
p=Q[front];
visit(p);
if(p->lchild!=NULL){
rear=(rear+1)%maxsize;
Q[rear]=p->lchild;
}
if(p->rchild!=NULL){
rear=(rear+1)%maxsize;
Q[rear]p->rchild;
}
}//while
}
}
1. 试编写二叉树的自下而上、从右到左的层次遍历算法。
【算法思想】
一般的二叉树层次遍历是自上而下,自左到右。在这里刚好相反。我们利用原有的层次遍历算法,各结点出队的同时将各结点指针入栈,在所有结点入栈后再从 栈顶开始依次访问。
void InvertLevelOrder(BiTree bt){
Stack S;
Queue Q;
if(bt!=NULL){
InitStack(S);
InitQueue(Q);
EnQueue(Q,bt);
BiTNode *P;
while(!IsEmpty(Q)){
DeQueue(Q,p);
Push(S,p);
if(p->lchild)
EnQueue(Q,P->lchild);
if(p->rchild)
EnQueue(Q,p->rchild);
}
while(!IsEmpty(S)){
Pop(S,p);
visit(p);//自下而上,从右到左的遍历
}
}//if
}
2.设二叉树采用二叉链表的存储结构,试着编写非递归算法二叉树的高度。
【算法思想】
采用层次遍历的算法,设置变量 level 记录当前结点所在的层次,设置变量 last指向当前层的最右结点。每层次遍历出队时与 last 指针比较,若两者相等,则层数+1,并且计算下一层的最右结点,直到遍历完成。level 的值即为二叉树的高度
int BtDepth(BiTree T){
if(T==NULL)
return 0;
else{
//采用手动模拟队列方式
int front=rear=-1;
int last=level=0;
BiTree *Q[maxsize];
Q[++rear]=T;
BiTree p;
while(front<rear){
p=Q[++front];
if(p->lchild)
Q[++rear]=p->lchild;
if(p->rchild)
Q[++rear]=p->rchild;
if(front==last){
level++;
last=rear;
}
}//while
return level;
}
}
//递归实现
int BtDepth(BiTree T){
if(T==NULL)
return 0;
ldep=BtDepth(T->lchild);
rdep=BtDepth(T->rchild);
if(ldep>rdep)
return ldep+1;
else
return rdep+1;
}
3.计算二叉树的最大宽度(二叉树的最大宽度是指二叉树所有层中结点个数的最大值)
//采用level数组记录每个结点所在层次
int BtWidth(BiTree T){
if(T==NULL)
return 0;
BiTree p;
int k;//记录结点所在层次
BiTree *Q[maxsize];
int front=rear=-1;
int level[maxsize];
Q[++rear]=T;
level[rear]=1;//根结点层次为1
while(front<rear){
p=Q[++front];//出队结点
k=level[front];//出队结点的层次
if(p->lchild){
Q[++rear]=p->lchild;
level[rear]=k+1;
}
if(p->rchild){
Q[++rear]=p->lchild;
level[rear]=k+1;
}
}//while
//遍历结束后,rear+1为结点数
int max=0;
int i=0;
k=1;
while(i<=rear){
n=0;//记录每一层的结点数
while(i<=rear&&level[i]==k){
n++;
i++;
}
k=level[i];//更新层数
if(n>max)
max=n;
}//while
return max;
}
//改进,不使用level数组,一边遍历一边统计
int BtWidth(BiTree T){
if(!T)
return 0;
BiTree *Q[maxsize];
front=rear=-1;
int last=1;//记录最右边结点在队列中位置
int wid=0;//记录局部宽度
int maxwidth=0;//记录最大宽度
Q[++rear]=T;
while(front<rear){
p=Q[++front];
wid++;
if(p->lchild)
Q[++rear]=p->lchild;
if(p->rchild)
Q[++rear]=p->rchild;
if(front>last){
last=rear;//last指向下一层最右边元素
if(wid>maxwidth)
maxwidth=wid;
wid=0;
}//if
}//while
return maxwidth;
}
4.假设二叉树采用二叉链存储结构存储,试设计一个算法,计算一棵给定二叉树的所有节点数。
//递归
int Nodes(BTNode *bt){
int left,right;
if(!bt)
return 0
else{
left=Nodes(bt->lchild);
right=Nodes(bt->rchild);
return (left+right+1);
}
}
5.假设二叉树采用二叉链存储结构存储,设计一个算法计算一棵给定二叉树的所有叶子节点个数。
//递归
int leafNodes(BiTNode *bt){
int m,n;
if(!bt)
return 0;
else if(bt->lchild==NULL&&bt->rchild==NULL)
return 1;
else{
m=leafNodes(bt->lchild);
n=leafNodes(bt->rchild);
return m+n;
}
}
6.假设二叉树采用二叉链存储结构存储,设计一个算法计算一棵给定二叉树的所有双分支节点。
//递归
int doubleNodes(BiTNode *bt){
int left,right,n;
if(!bt)
return 0;
else if(bt->lchild==NULL||bt->rchild==NULL)
n=0;
else
n=1;
left=doubleNodes(bt->lchild);
right=doubleNodes(bt->rchild);
return (left+right+n);
}
7.假设二叉树采用二叉链存储结构存储,所有节点的值为正整数,设计一个算法求所有节点值之和。
//递归
int Findsum(BiTNode *bt){
if(!bt)
return 0;
else
return (bt->data+Findsum(bt->lchild)+Findsum(bt->rchild));
}
8.假设二叉树采用二叉链存储结构存储,设计一个算法求其中节点值为 x的节点个数。
//递归
int count_x(BiTNode *bt,ElemType x){
if(!bt)
return 0;
else if(bt->data==x)
return (1+count_x(bt->lchild,x)+count_x(bt->rchild,x));
else
return (count_x(bt->lchild,x)+count_x(bt->rchild,x));
)
9 假设二叉树采用二叉链表结构存储,设计一个算法求先序遍历序列中第k(1<=k<=二叉树中节点个数)个节点的值。
int n=1;//标记结点序号
ElemType PreNode(BiTNode *bt,int k){
ElemType ch;
if(bt==NULL)
return '';
if(n==k)
return bt->data;
n++;
ch=PreNode(bt->lchild,k);//遍历左子树
if(ch!='')
return ch;
ch=PreNode(bt->rchild,k);
return ch;
}
10.假设二叉树采用二叉链存储结构存储,设计一个算法,求中序遍历序列中第k(1≤k≤二叉树中节点个数)个节点的值。
int n=1;
ElemType InOrder(BiTNode *bt,int k){
ElemType ch;
if(bt==NULL)
return '';
ch=InOrder(bt->lchild,k);
if(ch!='')
return ch;
else{
if(n==k)
return bt->data;
n++;
ch=InOrder(bt->rchild,k);
return ch;
}
}
11.假设二叉树采用二叉链存储结构存储,设计一个算法,求后序遍历序列中第k(1≤k≤二叉树中节点个数)个节点的值。
int n=1;
ElemType PostOrder(BiTNode *bt,int k){
ElemType ch;
if(bt==NULL)
return '';
ch=PostOrder(bt->rchild,k);
if(ch!='')
return ch;
else{
ch=PostOrder(bt->lchild,k);
if(ch!='')
return ch;
if(n==k)
return bt->data;
n++;
}
}
int wpl_PreOrder(BiTree root,int deep){
static int wpl=0;
if(root->lchild==NULL&&root->rchild==NULL)
wpl=wpl+deep*root->weight;//叶子结点
if(root->lchild!=NULL)
wpl_PreOrder(root->left,deep+1);
if(root->right!=NULL)
wpl_PreOrder(root->rchild,deep+1);
return wpl;
}
typedef struct node{
char data[maxsize];
struct node *left,*right;
}BiTree;
void BiTreeToExp(BiTree *bt,int deep){
if(bt==NULL)
return ;
else if(bt->left==NULL&&bt->right==NULL)//叶子结点
printf("%s",bt->data);
else{
if(deep>1)
printf("(");
BiTreeToExp(bt->left,deep+1);
printf("%s",bt->data);
BiTreeToExp(bt->right,deep+1);
if(deep>1)
printf(")");
}
}
17.判断一个树是否是完全二叉树
typedef struct BiTNode{
ElemType data[maxsize];
struct BiTNode *lchild,*rchild;
}
typedef struct Queue{
BiTNode *data[maxsize];
int front,rear;
}
bool isCompleteBiTNode(BiTNode *bt){
Queue Q;
InitQueue(Q);
if(bt==NULL)
return true;
EnQueue(Q,bt);
int tag=0;//判断前面是否有空结点的标志位
while(!isEmpty(Q)){
BiTNode p;
DeQueue(Q,p);
if(p->lchild&&!tag)
EnQueue(Q,p->lchild);
else{
if(p->lchild)
return false;
else
tag=1;//首次出现非空结点
}
if(p->rchild&&!tag)
EnQueue(Q,p->rchild);
else{
if(p->rchild)
return false;
else
tag=1;
}
}
return true;
}