二叉树:: 0个孩子,1个孩子,2个孩子;
左子树+右子树
二叉树顺序存储::一维数组,从上到下,从左到右 进行 放置;((适合完全二叉树))
二叉树链式存储::每一个都是结构体:包括[ lchild , data , rchild ];指针形式。
typedef struct BiTNode {
int data;//char data;
struct BiTNode *lchild,*rchild;
}BiTNode, *BiTree;
void Init_BiTree(BiTree &T){
T=NULL;
}
在这里插入代码片
输入创建 先序创建。。
按照先序进行创建二叉树:-+a##*b##-c##d##/e##f##
输入创建 先序创建。。输入的时候为什么要用#号来代表空指针??答案:保证创建的树是唯一的;
//树的按照先序次序进行创建
int Creat_BiTree(BiTree &T){
char ch;
cin>>ch;
if(ch=='#'){
T=NULL;
}else{
T=(BiTNode*)malloc(sizeof(BiTNode)); //T = new BiTNode;
if(!T) exit(-2);// 内存分配失败;
T->data=ch;
Creat_BiTree(T->lchild);
Creat_BiTree(T->rchild);
}
return OK;
}
在这里插入代码片
在这里插入代码片
在这里插入代码片
在这里插入代码片
在这里插入代码片
在这里插入代码片
在这里插入代码片
在这里插入代码片
在这里插入代码片
在这里插入代码片
void PreOrderTraverse (BiTree T){
if (!T) return;
visit(T->data);//访根//操作根
PreOrderTraverse (T->lchild);
PreOrderTraverse (T->rchild);
}
void PreOrderTraverse (BiTree bt){
if (!bt) return;
InitStack(S);
push(S, bt); //树根的指针进栈
while (!EmptyStack(S)){
pop(S, p);
while(p){ //沿着左链一路向下
visit(p->data); //访问
if(p->rchild) push(S,p->rchild); //右孩子进栈
p=p->lchild;
}
}
}
//非递归先序
void PreOrderTraverse (BiTree T){
if(T==NULL)
return;
SqStack s;
Init_Stack_Int(s);
while ( T || !StackEmpey(s)){
while(T){
cout<<T->data;
Push(s,T);
T=T->lchild;
}
BiTree p;
Init_BiTree(p);
Pop(s,p);
T=p->rchild;
}
}
void InOrderTraverse (BiTree T){
if (!T) return;
InOrderTraverse (T->lchild);
visit(T->data);//访根
InOrderTraverse (T->rchild);
}
void InOrderTraverse ( BiTree bt, void(*visit)(BiTree)){
//中序遍历的非递归算法
InitStack(S);
Push(S,T);
While (!StackEmpty(S)){ //栈非空时
While (GetTop(S,p)&&P) //对于每颗子树都需要将这颗子树的左左左走到头
Push(S,p->lchild); //一直向左走到头,并将所经历的结点入栈
Pop(s,p); //将空指针退出栈S
If (!StackEmpty(S)){ //栈非空时
Pop(s,p); //弹出结点p
If(!visit(p->data)) return ERROR;
Push(S,p->rchild); //将结点p的右子树入栈
} //if
} //while
}//InOrderTraverse
//非递归的中序遍历
void InOrderBiTreeF(BiTree T){
SqStack s;
Init_Stack_Int(s);
if(T==NULL){
return;
}
while(T||!StackEmpey(s)){
while(T){
Push(s,T);
T=T->lchild;
}
Pop(s,T);
cout<<T->data;
T=T->rchild;
}
}
void PostOrderTraverse (BiTree T){
if (!T) return;
PostOrderTraverse (T->lchild);
PostOrderTraverse (T->rchild);
visit(T->data);//访根
}
非递归:基本思想就行:判断每个节点的左右子节点是否为NULL,或者其左右子节点是否已经被访问过,如果是,那么访问该节点
typedef struct BiTNode{
char data;
int lvisited,rvisited;//左、右孩子是否访问过,1表示已访问(此项只在后序非递归2算法中需要)
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//后序非递归遍历1思路:因为后序非递归遍历二叉树的顺序是先访问左子树,再访问后子树,最后
//访问根结点。当用堆栈来存储结点,必须分清返回根结点时,是从左子树返回的,还是从右子树
//返回的。所以,使用辅助指针r,其指向最近访问过的结点。
void SqlPostOrder1(BiTree T)//后序非递归遍历1
{
stack<BiTree> s;
BiTree p=T,r;
while(p || !s.empty())
{
if(p) //走到最左边
{
s.push(p);
p=p->lchild;
}
else //向右
{
p=s.top();//取栈顶结点
if(p->rchild && p->rchild!=r)//如果右子树存在,且未被访问过
{
p=p->rchild;
s.push(p);
p=p->lchild; //再走到最左
}
else //否则,访问栈顶结点并弹出
{
cout<<p->data<<" ";
r=p; //记录该结点
s.pop();
p=NULL; //结点访问完后,重置p指针
}
}
}
}
//思路2:在结点中增加标志域,记录是否已被访问。
void SqlPostOrder2(BiTree T)//后序非递归遍历2
{
stack<BiTree> s;
BiTree p=T;
while(p || !s.empty())
{
if(p && p->lvisited==0) //左走,且左子树未被访问
{
p->lvisited=1;
s.push(p);
p=p->lchild;
}
else
{
p=s.top();
if(p->rchild!=NULL && p->rvisited==0)//右子树未被访问,右走一步
{
p->rvisited=1;
p=p->rchild;
}
else //访问栈顶元素并弹栈
{
cout<<p->data<<" ";
s.pop();
if(!s.empty())
p=s.top();
else //当最后一个元素弹栈出去后,结束
return ;
}
}
}
}
void LevelTraverse(BiTree bt) {
//按层次遍历二叉树算法
if( !bt ) return ; //空树
InitQueue(Q); //初始化空队列Q
EnQueue(Q, bt); //根入队
while( !EmptyQueue(Q) ) {
DeQueue(Q, p); //队头p出队
visit(p->data); //访问p
if(p->lchild) EnQueue(Q,p->lchild); //p的左孩子入队
if(p->rchild) EnQueue(Q,p->rchild); //p的右孩子入队
}
}
在这里插入代码片
二叉树结点数=1+左子树结点数+右子树结点数
int Number(BiTree bt){
if(!bt) return 0; //空二叉树
else { nl=Number(bt->lchild);
nr=Number(bt->rchild);
return 1+nl+nr;
}
}
void Number(BiTree bt, int &n) {
if(!bt) return;
n++; //累加结点数
Number(bt->lchild, n);
Number(bt->rchild, n);
}
叶子数=左子树叶子数+右子树叶子数
int Leafs(BiTree bt) {
if(!bt) return 0; //空二叉树
if(!bt->lchild && !bt->rchild)
return 1;
LL=Leafs(bt->lchild);
LR=Leafs(bt->rchild);
return LL+LR;
}
void Leafs(BiTree bt,int &n){
if(!bt) return ;
if(!(bt->lchild) && !(bt->rchild)){
n++;
}else{
Leafs(bt->lchild, n);
Leafs(bt->rchild, n);
}
}
int Leafs(BiTree bt,int h) {
//层序遍历二叉树,统计叶子结点的个数
len=2^h-1;
count=0;
for(i=1;i<=len;i++)
if(bt[i]!=0)
if(2*i>len) count++; //i结点没有孩子,i结点就是叶子结点
else if(bt[2*i+1]==0&&bt[2*i]==0) count++;
//i结点的左右孩子均为空,i结点就是叶子结点
return count;
}
深度 = max(左子树深度,右子树深度) + 1
int Depth(BiTree bt) {
int depthdata, depthLeft, depthRight;
if(!bt) depthval=0;
else{
depthLeft=Depth(bt->lchild);
depthRight = Depth(bt->rchild);
depthval=1+(depthLeft > depthRight? depthLeft:depthRight);
}
return depthval;
}