class TreeNode //书中的单个节点的类
{
friend class Tree;
friend class preorderIterator; //互为友元
friend int equal(TreeNode* a, TreeNode* b);
public:
TreeNode(int = 0);
TreeNode( TreeNode*);
private:
TreeNode* LeftChild; //每个节点的私有数据成员
int data = 0;
TreeNode* RightChild;
};
我们知道TreeNode类与Tree类互为friend,在此之外我向其中加入了preorderIterator类,用于通过Iterator的形式来实现二叉树的前序遍历;equal函数用于判断两棵二叉树是否相等。TreeNode类包含三个数据成员,易知为节点的左孩子,右孩子和该节点的数据。
class Tree //树类
{
friend class preorderIterator;
friend class TreeNode;
friend int operator == (const Tree&,const Tree&);
public:
Tree(int = 0);
Tree(const Tree&); //拷贝构造函数
~Tree();
int count(); //count函数,用于计算树中的叶子的数量
TreeNode* getRoot(); //返回TreeNode的私有数据成员root
void leftInsert(TreeNode*, TreeNode*); //在该节点后的左边插入
void rightInsert(TreeNode*, TreeNode*); //在该节点的右边插入
void inorder(); //中序遍历
void inorder(TreeNode*);
void preorder(); //前序遍历
void preorder(TreeNode*);
void postorder(); //后序遍历
void postorder(TreeNode*);
void LevelOrder(); //层序遍历
void deleteNode(TreeNode*); //递归法删除每个结点
TreeNode* copy(TreeNode*);
private:
TreeNode* root;
};
Tree类的结构也是较为简单,其数据成员仅为root根节点即可,public中全部是待实现的函数
int equal(TreeNode* a, TreeNode* b) //递归法判断两棵树是否相等,输入两棵树的根节点
{
if ((!a) && (!b))
return 1;
if (a && b && (a->data == b->data)
&& equal(a->LeftChild, b->LeftChild)
&& equal(a->RightChild, b->RightChild))
return 1;
return 0;
}
int operator == (const Tree& s, const Tree& t)
{
return equal(s.root, t.root);
}
可知equal函数的原理即是传入两棵树的根节点,递归逐步比较,最终return结果
Tree::~Tree() //destructor
{
stack<TreeNode*> stack;
TreeNode *CurrentNode = new TreeNode(*root);
while (CurrentNode || !stack.empty()) //只要栈非空或该点存在即进入循环
{
while(CurrentNode)//该点存在就x继续寻找左边 只有不存在了才出该循环
{
stack.push(CurrentNode);
TreeNode *n = new TreeNode(*CurrentNode);
delete n; //指向同一处后,删除
CurrentNode = CurrentNode->LeftChild;
}
if(!stack.empty())
{
CurrentNode = stack.top();
stack.pop();
CurrentNode = CurrentNode->RightChild;
}
}
}
Tree类的析构函数运用到了堆栈,一边将找到的节点存到栈中一边接着沿着树向下(左孩子方向)探寻,delete掉本次存入的节点,进行下一次,直到树底;随后开始弹出栈中存入数据,寻找其右孩子。(实际上就类似前序遍历)
int Tree::count() //计算叶子的数量
{
int count = 0;
TreeNode* CurrentNode = root;
stack<TreeNode*> stack;
while (CurrentNode || !stack.empty()) //只要栈非空或该点存在即进入循环
{
while (CurrentNode)//该点存在就x继续寻找左边 只有不存在了才出该循环
{
stack.push(CurrentNode);
CurrentNode = CurrentNode->LeftChild;
if (CurrentNode != nullptr)
{
if (CurrentNode->LeftChild == nullptr && CurrentNode->RightChild == nullptr) //判断是否为叶子
{
count += 1;
}
}
}
if (!stack.empty())
{
CurrentNode = stack.top();
stack.pop();
CurrentNode = CurrentNode->RightChild;
if (CurrentNode != nullptr)
{
if (CurrentNode->LeftChild == nullptr && CurrentNode->RightChild == nullptr) //判断是否为叶子
{
count += 1;
}
}
}
}
return count;
}
与析构函数原理类似,以前序遍历的方式遍历二叉树,若该节点非为nullpter则判断为存在,count+1,最终返回count值
TreeNode* Tree::copy(TreeNode* orignode) //递归法拷贝
{
if (orignode)
{
TreeNode* temp = new TreeNode;
temp->data = orignode->data;
temp->LeftChild = copy(orignode->LeftChild); //再次进入copy函数
temp->RightChild = copy(orignode->RightChild);
return temp;
}
else return 0;
}
原理既是以递归的方式实现数据复制
void Tree::inorder()
{
inorder(root);
}
void Tree::inorder(TreeNode* CurrentNode)//非递归表达用stack实现
{
stack<TreeNode*> stack;
while (CurrentNode || !stack.empty())
{
while (CurrentNode)
{
stack.push(CurrentNode);
CurrentNode = CurrentNode->LeftChild; //中序遍历,一直到leftChild的底部
}
if (!stack.empty()) //从栈中弹出,输出其rightChild
{
CurrentNode = stack.top();
stack.pop();
cout << CurrentNode->data << " ";
CurrentNode = CurrentNode->RightChild;
}
}
}
void Tree::preorder()
{
preorder(root);
}
void Tree::preorder(TreeNode* CurrentNode)
{
stack<TreeNode*> stack;
while (CurrentNode || !stack.empty())
{
while (CurrentNode)
{
stack.push(CurrentNode);
cout << CurrentNode->data<<" " ; //前序遍历,到达左边的底部同时输出左值
CurrentNode = CurrentNode->LeftChild;
}
if (!stack.empty())
{
CurrentNode = stack.top();
stack.pop();
CurrentNode = CurrentNode->RightChild;
}
}
}
void Tree::postorder()
{
postorder(root);
}
void Tree::postorder(TreeNode* CurrentNode) //后序遍历
{
if (CurrentNode)
{
postorder(CurrentNode->LeftChild);
postorder(CurrentNode->RightChild);
cout << CurrentNode->data<<" ";
}
}
void Tree::LevelOrder() //层序遍历
{
queue<TreeNode*> queue;
TreeNode* CurrentNode = root;//初始化定于root
queue.push(CurrentNode);
while (CurrentNode)
{
cout << CurrentNode->data << " ";
if (CurrentNode->LeftChild)
queue.push(CurrentNode->LeftChild);
if (CurrentNode->RightChild)
queue.push(CurrentNode->RightChild);
queue.pop();
if (!queue.empty()) //用于判断队列里面是否还有元素
CurrentNode = queue.front();
else
break;
}
}
void Tree::leftInsert(TreeNode* x, TreeNode* addNode)
{
if (x)
x->LeftChild = addNode;
}
void Tree::rightInsert(TreeNode* x, TreeNode* addNode)
{
if (x)
x->RightChild = addNode;
}
void Tree::deleteNode(TreeNode* CurrentNode)
{
if (CurrentNode == NULL)
return;
TreeNode* left = CurrentNode->LeftChild; //由树根至树叶递归删除
TreeNode* right = CurrentNode->RightChild;
delete CurrentNode;
if (left)
deleteNode(left);
if (right)
deleteNode(right);
}
可知在删除一个节点时需要考虑该节点的左右孩子,通过递归实现树的衔接
class preorderIterator //利用Iterator方法进行前序遍历
{
friend class Tree;
friend class TreeNode;
public:
int Next() //next函数,用于循环,获取返回data值
{
while ((CurrentNode)&&(CurrentNode->LeftChild != nullptr )) //到达左边倒数第二个节点
{
stack.push(CurrentNode);
int temp = CurrentNode->data;
CurrentNode = CurrentNode->LeftChild;
if (!c) //判断语句,判断当前CurrentNode是否为树的最后一个leftChild,c为bool型全局变量
{
return temp;
}
if (c)
{
c = false;
}
}
if ((CurrentNode) && (CurrentNode->LeftChild == nullptr)&&(!c)) //用于判断(子)树最后一个leftChild是否输出
//防止该数重复输出(因为该数也会在stack块中输出)
{
c = true; //修改布尔变量c,用于判断该数是否已输出
return CurrentNode->data;
}
if (!stack.empty())
{
CurrentNode = stack.top();
stack.pop();
CurrentNode = CurrentNode->RightChild;
if (CurrentNode == nullptr)
{
return -1; //为空时返回-1,-1会被滤去
}
else return CurrentNode->data;
}
else return -1;
}
preorderIterator(Tree* tree) //constructor
{
t = tree;
CurrentNode = t->root;
}
private:
Tree* t;
stack< TreeNode* > stack;
TreeNode* CurrentNode;
};
可知preorderIterator类中需要next()函数用来获取下一个节点,next函数中 c 为初始化为false的全局布尔变量,用于做flag;语句详细解释可参考注释。
//实现前序遍历的非递归版本,通过preorder Iterator实现
// 实现完整的C++二叉树类,包含构造函数,拷贝构造函数,析构函数,四种方式的遍历函数
// 写出count()函数,用于计算二叉树的树叶数
// 写出递归方式的析构函数Destructor()
#include //使用栈的遍历
#include
#include //不用栈的遍历
using namespace std;
bool c = false; //全局布尔变量,用于后面preorderIterator中的判断
class TreeNode //书中的单个节点的类
{
friend class Tree;
friend class preorderIterator; //互为友元
friend int equal(TreeNode* a, TreeNode* b);
public:
TreeNode(int = 0);
TreeNode( TreeNode*);
private:
TreeNode* LeftChild; //每个节点的私有数据成员
int data = 0;
TreeNode* RightChild;
};
class Tree //树类
{
friend class preorderIterator;
friend class TreeNode;
friend int operator == (const Tree&,const Tree&);
public:
Tree(int = 0);
Tree(const Tree&); //拷贝构造函数
~Tree();
int count(); //count函数,用于计算树中的叶子的数量
TreeNode* getRoot(); //返回TreeNode的私有数据成员root
void leftInsert(TreeNode*, TreeNode*); //在该节点后的左边插入
void rightInsert(TreeNode*, TreeNode*); //在该节点的右边插入
void inorder(); //中序遍历
void inorder(TreeNode*);
void preorder(); //前序遍历
void preorder(TreeNode*);
void postorder(); //后序遍历
void postorder(TreeNode*);
void LevelOrder(); //层序遍历
void deleteNode(TreeNode*); //递归法删除每个结点
TreeNode* copy(TreeNode*);
private:
TreeNode* root;
};
int equal(TreeNode* a, TreeNode* b) //递归法判断两棵树是否相等,输入两棵树的根节点
{
if ((!a) && (!b))
return 1;
if (a && b && (a->data == b->data)
&& equal(a->LeftChild, b->LeftChild)
&& equal(a->RightChild, b->RightChild))
return 1;
return 0;
}
int operator == (const Tree& s, const Tree& t)
{
return equal(s.root, t.root);
}
TreeNode::TreeNode(int x) //用于赋根节点的值
{
data = x;
LeftChild = 0;
RightChild = 0;
}
TreeNode::TreeNode( TreeNode* treeNode) //拷贝
{
data = treeNode->data;
LeftChild = treeNode->LeftChild;
RightChild = treeNode->RightChild;
}
Tree::Tree(int x)
{
root = new TreeNode(0);
}
Tree::Tree(const Tree& tree)
{
root = copy(tree.root);
}
Tree::~Tree() //destructor
{
stack<TreeNode*> stack;
TreeNode *CurrentNode = new TreeNode(*root);
while (CurrentNode || !stack.empty()) //只要栈非空或该点存在即进入循环
{
while(CurrentNode)//该点存在就x继续寻找左边 只有不存在了才出该循环
{
stack.push(CurrentNode);
TreeNode *n = new TreeNode(*CurrentNode);
delete n; //指向同一处后,删除
CurrentNode = CurrentNode->LeftChild;
}
if(!stack.empty())
{
CurrentNode = stack.top();
stack.pop();
CurrentNode = CurrentNode->RightChild;
}
}
}
int Tree::count() //计算叶子的数量
{
int count = 0;
TreeNode* CurrentNode = root;
stack<TreeNode*> stack;
while (CurrentNode || !stack.empty()) //只要栈非空或该点存在即进入循环
{
while (CurrentNode)//该点存在就x继续寻找左边 只有不存在了才出该循环
{
stack.push(CurrentNode);
CurrentNode = CurrentNode->LeftChild;
if (CurrentNode != nullptr)
{
if (CurrentNode->LeftChild == nullptr && CurrentNode->RightChild == nullptr) //判断是否为叶子
{
count += 1;
}
}
}
if (!stack.empty())
{
CurrentNode = stack.top();
stack.pop();
CurrentNode = CurrentNode->RightChild;
if (CurrentNode != nullptr)
{
if (CurrentNode->LeftChild == nullptr && CurrentNode->RightChild == nullptr) //判断是否为叶子
{
count += 1;
}
}
}
}
return count;
}
TreeNode* Tree::copy(TreeNode* orignode) //递归法拷贝
{
if (orignode)
{
TreeNode* temp = new TreeNode;
temp->data = orignode->data;
temp->LeftChild = copy(orignode->LeftChild); //再次进入copy函数
temp->RightChild = copy(orignode->RightChild);
return temp;
}
else return 0;
}
TreeNode* Tree::getRoot()
{
return root;
}
void Tree::inorder()
{
inorder(root);
}
void Tree::inorder(TreeNode* CurrentNode)//非递归表达用stack实现
{
stack<TreeNode*> stack;
while (CurrentNode || !stack.empty())
{
while (CurrentNode)
{
stack.push(CurrentNode);
CurrentNode = CurrentNode->LeftChild; //中序遍历,一直到leftChild的底部
}
if (!stack.empty()) //从栈中弹出,输出其rightChild
{
CurrentNode = stack.top();
stack.pop();
cout << CurrentNode->data << " ";
CurrentNode = CurrentNode->RightChild;
}
}
}
void Tree::preorder()
{
preorder(root);
}
void Tree::preorder(TreeNode* CurrentNode)
{
stack<TreeNode*> stack;
while (CurrentNode || !stack.empty())
{
while (CurrentNode)
{
stack.push(CurrentNode);
cout << CurrentNode->data<<" " ; //前序遍历,到达左边的底部同时输出左值
CurrentNode = CurrentNode->LeftChild;
}
if (!stack.empty())
{
CurrentNode = stack.top();
stack.pop();
CurrentNode = CurrentNode->RightChild;
}
}
}
void Tree::postorder()
{
postorder(root);
}
void Tree::postorder(TreeNode* CurrentNode) //后序遍历
{
if (CurrentNode)
{
postorder(CurrentNode->LeftChild);
postorder(CurrentNode->RightChild);
cout << CurrentNode->data<<" ";
}
}
void Tree::LevelOrder() //层序遍历
{
queue<TreeNode*> queue;
TreeNode* CurrentNode = root;//初始化定于root
queue.push(CurrentNode);
while (CurrentNode)
{
cout << CurrentNode->data << " ";
if (CurrentNode->LeftChild)
queue.push(CurrentNode->LeftChild);
if (CurrentNode->RightChild)
queue.push(CurrentNode->RightChild);
queue.pop();
if (!queue.empty()) //用于判断队列里面是否还有元素
CurrentNode = queue.front();
else
break;
}
}
void Tree::leftInsert(TreeNode* x, TreeNode* addNode)
{
if (x)
x->LeftChild = addNode;
}
void Tree::rightInsert(TreeNode* x, TreeNode* addNode)
{
if (x)
x->RightChild = addNode;
}
void Tree::deleteNode(TreeNode* CurrentNode)
{
if (CurrentNode == NULL)
return;
TreeNode* left = CurrentNode->LeftChild; //由树根至树叶递归删除
TreeNode* right = CurrentNode->RightChild;
delete CurrentNode;
if (left)
deleteNode(left);
if (right)
deleteNode(right);
}
class preorderIterator //利用Iterator方法进行前序遍历
{
friend class Tree;
friend class TreeNode;
public:
int Next() //next函数,用于循环,获取返回data值
{
while ((CurrentNode)&&(CurrentNode->LeftChild != nullptr )) //到达左边倒数第二个节点
{
stack.push(CurrentNode);
int temp = CurrentNode->data;
CurrentNode = CurrentNode->LeftChild;
if (!c) //判断语句,判断当前CurrentNode是否为树的最后一个leftChild,c为bool型全局变量
{
return temp;
}
if (c)
{
c = false;
}
}
if ((CurrentNode) && (CurrentNode->LeftChild == nullptr)&&(!c)) //用于判断(子)树最后一个leftChild是否输出
//防止该数重复输出(因为该数也会在stack块中输出)
{
c = true; //修改布尔变量c,用于判断该数是否已输出
return CurrentNode->data;
}
if (!stack.empty())
{
CurrentNode = stack.top();
stack.pop();
CurrentNode = CurrentNode->RightChild;
if (CurrentNode == nullptr)
{
return -1; //为空时返回-1,-1会被滤去
}
else return CurrentNode->data;
}
else return -1;
}
preorderIterator(Tree* tree) //constructor
{
t = tree;
CurrentNode = t->root;
}
private:
Tree* t;
stack< TreeNode* > stack;
TreeNode* CurrentNode;
};
int main()
{
Tree* tree = new Tree();
TreeNode* node1 = new TreeNode(1); //共9个结点
TreeNode* node2 = new TreeNode(2);
TreeNode* node3 = new TreeNode(3);
TreeNode* node4 = new TreeNode(4);
TreeNode* node5 = new TreeNode(5);
TreeNode* node6 = new TreeNode(6);
TreeNode* node7 = new TreeNode(7);
TreeNode* node8 = new TreeNode(8);
tree->leftInsert(tree->getRoot(), node1); //构建二叉树
tree->rightInsert(tree->getRoot(), node2);
tree->leftInsert(node1, node3);
tree->rightInsert(node1, node4);
tree->leftInsert(node2, node5);
tree->rightInsert(node2, node6);
tree->leftInsert(node3, node7);
tree->rightInsert(node3, node8);
cout << "Output by inorder function : ";
tree->inorder();
cout << endl;
cout << "Output by postorder function : ";
tree->postorder();
cout << endl;
cout << "Output by LevelOrder function : ";
tree->LevelOrder();
cout << endl;
cout << "Output by preorder function : ";
tree->preorder();
cout << endl;
preorderIterator* it = new preorderIterator(tree);
cout <<"Output by preorder Iterator function : ";
while (it)
{
int n = it->Next();
if (n == -1)
break;
cout << n<<" ";
}
cout << endl;
cout << "The leaf number is : ";
cout << tree->count();
cout << endl;
cout << "The Tree has been destructed " << endl;
system("pause");
return 0;
}