三:二叉树的初始化操作及应用

内容

    • 二叉树简介
    • 顺序存储结构
    • 链式存储结构
    • 初始化空二叉树 InitBiTree(&T)
    • 销毁二叉树 DestroyBiTree(&T)
    • 创建二叉树 CreateBiTree(&T, definition)
    • 清空二叉树 ClearBiTree(&T)
    • 判断空二叉树 BiTreeEmpty(T)
    • 求二叉树深度 BiTreeDepth(T)
    • 求双亲 parent(T, e)
    • 求左孩子 LeftChild(T, e)
    • 求右孩子 RightChild(T, e)
    • 求左兄弟 LeftSibling(T, e)
    • 求右兄弟 RightSibling(T, e)
    • 插入子树 InsertChild(T, p, LR, c)
    • 删除子树 DeleteChild(T, p, LR)
    • 先序遍历二叉树 PreOrderTraverse(T,visite())
    • 中序遍历二叉树 InOrderTraverse(T,visite())
    • 后序遍历二叉树 PostOrderTraverse(T,visite())
    • 按层次遍历 levelTraverse(T, visite())
    • 表达式求值
    • 计算二叉树中的结点数 Number(…)
    • 二叉树中叶子结点的数目 Leafs(…)
    • 深度为h的二叉树以一维数组BT(1:2h-1)
    • 计算二叉树的深度 Depth(…)

二叉树简介

二叉树:: 0个孩子,1个孩子,2个孩子;

左子树+右子树

顺序存储结构

二叉树顺序存储::一维数组,从上到下,从左到右 进行 放置;((适合完全二叉树))

链式存储结构

二叉树链式存储::每一个都是结构体:包括[ lchild , data , rchild ];指针形式。

typedef struct BiTNode {
    int data;//char data;
    struct BiTNode *lchild,*rchild;
}BiTNode, *BiTree;

在这里插入图片描述

初始化空二叉树 InitBiTree(&T)

void Init_BiTree(BiTree &T){
  T=NULL;
}

销毁二叉树 DestroyBiTree(&T)

在这里插入代码片

创建二叉树 CreateBiTree(&T, definition)

输入创建 先序创建。。
按照先序进行创建二叉树:-+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;
}

清空二叉树 ClearBiTree(&T)

在这里插入代码片

判断空二叉树 BiTreeEmpty(T)

在这里插入代码片

求二叉树深度 BiTreeDepth(T)

在这里插入代码片

求双亲 parent(T, e)

在这里插入代码片

求左孩子 LeftChild(T, e)

在这里插入代码片

求右孩子 RightChild(T, e)

在这里插入代码片

求左兄弟 LeftSibling(T, e)

在这里插入代码片

求右兄弟 RightSibling(T, e)

在这里插入代码片

插入子树 InsertChild(T, p, LR, c)

在这里插入代码片

删除子树 DeleteChild(T, p, LR)

在这里插入代码片

先序遍历二叉树 PreOrderTraverse(T,visite())

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;

	}
}

中序遍历二叉树 InOrderTraverse(T,visite())

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;
    }

}

后序遍历二叉树 PostOrderTraverse(T,visite())

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 ;
            }
        }
    }
}

按层次遍历 levelTraverse(T, visite())

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的右孩子入队
      }
}

表达式求值

在这里插入代码片

计算二叉树中的结点数 Number(…)

二叉树结点数=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);
}

二叉树中叶子结点的数目 Leafs(…)

叶子数=左子树叶子数+右子树叶子数

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);
	}
 }
 

深度为h的二叉树以一维数组BT(1:2h-1)

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;
}

计算二叉树的深度 Depth(…)

深度 = 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;
 }

你可能感兴趣的:(#,大二上数据结构,算法,数据结构,c++)