1、题目:
二叉树基本算法的实现
2、功能要求:
(1)键盘输入二叉树结点前序序列,创建一棵二叉树;
(2)实现SwapTree方法,以根结点为参数,交换每个结点的左子树和右子树(提示:前序递归);
(3)实现Find方法,查找值为key的结点,并输出该结点的所有祖先结点。
3、创建要求:
(1)要求键盘输入二叉树前序序列(程序5.12)
(2)空结点以#表示
4、可选方法:
(1)对BinaryTree模板进行功能扩充
(2)自己定义并实现二叉树类
本题要求我们实现二叉树的基本算法,并进行相应的功能补充,由数据结构中二叉树的定义可知,二叉树的结点由一个数据元素和分别指向其左、右子树的两个分支构成,所以在本程序二叉树的构造是采用二叉链表的链式存储结构,链表中的结点应包含三个域:数据域和左、右孩子的指针域。这种存储结构可以方便二叉树的建立以及遍历。输入二叉树的先序序列字符,建立二叉链表。
本题我选用的方法是对BinaryTree模板进行功能扩充,根据题意,我们需要增加两个功能函数;首先第一个函数是要实现左右子树的交换,题目中提示我们可以运用前序递归,这里我们就可以运用值传递的原理来进行左右指数的交换;第二的函数要求我们实现Find的方法,(这里我额外编写了函数FindAncestor来完成相关功能)查找值为key的结点,并输出该结点的所有祖先结点,所以我们不光要实现key结点的查找,还要运用parent函数把所有的祖先节点全部输出。
本题要求我们实现键盘输入二叉树结点前序序列,创建一棵二叉树,然后交换每个结点的左子树和右子树,并输出,再查找值为key的结点,并打印该结点的所有祖先结点。为实现上述功能,需要解决的关键问题是二叉树建立过程、二叉树左右子树的交换、查找值等于key的结点过程和存储查找结点的所有祖先结点过程。基本可以归结为以下三点:
1.建立二叉树时,按照完全二叉树的结点顺序输入,#表示空结点。 若不是空结点时,则建立一个新结点,并且将其作为左孩子或右孩子结点连接到它的父结点上(第一个结点无父结点);若是空结点,则将空结点(NULL)作为左孩子或右孩子结点连接到它的父节点上;
2.为实现二叉树左右子树的交换,则需要利用前序递归,原理同值传递的原理相同,设置中间指针变量med,然后再进行交换操作;
3.为实现输出所有祖先节点,则需要利用递归前序遍历算法遍历二叉树,在遍历过程中,将遍历的根结点的关键字与所给查找关键字key比较,相等时结束遍历;不等时继续遍历查找直至找到等于所给查找关键字的根结点或遍历完整棵二叉树;在遍历过程中,需将访问过的结点存入栈中,并同时访问该结点的左孩子结点,若左孩子结点是待查找结点,则栈中结点即是左孩子结点的所有祖先结点,然后依次出栈输出信息。
【调试一】
起初,我编写了SwapTree函数,在测试过程中我发现,输出的前序序列结果并不正确(如图①所示),经过调试,我发现,在运行时,并没有实际调用SwapTree函数,原来是因为我并没有把二叉树的根节点传入SwapTree函数,导致直接输出了所输入的前序序列。
于是,为方便传入根节点,也方便在主函数中的调用,这里我效仿BinaryTree头文件中对于Find、Parent等函数的方式在编写了公有函数SwapTree,即BinTreeNode * SwapTree(){return SwapTree(root);},在这个函数中把根节点传入,即可正常运行并输出正确的交换后的前序序列。
图①
【调试二】
在测试过程中出现如图②所示的错误,经过调试发现结点指针a我把它初始化给了根节点,所以造成如下错误。此外在修改代码的过程我发现我的Find函数也出现了问题,于是我在原Find函数的基础上进行了如下更改:
bool Find(T &x, BinTreeNode<T> * &a){
return Find(root, x, a);}
template<typename T>bool BinaryTree<T>::Find(BinTreeNode<T> *subTree, T &x, BinTreeNode<T>* &a)const{
//在子树中寻找数据为x的结点
if (!subTree){
return false;
}
if (subTree->data == x){
a = subTree;
return true;
}
bool p = false;
p = Find(subTree->leftChild, x, a);
if (p) {
return true;
}
else{
return Find(subTree->rightChild, x, a);
}
}
【调试三】
为了把二叉树按照目录结构方式输出二叉树这里在主函数中调用了头文件BinaryTree中的Output函数如图④所示。输出结果显示,交换前的二叉树并不是正确的结构,而左右子树交换后的二叉树也不是正确结构,二者正好相反,通过检查发现,在头文件BinaryTree中的Output函数存在一点小问题,需要吧函数中的左右子树结点更改一下,即可正确输出,如图⑤所示。
图④
图⑤
【调试四】
最后,把输出界面、提示完善一下,如图⑥所示。
图⑥
BinaryTree.h核心函数
bool Find(T &x, BinTreeNode<T> * &a){
return Find(root, x, a);}
BinTreeNode<T> * SwapTree(){
return SwapTree(root);}
void FindAncestor(void(*visit)(BinTreeNode<T> *t), T &x){
FindAncestor(root, visit, x);}
bool Find(BinTreeNode<T> *subTree, T &x, BinTreeNode<T>* &a)const;//在子树中寻找数据为x的结点
BinTreeNode<T> * SwapTree(BinTreeNode<T> *subTree); //交换左右数结点
void FindAncestor(BinTreeNode<T> *subTree, void(*visit)(BinTreeNode<T> *t), T &x); //输出所有祖先节点
template<typename T>bool BinaryTree<T>::Find(BinTreeNode<T> *subTree, T &x, BinTreeNode<T>* &a)const{
//在子树中寻找数据为x的结点
if (!subTree){
return false;
}
if (subTree->data == x){
a = subTree;
return true;
}
bool p = false;
p = Find(subTree->leftChild, x, a);
if (p) {
return true;
}
else{
return Find(subTree->rightChild, x, a);
}
}
.cpp文件代码
#include "stdafx.h"
#include
#include"BinaryTree.h"
using namespace std;
template <typename T>
BinTreeNode<T> *BinaryTree<T>::SwapTree(BinTreeNode<T> *subTree){
BinTreeNode<T> *med;
if (subTree == NULL)
return NULL;
else{
med = SwapTree(subTree->leftChild);
subTree->leftChild = SwapTree(subTree->rightChild);
subTree->rightChild = med;
return subTree;
}
}
template <typename T>void BinaryTree<T>::FindAncestor(BinTreeNode<T> *subTree, void(*visit)(BinTreeNode<T> *t), T &x){
BinTreeNode<T> *a;
if (Find(subTree, x, a))
{
LinkedStack<BinTreeNode<T> *> S;
if (subTree == a)
{
cout << "The node has been queried,but it is the root node which has no parent node." << endl;
}
else
{
do{
a = Parent(subTree, a);
S.Push(a);
} while (a != subTree);
while (S.Pop(a)) visit(a);
}
}
else
{
cout << "Unable to find a node with a value of key." << endl;
}
}
void visit(BinTreeNode<char> *t){
cout << t->data << " ";
}
int _tmain(int argc, _TCHAR* argv[])
{
BinaryTree<char> binTree('#');
char b;
cout << "Please enter the binray tree prefix sequence of tree nodes:"<<endl;
cin >> binTree;
binTree.Output();
cout << "After swapping the position of the left and right subtree, the binray tree prefix sequence of tree nodes is : "<<endl;
binTree.SwapTree();
binTree.PreOrder(visit);
cout << endl;
binTree.Output();
cout << endl;
cout << "Please enter the value of key:";
cin >> b;
cout << "All ancestral nodes of the node are:";
binTree.FindAncestor(visit, b);
cout << endl;
return 0;
}
1、前序序列:ABC##DE#G##F###; 值为key的结点:C
2、前序序列:ABC##DE#G##F###; 值为key的结点:A
3、前序序列:ABC##DE#G##F###; 值为key的结点:H