数据结构 二叉树

1、二叉树顺序存储(数组)

 按满二叉树的结点层次编号,依次存放二叉树中的数据元素。

必须按照满二叉树顺序编号,空的位置存为0

// 二叉树顺序存储表示
#define MAXTSIZE 100  //最大节点数
typedef TElemType SqBiTree[MAXSTIZE]; // TElemType 可为Int、char
SqBiTree bt;

缺点:存储密度小、存储空间大小确定,适合满二叉树、完全二叉树、堆

2、二叉树链式存储

(1)二叉链表

空的孩子指针存为^。

typedef struct BiNode
{
    TElemType data;
    struct BiNode *lchild, *rchild;
    //左右孩子指针
} BiNode, *BiTree;

 (2)三叉链表

 在二叉链表基础上增加一个指向双亲结点的指针域。

typedef struct TriTNode
{
    TelemType data;
    struct TriTNode *lchild, *parent, *rchild;
} TriTNode, *TriTree;

3、遍历二叉树

(1)先序遍历(DLR)

若二叉树为空,则空操作;否则
(1)访问根结点;
(2)先序遍历左子树

(3)先序遍历右子树

*遍历至子树为空
 

Status PreQrderTraverse(BiTree T){
    if (T == NULL)
        return OK;           // 空树
        else
        {
    visit(T);                // 访问根结点
    PreOrderTraverse(T->lchild);//递归遍历左子树
    PreOrderTraverse(T->rchild);//递归遍历右子树
    }
}

 (2)中序遍历(LDR)

若二叉树为空,则空操作;否则
(1)中序遍历左子树;
(2)访问根结点;

(3)中序遍历右子树。

Status InOrderTraverse(BiTree T)
{
    if (T == NULL)
    return OK;                  // 空二叉树else{
    lnOrderTraverse(T->lchild); // 递归遍历左子树
    visit(T);//访问根结点;
    InOrderTraverse(T->rchild); // 递归遍历右子树}
    }

非递归算法:

1.栈

二叉树中序遍历的非递归算法的关键:在中序遍历过某结点的整个左子树后,如何找到该结点的根以及右子树。
基本思想:
(1)建立一个栈
(2根结点进栈,遍历左子树
(3)根结点出栈,输出根结点,遍历右子树。
 

Status InOrderTraverse(BiTree T)
{    BiTree p;
    lnitStack(S);
    p = T;
    while (p || !StackEmpty(S))
    {
    if (p)
    {
        Push(S, p);
        p = p->lchild;
    }
    else
    {
        Pop(S,q);
        cout << q->data;
        p =q->rchild;
    }
    } // while
    return OK;
}

时间、空间复杂度:O(n)

2.层次遍历

按层数遍历:先遍历1层、后2层……利用队列实现

(1)根节点入队

(2)队不空时循环:从队列中出列一个节点*p并访问(出队并输出)

有左孩子时入队、有右孩子时入队

void LevelOrder(BTNode *b)
 {
 	BTNode *p; 
	SqQueue *qu;
    InitQueue(qu);
	enQueue(qu,b);//根节点指针入队
	while (!QueueEmpty(qu)) { 
	deQueue(qu, p); //出队p
	printf("%c ",p->data);
	if (p-> Ichild!=NUL) enQueue(qu, p-> Ichild);//有左孩子时入队
	if (p-> rchild!=NULL) enQueue(qu, p-> rchild);//有右孩子时入队
}
}

 (3)后序遍历(LRD)

若二叉树为空,则空操作;否则
(1)后序遍历左子树;
(2)后序遍历右子树;

(3)访问根结点。

Status PostOrderTraverse(BiTree T)
    {
    if (T == NULL)
    return OK;                    // 空二叉树else{
    PostOrderTraverse(T->Ichild); // 递归遍历左子树
    PostOrderTraverse(T->rchild);//递归遍历右子树
    visit(T);//访问根结点
    }

如果去掉输出语句,从递归的角度看,三种算法是完全相同的,或说这三种算法的访问路径是相同的,只是访问结点的时机不同。

时间效率:O(n)//每个结点只访问一次·

空间效率:O(n)//栈占用的最大辅助空间


若二叉树中各结点的值均不相同,则二叉树结点的先序序列、中序序列、后序列都是唯一的。
由二叉树的先序序列和中序序列,或由二叉树的后序序列和中序序列可以确定唯一一棵二叉树(只知道先后不行)

先序序列和中序序列:

先序确定根(首位),中序确定左右

//根据先序序列pre[pre_low..pre_low+len-1]和中序序列in[in_low..in_low+len-1]建树t
void BuildTree(BiTree& t, char pre[], int pre_low, char in[], int in_low, int len)
{
    t= new BiTNode;
    t->data=pre[pre_low];
    t->lchild=NULL;
    t->rchild=NULL;
    int i;
    for(i=in_low;i<len;i++)
    {
        if(in[i]==pre[pre_low])
            break;

    }
    int l = i-in_low;
    if(i>in_low) BuildTree(t->lchild,pre,pre_low+1,in,in_low,i);
    if(i+1<len)BuildTree(t->rchild,pre,pre_low+l+1,in,i+1,len);
}

后序序列和中序序列:

后序确定根(尾部)中序确定左右

 


4、二叉链表创建

void CreateBiTree(BiTree &T)
{
   //按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
   TElemType ch;

   //要处理多组数据,输入ch如果遇到EOF,应该结束程序 所以main函数用while(1)
   //if(!(cin >> ch)) exit(0);

        if(ch=='#') T=NULL ;//空树
else{
        T = new BiTNode;//生成根节点
        T->data=ch;
        CreateBiTree(T->lchild);//递归创造左子树
        CreateBiTree(T->rchild);//递归创造右子树
}
}   //CreateBiTree

5、销毁二叉树

void DestroyBitree(BiTree &T)
{
     if(T->data=='#')
        free(T);
       DestroyBitree(T->lchild);
       DestroyBitree(T->rchild);
       free(T);
       T=NULL;//不可丢
}

6、复制二叉树

如果是空树,递归结束;
否则,申请新结点空间,复制根结点
➢递归复制左子树
➢递归复制右子树

int Copy(BiTree T, BiTree &NewT){
	if(T==NULL){ //空树递归结束
	NewT= NULL;
	 return 0;}
	else {
		NewT=new BiTNode;
		NewT-> data=T-> data;
		Copy(T->IChild,NewT-> Ichild);
		Copy(T->rChild,NewT-> rchild);
}
}

7、计算深度

如果是空树,则深度为0;
否则,递归计算左子树的深度记为m,递归计算右子树的深度记为n,二叉树的深度则为m与n的较大者加1。

int Depth( BiTree T){
if(T==NULL)return 0; //空树度为0
else {
m= Depth(T-> lChild);
n = Depth(T-> rChild);
if(m>n) return (m+1); 
else return(n+1);
}

8、统计节点个数

如果是空树,则结点个数为0;
否则,结点个数为左子树的结点个数+右子树的结点个数再+1。

int NodeCount(BiTree T){
if(T == NULL)return 0;
else 
return NodeCount(T-> lchild)+NodeCount(T-> rchild)+1;
}

叶子节点:

如果是空树,则叶子结点个数为0;
否则,为左子树的叶子结点个数+右子树的叶子结点个数。
 

int LeadCount(BiTree T)
{
if(T= =NULL) 
return 0;
if (T->lchild == NULL && T->rchild == NULL)return 1; 
else return LeafCount(T-> lchild) +LeafCount(T-> rchild); 
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值