最近在mooc上发现了清华、北大2门数据结构的课程,一直在潜心学习他们的课程,博客没有及时更新,今天刚刚学习了二叉树,趁热打铁,记录下二叉树的学习经历吧,老规矩,还是看代码
二叉树节点类的实现:
#ifndef BINARY_TREE_NODE_H
#define BINARY_TREE_NODE_H
template <typename T> class BinaryTree;
template <typename T>
class BinaryTreeNode
{
friend class BinaryTree<T>;
private:
T data; //二叉树结点数据域
BinaryTreeNode<T>* left; //二叉树结点指向左子树的指针
BinaryTreeNode<T>* right; //二叉树结点指向左子树的指针
public:
//缺省构造函数
BinaryTreeNode()
{
left = right = nullptr;
}
//给定了结点值和左右子树的构造函数
BinaryTreeNode(T val,BinaryTreeNode<T> *lc = nullptr,BinaryTreeNode<T> *rc = nullptr) : data(val),left(lc),right(rc)
{
}
//返回当前结点的数据
T value() const
{
return this->data;
}
//返回当前结点左子树
BinaryTreeNode<T> * leftChild() const
{
return this->left;
}
//返回当前结点右子树
BinaryTreeNode<T> * rightChild() const
{
return this->right;
}
//设置当前结点的左子树
void setLeftChild(BinaryTreeNode<T> * lc)
{
this->left = lc;
}
//设置当前结点的右子树
void setRightChild(BinaryTreeNode<T> * rc)
{
this->right = rc;
}
//设置当前结点的数据域
void setValue(T val)
{
this->data = val;
}
//判定当前结点是否为叶结点,若是返回true
bool isLeaf() const
{
return (this->left == nullptr) && (this->right == nullptr);
}
//重载赋值操作符
BinaryTreeNode<T>& operator = (const BinaryTreeNode<T>& Node)
{
this = Node;
}
};
#endif
二叉树的实现:
#ifndef BINARY_TREE_H
#define BINARY_TREE_H
#include "BinaryTreeNode.h"
#include <iostream>
#include <stack>
#include <queue>
using std::cout;
using std::endl;
using std::stack;
using std::queue;
enum Tags{Left,Right}; //枚举类型
template <class T>
class StackElement
{ //StackElement
public:
BinaryTreeNode<T>* pointer;
Tags tag;
};
template <typename T>
class BinaryTree
{
private:
BinaryTreeNode<T> *root;
public:
BinaryTree(BinaryTreeNode<T> *r = nullptr)
{
root = r;
}
~BinaryTree()
{
deleteBinaryTree(root);
}
//以后序周游的方式删除二叉树
void deleteBinaryTree(BinaryTreeNode<T> *r)
{
if(r)
{
deleteBinaryTree(r->left);
deleteBinaryTree(r->right);
delete r;
}
}
//判定二叉树是否为空树
bool isEmpty() const
{
return this->root == nullptr;
}
//返回二叉树根结点
BinaryTreeNode<T>* getRoot()
{
return root;
}
//构造一棵以info为根、leftTree和rightTree为左右子树的新二叉树
void createTree(const T& info, BinaryTree<T>& leftTree, BinaryTree<T>& rightTree)
{
root = new BinaryTreeNode<T>(info,leftTree.root,rightTree.root);
leftTree.root = rightTree.root = nullptr;
}
void visit(BinaryTreeNode<T> *node)
{
cout << node->value() << "\t";;
}
//前序周游二叉树
void preOrder (BinaryTreeNode<T> *root)
{
if(root)
{
visit(root);
preOrder(root->leftChild());
preOrder(root->rightChild());
}
}
//前序周游二叉树without递归
void preOrderWithoutRecursion(BinaryTreeNode<T> *root)
{
stack<BinaryTreeNode<T> * > aStack;
BinaryTreeNode<T> *point = root;
while(!aStack.empty() || point)
{
if(point)
{
visit(point); //访问当前结点
aStack.push(point);//当前结点地址入栈,为了便于查找右孩子
point = point->leftChild();//当前链接结构指向左孩子
}
else //左子树访问完毕,转向访问右子树
{
point = aStack.top();//栈顶元素退栈
aStack.pop();
point = point->rightChild();//当前链接结构指向右孩子
}
}
}
//中序周游二叉树
void inOrder (BinaryTreeNode<T> *root)
{
if(root)
{
inOrder(root->leftChild());
visit(root);
inOrder(root->rightChild());
}
}
//中序周游二叉树without递归
void inOrderWithoutRecursion(BinaryTreeNode<T> *root)
{
stack<BinaryTreeNode<T> * > aStack;
BinaryTreeNode<T> *point = root;
while(!aStack.empty() || point)
{
if(point)
{
aStack.push(point);//当前结点地址入栈
point = point->leftChild();//当前链接结构指向左孩子
}
else //左子树访问完毕,转向访问右子树
{
point = aStack.top();//栈顶元素退栈
aStack.pop();
visit(point); //访问当前结点
point = point->rightChild();//当前链接结构指向右孩子
}
}
}
//后序周游二叉树
void postOrder (BinaryTreeNode<T> *root)
{
if(root)
{
postOrder(root->leftChild());
postOrder(root->rightChild());
visit(root);
}
}
//后序周游二叉树without递归
void postOrderWithoutRecursion(BinaryTreeNode<T> *root)
{
StackElement<T> element;
stack<StackElement<T> > aStack;
BinaryTreeNode<T> *point;
if(root == nullptr)
{
return ;
}
else
{
point = root;
}
while(!aStack.empty() || point)
{
while(point)
{
element.pointer = point;
element.tag = Left;
aStack.push(element);
point = point->leftChild();//沿左子树方向向下周游
}
element = aStack.top();
aStack.pop();//托出栈顶元素
point = element.pointer;
if(element.tag == Left)
{
//从左子树回来
element.tag = Right;
aStack.push(element);
point = point->rightChild();
}
else
{
//从右子树回来
visit(point); //访问当前结点
point = nullptr;
}
}
}
//按层次周游二叉树或其子树
void LevelOrder(BinaryTreeNode<T>* root)
{
queue<BinaryTreeNode<T> * > aQueue;
BinaryTreeNode<T> *point = root;
if(point)
{
aQueue.push(point);//根结点入队列
}
while(!aQueue.empty())//队列非空
{
point = aQueue.front();//取队列首结点
aQueue.pop();//当前结点出队列
visit(point);//访问当前结点
if(point->leftChild() != nullptr)
{
aQueue.push(point->leftChild());//左子树进队列
}
if(point->rightChild() != nullptr)
{
aQueue.push(point->rightChild());//右子树进队列
}
}
}
};
#endif
测试代码
#include "BinaryTree.h"
#include <iostream>
int main()
{
//建一棵树(如图5.5所示)
BinaryTree<char> a, b, c, d, e, f, g, h, i,nulltree;
d.createTree('D', nulltree, nulltree);
g.createTree('G', nulltree, nulltree);
h.createTree('H', nulltree, nulltree);
i.createTree('I', nulltree, nulltree);
f.createTree('F', h, i);
e.createTree('E', g, nulltree);
b.createTree('B', d, e);
c.createTree('C', nulltree, f);
a.createTree('A', b, c);
//前序周游二叉树
cout << "Preorder sequence is: "<<endl;
a.preOrder(a.getRoot()); //递归
cout << endl;
cout << "Preorder sequence Without Recursion is: " <<endl;
a.preOrderWithoutRecursion(a.getRoot());//非递归
cout << endl;
//中序周游二叉树
cout << "Inorder sequence is: "<<endl;
a.inOrder(a.getRoot()); //递归
cout << endl;
cout << "Inorder sequence Without Recursion is: " <<endl;
a.inOrderWithoutRecursion(a.getRoot());//非递归
cout << endl;
//后序周游二叉树
cout << "Postorder sequence is: "<<endl;
a.postOrder(a.getRoot()); //递归
cout << endl;
cout << "Postorder sequence Without Recursion is: " <<endl;
a.postOrderWithoutRecursion(a.getRoot());//非递归
cout << endl;
cout << "Levelorder sequence Without Recursion is: " <<endl;
a.LevelOrder(a.getRoot());//非递归
cout << endl;
//root
cout << "Root is: " << a.getRoot()->value() <<endl;
/* //delete tree
a.deleteBinaryTree(a.getRoot());
cout<<"Tree is deleted."<<endl; //没有问题,在析构函数中调用
*/
system("pause");
return 0;
}