二叉树是每个结点最多有两个子树的有序树。通常子树的根被称作“左子树”(left subtree)和“右子树”(right subtree)。
二叉树常被用作二叉查找树和二叉堆或是二叉排序树。二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。
二叉树的基本性质:
(1)二叉树的第i层至多有2的 i-1次方个结点(i>=1);
(2)深度为k的二叉树至多有2^(k) -1个结点,最少有K个节点;
最多的原因:2^(1-1)+2^(2-1)+2^(3-1)+....+2^(k-1)=(2^k)-1
最少的原因:最少一层一个,K层k个节点,不一定全是斜的
(3)对任何一棵二叉树T,如果其终端结点数(即叶子结点数)为n0,度为2的结点数为n2,则 n0 = n2 + 1。
原因:若B为总分枝数,n是总节点数
@1:n=n0+n1+n2
@2:入枝的数量:B=n-1
@3:出枝的数量:B=n1+2n2
得出:n0=n2+1;
当二叉树是完全二叉树时,可以用顺序存储结构:
否则的话用顺序结构则会浪费空间,例如当深度是k的右斜树,只有K个节点,需要分配(2^k)-1个存储单元,浪费了(2^k)-1-K个空间
一般情况下二叉树用二叉链表(binary linked list)存储:
lchild | data | rchild |
lchild:左指针域
data:数据域,存放节点的数据信息
rchild:右指针域
二叉树的节点用链式存储结构,其形式定义如下:
BiNode.h如下:
template <class T> struct BiNode //结点结构 { T data; BiNode<T> *lchild; BiNode<T> *rchild; };
//StackElem.h
template <class T> struct StackElem//非递归后序遍历时,栈元素结构 { BiNode<T> *ptr; int flag; };
为了避免类的调用者访问BITree类的私有变量root,在勾走函数,析构函数,以及遍历函数中调用了相应的私有函数,
//BiTree.h
#include "BiNode.h" #include"StackElem.h" template <class T> class BiTree //二叉树类的定义 { public: BiTree();//二叉链表建立 ~BiTree(); void Prn();//二叉树的输出 void PreOrder();//前序遍历二叉树 void InOrder();//中序遍历二叉树 void PostOrder();//后序遍历二叉树 void LeverOrder();//层序遍历二叉树 private: BiNode<T> *root;//整个二叉树的根 BiNode<T> *creat();//二叉链表的生成 void release(BiNode<T> *bt);//二叉链表的撤销 void PrnIn(BiNode<T>* bt,int depth);//根为bt的二叉树的输出 void PreOrder(BiNode<T>* bt);//前序遍历根为bt的二叉树 void InOrder(BiNode<T>* bt);//中序遍历根为bt的二叉树 void PostOrder(BiNode<T>* bt);//后序遍历根为bt的二叉树 };
前序遍历的思想:
中序遍历的思想:
后序遍历的思想:左孩子标志位是1,右孩子标志位是2
//BiTree的实现BiTree.cpp:
#include<iostream> #include"BiTree.h" using namespace std; template<class T> BiTree<T>::BiTree() { root=creat(); } template<class T> BiNode<T> *BiTree<T>::creat()//二叉链表的生成 { BiNode<T> *bt; T ch; cin>>ch; if(ch=='#') bt=NULL; else { bt=new BiNode<T>; bt->data=ch; bt->lchild=creat(); bt->rchild=creat(); } return bt; } template <class T> //析构函数 BiTree<T>::~BiTree() { release(root); } template <class T> void BiTree<T>::release(BiNode<T> *bt)//二叉链表的撤销 { if(bt!=NULL) { release(bt->lchild); release(bt->rchild); delete bt; } else return; } template <class T> void BiTree<T>:: Prn()//二叉树的输出 { PrnIn(root,1); } template <class T> void BiTree<T>::PrnIn(BiNode<T> *bt,int depth)//根为bt的二叉树的输出 { if(bt!=NULL) { PrnIn(bt->rchild,depth+1); for(int i=0;i<4*(depth-1);i++) cout<<" "; cout<<"--"<<bt->data<<endl; PrnIn(bt->lchild,depth+1); } else return ; } //前序遍历算法实现 template <class T> void BiTree<T>::PreOrder() { PreOrder(root); } //**************前序遍历 //template <class T> //前序遍历递归算法 //void BiTree<T>::PreOrder(BiNode<T> *bt) //{ // if(bt!=NULL) // { // cout<<bt->data; // PreOrder(bt->lchild); // PreOrder(bt->rchild); // } // else return; //} template <class T> //前序遍历非递归算法 void BiTree<T>::PreOrder(BiNode<T> *bt) { BiNode<T> * s[100]; //栈 int top=-1; while(top!=-1 || bt!=NULL) { while(bt!=NULL) { cout<<bt->data; s[++top]=bt; bt=bt->lchild; } if(top!=-1) { bt=s[top--]; bt=bt->rchild; } } } //**************中序遍历 template <class T> void BiTree<T>::InOrder() { InOrder(root); } template <class T> //中序遍历递归算法 void BiTree<T>::InOrder(BiNode<T>* bt) { if(bt!=NULL) { InOrder(bt->lchild); cout<<bt->data; InOrder(bt->rchild); } else return ; } //template <class T> //中序遍历非递归算法 //void BiTree<T>::InOrder(BiNode<T> *bt) //{ // BiNode<T> * s[100];//定义一个栈 // int top=-1; // while(bt!=NULL||top!=-1) // { // while(bt!=NULL) // { // s[++top]=bt; //根指针Bt入栈 // bt=bt->lchild; // } // if(top!=-1) //栈非空 // { // bt=s[top--]; // cout<<root->data; // bt=bt->rchild; // } // } //} //**************后序遍历 template <class T> void BiTree<T>::PostOrder() { PostOrder(root); } //template <class T> //后序遍历递归算法 //void BiTree<T>::PostOrder(BiNode<T>* bt) //{ // if(bt!=NULL) // { // PostOrder(bt->lchild); // PostOrder(bt->rchild); // cout<<bt->data; // } // else return ; //} //后序遍历非递归算法 template <class T> void BiTree<T>::PostOrder(BiNode<T> *bt) { StackElem<T> s[100]; int top=-1; while(bt!=NULL|| top!=-1)//2个条件都不成立才退出循环 { while(bt!=NULL) { ++top; s[top].ptr=bt;//压栈 s[top].flag=1;//设置标志位 bt=bt->lchild;////继续访问左子树 } while(top!=-1 && s[top].flag==2) //栈顶标志位是2,弹栈输出 { cout<<s[top--].ptr->data; } if(top!=-1)//栈顶标志位是1,栈顶标志位设2,bt指向有右孩子 { s[top].flag=2; bt=s[top].ptr->rchild; } } } //以下为层序遍历算法的实现 template <class T> void BiTree<T>::LeverOrder() { BiNode<T> *bt; int front=0; int rear=0; BiNode<T>* s[20]; if(root==NULL) return; rear=(rear+1)%20; s[rear]=root; while(front!=rear) { front=(front+1)%20; bt=s[front]; cout<<bt->data; if(bt->lchild!=NULL) { rear=(rear+1)%20; s[rear]=bt->lchild; } if(bt->rchild!=NULL) { rear=(rear+1)%20; s[rear]=bt->rchild; } } }
测试Main函数
#include"BiTree.cpp" void main() { BiTree<char> tree; //tree.creat(); cout<<"二叉树的输出:"<<endl; tree.Prn(); cout<<endl; cout<<"前序遍历输出:"<<endl; tree.PreOrder(); cout<<endl; cout<<"中序遍历输出:"<<endl; tree.InOrder(); cout<<endl; cout<<"后序遍历输出:"<<endl; tree.PostOrder(); cout<<endl; cout<<"层序遍历输出:"<<endl; tree.LeverOrder(); cout<<endl; }