由于本人能力有限,本文参考另一位大牛的代码,在此对他表示感谢!
vs2008运行正确,如有误,请各位大牛指正!
// BiTree.cpp : 定义控制台应用程序的入口点。
//三叉链表实现二叉树,有双亲域
#include "stdafx.h"
#include <iostream>
using namespace std;
const int MaxBTreeSize = 20;
template<class T>
//二叉树节点类
class BTNode
{
public:
T data;
BTNode* lchild;
BTNode* rchild;
BTNode* parent;
BTNode():lchild(NULL),rchild(NULL),parent(NULL)
{ }
};
//二叉树类
template<class T>
class BTree
{
public: //提供接口
BTree();
BTree(const BTree<T>& bTree);//拷贝构造函数
~BTree();
const BTree<T>& operator=(const BTree<T>& bTree);//重载赋值运算符
void createBTree();//按先序建立二叉树
void InitBiTree(); //初始化二叉树
void destoryBTree();//销毁二叉树
bool isEmptyBTree();//检查二叉树是否为空
void inOrderTraverse(); //中序遍历
void preOrderTraverse();//先序遍历
void postOrderTraverse(); //后序遍历
void levelOrderTraverse();//层序遍历
int heightBTree();//二叉树高度
int widthBTree(); //二叉树宽度
int nodeCountBTree(); //二叉树结点个数
int LeavesCountBTree();//二叉树叶子个数
int nodeLevelBTree(T item);//结点item在的层次
bool allParentBTree(T item);//找item的所有祖先
void findCommonAncestor(const BTNode<T>* p1,const BTNode<T>* p2,BTNode<T>*& ancestor);//二叉树中2个节点p1, p2的最小公共祖先节点
void longPathBTree();//输出从每个叶子结点到根结点的最长路径
bool isFullBTree(); //判断二叉树是否是完全二叉树
void exchangeChildBTree();//交换二叉树的孩子
bool findBTree(const T item,BTNode<T>*& ret)const; //查找结点
bool getParent(const BTNode<T>* p,BTNode<T>*& ret) const; //返回父亲
bool getLeftChild(const BTNode<T>* p,BTNode<T>*& ret) const; //返回左孩子
bool getRightChild(const BTNode<T>* p,BTNode<T>*& ret) const; //返回右孩子
bool getLeftSibling(const BTNode<T>* p,BTNode<T>*& ret) const; //返回左兄弟
bool getRightSibling(const BTNode<T>* p,BTNode<T>*& ret) const;//返回右兄弟
protected://为了继承
BTNode<T>* root;
private://为了实现公有函数
void create(BTNode<T>*& p); //以p为根结点建树
void createParent(BTNode<T>* p);//为以p为根节点的树设置其指向双亲的结点
void copyTree(BTNode<T>*& copyTreeRoot,BTNode<T>* otherTreeRoot);//把以otherTreeRoot为根节点的部分拷贝到copyTreeRoot为根节点的部分
void destory(BTNode<T>*& p);//销毁以p为根节点的子树
void inOrder(BTNode<T>* p);//中序遍历以p为根节点的子树
void preOrder(BTNode<T>* p);//先序遍历以p为根节点的子树
void postOrder(BTNode<T>* p);//后序遍历以p为根节点的子树
void levelOrder(BTNode<T>* p);//层次遍历以p为根节点的子树
int height(BTNode<T>* p);//计算以p为根节点的高度
int width(BTNode<T>* p);
int max(int x,int y);
int min(int x,int y);//计算以p为根,俩孩子的最值
int nodeCount(BTNode<T>* p);//计算以p为根节点的结点个数
int leavesCount(BTNode<T>* p);//计算以p为根节点的叶子个数
void nodeLevel(T item,BTNode<T>* p,int level,int& nlevel);//计算以p为根节点的树中item所在层次,如有多个元素,则返回一个最小值(离根最近),如果没有出现,则返回0
bool find(BTNode<T>*p,const T item,bool& isFind,BTNode<T>*& cur)const;//在p指向的二叉树中,返回值为item的指针
bool allParent(T item,BTNode<T>* p,BTNode<T>* path[MaxBTreeSize],int& len,int& number,bool& isFind);//找item的所有祖先
void longPath(BTNode<T>* p,int len,int& maxLen,BTNode<T>*& longNode);//输出从每个叶子结点到根结点的最长路径
bool isFull(BTNode<T>* p);//判断以p为根的二叉树是不是完全二叉树
void exchangeChild(BTNode<T>*& p);//交换以p为根节点的二叉树
};
template<class T>
BTree<T>::BTree()
{
root = NULL;
}
template<class T>
BTree<T>::BTree(const BTree<T>& bTree)//拷贝构造函数
{
if (bTree.root == NULL)
{
root = NULL;
}
else
{
copyTree(root,bTree.root);
}
}
template<class T>
void BTree<T>::copyTree(BTNode<T>*& copyTreeRoot,BTNode<T>* otherTreeRoot)//把以otherTreeRoot为根节点的部分拷贝到copyTreeRoot为根节点的部分
{//利用先序遍历实现 递归
if (otherTreeRoot != NULL)
{
copyTreeRoot = new BTNode<T>;
copyTreeRoot->data = otherTreeRoot->data;
copyTree(copyTreeRoot->lchild,otherTreeRoot->lchild);
copyTree(copyTreeRoot->rchild,otherTreeRoot->rchild);
if (copyTreeRoot->lchild != NULL)//别忘了双亲域
{
copyTreeRoot->lchild->parent = copyTreeRoot;
}
if (copyTreeRoot->rchild != NULL)
{
copyTreeRoot->rchild->parent = copyTreeRoot;
}
}
}
template<class T>
BTree<T>::~BTree()
{
destory(root);
}
template<class T>
void BTree<T>::destory(BTNode<T>*& p)//以后根遍历的方式销毁以p为根节点的子树
{
if (p!=NULL)
{
destory(p->lchild);
destory(p->rchild);
delete p;
p = NULL;
}
}
template<class T>
const BTree<T>& BTree<T>::operator=(const BTree<T>& bTree)
{
if (this != &bTree)//避免自赋值
{
if (root!=NULL)//如果被赋值对象不空,则释放资源
{
destory(root);
}
if (bTree.root == NULL)
{
root = NULL;
}
else
{
copyTree(root,bTree.root);
}
}
return *this;
}
template<class T>
void BTree<T>::createBTree()//按先序建立二叉树
{
cout<<"请按先序次序输入节点的值,#表示空结点:";
create(root);
}
template<class T>
void BTree<T>::create(BTNode<T>*& p)//以p为根结点建树(借助先序遍历)
{
T newData;
cin>>newData;
if (newData == '#')//输入#表示结点为空
{
p = NULL;
}
else
{
p = new BTNode<T>;//输入非#则新建一个结点
p->data = newData;
create(p->lchild);//递归建立左子树
create(p->rchild);//递归建立右子树
if (p->lchild != NULL)
{
p->lchild->parent = p;//别忘了双亲域
}
if (p->rchild != NULL)
{
p->rchild->parent = p;
}
}
}
template<class T>
void BTree<T>::createParent(BTNode<T>* p)//为以p为根节点的树设置其指向双亲的结点
{//利用先序遍历,边遍历边初始化,在父亲找到儿子时,为儿子赋值
if (p == root)
{
p->parent = NULL;
}
if (p->lchild != NULL)
{
p->lchild->parent = p;
}
if (p->rchild != NULL)
{
p->rchild->parent = p;
}
createParent(p->lchild);
createParent(p->rchild);
}
template<class T>
void BTree<T>::InitBiTree() //初始化二叉树
{
root = NULL;
}
template<class T>
void BTree<T>::destoryBTree()//销毁二叉树
{
destory(root);
}
template<class T>
bool BTree<T>::isEmptyBTree()//检查二叉树是否为空
{
return (root == NULL);
}
template<class T>
void BTree<T>::preOrderTraverse()//先序遍历
{
preOrder(root);
}
template<class T>
void BTree<T>::preOrder(BTNode<T>* p)//先序遍历以p为根节点的部分
{
if (p != NULL)
{
cout<<p->data<<" ";
preOrder(p->lchild);
preOrder(p->rchild);
}
/*if (p==NULL)
{
return;
}
cout<<p->data<<" ";
preOrder(p->lchild);
preOrder(p->rchild);*/
}
template<class T>
void BTree<T>::inOrderTraverse() //中序遍历
{
inOrder(root);
}
template<class T>
void BTree<T>::inOrder(BTNode<T>* p)//中序遍历以p为根节点的部分
{
if (p != NULL)
{
inOrder(p->lchild);
cout<<p->data<<" ";
inOrder(p->rchild);
}
}
template<class T>
void BTree<T>::postOrderTraverse() //后序遍历
{
postOrder(root);
}
template<class T>
void BTree<T>::postOrder(BTNode<T>* p)//后序遍历以p为根节点的部分
{
if (p != NULL)
{
postOrder(p->lchild);
postOrder(p->rchild);
cout<<p->data<<" ";
}
}
template<class T>
void BTree<T>::levelOrderTraverse()//层序遍历
{
levelOrder(root);
}
template<class T>
void BTree<T>::levelOrder(BTNode<T>* p)//层次遍历以p为根节点的子树
{
//定义循环队列
BTNode<T> *queue[MaxBTreeSize];
int front = 0;
int rear = 0;
BTNode<T> *current;
if (p != NULL)
{
queue[(rear++)%MaxBTreeSize] = p;//根结点如队列
while(rear!=front)//队列空时循环结束
{
current = queue[(front++)%MaxBTreeSize]; //出队列
cout<<current->data<<" ";//访问结点
//当前被访问结点的左右孩子依次入队列
if ((rear+1)%MaxBTreeSize != front)//队列不满
{
if (current->lchild != NULL)//左孩子不空,入队列
{
queue[(rear++)%MaxBTreeSize] = current->lchild;
}
}
if ((rear+1)%MaxBTreeSize != front)//队列不满
{
if (current->rchild != NULL)//右孩子不空,入队列
{
queue[(rear++)%MaxBTreeSize] = current->rchild;
}
}
}
}
}
template<class T>
int BTree<T>::heightBTree()//二叉树高度
{
return height(root);
}
template<class T>
int BTree<T>::height(BTNode<T>* p)//计算以p为根节点的高度 利用后序遍历,先计算左右子树的高度
{
if (p == NULL)
{
return 0;
}
else
{
return max(height(p->lchild),height(p->rchild))+1;
}
}
template<class T>
int BTree<T>::widthBTree() //二叉树宽度
{
return width(root);
}
template<class T>
int BTree<T>::width(BTNode<T>* p)//利用一般队列
{
//定义队列
BTNode<T> *queue[MaxBTreeSize];
int front = 0;//指向队列中第一个元素
int rear = 0;//指向队列中最后一个元素,注意此处与循环队列不同
//根结点入队列
queue[rear] = p;//注意此处与循环队列不同
BTNode<T> *current;
int last = 0;//last记录本层最后一个元素的下标
int maxWidth = 0;//最终的宽度
int temWidth = 0;//记录每层的宽度
while(front <= last)//本层结点没有完全出队列
{
current = queue[front++]; //出队列
temWidth++;//记录本层的宽度
if (current->lchild != NULL)//左孩子不空,入队列
{
queue[++rear] = current->lchild;
}
if (current->rchild != NULL)//右孩子不空,入队列
{
queue[++rear] = current->rchild;
}
if (last < front)//当本层出队列完毕,更新下一层的last
{
last = rear;
if (temWidth > maxWidth)
{
maxWidth = temWidth;//更新最大宽度
}
temWidth = 0;//每层宽度求完,归零
}
}
return maxWidth;
}
template<class T>
int BTree<T>::nodeCountBTree() //二叉树结点个数
{
return nodeCount(root);
}
//利用后根遍历得到
template<class T>
int BTree<T>::nodeCount(BTNode<T>* p)//计算以p为根节点的结点个数
{
if (p == NULL)
{
return 0;
}
else
{
return nodeCount(p->lchild)+nodeCount(p->rchild)+1;
}
}
template<class T>
int BTree<T>::LeavesCountBTree()//二叉树叶子个数
{
return leavesCount(root);
}
//利用先根遍历
template<class T>
int BTree<T>::leavesCount(BTNode<T>* p)//计算以p为根节点的叶子个数
{
if (p == NULL)//递归出口一
{
return 0;
}
if (p->lchild==NULL && p->rchild==NULL)//出口二
{
return 1;
}
else
{
return leavesCount(p->lchild)+leavesCount(p->rchild);
}
}
template<class T>
int BTree<T>::nodeLevelBTree(T item)//结点item在的层次,如有多个结点,返回最近的层次
{
int nlevel = 0;
nodeLevel(item,root,1,nlevel);
return nlevel;
}
//利用先序次序,遇到第一次结点即停止 用一个变量记录层次
template<class T>
void BTree<T>::nodeLevel(T item,BTNode<T>* p,int level,int& nlevel)//计算以p为根节点的中item所在层次,如有多个元素,则返回一个最小值(离根最近),如果没有出现,则返回0
{
if (p == NULL)
{
nlevel = 0;
//return;
}
else
{
if (p->data == item)
{
nlevel = level; //level记录的是本层层数,level初始值为1
//return;
}
else//没有找到,在左右子树中递归的查找
{
if (nlevel == 0)//nlevel=0表示没有找到
{
nodeLevel(item,p->lchild,level+1,nlevel);
}
if (nlevel == 0)//如果在左子树上找到就停止,不会再到右子树上查找
{
nodeLevel(item,p->rchild,level+1,nlevel);
}
}
}
}
template<class T>
bool BTree<T>::allParentBTree(T item)//找item的所有祖先
{
BTNode<T> *path[MaxBTreeSize];
int len = 0;
int number = 0;
bool isFind = false;
allParent(item,root,path,len,number,isFind);
cout<<item<<"的所有祖先:";
for (int i=0; i<number;i++)
{
cout<<path[i]->data<<" ";
}
cout<<endl;
return true;
}
//利用先序遍历,将item所有的祖先存放到数组path中,然后从根开始输出
//找到第一个值为item的祖先
template<class T>
bool BTree<T>::allParent(T item,BTNode<T>* p,BTNode<T>* path[MaxBTreeSize],int& len,int& number,bool& isFind)//找item的所有祖先
{//参数的设置很重要,要找item,因此要有标志isFind,祖先很多用数组存储,祖先个数用number
if (p!=NULL)
{
if (!isFind)//没有找到
{
if (p->data!=item)
{
path[len++] = p;//没有找到,将当前节点放入数组path中
allParent(item,p->lchild,path,len,number,isFind);//在左右子树中继续查找
allParent(item,p->rchild,path,len,number,isFind);
len--;//将不是祖先的结点从数组中剔除
}
else
{
isFind = true;
number = len;
}
}
}
return isFind;
}
template<class T>
void BTree<T>::findCommonAncestor(const BTNode<T>* p1,const BTNode<T>* p2,BTNode<T>*& ancestor)//二叉树中2个节点p1, p2的最小公共祖先节点
{
BTNode<T> *path1[MaxBTreeSize];
int p1_len = 0;
int p1_number = 0;
bool isFind_p1 = false;
BTNode<T> *path2[MaxBTreeSize];
int p2_len = 0;
int p2_number = 0;
bool isFind_p2 = false;
allParent(p1->data,root,path1,p1_len,p1_number,isFind_p1);
allParent(p2->data,root,path2,p2_len,p2_number,isFind_p2);
/*for (int i=0; i<p1_number&&i<p2_number; i++)*/
for (int i=0; i<min(p1_number,p2_number); i++)
{
if (path1[i] != path2[i])
{
ancestor = path1[i-1];
break;
}
if (i==min(p1_number,p2_number)-1)
{
ancestor = path1[i];
}
}
}
template<class T>
void BTree<T>::longPathBTree()//输出从每个叶子结点到根结点的最长路径
{
int len = 0;
int maxLen = 0;//最大路径长度
BTNode<T> *longNode;//记录最长路径上的叶子结点
longPath(root,len,maxLen,longNode);
if (root == NULL)
{
cout<<"二叉树为空!"<<endl;
}
else
{
cout<<"从叶子结点到根结点的最长路径:";
while(longNode!=NULL)
{
cout<<longNode->data<<" ";
longNode = longNode->parent;
}
cout<<endl;
}
}
/*
求出最长路径的那个叶子节点,只有路径可以借助parent和longNode求出
方法:借助先序遍历完成
p:要求二叉树的最长路径
len: 正在处理节点的层次数 longNode表示找到后,指向最长路径
maxLen:表示最长的长度 */
template<class T>
void BTree<T>::longPath(BTNode<T>* p,int len,int& maxLen,BTNode<T>*& longNode)//输出从每个叶子结点到根结点的最长路径
{
if (p == NULL)
{
len = 0;
}
else
{
len++;//记录正在处理结点的层数
if (p->lchild==NULL && p->rchild==NULL)//找到叶子结点 先考虑特殊情况
{
if (len>maxLen)
{
maxLen = len;//更新最大路径长度
longNode = p;
}
}
else//当前处理的结点不是叶子结点
{
longPath(p->lchild,len,maxLen,longNode);//在左右子树上继续查找叶子结点
longPath(p->rchild,len,maxLen,longNode);
len--;//注意此步 找路径和找祖先一样都需要减
}
}
}
template<class T>
bool BTree<T>::isFullBTree() //判断二叉树是否是完全二叉树
{
if (isFull(root))
{
return true;
}
else
{
return false;
}
}
/*思路:按层次遍历方式,先把所有结点(不管当前结点是否有左右孩子)都入队列.
若为完全二叉树,则层次遍历时得到的肯定是一个连续的不包含空指针的序列.
如果序列中出现了空指针,则说明不是完全二叉树。*/
template<class T>
bool BTree<T>::isFull(BTNode<T>* p)//判断以p为根的二叉树是不是完全二叉树
{
bool isExist = false;//表示现在这个状态下,队列中是不是存在空指针
/* 当队中出现空指针时,看看空指针之后是不是有非空的指针,
如果空指针后有非空指针出现,则肯定不是完全二叉树,
如果空指针之后没有非空指针,则是完全二叉树 */
BTNode<T> *queue[MaxBTreeSize];
int front = 0;
int rear = 0;
BTNode<T> *current;
if (p!=NULL)
{
queue[(rear++)%MaxBTreeSize] = p;
while(front != rear)
{
current = queue[(front++)%MaxBTreeSize];
if (current == NULL)//存在空指针
{
isExist = true;
}
else
{//在current之前就已经出现空指针
if (isExist && (current->lchild!=NULL || current->rchild!=NULL))
{
return false;
}
if ((rear+1)%MaxBTreeSize != front)
{
queue[(rear++)%MaxBTreeSize] = current->lchild;
}
if ((rear+1)%MaxBTreeSize != front)
{
queue[(rear++)%MaxBTreeSize] = current->rchild;
}
}
}
}
return true;
}
template<class T>
void BTree<T>::exchangeChildBTree()//交换二叉树的孩子
{
exchangeChild(root);
}
template<class T>
void BTree<T>::exchangeChild(BTNode<T>*& p)//交换以p为根节点的二叉树 以先序的方式递归实现
{
if (p!=NULL)
{
if (p->lchild!=NULL || p->rchild!=NULL)
{
BTNode<T> *temp;
temp = p->lchild;
p->lchild = p->rchild;
p->rchild =temp;
}
exchangeChild(p->lchild);
exchangeChild(p->rchild);
}
}
template<class T>
bool BTree<T>::findBTree(const T item,BTNode<T>*& ret)const //查找结点
{
bool isFind = false;
return find(root,item,isFind,ret);
}
template<class T>
bool BTree<T>::find(BTNode<T>*p,const T item,bool& isFind,BTNode<T>*& cur)const//在p指向的二叉树中,返回值为item的指针
{
if (p!=NULL)
{
if (!isFind)
{
if (p->data != item)//没有找到,在左子树中继续查找
{
find(p->lchild,item,isFind,cur);
}
else
{
isFind = true;
cur = p;
}
if (p->data != item)//没有找到,在右子树中继续查找
{
find(p->rchild,item,isFind,cur);
}
else
{
isFind = true;
cur = p;
}
}
}
return isFind;
}
template<class T>
bool BTree<T>::getParent(const BTNode<T>* p,BTNode<T>*& ret) const //返回父亲
{
if (p->parent!=NULL)
{
ret = p->parent;
return true;
}
return false;
}
template<class T>
bool BTree<T>::getLeftChild(const BTNode<T>* p,BTNode<T>*& ret) const //返回左孩子
{
if (p->lchild!=NULL)
{
ret = p->lchild;
return true;
}
return false;
}
template<class T>
bool BTree<T>::getRightChild(const BTNode<T>* p,BTNode<T>*& ret) const //返回右孩子
{
if (p->rchild!=NULL)
{
ret = p->rchild;
return true;
}
return false;
}
template<class T>
bool BTree<T>::getLeftSibling(const BTNode<T>* p,BTNode<T>*& ret) const //返回左兄弟
{
if (p->parent!=NULL)
{
if (p->parent->lchild != p)
{
ret = p->parent->lchild;
return true;
}
}
return false;
}
template<class T>
bool BTree<T>::getRightSibling(const BTNode<T>* p,BTNode<T>*& ret) const//返回右兄弟
{
if (p->parent!=NULL)
{
if (p->parent->rchild != p)
{
ret = p->parent->rchild;
return true;
}
}
return false;
}
template<class T>
int BTree<T>::max(int x,int y)
{
return (x>y?x:y);
}
template<class T>
int BTree<T>::min(int x,int y)//计算以p为根,俩孩子的最值
{
return (x<y?x:y);
}
int _tmain(int argc, _TCHAR* argv[])
{
BTree<char> *tree = new BTree<char>;
tree->createBTree();
cout<<"先序遍历:";
tree->preOrderTraverse();
cout<<endl;
cout<<"中序遍历:";
tree->inOrderTraverse();
cout<<endl;
cout<<"后序遍历:";
tree->postOrderTraverse();
cout<<endl;
cout<<"层序遍历:";
tree->levelOrderTraverse();
cout<<endl;
cout<<"树的高度:"<<tree->heightBTree()<<endl;
cout<<"树的宽度:"<<tree->widthBTree()<<endl;
cout<<"树的结点个数:"<<tree->nodeCountBTree()<<endl;
cout<<"树的叶子结点个数:"<<tree->LeavesCountBTree()<<endl;
cout<<"E所在的层次:"<<tree->nodeLevelBTree('E')<<endl;
char a = 'F';
cout<<tree->allParentBTree(a);
cout<<"树是否为完全二叉树?1表示是,0表示否。结果是:"<<tree->isFullBTree()<<endl;
tree->longPathBTree();
BTNode<char> *ret;
if (tree->findBTree('E',ret))
{
if (ret->lchild)
{
cout<<"左孩子:"<<ret->lchild->data<<endl;
}
else
{
cout<<ret->data<<"没有左孩子!"<<endl;
}
if (ret->rchild)
{
cout<<"右孩子:"<<ret->rchild->data<<endl;
}
else
{
cout<<ret->data<<"没有右孩子!"<<endl;
}
}
BTNode<char> *node1;
BTNode<char> *node2;
tree->findBTree('F',node1);
tree->findBTree('E',node2);
BTNode<char> *ancesor;
tree->findCommonAncestor(node1,node2,ancesor);
cout<<node1->data<<"和"<<node2->data<<"的最小公共祖先:"<<ancesor->data<<endl;
system("pause");
return 0;
}