数据结构练习题——树和二叉树(算法设计题)

简介: 以二叉链表作为二叉树的存储结构,编写以下算法:(1)统计二叉树的叶结点个数。[题目分析]如果二叉树为空,返回0,如果二叉树不为空且左右子树为空,返回1,如果二叉树不为空,且左右子树不同时为空,返回左子树中叶子节点个数加上右子树中叶子节点个数。[算法描述]

以二叉链表作为二叉树的存储结构,编写以下算法:

(1)统计二叉树的叶结点个数。

[题目分析]如果二叉树为空,返回0,如果二叉树不为空且左右子树为空,返回1,如果二叉树不为空,且左右子树不同时为空,返回左子树中叶子节点个数加上右子树中叶子节点个数。

[算法描述]

int LeafNodeCount(BiTree T)
{
if(T==NULL)
    return 0; //如果是空树,则叶子结点个数为0
else if(T->lchild==NULL&&T->rchild==NULL)
    return 1; //判断结点是否是叶子结点(左孩子右孩子都为空),若是则返回1
else
    return LeafNodeCount(T->lchild)+LeafNodeCount(T->rchild);
}

(2)判别两棵树是否相等。

[题目分析]先判断当前节点是否相等(需要处理为空、是否都为空、是否相等),如果当前节点不相等,直接返回两棵树不相等;如果当前节点相等,那么就递归的判断他们的左右孩子是否相等。

[算法描述]

int compareTree(TreeNode* tree1, TreeNode* tree2)
//用分治的方法做,比较当前根,然后比较左子树和右子树
{bool tree1IsNull = (tree1==NULL);
bool tree2IsNull = (tree2==NULL);
if(tree1IsNull != tree2IsNull)
{
return 1;
}
if(tree1IsNull && tree2IsNull)
{//如果两个都是NULL,则相等
return 0;
}//如果根节点不相等,直接返回不相等,否则的话,看看他们孩子相等不相等
if(tree1->c != tree2->c)
{
 return 1;
}
return (compareTree(tree1->left,tree2->left)&compareTree(tree1->right,tree2->right))
 (compareTree(tree1->left,tree2->right)&compareTree(tree1->right,tree2->left));
}//算法结束

(3)交换二叉树每个结点的左孩子和右孩子。

[题目分析]如果某结点左右子树为空,返回,否则交换该结点左右孩子,然后递归交换左右子树。

[算法描述]

void ChangeLR(BiTree &T)
{
BiTree temp;
if(T->lchild==NULL&&T->rchild==NULL)
         return;
else
{
         temp = T->lchild;
         T->lchild = T->rchild;
         T->rchild = temp;
}//交换左右孩子
ChangeLR(T->lchild);  //递归交换左子树
ChangeLR(T->rchild);  //递归交换右子树
}
(4)设计二叉树的双序遍历算法(双序遍历是指对于二叉树的每一个结点来说,先访问这个结点,再按双序遍历它的左子树,然后再一次访问这个结点,接下来按双序遍历它的右子树)。
[题目分析]若树为空,返回;若某结点为叶子结点,则仅输出该结点;否则先输出该结点,递归遍历其左子树,再输出该结点,递归遍历其右子树。
[算法描述]
void DoubleTraverse(BiTree T)
{
if(T == NULL)
    return;
else if(T->lchild==NULL&&T->rchild==NULL)
    cout<<T->data;     //叶子结点输出
else
{
    cout<<T->data;
    DoubleTraverse(T->lchild);   //递归遍历左子树
    cout<<T->data;
    DoubleTraverse(T->rchild);   //递归遍历右子树
}
}

(5)计算二叉树最大的宽度(二叉树的最大宽度是指二叉树所有层中结点个数的最大值)。

[题目分析] 求二叉树高度的算法见上题。求最大宽度可采用层次遍历的方法,记下各层结点数,每层遍历完毕,若结点数大于原先最大宽度,则修改最大宽度。

[算法描述]

