zoukankan      html  css  js  c++  java
  • 数据结构之二叉树

    树的结构示意图如下所示:

            上图就是一种数据结构----树,之所以在每个框中都留出空白,主要原因是这种结构如果根据上下文是能够传达一些重要的结构信息,比如我们可以作如下思考:

            1、上图可以表示某公司的职能组织结构;

            2、可以表示某公司从上层到底层的各种职位分布图;

            3、可以表示某家族的族谱血缘关系;

            4、可以表示计算机中的目录结构;

            5、可以表示某个家族的家谱。

            后面可以发挥自己的想象,只要能符合以上结构的都可以称之为树型结构。通过上述思考就可以发现树型结构的用途之广泛,它表示的是数据之间的一种层次关系,层与层之间存在着某种关系,我认为这就是树型结构的重要特点,这与其它结构有着很大的区别。

            对树而言,先了解以下基本概念:

                                            1

                                         /      

                                      2         3

                                    /          /    

                                  4     5   6     

            1、每棵树都有一个“根”,这是树的“根基”,称为root,通过root我们可以很容易的找到树上的各个支点,上图中“1”为树的root;

            2、一棵树上的每个节点,它们有可能有分支,有可能没有分支,分支的数目称为分支因子。如上图中,最大的分支结因子为2,"3"结点的分支因子为1

            3、每棵树都有一个高度,数据的层次数就是树的高度,上图中树的高度为3。

            4、通用概念:

                 1与2,3之间的关系为:1是父,2是其左孩子,3是其右孩子。2与3相互之间称为兄弟。 没有孩子的结点称为叶子结点,如456结点。  

    二、什么是二叉树

            对树而言,需要重点掌握二叉树。二叉树是一种特殊的顺序树,它规定有左右两个孩子,即左右孩子顺序不能替换,所以二叉树是一种有序树。二叉树的结点数为大于0小于等于2。对于二叉树,需要掌握以下性质:

            性质1 在二叉树的第i层上至多有个结点(i>=1)

            由数据归纳法即可证明,

            i=1,结点数为1

            i=2,结点数为2

            i=3,结点数为4

            i=4,结点数为8

            I=n, 结点数为.

            性质2 深度为K的二叉树至多有-1个结点(k >=1)

            换言之,如果二叉树的深度确定,则其最大的结点数也是确定的。

            证明(可以利用性质1)

            深度为K的二叉树的结点个数=二叉树中每一层结点个数的总和。即为:

    = 1 + 2 + 4 + 8 + … + =-1(等比公式)

            性质3 二叉树中,终端结点个数与度为2的结点个数有如下关系:

      =  + 1

            (注:度表示分支的个数,也指分支因子,终端结点也指叶子结点)

            分析:二叉树中结点的度可以为0,1,2,也就是说需要证明结点的度为0与度为2的结点之间的关系是不变的。

            证明:设二叉树中度为i的结点数为

                    则整棵二叉树的结点总数为:n =++  ------------(1)

                    除根结点外,每一个结点都是另一个结点的孩子,所以孩子数为n-1 --------(2)

                    度为i(I = 0,1,2)的结点,有i个孩子,

                    孩子数 = x 0 +x 1 +x 2 = 2 +  ---------------(3)

                    因为:(3) = (2),所以,

                            n-1 = 2+   ------(4)

                    (4) – (1) ,得,

                    -1=  - , 即 = +  1证毕.

            性质1、2、3是二叉树的通用特性。

            在介绍其它性质之前,先了解另一种特殊的二叉树,即满二叉树,其定义如下:

            满二叉树是指深度为K,且有-1个结点的二叉树。

            特点:(1) 每层上结点数都达到最大

                        (2) 度为1的结点个数=0,即不存在分支数为1的结点

             如下即为一棵满二叉树:(注意其顺序:结点层序编号方法,从根结点起从上至下逐层从左至右对二叉树的结点进行连续编号)

                              1

                             / 

                          2      3

                         /       / 

                        4  5    6  7

            当K = 3, 结点数-1 = 7

            完全二叉树:深度为k,结点数为n的二叉树,当且仅当每个结点的编号都与相同深度的满二叉树中从1到n的结点一一对应时,称为完全二叉树。

            根据定义可以理解:深度为k的完全二叉树,其结点总数比深度k-1的满二叉树要多,但一定比深度为k的满二叉树要少。即有:完全二叉树示意如下:

                                 1

                                / 

                             2    3

                            /   

                           4   5   (注意编号顺序,与满二叉树一一对应)

            性质4:结点数为n的完全二叉树,其深度为(向下取整)+ 1

            由性质2及完全二叉树的定义有:

            结点数满足:

                                 

            性质5:在按层序编号的n个结点的完全二叉树中,任意一个结点i()有:

            (1)    i = 1时,结点i是树的根,否则(i> 1),结点i的双亲为i/2(向下取整),如

            ,取i = 2.

            (2)    2i > n时,结点i无左孩子,为叶结点,否则结点i的左孩子为结点2i

            (3)    2i+1 > n时,结点i无右孩子,否则结点i的右孩子为结点2i +1.

            性质4与性质五是针对完全二叉树而言的。性质6是针对二叉树的链式存储结构而言。

            性质6: 含有n个结点的二叉链表中,有n + 1个空链域。

            

    文章内容转载来自:

    http://blog.csdn.net/ab198604

     

    、什么是完全二叉树

     

    完全二叉树(Complete Binary Tree)

     

    若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。

     

    完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。

     

    一棵二叉树至多只有最下面的两层上的结点的度数可以小于2,并且最下层上的结点都集中在该层最左边的若干位置上,则此二叉树成为完全二叉树。
    对于完全二叉树的顺序查找:
    #include <iostream>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    using namespace std;
    #define LIST_INT_SIZE 2500
    #define NIL 0
    typedef struct List
    {
        int *elem;
    } SqList;
    void createtree(SqList &L,int n)
    {
        L.elem=(int *)malloc(LIST_INT_SIZE*sizeof(int));
        int i;
        for(i=0; i<=LIST_INT_SIZE; i++)
        {
            L.elem[i]=NIL;
        }
        for(i=1; i<=n; i++)
        {
            L.elem[i]=i;
        }
    }
    void visit(SqList &L,int x)
    {
       cout<<L.elem[x]<<" ";
    }
    bool emptytree(SqList &L)
    {
        if(L.elem[1]==NIL)
            return true;
        else return false;
    }
    void Destory(SqList &L)
    {
        free(L.elem);
    }
    void pretraverse(SqList &L,int e)
    {
        visit(L,e);
        if(L.elem[2*e]!=NIL)
            pretraverse(L,2*e);
        if(L.elem[2*e+1]!=NIL)
            pretraverse(L,2*e+1);
    }
    void preordertraverse(SqList &L)
    {
        if(!emptytree(L))
            pretraverse(L,1);
    }
    void intraverse(SqList &L,int e)
    {
        if(L.elem[2*e]!=NIL)
            intraverse(L,2*e);
        visit(L,e);
        if(L.elem[2*e+1]!=NIL)
            intraverse(L,2*e+1);
    }
    void inordertraverse(SqList &L)
    {
        if(!emptytree(L))
            intraverse(L,1);
    }
    void posttraverse(SqList &L,int e)
    {
         if(L.elem[2*e]!=NIL)
            posttraverse(L,2*e);
         if(L.elem[2*e+1]!=NIL)
            posttraverse(L,2*e+1);
            visit(L,e);
    }
    void postordertraverse(SqList &L)
    {
        if(!emptytree(L))
            posttraverse(L,1);
    }
    int main()
    {
        int n,i;
        while(cin>>n)
        {
            SqList L;
            createtree(L,n);
            preordertraverse(L);
            cout<<endl;
            inordertraverse(L);
            cout<<endl;
            postordertraverse(L);
            cout<<endl;
            Destory(L);
        }
        return 0;
    }

    对于二叉树的建立以及查找:

    #include <iostream>
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    using namespace std;
    typedef struct BiTNode
    {
        char data;
        struct BiTNode *right,*lift;
    } *BiTree;
    typedef BiTree ElemType;
    typedef struct QNode
    {
        ElemType  data;
        struct QNode *next;
    }QNode,*QueuePtr;
    typedef struct
    {
        QueuePtr front;
        QueuePtr rear;
    }LinkQueue;
    void InitQueue(LinkQueue *Q)//清空
    {
        Q->front=Q->rear=(QueuePtr)malloc(sizeof(QNode));
        if (!(Q->front)) exit(0);
        Q->front->next=NULL;
    }
    int QueueEmpty(LinkQueue Q)//判空
    {
        if (Q.front==Q.rear)     return 1;
        else      return 0;
    }
    void DeQueue(LinkQueue *Q, ElemType *e)//出队
    {
        QueuePtr p;
        if (Q->front!=Q->rear)
        {
            p=Q->front->next;
            *e=p->data;
            Q->front->next=p->next;
            if (Q->rear==p) Q->rear=Q->front;
            free(p);
        }
    }
    void EnQueue(LinkQueue *Q, ElemType e)//入队
    {
        QueuePtr p;
        p=(QueuePtr)malloc(sizeof(QNode));
        if (!p) exit(0);
        p->data=e;
        p->next=NULL;
        Q->rear->next=p;
        Q->rear=p;
    }
    ElemType GetHead(LinkQueue Q)
    {
        if (Q.front!=Q.rear)     return Q.front->next->data;
    }
    void createBiTree(BiTree &head)
    {
        char data;
        cin.get(data);
        if(data==' ')
        {
            head=NULL;
        }
        else
        {
            head=(BiTNode*)malloc(sizeof(BiTNode));
            head->data=data;
            createBiTree(head->lift);
            createBiTree(head->right);
        }
    }
    void visit(BiTree &p)
    {
        if(p->data!=' ') cout<<p->data<<" ";
    }
    void preorder(BiTree &p)
    {
        if(p!=NULL)
        {
            visit(p);
            preorder(p->lift);
            preorder(p->right);
        }
    }
    void inorder(BiTree &p)
    {
        if(p!=NULL)
        {
            inorder(p->lift);
            visit(p);
            inorder(p->right);
        }
    }
    void postorder(BiTree &p)
    {
        if(p!=NULL)
        {
            postorder(p->lift);
            postorder(p->right);
            visit(p);
        }
    }
    //删除二叉树
    void DestoryBiTree(BiTree &p)
    {
        if(p)
        {
            if(p->lift)
                DestoryBiTree(p->lift);
            if(p->right)
                DestoryBiTree(p->right);
            free(p);
            p=NULL;
        }
    }
    //二叉树的深度
    int BiTreeDepth(BiTree &p)
    {
        int i,j;
        if(!p) return 0;
        if(p->lift)
            i=BiTreeDepth(p->lift);
        else
            i=0;
        if(p->right)
            j=BiTreeDepth(p->right);
        else
            j=0;
        return i>j?i+1:j+1;
    }
    BiTree parent(BiTree &t,char e)//寻找双亲节点
    {
        LinkQueue q;
        BiTree a;
        char pare;
        if(t)
        {
            InitQueue(&q);
            EnQueue(&q,t);
            while(!QueueEmpty(q))
            {
                DeQueue(&q,&a);
                if(a->lift&&a->lift->data==e||a->right&&a->right->data==e)
                  {
                       return a;
                  }
                else
                {
                   if(a->lift)
                    EnQueue(&q,a->lift);
                    if(a->right)
                        EnQueue(&q,a->right);
                }
            }
        }
       return NULL;
    }
    ///返回二叉树中指向元素值为e的结点的指针
    BiTree point(BiTree &t,char e)
    {
        LinkQueue q;
        BiTree a;
        if(t)
        {
            InitQueue(&q);
            EnQueue(&q,t);
            while(!QueueEmpty(q))
            {
                DeQueue(&q,&a);
                if(a->data==e)
                    return a;
                if(a->lift)
                    EnQueue(&q,a->lift);
                if(a->right)
                    EnQueue(&q,a->right);
            }
        }
        return NULL;
    }
    ///返回左孩子
    char leftchild(BiTree &t,char e)
    {
        BiTree a;
        if(t)
        {
            a=point(t,e);
            if(a&&a->lift)
                return a->lift->data;
        }
    }
    ///返回右孩子
    char rightchild(BiTree &t,char e)
    {
        BiTree a;
        if(t)
        {
            a=point(t,e);
            if(a&&a->right)
                return a->right->data;
        }
    }
    ///返回左兄弟,返回右孩子同理
    char leftsibling(BiTree &t,char e)
    {
        BiTree a;
        BiTree p;
        if(t)
        {
            a=parent(t,e);
            if(a!=NULL)
            {
                p=point(t,a->data);
                if(p->lift&&p->right&&p->right->data==e)
                    return p->lift->data;
            }
        }
    }
    ///lr为0或1,删除t中p所指的结点的左子树或右子树
    int Insertchild(BiTree p,int lr,BiTree c)
    {
        if(p)
        {
            if(lr==0)
            {
                c->right=p->lift;
                p->lift=c;
            }
            else
            {
                c->right=p->right;
                p->right=c;
            }
            return 1;
        }
        return 0;
    }
    int deletechild(BiTree &p,int lr)
    {
        if(p)
        {
            if(lr==0)
               DestoryBiTree(p->lift);
               else
                    DestoryBiTree(p->right);
               return 1;
        }
        return 0;
    }
    int main()
    {
        BiTree p,c;
        BiTree q;
        char child;
        createBiTree(p);
        cout<<BiTreeDepth(p)<<endl;
        cin>>child;
        q=parent(p,child);
        cout<<q->data<<endl;
        cout<<leftchild(p,child)<<endl;
        cout<<rightchild(p,child)<<endl;
        cout<<leftsibling(p,child)<<endl;
        preorder(p);
        cout<<endl;
        inorder(p);
        cout<<endl;
        postorder(p);
        cout<<endl;
    }

     

     

     

  • 相关阅读:
    给定中序和后序遍历,求前序序列(C++递归方式实现)
    myeclipse2014删除antlr-2.7.2.jar--解决struts和hibernate包冲突
    hadoop1.2.1配置与运行子串统计程序
    任务计划crontab
    建NTP
    vnc下运行runInstall报java错误
    rpm软件安装
    redis
    rpm包和deb包转换
    新老版本centos下载
  • 原文地址:https://www.cnblogs.com/famousli/p/4231498.html
Copyright © 2011-2022 走看看