11月27日更新,终于,在延迟两天之后将二叉树的相关内容写完发不出来。
其实还是感觉有很多的地方不完善,比如,在setroot函数、detachSubTree卸载子树、destroySubTree销毁子树的相关方面还没有思路(应该是在操作的时候需要引入一个父节点指针来保证删除之后其子节点的指针被置为空——和链表中的删除差不多)。
另外还有一点体会就是在树的操作中,递归的思想是很重要的一个要素,有了递归操作的思路之后,很多的成员函数能够在子函数化之后变得简洁。
如前所述,在这两天需要把树以及二叉树的内容交上来,第一遍内容已经完成,现在先将框架摆上来,明天会把完整的内容补上。
其实在上海交大的数据结构课程中就已经能够体会到,二叉树中, 最大的特点就是在于递归方法的使用。其遍历操作,节点数目统计和树的高度统计都具有很强的递归的特点,包括在销毁树、销毁节点的时候都具有递归的属性。
首先需要给出节点的定义和相关操作:
#ifndef _H_BTREENODE_H_
#define _H_BTREENODE_H_
#include
////////////////// D E C L A R A T I O N //////////////
template<class T>
class BTreeNode
{
public:
BTreeNode(void);
BTreeNode(T value, BTreeNode<T>* l = NULL, BTreeNode<T>* r = NULL);
BTreeNode(BTreeNode<int>& btn);
BTreeNode<T>* getLeft(void);
BTreeNode<T>* getRight(void);
void setLeft(BTreeNode<T>* node);
void setRight(BTreeNode<T>* node);
T getElement(void);
void setElement(T val);
~BTreeNode();
private:
BTreeNode<T>* lChild;
BTreeNode<T>* rChild;
T element;
};
////////////////// D E F I N I T I O N //////////////
template<class T>
BTreeNode<T>::BTreeNode(void)///
{
element = 0;
lChild = NULL;
rChild = NULL;
}
template<class T>
BTreeNode<T>::BTreeNode(T value, BTreeNode<T>* l = NULL, BTreeNode<T>* r = NULL)
{
element = value;
lChild = l;
rChild = r;
}
template<class T>
BTreeNode<T>::BTreeNode(BTreeNode<int>& btn)
{
element = btn.getElement();
lChild = btn.getLeft();
rChild = btn.getRight();
}
template<class T>
BTreeNode<T>* BTreeNode<T>::getLeft(void)
{
return lChild;
}
template<class T>
BTreeNode<T>* BTreeNode<T>::getRight(void)
{
return rChild;
}
template<class T>
void BTreeNode<T>::setLeft(BTreeNode<T>* node)
{
lChild = node;
}
template<class T>
void BTreeNode<T>::setRight(BTreeNode<T>* node)
{
rChild = node;
}
template<class T>
T BTreeNode<T>::getElement(void)
{
return element;
}
template<class T>
void BTreeNode<T>::setElement(T val)
{
element = val;
}
template<class T>
BTreeNode<T>::~BTreeNode()
{
if (NULL != lChild)
{
delete lChild;
}
if (NULL != rChild)
{
delete rChild;
}
}
#endif
下面给出的树的相关成员和函数定义
#ifndef _H_BTREE_H_
#define _H_BTREE_H_
#include "BTreeNode.cpp"
#include
////////////////// D E C L A R A T I O N //////////////
template<class T>
class BTree
{
private:
BTreeNode<T>* root;
public:
BTree(void);
BTree(BTreeNode<T>* rootNode);
BTree(BTree<T>& tree);
~BTree();
void setRoot(BTreeNode<T>* node);
BTreeNode<T>* getRoot(void);
int getNodeNum(void);
int getHeight(void);
void printTree(int mode);
bool isSame(BTree<T>& tree);
void clear(void);
void destroySubTree(BTreeNode<T>* subNode);
void detachSubTree(BTreeNode<T>* subNode);
private:
void add(BTreeNode<T>* l, BTreeNode<T>* r);
void preOrder(BTreeNode<T>* node);
void inOrder(BTreeNode<T>* node);
void postOrder(BTreeNode<T>* node);
void preCount(BTreeNode<T>* node, int& cnt);
bool cmp(BTreeNode<T>* l, BTreeNode<T>* r);
int preGetHeight(BTreeNode<T>* node, int currHeight);
public:
//// 下面三个变量因为是const的原因,所以需要在声明的同时立即初始化
//// 如果仅仅是static,可以在类外声明
static const int PREORDER = 0;
static const int INORDER = 1;
static const int POSTORDER = 2;
};
////////////////// D E F I N I T I O N //////////////
//template<class T>
//int BTree<T>::PREORDER = 0;
//template<class T>
//int BTree<T>::INORDER = 1;
//template<class T>
//int BTree<T>::POSTORDER = 2;
template<class T>
BTree<T>::BTree(void)
{
root = NULL;
}
template<class T>
BTree<T>::BTree(BTreeNode<T>* rootNode)
{
root = new BTreeNode<T>;
add(root, rootNode);
}
template<class T>
BTree<T>::BTree(BTree<T>& tree)
{
/////其实可以不用增加这个判断,因为进去之后本来就会判断
root = NULL;
if (NULL != tree.getRoot())
{
root = new BTreeNode<T>;
add(root, tree.getRoot());
}
}
template<class T>
BTree<T>::~BTree()
{
delete root;
}
template<class T>
void BTree<T>::setRoot(BTreeNode<T>* node)
{
////这个设置,其实是将原来的树,完全的指向了一棵别的树,还应该增加一个将原来的树删除
if (NULL != root)
{
delete root;///// 会递归析构
}
root = node;
}
template<class T>
BTreeNode<T>* BTree<T>::getRoot(void)
{
return root;
}
template<class T>
int BTree<T>::getNodeNum(void)
{
int cnt = 0;
preCount(root, cnt);
return cnt;
}
template<class T>
int BTree<T>::getHeight(void)
{
return (preGetHeight(root, 0));
}
template<class T>
void BTree<T>::printTree(int mode)
{
switch (mode)
{
case 0:
{
preOrder(root);
break;
}
case 1:
{
inOrder(root);
break;
}
case 2:
{
postOrder(root);
break;
}
default:
{
std::cout<<"Default mode: preOrder"<(root) ;
break;
}
}
}
template<class T>
bool BTree<T>::isSame(BTree<T>& tree)
{
return (cmp(root, tree.getRoot()));
}
template<class T>
void BTree<T>::clear(void)
{
delete root;///递归销毁
root = NULL;
}
template<class T>
void BTree<T>::destroySubTree(BTreeNode<T>* subNode)
{
///首先需要判断该节点是否存在于树中,暂时没有想到办法
delete subNode;
subNode = NULL;///这个方法是不对的,因为还需要把前面的childNode设置为NULL
}
template<class T>
void BTree<T>::detachSubTree(BTreeNode<T>* subNode)
{
}
/********************************************************
* @function:
* @brief:
* @input:
* @output:
* @return:
* @author: @JT C [2017/11/26 21:52]
* @History:
*********************************************************/
template<class T>
void BTree<T>::add(BTreeNode<T>* l, BTreeNode<T>* r)
{
if (NULL != r)
{
l->setElement(r->getElement());
if (NULL != r->getLeft())
{
l->setLeft(new BTreeNode<T>);
add(l->getLeft(), r->getLeft());
}
if (NULL != r->getRight())
{
l->setRight(new BTreeNode<T>);
add(l->getRight(), r->getRight());
}
}
}
template<class T>
void BTree<T>::preOrder(BTreeNode<T>* node)
{
if (NULL != node)
{
std::cout<getElement();
preOrder(node->getLeft());
preOrder(node->getRight());
}
}
template<class T>
void BTree<T>::inOrder(BTreeNode<T>* node)
{
if (NULL != node)
{
inOrder(node->getLeft());
std::cout<getElement();
inOrder(node->getRight());
}
}
template<class T>
void BTree<T>::postOrder(BTreeNode<T>* node)
{
if (NULL != node)
{
postOrder(node->getLeft());
postOrder(node->getRight());
std::cout<getElement();
}
}
template<class T>
void BTree<T>::preCount(BTreeNode<T>* node, int& cnt)
{
if (NULL != node)
{
cnt = cnt + 1;
preCount(node->getLeft(), cnt);
preCount(node->getRight(), cnt);
}
}
template<class T>
int BTree<T>::preGetHeight(BTreeNode<T>* node, int currHeight)
{
int leftHeight = currHeight;
int rightHeight = currHeight;
if (NULL != node)
{
currHeight = currHeight + 1;
leftHeight = preGetHeight(node->getLeft(), currHeight);
rightHeight = preGetHeight(node->getRight(), currHeight);
currHeight = std::max(currHeight,leftHeight);
currHeight = std::max(currHeight, rightHeight);
}
return currHeight;
}
template<class T>
bool BTree<T>::cmp(BTreeNode<T>* l, BTreeNode<T>* r)
{
if (NULL != l && NULL != r)
{
if (l->getElement() != r->getElement())
{
return false;
}
if (!cmp(l->getLeft(), r->getLeft()))
{
return false;
}
if (!cmp(l->getRight(), r->getRight()))
{
return false;
}
return true;
}
else
{
return false;
}
}
#endif
下面是测试的源文件:
#include
#include "BTree.cpp"
#include "BTreeNode.cpp"
void main(void)
{
BTreeNode<int> *btnode7 = new BTreeNode<int>(7);
BTreeNode<int> *btnode6 = new BTreeNode<int>(6);
BTreeNode<int> *btnode5 = new BTreeNode<int>(5);
BTreeNode<int> *btnode4 = new BTreeNode<int>(4);
BTreeNode<int> *btnode3 = new BTreeNode<int>(3, btnode6, btnode7);
BTreeNode<int> *btnode2 = new BTreeNode<int>(2, btnode4, btnode5);
BTreeNode<int> *btnode1 = new BTreeNode<int>(1, btnode2, btnode3);
BTree<int> *btree = new BTree<int>(btnode1);
btree->printTree(BTree<int>::PREORDER);
BTree<int> *btree2 = new BTree<int>(*btree);
btree2->printTree(BTree<int>::POSTORDER);
std::cout<getNodeNum()<<std::endl;
std::cout<getNodeNum()<<std::endl;
std::cout<getHeight()<<std::endl;
std::cout<getHeight()<<std::endl;
std::system("pause");
}