树与二叉树

一、树

树的定义是递归的,即在树的定义中又用到了其自身,树是一种递归的数据结构。树作为一种逻辑结构,同时也是一种分层结构,结点间关系是前驱唯一而后继不唯一,即结点之间是一对多的关系。

树中结点的最大度数就是树的度;树中一个结点的孩子个数称为该结点的度

n个结点的树中有n-1条边  ;结点数=总度数+1

度为m的树中第i层上至多有mi-1结点(i>.=1)

高度为h的m叉树至多有(mh-1)/(m-1)个结点

二、二叉树

(1)每个结点的度不大于2(2)每个结点的孩子结点次序不能任意颠倒

一个二叉树中的每个结点只能含有0个,1个,2个孩子,并且每个孩子有左右孩子之分.

二叉树的五种形态:(1)空二叉树(2)只有根结点的二叉树(3)只有左子树的二叉树(4)只有右子树的二叉树(5)左右子树非空的二叉树

二叉树是有序的树,若将其左右子树颠倒,则成为另一棵不同的二叉树,它的左右子树是确定的,而树若某个结点只有一个孩子,则这个孩子无须分次序。

满二叉树:除了叶子结点外每个结点的度都为2  编号为i的结点:双亲i/2向下取整,左孩子:2i  右孩子:2i+1

完全二叉树:当且仅当每个结点都与高度为h的满二叉树中编号1-n的结点一一对应时,称为完全二叉树

对于完全二叉树:i<=n/2向下取整,则结点i为分支结点,否则为叶子结点

二叉排序树:右>根>左

平衡二叉树:树中任一结点的左子树和右子树的深度之差不超过1

二叉树的性质:

n0=n2+1;n=n0+n1+n2=n2+1+n1+n2=2n2+n1+1

二叉树的存储结构

1.顺序存储结构

依二叉树的性质,完全二叉树和满二叉树采用顺序存储比较合适,既不浪费空间,又可以根据公式计算出每一个结点的左、右孩子的位置。,但是,对于一般的二叉树,必须用‘虚结点’将其补成一棵“完全二叉树”来存储,这就会造成空间浪费。

#include "stdio.h"
#include "stdlib.h"
#define MaxSize 100
typedef char Elemtype;
typedef struct TreeNode {
    Elemtype value;
    bool isEmpty;
};
TreeNode t[MaxSize];
void InitTree(TreeNode t[MaxSize]) {
    for (int i = 0; i < MaxSize; i++) {
        t[i].isEmpty = true;
    }
}
void CreateTree(TreeNode t[MaxSize]) {
    for (int i = 1; t[i].value!='\0'; i++) {
        scanf_s("%c\n", &t[i].value);
        t[i].isEmpty = false;
    }
}
//寻找最近公共结点 Elemtype Search(TreeNode t[MaxSize],
int i, int j) { if (!(t[i].isEmpty && t[j].isEmpty)){ while (i != j) { if (i > j) i = i / 2; else j = j / 2; } return t[i].value; } } void main() { TreeNode t[MaxSize]; InitTree(t); CreateTree(t); Search(t,4,9); system("pause"); }

2.链式存储结构

二叉树一般采用链式存储结构;二叉链表至少包含三个域:数据域、左指针域、右指针域

若二叉树有n个结点,,则它的二叉链表中有2n个链域,其中有n-1个非空链域,其余都是空链域,空链域有n+1个,利用这些链域可组成另一种链表结构---线索链表。

 (1)找i 、j 两结点最近的公共祖先结点;

分析二叉树中任意两个结点必然存在最近的公共祖先结点,最坏的情况下是根结点,而且从最近的公共祖先结点到根结点的全部祖先结点都是公共的:

若 i> j,i的双亲结点i/2,若i/2=j,则结点i/2是原结点i和结点j的最近公共祖先结点,否则 i=i/2;

若j > i,  结点j的双亲结点为结点j/2,若 j/2=i,则结点j/2是原结点i和结点j的最近公共祖先结点, 否则 j=j/2

重复上述过程,直到找到为止;

//找两结点最近的公共祖先结点
ElemType CommonAncestor(SeqTree T, int i, int j) {
    if (T[i] != '#' && T[j] != '#') {
        while (i != j)
        {
            if (i > j)
                i = i / 2;
            else
                j = j / 2;
        }
        return T[i];
    }
}
BiTNode* CommonAncestor2(BiTree *T, BiTNode *p,BiTNode *q) {

    if (T == NULL)
        return NULL;
    if (p == T || q == T)
        return T;
    BiTNode left = CommonAncestor2(T->lchild, p, q);
    BiTNode right = CommonAncestor2(T->rchild, p, q);
    if (left != null && right != null) {
        return T;
    }
    return left != null ? left : right;
}

 

posted @ 2021-10-05 22:15  #Lorraine#  阅读(270)  评论(0)    收藏  举报