前序遍历算法思想:访问根结点,递归访问左子树,递归访问右子树。
Status PreOrderTraverse(BiTree T, Status(*Visit)(TElemType e))
{
if (T)
{
if (Visit(T->data))//访问根结点
if (PreOrderTraverse(T->lchild, Visit))//访问左子树
if (PreOrderTraverse(T->rchild, Visit))//访问右子树
return OK;
return ERROR;
}
else
return OK;
}
中序遍历算法思想:递归访问左子树,访问根结点,递归访问右子树
Status InOrderTraverse(BiTree T, Status(*Visit)(TElemType e))
{
if (T)
{
if (InOrderTraverse(T->lchild, Visit))//访问左子树
if (Visit(T->data))//访问根结点
if (InOrderTraverse(T->rchild, Visit))//访问右子树
return OK;
return ERROR;
}
else
return OK;
}
-
后序遍历算法思想:递归访问左子树,递归访问右子树,访问根结点。
Status PostOrderTraverse(BiTree T, Status(*Visit)(TElemType e))
{
if (T)
{
if (PostOrderTraverse(T->lchild, Visit))//访问左子树
if (PostOrderTraverse(T->rchild, Visit))//访问右子树
if (Visit(T->data))//访问根结点
return OK;
return ERROR;
}
else
return OK;
}
求二叉树中叶子结点数目的算法思想:如果二叉树为空,那么叶子结点数目为 0。否则,如果二叉树的左右子树都是空,那么叶子结点数目为 1。否则,叶子结点数目为左子树的叶子结点数目加上右子树的叶子结点数目。
int LeafNodes(BiTree T)
{
if (T == NULL)
return 0;
else if (T->lchild == NULL && T->rchild == NULL)
return 1;
else
return LeafNodes(T->lchild) + LeafNodes(T->rchild);
}
编写求二叉树深度的递归算法的算法思想:如果二叉树为空,那么二叉树的深度为 0。否则,二叉树的深度为左子树的深度和右子树的深度中较大者加 1。
int Depth(BiTree T)
{
if (T == NULL)
return 0;
else
{
int left_depth = Depth(T->lchild);
int right_depth = Depth(T->rchild);
return (left_depth > right_depth ? left_depth : right_depth) + 1;
}
}
编写判断二叉树是否相似的递归算法的算法思想:如果两个二叉树都为空,那么它们是相似的。如果两个二叉树只有一个为空,那么它们不是相似的。如果两个二叉树的根结点的值不同,那么它们不是相似的。否则,分别判断两个二叉树的左子树和右子树是否相似。如果它们都相似,那么两个二叉树是相似的。否则,它们不是相似的。
int SimilarTrees(BiTree T1, BiTree T2)
{
if (T1 == NULL && T2 == NULL)
return 1;
else if (T1 == NULL || T2 == NULL)
return 0;
else if (T1->data != T2->data)
return 0;
else
return SimilarTrees(T1->lchild, T2->lchild) && SimilarTrees(T1->rchild, T2->rchild);
}
data:这是二叉树结点的数据域,它存储结点的数据值。
*lchild:这是二叉树结点的左孩子指针。它指向结点的左孩子,如果结点没有左孩子,则该指针为 NULL。
*rchild:这是二叉树结点的右孩子指针。它指向结点的右孩子,如果结点没有右孩子,则该指针为 NULL。
实验总结
通过本次实验,我学习了二叉树的二叉链表存储结构、前、中、后序遍历算法、求二叉树中叶子结点数目的算法、求二叉树深度的算法和判断二叉树是否相似的算法。我也学习了如何分析算法的复杂度,以及如何权衡算法的优缺点。
时间复杂度
前序遍历、中序遍历和后序遍历算法的时间复杂度都是 O(n),其中 n 是二叉树中的结点数。这是因为这三个算法都需要访问二叉树中的每个结点一次。
求二叉树中叶子结点数目的算法的时间复杂度也是 O(n)。这是因为该算法需要访问二叉树中的每个结点一次。
编写求二叉树深度的递归算法的时间复杂度也是 O(n)。这是因为该算法需要访问二叉树中的每个结点一次。
编写判断二叉树是否相似的递归算法的时间复杂度也是 O(n)。这是因为该算法需要访问两个二叉树中的每个结点一次。
优点:简单易懂:这几个算法都很简单易懂,易于实现。
效率较高:这几个算法的时间复杂度和空间复杂度都是 O(n),效率较高。
缺点:递归算法可能会导致栈溢出:**这几个算法都是递归算法,如果二叉树很深,可能会导致栈溢出。
非递归算法需要使用栈:**非递归算法需要使用栈来存储已经访问过的结点,这可能会占用较多的空间。