数据结构--二叉树
来源:互联网 发布:python 马科维兹模型 编辑:程序博客网 时间:2024/05/23 01:21
类定义:
/*
*FileName: BinaryTree
*Creator: QianChenglong
*Date: 2011/10/30
*Comments: 因为BinaryTree把根节点指针作为数据成员,所以在后面的递归算法的实现上,都需要先处理下根节点,在设计辅助函数去实现递归处理;之所以这样是因为递归入口不一样,且需要初始化,在建立过程中就需要先给流输入数据,还要是根节点指针指向根节点,而在子部分中就不需要这些处理,所以应该分开来写;
*/
#ifndef BINARYTREE_H
#define BINARYTREE_H
#include<string>
#include<vector>
template<typename T>
class BinaryTree{
private:
struct Node; /* 嵌套类定义,用来辅助实现*/
Node* rootNode;//指向树的根节点;
//辅助函数;
Node* _find(Node* node,const T& value) const;//返回value的指针
int _getHeight(Node* node) const;//求树的高度;
int _getLeaves(Node* node) const;//返回叶子节点数
void _preOrderOut(Node* node);//前序遍历二叉树;
void _infixOrderOut(Node* node);
void _postOrderOut(Node* node);
Node* _creat(std::istringstream& in);//利用string对象创建二叉树;
Node* _creat();
public:
BinaryTree():rootNode(0){}//二叉树的初始化;
~BinaryTree(){destroy();}
//建立
Node* creat();//利用前序来创建二叉树,返回树的根节点;
Node* creat(std::string& str);//利用前序序列的字符串创建二叉树,返回树的根节点;
//销毁
void destroy();//销毁二叉树;
//遍历
void preOrderOut();//前序递归遍历
void infixOrderOut();//中序递归遍历
void postOrderOut();//后序递归遍历
void levelTraversing() const;//按层次遍历;
void preOut();//前序非递归遍历
void infixOut();//中序非递归遍历
void postOut();//后序非递归遍历
//访问操作
bool getLeftNodeValue(Node* node,T& gotValue) const;//用gotValue返回node的左孩子的值,成功返回1,失败返回0;
bool getRightNodeValue(Node* node,T& gotValue) const;//用gotValue返回node的右孩子的值,成功返回1,失败返回0;
int getHeight() const;//返回树的高度;
int getWidth() const;//返回树的宽度;
int getNodeCount() const;//返回节点数;
int getLeaves() const;//返回叶子节点数;
Node* getRoot() const;//返回二叉树的根节点指针;
Node* find(const T& value) const;//返回value的指针;
//判断操作
bool isEmpty() const;//判断是否为空树;
bool isComplete() const;//判断是否是完全二叉树;
bool isSemmetrical() const;//判断一棵树是否是对称的;
};
//定义树的节点;
template<typename T>
struct BinaryTree<T>::Node{
T data;
Node* leftNode;//指向该节点的左子树;
Node* rightNode;//指向该节点的右子树;
Node();/* 默认构造函数 */
Node(T& _data);
};
#include "BinaryTree.cpp"
#endif
类实现:
/*=============================================================================
# FileName: BinaryTree.cpp
# Desc: 实现二叉树
# Author: QianChenglong
# Email: qian_cheng_long@163.com
# HomePage: waiting...
# Version: 0.0.1
# LastChange: 2011-11-29 19:09:41
# History:
=============================================================================*/
#ifndef BINARYTRR_CPP
#define BINARYTRR_CPP
#include "BinaryTree.h"
#include "SeqQueue.h"
#include<iostream>
#include<sstream>
#include "SeqStack.h"
///////////////////////////////////////////////////////////////////////
template<typename T>
BinaryTree<T>::Node::Node()
:leftNode(0),rightNode(0)
{
}
/////////////////////////////////////////////////////////////////////////
template<typename T>
BinaryTree<T>::Node::Node(T& _data)
:data(_data),leftNode(0),rightNode(0)
{
}
///////////////////////////////////////////////////////////////////////////////////
template<typename T>
typename BinaryTree<T>::Node* BinaryTree<T>::creat(){//采用前序遍历一个满二叉树建立,虚节点采用'*'标识,结束标记为'#';
T nullNode;//用来吸收虚节点;
if(std::cin.peek()=='*'){//当第一个就为虚节点标识时,则为空树;
std::cin>>nullNode;
rootNode=0;
return rootNode;
}
T data_;//用来存储节点值;
std::cin>>data_;
rootNode=new Node(data_);
rootNode->leftNode=_creat();
rootNode->rightNode=_creat();
return rootNode;
}
//////////////////////////////////////////////////////////////////////////////
template<typename T>
typename BinaryTree<T>::Node* BinaryTree<T>::_creat(){//采用前序遍历一个满二叉树建立,虚节点采用'*'标识,结束标记为'#';
T data_;
//处理虚节点和结束符;
char nullNode;
if(std::cin.peek()=='*'){ //将下一字节作为int值返回,但不移除它;
std::cin.get(nullNode);
return 0;
}
std::cin>>data_;
Node* newNode=new Node(data_);
newNode->leftNode=_creat();
newNode->rightNode=_creat();
return newNode;
}
///////////////////////////////////////////////////////////////////////////////////
template<typename T>
typename BinaryTree<T>::Node* BinaryTree<T>::_creat(std::istringstream& in){//采用前序遍历一个满二叉树建立,虚节点采用'*'标识
//处理虚节点和结束符;
char nullNode;
if(in.peek()=='*'){ //将下一字节作为int值返回,但不移除它;
in.get(nullNode);
return 0;
}
T data_;
in>>data_;
Node* newNode=new Node(data_);
newNode->leftNode=_creat(in);
newNode->rightNode=_creat(in);
return newNode;
}
////////////////////////////////////////////////////////////////////////
template<typename T>
typename BinaryTree<T>::Node* BinaryTree<T>::creat(std::string& str){
std::istringstream in(str);//用str初始化istringstream流;
if(in.peek()=='*'){ //若第一个节点就为虚节点,则为空树;
rootNode=0;
return rootNode;
}
T data_;
in>>data_;
rootNode=new Node(data_);
rootNode->leftNode=_creat(in);
rootNode->rightNode=_creat(in);
return rootNode;
}
template<typename T>//销毁树;
void BinaryTree<T>::destroy(){//层次遍历二叉树,挨个delete
if(rootNode==0)
return;
SeqQueue<Node*> qu;
qu.push(rootNode);
Node* work=0;
if(!qu.isEmpty()){
work=qu.pop();
if(work->leftNode!=0)
qu.push(work->leftNode);
if(work->rightNode!=0)
qu.push(work->rightNode);
delete work;
work=0;
}
}
/////////////////////////////////////////////////////////////////////////////////
template<typename T>//前序输出二叉树;
void BinaryTree<T>::_preOrderOut(Node* node){
if(node!=0){
std::cout<<node->data<<' ';
_preOrderOut(node->leftNode);
_preOrderOut(node->rightNode);
}
}
////////////////////////////////////////////////////////////////////////////
template<typename T>
void BinaryTree<T>::preOrderOut(){
_preOrderOut(rootNode);
std::cout<<std::endl;
}
//////////////////////////////////////////////////////////////////////////////
template<typename T>
typename BinaryTree<T>::Node* BinaryTree<T>::getRoot() const{//返回根节点的指针;
return rootNode;
}
////////////////////////////////////////////////////////////////////
template<typename T>
bool BinaryTree<T>::isEmpty() const{//判断是否为空树;
return rootNode==0;
}
//////////////////////////////////////////////////////////////////////////////
template<typename T>
typename BinaryTree<T>::Node* BinaryTree<T>::find(const T& value) const{
return _find(rootNode,value);
}
////////////////////////////////////////////////////////////////////////
template<typename T>
typename BinaryTree<T>::Node* BinaryTree<T>::_find(Node* node,const T& value) const{
if(node==0)
return 0;
if(node->data==value)
return node;
else{
Node* p=0;
p=_find(node->leftNode,value);
if(p!=0) return p;
p=_find(node->rightNode,value);
return p;
}
}
//////////////////////////////////////////////////////////////////////
template<typename T>//用gotValue返回node的左孩子的值,成功返回1,失败返回0;
bool BinaryTree<T>::getLeftNodeValue(Node* node,T& gotValue) const{
if(node->leftNode==0)
return 0;
gotValue=node->leftNode->data;
return 1;
}
/////////////////////////////////////////////////////////////////////
template<typename T>//用gotValue返回node的右孩子的值,成功返回1,失败返回0;
bool BinaryTree<T>::getRightNodeValue(Node* node,T& gotValue)const{
if(node->rightNode==0)
return 0;
gotValue=node->rightNode->data;
return 1;
}
/////////////////////////////////////////////////////////////////////////
template<typename T>//返回树的高度;
int BinaryTree<T>::getHeight() const{
return _getHeight(rootNode);
}
//////////////////////////////////////////////////////////////////////////
template<typename T>//返回树的高度;
int BinaryTree<T>::_getHeight(Node* node) const{
if(node==0)
return 0;
int leftHeight=_getHeight(node->leftNode);
int rightHeight=_getHeight(node->rightNode);
if(leftHeight>rightHeight)
return leftHeight+1;
else
return rightHeight+1;
}
////////////////////////////////////////////////////////////////////
template<typename T>
int BinaryTree<T>::getNodeCount() const{
SeqQueue<Node*> qu;
qu.push(rootNode);
Node* work=0;
int count=0;
while(!qu.isEmpty()){
work=qu.pop();
++count;
if(work->leftNode!=0)
qu.push(work->leftNode);
if(work->rightNode!=0)
qu.push(work->rightNode);
}
return count;
}
/////////////////////////////////////////////////////////////////////////
template<typename T>
int BinaryTree<T>::getWidth() const{//返回树的宽度;
Node* work;
SeqStack<Node*> stack1,stack2;
stack1.push(rootNode);
int width=0;
while(!(stack1.isEmpty()&&stack2.isEmpty())) /* 当两个栈 !都为空的时候*/
{
while(!stack1.isEmpty()) /* 当stack1不为空时*/
{
work=stack1.pop(); /* 出栈一个元素*/
if( work->leftNode ) /* 判断当前出栈元素的左孩子是否存在*/
{
stack2.push(work->leftNode); /* 若存在则把它压入stack2*/
}
if( work->rightNode ) /* 判断当前出栈元素的右孩子是否存在*/
{
stack2.push(work->rightNode); /* 若存在则把他压入stack2*/
}
} /* 这样所有stack1的孩子节点就进入了stack2*/
if( width < stack2.length() ) /* 若当前宽度值小于某一层的节点数*/
{
width = stack2.length(); /* 则该层的节点数就为当前宽度*/
}
while(!stack2.isEmpty()) /* 当stack2不为空时*/
{
work=stack2.pop(); /* 出栈一个元素*/
if( work->leftNode ) /* 判断当前出栈元素的左孩子是否存在*/
{
stack1.push(work->leftNode); /* 若存在则把它压入stack1*/
}
if( work->rightNode ) /* 判断当前出栈元素的右孩子是否存在*/
{
stack1.push(work->rightNode); /* 若存在则把他压入stack1*/
}
} /* 这样所有stack2的孩子节点就进入了stack1*/
if( width < stack1.length() ) /* 若当前宽度值小于某一层的节点数*/
{
width = stack1.length(); /* 则该层的节点数就为当前宽度*/
}
}
return width; /* 返回宽度*/
}
//////////////////////////////////////////////////////////////////////////////////////
template<typename T>
int BinaryTree<T>::getLeaves() const{//返回叶子节点数;
return _getLeaves(rootNode);
}
/////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
int BinaryTree<T>::_getLeaves(Node* node) const{
if(node==0)
return 0;
if(node->leftNode==0&&node->rightNode==0)
return 1;
return _getLeaves(node->leftNode)+_getLeaves(node->rightNode);
}
/////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
void BinaryTree<T>::levelTraversing() const{//按层次遍历;
SeqQueue<Node*> qu;//定义一个存储节点指针的队列;
Node* work=0;//工作指针;
if(rootNode==0) return;//若为空树,则结束遍历
qu.push(rootNode);//根节点入队;
while(qu.isEmpty()==0){//队列是否为空;
work=qu.pop();//出队;
std::cout<<work->data<<' ';//访问出队节点的数据;
if(work->leftNode!=0)//若出队节点的左孩子不为空;
qu.push(work->leftNode);//左孩子入队;
if(work->rightNode!=0)//若出队节点的右孩子不为空:
qu.push(work->rightNode);//右孩子入队;
}
std::cout<<std::endl;
}
///////////////////////////////////////////////////////////////////////////
template<typename T>
bool BinaryTree<T>::isComplete() const{//采用层次遍历,判断每一个节点前面是否有空位,若有,则不是完全二叉树;
SeqQueue<Node*> qu;
if(rootNode==0) return 1;
qu.push(rootNode);
Node* work=0;
int flag=0;//标记位,0表示前面一个为数据,1表示前面上个空位;
while(qu.isEmpty()==0){
work=qu.pop();//出队一个节点;
if(work!=0){//若出队节点不为空;
if(flag==1)//若标记位为1;
return 0;//则说明不是完全二叉树;
qu.push(work->leftNode);//出队节点的左右孩子入队,空节点也入队;
qu.push(work->rightNode);
}
else//说明为空节点;
flag=1;//标记位置为1;
}
return 1;
}
///////////////////////////////////////////////////////////////////////////
template<typename T>//中序遍历
void BinaryTree<T>::infixOrderOut(){
_infixOrderOut(rootNode);
std::cout<<std::endl;
}
/////////////////////////////////////////////////////////
template<typename T>
void BinaryTree<T>::_infixOrderOut(Node* node){
if(node!=0){
_infixOrderOut(node->leftNode);
std::cout<<node->data<<' ';
_infixOrderOut(node->rightNode);
}
}
//////////////////////////////////////////////////////////
template<typename T>//后序遍历
void BinaryTree<T>::postOrderOut(){
_postOrderOut(rootNode);
std::cout<<std::endl;
}
///////////////////////////////////////////////
template<typename T>
void BinaryTree<T>::_postOrderOut(Node* node){
if(node!=0){//若节点为空,则不访问,返回上一级,若节点不为空,则后序遍历该树
_postOrderOut(node->leftNode);
_postOrderOut(node->rightNode);
std::cout<<node->data<<' ';
}
}
////////////////////////////////////////////////////////////
template<typename T>//前序非递归遍历
void BinaryTree<T>::preOut(){
SeqStack<Node*> sk;
if(rootNode==0)
return;
sk.push(rootNode);
Node *work=0;
while(!sk.isEmpty()){
work=sk.pop();
std::cout<<work->data<<' ';//访问节点
if(work->rightNode!=0)
sk.push(work->rightNode);
if(work->leftNode!=0)
sk.push(work->leftNode);
}
std::cout<<std::endl;
}
//////////////////////////////////////////////
template<typename T>//中序非递归遍历
void BinaryTree<T>::infixOut(){
SeqStack<Node*> sk;
if(rootNode==0) return;
Node* work=rootNode;
while(work!=0||!sk.isEmpty()){
while(work!=0){//将work的左子树,当左节点不为空,则进栈
sk.push(work);//当处理的是根节点是,就是将所有的左子树依次进栈
work=work->leftNode;
}
if(!sk.isEmpty()){
work=sk.pop();
std::cout<<work->data<<' ';//访问左节点后
work=work->rightNode;//处理右子树
}
}
std::cout<<std::endl;
}
///////////////////////////////////////////////////////////
template<typename T>//后序非递归遍历
void BinaryTree<T>::postOut(){
int flag;
SeqStack<Node*> sk;
Node* work=rootNode;
Node* pre;
if(work!=0){
do{
while(work!=0){//将work所有的左节点依次进栈
sk.push(work);
work=work->leftNode;
}
pre=0;//pre指向栈顶节点的前一个已访问过的节点
flag=1;//1表示*work的左孩子已访问或为空
while(!sk.isEmpty()&&flag==1){
work=sk.getTop();
if(work->rightNode==pre){
std::cout<<work->data<<' ';
pre=work;
sk.pop();
}else{
work=work->rightNode;
flag=0;//
}
}
}while(!sk.isEmpty());
}
std::cout<<std::endl;
}
#endif
功能测试:
/*=============================================================================
# FileName: main.cpp
# Desc:
# Author: QianChenglong
# Email: qian_cheng_long@163.com
# HomePage: waiting...
# Version: 0.0.1
# LastChange: 2011-11-29 19:06:57
# History:
=============================================================================*/
#include<iostream>
#include "BinaryTree.h"
int main(){
BinaryTree<char> Tree;
std::cout<<"请按前序输入二叉树:\n";
std::string str("ABD*G***CE**F**");
//std::string str("ABc*****");
//std::string str("AB**C**");
Tree.creat(str);
std::cout<<"二叉树创建成功!\n";
std::cout<<Tree.getWidth()<<std::endl;
Tree.preOut();
Tree.infixOut();
Tree.postOut();
/*
Tree.preOrderOut();
Tree.infixOrderOut();
Tree.postOrderOut();
/*
Tree.levelTraversing();
if(Tree.isComplete()==1)
std::cout<<"是完全二叉树\n";
else
std::cout<<"不是完全二叉树\n";
/*
Tree.preOrderOut();
std::cout<<std::endl;
Node<char>* p=Tree.find('A');
char gotValue;
if(p!=0){
Tree.getLeftNodeValue(p,gotValue);
std::cout<<gotValue;
Tree.getRightNodeValue(p,gotValue);
std::cout<<gotValue;
}
std::cout<<Tree.getHeight()<<std::endl
<<Tree.getNodeCount()
<<Tree.getWidth()
<<Tree.getLeaves();
return 0;
*/
}
- 数据结构-树-二叉树
- 数据结构::树,二叉树
- 数据结构-二叉树
- 二叉树的数据结构
- 数据结构-二叉树算法
- java数据结构:二叉树
- 数据结构---二叉树
- 数据结构(C++)--二叉树
- JAVA 数据结构 二叉树
- 数据结构-二叉树 问题
- 转贴:数据结构:二叉树
- 二叉树(数据结构 c++)
- 数据结构-二叉树操作
- java数据结构----二叉树
- 数据结构二叉树
- 数据结构中的二叉树
- 数据结构--二叉树
- 数据结构二叉搜索树
- 来淘宝的这一年:前篇、生活和工作
- 部分函数列举
- 《华为研发》阅读 - 15 (分解“满汉全席”,“先谋而后动”)
- CreateEvent、CreateSemaphore、ReleaseSemaphore、CreateMutex
- sicily 1765
- 数据结构--二叉树
- js获取GridView中行数据的两种方法
- 如何交叉编译Python到ARM-Linux平台
- 如何:在 Visual Studio 中添加或移除引用
- 实时操作系统与通用操作系统的一些比较
- BTree,B-Tree,B+Tree,B*Tree
- 《满江红》
- Ubuntu Locale配置问题根源解决之道
- 图像 ROI