您的位置:首页 > 理论基础 > 数据结构算法

数据结构基础 之 树与二叉树 各类操作、思想与实现

2015-07-05 20:40 811 查看
【摘要】

本文首先阐述树的基本概念与特点,二叉树的基本概念与特点;然后,给出二叉树的代码实现,包括二叉树的创建、三序遍历+层序遍历、深度求解和平衡二叉树判断的源码,最后将给出常见OJ树题目的实现思想。

【基本概念】

树的定义

指任意两个节点间有且只有一条路径的无向图。只有是没有回路的连通无向图就是树。

树的特征

1.一棵树中的任意两个节点有且仅有唯一的一条路径连通;

2.一棵树如果有n个节点,那么它一定恰好有n-1条边;

3.在一棵树中加一条边将会构成一个回路。

树的深度

从根到这个节点的层数(根为第一层)。

根节点

一棵树有且只有一个根节点。

没有子节点的节点称为叶节点。

二叉树

二叉树特点:每个节点最多有两个儿子,左儿子,右儿子,或者说每个节点最多有两颗子树。

二叉树要么为空,要么由根节点,左子树和右子树组成。

满二叉树

二叉树中每个内部节点(既不是根节点也不是叶节点)都有两个儿子,或者说满二叉树中所有的叶节点都有同样的深度。

深度为 h 的满二叉树,有 2^h-1 个节点。

完全二叉树

除了最右边位置上有一个或者几个叶子节点缺少外,其它是满的。

完全二叉树高度为 h,除第 h 层外,其他各层(1~h-1)的节点数都达到最大个数。

若完全二叉树的某一个节点有右儿子,那它一定也有左儿子。

完全二叉树中,一个父节点编号为k,那么左儿子编号是2*k,右儿子编号是2*k+1.如果已知儿子(不管是左还有右)编号为x,那么它父节点编号就是x/2。

完全二叉树有N个节点,那么这个完全二叉树的高度就是log2N,或者为logN,即最多有logN层节点。

二叉查找树

二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

【二叉树的实现】

二叉树的创建

// 二叉树结构体
typedef struct BiTNode  
{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode;

// 创建二叉树
int CreateBiTree( BiTree *T )  
{
    char ch;
    ch=getchar();
    if( ch == '#' )
        T=NULL;
    else
    {
        if( ! ( T = ( BiTree* )malloc( sizeof( BiTNode ) ) ) )
            exit( 0 );
        T->data = ch;
        CreateBiTree( T->lchild );
        CreateBiTree( T->rchild );
    }
    return 0;
}


二叉树的遍历

// 二叉树输出
void Visit(BiTree *T)    
{  
    if(T->data != '#')
    {  
        printf("%c ",T->data);  
    }  
} 
// 先序遍历  
void PreOrder(BiTree *T)
{  
    if( T!=NULL )
    {   
        Visit(T);   
        PreOrder(T->lchild); 
        PreOrder(T->rchild);  
    }  
}
// 中序遍历    
void InOrder(BiTree *T)
{    
    if( T!=NULL )
    {       
        InOrder(T->lchild);    
        Visit(T);       
        InOrder(T->rchild);    
    }    
} 
// 后序遍历  
void PostOrder(BiTree *T)
{  
    if( T!=NULL )
    {    
        PostOrder(T->lchild);   
        PostOrder(T->rchild);  
        Visit(T);  
    }  
}


【二叉树的层序遍历】

#include <queue>  
#include <assert.h> 
void PrintInLayer(Node* head)  
{  
    assert(p!=NULL);
    Node* p = head;
    queue<Node*> MyQueue;  
    int MyQueue_size;  
    int MyQueue_pos;  
    MyQueue.push(p);  
    while(p!=NULL||!MyQueue.empty())  
    {  
        MyQueue_size=MyQueue.size();  
        MyQueue_pos=0;  
        while(MyQueue_pos<MyQueue_size)  
        {  
            cout<<p->num<<" ";  
            MyQueue.pop();  
            if(p->pLeft!=NULL)  
                MyQueue.push(p->pLeft);  
            if (p->pRight!=NULL)  
                MyQueue.push(p->pRight);  
            if(!MyQueue.empty())  
            {  
                p=MyQueue.front();  
                //MyQueue.pop();  
            }  
            else  
            p=NULL;  
            MyQueue_pos++;  
        }  
        cout<<endl;        
    }  
}


【二叉树相关操作】

求二叉树的叶子数

// 求二叉树叶子数
int sumleaf( BiTree *T )  
{
    if( T!=NULL )
    {
        if( T->lchild || T->rchild )
            return( sumleaf( T->lchild ) + sumleaf( T->rchild ) );
        else
            return 1;
    }
    return 0;
}


求解二叉树的深度

// 返回两个整数中较大的一个
int themax( int a, int b )  
{
    if( a>b )
        return a;
    else 
        return b;
}
// 求二叉树的深度
int Depth( BiTree *T )  
{
    if( T!=NULL )
        return( 1 + themax( Depth( T->lchild ), Depth( T->rchild ) ) );
    return 0;
}


平衡二叉树的判断

// 判断二叉树是否为平衡二叉树
// 平衡二叉树:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
bool bebalance( BiTree *T )
{
    if ( T==NULL )
        return true;

    int ld=Depth(T->lchild);
    int lr=Depth(T->rchild);

    int di=abs(ld-lr);
    if (di>1)                 //根节点平衡
        return false;
    // 不仅仅是高度差小于1,就够了,还有子树也要平衡,这很重要!!!
    return bebalance(T->lchild) && bebalance(T->rchild);  //左右子树平衡
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: