复制二叉树
【算法步骤】
如果是空树,递归结束,否则执行以下操作:
●申请一个新结点空间,复制根结点。
●递归复制左子数。
●递归复制右子数。
【算法描述】
1 //复制二叉树(递归) 2 void Copy(BiTree T, BiTree &NewT) 3 {//复制一颗和T完全相同的二叉树 4 if(T == NULL)//如果是空数,递归结束 5 { 6 NewT = NULL; 7 return; 8 } 9 else 10 { 11 NewT = new BiTNode; 12 NewT->data = T->data;//复制根节点 13 Copy(T->lchild, NewT->lchild);//递归复制左指数 14 Copy(T->rchild, NewT->rchild);//递归复制右指数 15 }//else 16 }
计算二叉树的深度。
【算法步骤】
如果是空树,递归结束,否则执行以下操作:
●递归计算左子数的深度记为m。
●递归计算右子数的深度记为n。
●如果m大于n,二叉树的深度为m+1,否则为n+1。
【算法描述】
1 //计算二叉树的深度 2 int Depth(BiTree T) 3 {//计算二叉树T的深度 4 int m,n; 5 if(T == NULL)return 0;//如果是空数,深度为0,递归结束 6 else 7 { 8 m = Depth(T->lchild);//递归计算左指数的深度计为m 9 n = Depth(T->rchild);//递归计算右指数的深度计为n 10 if(m>n) return(m+1);//二叉树的深度为m与n的较大者加1 11 else return n+1; 12 }//else 13 14 }
统计二叉树中结点个数。
【算法步骤】
如果是空数,则结点个数为0;否则,结点个数为左子数的节点个数加上右子数的节点个数在加1。
【算法描述】
1 //统计二叉树中节点的个数 2 int NodeCount(BiTree T) 3 {//统计二叉树中节点T的个数 4 if(T == NULL) return 0;//如果是空数,则节点个数为0,递归结束 5 else return NodeCount(T->lchild) + NodeCount(T->rchild) +1;//否则节点个数为左子数的节点个数+右子数的节点个数+1 6 7 }
统计二叉树的叶节点个数。
【算法思想】
利用递归实现,递归结束的条件有两个:一个是二叉树为空,另一个是遇到叶子节点。当二叉树为空时,递归结束返回0;当二叉树不为空,且左、右子树为空(页子结点)时,递归结束返回1;
当二叉树不为空,且左、右子树不同时为空(非叶子节点),递归调用统计函数,返回左子树中叶子节点个数加上右子树中叶子节点个数。
【算法描述】
1 int LeafNode(BiTree T) 2 {//统计二叉树T中叶子节点个数 3 if(T == NULL)//空数返回0 4 return 0; 5 else if(T->lchild == NULL && T->rchild == NULL)//叶子节点返回1 6 return 1; 7 else //递归 8 return LeafNode(T->lchild)+LeafNode(T->rchild); 9 }
判断两颗树是否相等。
【算法思想】
利用递归实现,递归结束条件有3个:一是两棵树均为空,返回相等;二是只有一棵树为空,返回不等;三是结点数据域不等,返回不等。其他情况下则递归判断相应的孩子节点是否相等。
【算法描述】
1 bool CmpTree(BiTree T1, BiTree T2) 2 {//判断两颗二叉树是否相等 3 if(T1 == NULL && T2 == NULL)//都为NULL,相等 4 return true; 5 else if(T1 == NULL || T2 == NULL)//只有一个为NULL,不等 6 return false; 7 else if(T1->data != T2->data)//跟结点不相等,直接返回不等否则递归结束 8 return false; 9 else return CmpTree(T1->lchild, T2->lchild)&&CmpTree(T1->rchild, T2->rchild); 10 11 }
交换二叉树每个节点的左孩子和右孩子
【算法思想】
如果某节点的左、右子树有一个为空,则返回,否则交换该结点的左、右孩子节点,然后递归交换左、右子树。
【算法描述】
1 void ChangeLR(BiTree &T) 2 {//交换二叉树每个节点的左孩子和右孩子 3 4 if(T->lchild == NULL || T->rchild == NULL)//左右孩子有一个为空返回 5 return; 6 else//交换左右孩子节点 7 { 8 9 //直接交换指针 10 BiTree temp = T->lchild; 11 T->lchild = T->rchild; 12 T->rchild = temp; 13 14 }//递归 15 ChangeLR(T->lchild); 16 ChangeLR(T->rchild); 17 18 }
这个是另一种交换方法(不满足题意)
1 void ChangeLR(BiTree &T) 2 {//交换二叉树每个节点的左孩子和右孩子 3 4 if(T->lchild == NULL || T->rchild == NULL)//左右孩子有一个为空返回 5 return; 6 else//交换左右孩子节点 7 { 8 9 10 //交换左右值 11 BiTree p, q; 12 ElemType temp; 13 p = T->lchild; 14 q = T->rchild; 15 temp = p->data; 16 p->data = q->data; 17 q->data = temp; 18 19 }//递归 20 ChangeLR(T->lchild); 21 ChangeLR(T->rchild); 22 23 }
设计二叉树的双序遍历算法(双序遍历是指对于二叉树的每一个结点来说,先访问这个结点,再按双序遍历它的左子树,然后再一次访问这个结点,接下来按双序遍历它的右子树)。
【算法思想】
双序遍历与先序遍历相比,只是多了一次访问,即在递归遍历其左子树后再访问一次该结点。
因此,
步骤如下:
若二叉树为空,则空操作;否则:
(1)访问根结点;
(2)先序遍历左子树;
(3)访问根结点;
(4)先序遍历右子树。
【算法描述】
1 void DoubleTraverse(BiTree T) 2 {//双序遍历二叉树T的递归算法 3 if(T)//若二叉树非空 4 { 5 cout<<T->data<<ends;//访问根节点 6 DoubleTraverse(T->lchild);//双序遍历左子数 7 cout<<T->data<<ends;//访问根节点 8 DoubleTraverse(T->rchild);//双序遍历右子数 9 } 10 }
计算二叉树最大的宽度(二叉树的最大宽度是指二义树所有层中结点个数的最大值)。
【算法思想】
计算二叉树最大的宽度可采用层次遍历的方法,利用队列来实现。首先判断是否为空树,如果为空树则宽度为0;不为空则分别记录局部的宽度和当前的最大宽度,逐层遍历结点,如果结点有孩子结点,则将其孩子加人队尾;每层遍历完毕之后,若局部宽度大于当前的最大宽度,则修改最大宽度。
【算法描述】
1 int Width(BiTree T) 2 {//求二叉树T的最大宽度 3 if(T == NULL)//如果数为空宽度为零 4 return 0; 5 else 6 { 7 BiTree p; 8 BiTree Q[10000];//Q是队列,元素为二叉数结点指针,容量足够大 9 int front = 1;//队头指针 10 int rear = 1;//队尾指针 11 int last = 1;//同层最后结点的位置 12 int maxW = 0;//最大宽度 13 int temp = 0;//局部宽度 14 15 Q[rear] = T; 16 while(front <= last) 17 { 18 p = Q[front++]; 19 temp++; 20 21 if(p->lchild != NULL)//左子数入队 22 Q[++rear] = p->lchild; 23 if(p->rchild != NULL)//右子数入队 24 Q[++rear] = p->rchild;//一层结束 25 26 if(front > last) 27 { 28 last = rear; 29 if(temp > maxW) 30 maxW = temp; 31 temp = 0; 32 }//if 33 34 }//while 35 36 return maxW; 37 38 } 39 40 }
用按层次顺序遍历又树的方法, 统计树中度为I的结点数目。
【算法思想】
可以借助队列实现层次顺序遍历二叉树。从根结点开始,首先将结点进队,然后依次访问队列中的结点,访问之后将其出队。若该结点左子树为空、右子树非空或者右子树为空、左子树非空,则该结点为度为1的结点,计数加1,并将该结点的非空孩子结点人队,直到队列为空则统计结束。
【算法描述】
1 int Level(BiTree T) 2 {//层次遍历二叉树,并统计树中度为1的结点的个数 3 cout<<endl<<endl<<"用按层次遍历二叉树的方法,统计树中度为1的结点数目:"<<endl; 4 int count = 0;//count为树中度为1的结点数目 5 if(T) 6 { 7 queue<BiTree> s; 8 BiTree p; 9 BiTree q; 10 11 p = T; 12 s.push(p);//将根节点入队 13 while(!s.empty()) 14 { 15 p = s.front(); //p出队访问结点 16 s.pop(); 17 cout<<p->data<<ends;//访问出队的结点 18 19 if( (p->lchild && !p->rchild) || ( !p->lchild && p->rchild ) ) 20 count++; 21 22 if(p->lchild != NULL)//如果左节点不为空 左节点入队 23 { 24 q = p->lchild; 25 s.push(q); 26 27 } 28 if(p->rchild != NULL)//如果右节点不为空 左节点入队 29 { 30 q = p->rchild; 31 s.push(q); 32 33 } 34 35 36 } 37 38 } 39 return count; 40 41 }