int Width(BiTree bt)//求二叉树bt的最大宽度
{if (bt==null) return (0);  //空二叉树宽度为0
else
{BiTree Q[];//Q是队列,元素为二叉树结点指针,容量足够大
front=1;rear=1;last=1;
//front队头指针,rear队尾指针,last同层最右结点在队列中的位置
temp=0; maxw=0;       //temp记局部宽度, maxw记最大宽度
Q[rear]=bt;           //根结点入队列
while(front<=last)
    {p=Q[front++]; temp++; //同层元素数加1
if (p->lchild!=null)  Q[++rear]=p->lchild;   //左子女入队
if (p->rchild!=null)  Q[++rear]=p->rchild;   //右子女入队
if (front>last)      //一层结束,
        {last=rear;
if(temp>maxw) maxw=temp;
//last指向下层最右元素, 更新当前最大宽度
         temp=0;
 }//if   
}//while
return (maxw);
}//结束width

(6)用按层次顺序遍历二叉树的方法,统计树中具有度为1的结点数目。

[题目分析]

若某个结点左子树空右子树非空或者右子树空左子树非空,则该结点为度为1的结点

[算法描述]

int Level(BiTree bt) //层次遍历二叉树,并统计度为1的结点的个数
{int num=0; //num统计度为1的结点的个数
 if(bt){QueueInit(Q); QueueIn(Q,bt);//Q是以二叉树结点指针为元素的队列
while(!QueueEmpty(Q))
{p=QueueOut(Q); cout<<p->data;     //出队,访问结点
if(p->lchild && !p->rchild ||!p->lchild && p->rchild)num++;
//度为1的结点
if(p->lchild) QueueIn(Q,p->lchild); //非空左子女入队
if(p->rchild) QueueIn(Q,p->rchild); //非空右子女入队
} // while(!QueueEmpty(Q))
}//if(bt)        
return(num);
}//返回度为1的结点的个数

(7)求任意二叉树中第一条最长的路径长度,并输出此路径上各结点的值。


[题目分析]因为后序遍历栈中保留当前结点的祖先的信息,用一变量保存栈的最高栈顶指针,每当退栈时,栈顶指针高于保存最高栈顶指针的值时,则将该栈倒入辅助栈中,辅助栈始终保存最长路径长度上的结点,直至后序遍历完毕,则辅助栈中内容即为所求。


[算法描述]

void LongestPath(BiTree bt)//求二叉树中的第一条最长路径长度
{BiTree p=bt,l[],s[];
//l, s是栈,元素是二叉树结点指针,l中保留当前最长路径中的结点
int i,top=0,tag[],longest=0;
while(p || top>0)
{while(p) {s[++top]=p;tag[top]=0; p=p->Lc;} //沿左分枝向下
if(tag[top]==1)    //当前结点的右分枝已遍历
{if(!s[top]->Lc && !s[top]->Rc)  //只有到叶子结点时,才查看路径长度
if(top>longest)
{for(i=1;i<=top;i++) l[i]=s[i]; longest=top; top--;}
//保留当前最长路径到l栈,记住最高栈顶指针,退栈
}
else if(top>0) {tag[top]=1; p=s[top].Rc;}   //沿右子分枝向下
}//while(p!=null||top>0)
}//结束LongestPath

(8)输出二叉树中从每个叶子结点到根结点的路径。

[题目分析]采用先序遍历的递归方法,当找到叶子结点*b时,由于*b叶子结点尚未添加到path中,因此在输出路径时还需输出b->data值。

[算法描述]

void AllPath(BTNode *b,ElemType path[],int pathlen)
{int i;
 if (b!=NULL)
{if (b->lchild==NULL && b->rchild==NULL) //*b为叶子结点
{cout << " " << b->data << "到根结点路径:" << b->data;
      for (i=pathlen-1;i>=0;i--)
      cout << endl;
}
    else
     {path[pathlen]=b->data;           //将当前结点放入路径中
      pathlen++;                     //路径长度增1
      AllPath(b->lchild,path,pathlen);   //递归扫描左子树
      AllPath(b->rchild,path,pathlen);   //递归扫描右子树
      pathlen--;                     //恢复环境
     }
  }// if (b!=NULL)
}//算法结束

相关文章
|
28天前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
63 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
8天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
49 16
|
4天前
|
存储 缓存 算法
如何提高二叉树遍历算法的效率?
选择合适的遍历算法,如按层次遍历树时使用广度优先搜索(BFS),中序遍历二叉搜索树以获得有序序列。优化数据结构,如使用线索二叉树减少空指针判断,自定义节点类增加辅助信息。利用递归与非递归的特点,避免栈溢出问题。多线程并行遍历提高速度,注意线程安全。缓存中间结果,避免重复计算。预先计算并存储信息,提高遍历效率。综合运用这些方法,提高二叉树遍历算法的效率。
17 5
|
1天前
|
算法
分享一些提高二叉树遍历算法效率的代码示例
这只是简单的示例代码,实际应用中可能还需要根据具体需求进行更多的优化和处理。你可以根据自己的需求对代码进行修改和扩展。
|
8天前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
44 8
|
4天前
|
算法
树的遍历算法有哪些?
不同的遍历算法适用于不同的应用场景。深度优先搜索常用于搜索、路径查找等问题;广度优先搜索则在图的最短路径、层次相关的问题中较为常用;而二叉搜索树的遍历在数据排序、查找等方面有重要应用。
10 2
|
7天前
|
机器学习/深度学习 JSON 算法
二叉树遍历算法的应用场景有哪些?
【10月更文挑战第29天】二叉树遍历算法作为一种基础而重要的算法,在许多领域都有着不可或缺的应用,它为解决各种复杂的问题提供了有效的手段和思路。随着计算机科学的不断发展,二叉树遍历算法也在不断地被优化和扩展,以适应新的应用场景和需求。
14 0
|
24天前
|
存储 算法 Java
Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性
Java Set因其“无重复”特性在集合框架中独树一帜。本文解析了Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性,并提供了最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的hashCode()与equals()方法。
31 4
|
28天前
|
Java C++
【数据结构】探索红黑树的奥秘:自平衡原理图解及与二叉查找树的比较
本文深入解析红黑树的自平衡原理,介绍其五大原则,并通过图解和代码示例展示其内部机制。同时,对比红黑树与二叉查找树的性能差异,帮助读者更好地理解这两种数据结构的特点和应用场景。
24 0
|
1月前
|
机器学习/深度学习 搜索推荐 算法
探索数据结构:初入算法之经典排序算法
探索数据结构:初入算法之经典排序算法
下一篇
无影云桌面