(1)二叉树
基本特征:
•① 每个结点最多只有两棵子树(不存在度大于2的结点)
•② 左子树和右子树次序不能颠倒。下面是两棵不同的树:
l结点的层次:根结点的层数为0,根的孩子层数为1,依此类推。
l二叉树深度:树中结点的最大层次。
l二叉树的高度:层数最大的叶结点的层数加1。
满二叉树和完全二叉树
满二叉树:棵二叉树的任何结点,或者是树叶,或者恰有两棵非空子树,这样的二叉树称为满二叉树。
完全二叉树:如果一棵深度为k,有n个结点的二叉树中各结点能够与深度为k的顺序编号的满二叉树从1到n标号的结点相对应的二叉树称为完全二叉树。(只有最下两层结点可以度小于2)
特点:
•叶子结点只可能在层次最大的两层上出现;
•前k-1层中的结点都是“满”的,且第k 层的结点都集中在左边。
(2)二叉树的遍历
•遍历
–按一定的规律,走遍二叉树的每个结点,使每个结点被访问一次,且只被访问一次。
•遍历方式
–深度优先遍历
按根、左子树、右子树三个部分进行访问
–广度优先遍历(逐层遍历)
•从根节点开始,向下逐层访问每个节点,在每一层次上,从左到右访问每个节点。
•基于二叉树的递归定义,这三种深度优先周游的递归定义
(1) 前序法(tLR次序,preorder traversal)。其递归定义是
访问根结点;
按前序周游左子树;
按前序周游右子树。
(2) 中序法(LtR次序,inorder traversal)。其递归定义是
按中序周游左子树;
访问根结点;
按中序周游右子树。
(3) 后序法(LRt次序,postorder traversal)。其递归定义是
按后序周游左子树;
按后序周游右子树;
访问根结点。
BinaryTreeNode.h
#include<iostream>
using namespace std;
class BinaryTreeNode
{
friend class BinaryTree;
private:
int element; //二叉树结点数据域
BinaryTreeNode* left;//二叉树结点指向左子树的指针
BinaryTreeNode* right;//二叉树结点指向左子树的指针
public:
BinaryTreeNode();
BinaryTreeNode(const int & ele);//给定数据的构造函数
BinaryTreeNode(const int & ele,BinaryTreeNode* l, BinaryTreeNode* r);//给定数据的左右指针的构造函数
int value() const; //返回当前结点的数据
//BinaryTreeNode& operator= (const BinaryTreeNode& Node){this=Node;};//重载赋值操作符
BinaryTreeNode* leftchild() const; //返回当前结点指向左子树的指针
BinaryTreeNode* rightchild() const;//返回当前结点指向右子树的指针
void setLeftchild(BinaryTreeNode*); //设置当前结点的左子树
void setRightchild(BinaryTreeNode*);//设置当前结点的右子树
void setValue(const int & val); //设置当前结点的数据域
bool isLeaf() const; //判定当前结点是否为叶结点,若是返回true
};
BinaryTreeNode::BinaryTreeNode()
{
left=right=NULL;
}
BinaryTreeNode::BinaryTreeNode(const int & ele) //给定数据的构造函数
{
element=ele;
left=right=NULL;
}
BinaryTreeNode::BinaryTreeNode(const int & ele,BinaryTreeNode* l, BinaryTreeNode* r)//给定数据的左右指针的构造函数
{
element=ele;
left=l;
right=r;
}
int BinaryTreeNode::value() const
{
return element;
}
BinaryTreeNode* BinaryTreeNode::leftchild() const//返回当前结点指向左子树的指针
{
return left;
}
BinaryTreeNode* BinaryTreeNode::rightchild() const//返回当前结点指向右子树的指针
{
return right;
}
void BinaryTreeNode::setLeftchild(BinaryTreeNode* subroot)//设置当前结点的左子树
{
left=subroot;
}
void BinaryTreeNode::setRightchild(BinaryTreeNode* subroot)//设置当前结点的右子树
{
right=subroot;
}
void BinaryTreeNode::setValue(const int & val) //设置当前结点的数据域
{
element = val;
}
bool BinaryTreeNode::isLeaf() const //判定当前结点是否为叶结点,若是返回true
{
return (left == NULL) && (right == NULL);
}
BinaryTree.cpp
#include<iostream>
#include<stack>
#include<queue>
#include "BinaryTreeNode.h"
using namespace std;
class BinaryTree{
private:
BinaryTreeNode * root; //二叉树根节点
public:
BinaryTree(){root=NULL;} //构造函数
~BinaryTree(){DeleteBinaryTree(root);} //析构函数
bool isEmpty()const; //判断二叉树是否为空
BinaryTreeNode * Root(){return root;} //返回二叉树的根节点
BinaryTreeNode * Parent(BinaryTreeNode * current); //返回当前节点的父节点
BinaryTreeNode * LeftSibling(BinaryTreeNode * current); //返回当前节点的左兄弟
BinaryTreeNode * RightSibling(BinaryTreeNode * current);//返回当前节点的右兄弟
void CreateTree(const int & info,BinaryTree &leftTree,BinaryTree & rightTree); //构造新数
void PreOrder(BinaryTreeNode * root); //递归前序周游
void InOrder(BinaryTreeNode * root); //递归中序周游
void PostOrder(BinaryTreeNode * root); //递归后序周游
void LevelOrder(BinaryTreeNode * root); //广度优先周游
void DeleteBinaryTree(BinaryTreeNode * root); //删除给定的二叉树
void Visit(int data){ cout<<data<<" "<<endl;};
void PreOrderWithoutRecursion(BinaryTreeNode * root); //非递归前序周游
void InOrderWithoutRecursion(BinaryTreeNode * root); //非递归中序周游
void PostOrderWithoutRecursion(BinaryTreeNode * root); //非递归后序周游
}
void BinaryTree::PreOrder(BinaryTreeNode * root){
if (root!=NULL)
{
Visit(root->value());
PreOrder(root->leftchild());
PreOrder(root->rightchild());
}
}
void BinaryTree::InOrder(BinaryTreeNode * root){
if (root!=NULL)
{
InOrder(root->leftchild());
Visit(root->value());
InOrder(root->rightchild());
}
}
void BinaryTree::PostOrder(BinaryTreeNode * root){
if (root!=NULL)
{
PostOrder(root->leftchild());
PostOrder(root->rightchild());
Visit(root->value());
}
}
void BinaryTree::PostOrderWithoutRecursion(BinaryTreeNode * root){
using std::stack; //使用STL中的栈
stack<BinaryTreeNode * > aStack;
BinaryTreeNode * pointer=root;
aStack.push(NULL); //栈底监视哨
while (pointer)
{
Visit(pointer->value());
if(pointer->rightchild()!=NULL)
aStack.push(pointer->rightchild());
if (pointer->leftchild()!=NULL)
pointer=pointer->leftchild();
else{
pointer=aStack.top(); //获得栈顶元素
aStack.pop();
}
}
}
void BinaryTree::InOrderWithoutRecursion(BinaryTreeNode * root){
using std::stack;
stack<BinaryTreeNode* > aStack;
BinaryTreeNode * pointer;
while (!aStack.empty() || pointer)
{
if (pointer){
aStack.push(pointer);
pointer=pointer->leftchild();
}
else{
pointer=aStack.top();
aStack.pop();
Visit(pointer->value());
pointer=pointer->rightchild();
}
}
}
enum Tags{Left,Right}; //定义枚举类型标志位
class StackElement{
public:
BinaryTreeNode * pointer;
Tags tag;
};
void BinaryTree::PostOrderWithoutRecursion(BinaryTreeNode * root){
using std::stack;
StackElement element;
stack<StackElement> aStack;
BinaryTreeNode * pointer;
if (root==NULL)
return;
else
pointer=root;
while (!aStack.empty() || pointer){
while (pointer!=NULL){
element.pointer=pointer;
element.tag=Left; //标志位为Left表示进入左子树
aStack.push(element);
pointer=pointer->leftchild();
}
element=aStack.top();
aStack.pop();
pointer=element.pointer;
if(element.tag==Left){ //如果从左子树返回
element.tag=Right; //标志位为Right表示进入右子树
aStack.push(element);
pointer=pointer->rightchild();
}
else{ //如果从右子树返回
Visit(pointer->value());
pointer=NULL;
}
}
}
void BinaryTree::LevelOrder(BinaryTreeNode * root){
using std::queue;
queue<BinaryTreeNode *> aQueue;
BinaryTreeNode * pointer=root;
if(pointer)
aQueue.push(pointer); //根节点入队列
while (!aQueue.empty()){ //队列非空
pointer=aQueue.front(); //获得列首节点
aQueue.pop(); //列首节点出队列
Visit(pointer->value());
if(pointer->leftchild()!=NULL)
aQueue.push(pointer->leftchild());
if(pointer->rightchild()!=NULL)
aQueue.push(pointer->rightchild());
}
}