树与二叉树

*个人学习笔记*


树与二叉树

1. 二叉树的性质

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

性质2:深度为k的二叉树上至多含2^k-1个结点(k>=1)。

性质3:对任何一棵二叉树T,设叶子结点数为n0,度为2的结点数为n2,那么,n0=n2+1。

性质4:具有n个结点的完全二叉树的深度为log2n+1。

性质5:对有n个结点的完全二叉树的结点按层序编号,则对任一结点i(1<=i<=1),有:
- 如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲是i/2;
- 如果2i>n,则结点i无左孩子;如果2i<=n,则其左孩子是2i;
- 如果2i+1>n,则结点i无右孩子;如果2i+1<=n,则其右孩 子是2i+1。

2. 二叉树的存储

//链式存储
/*二叉链表*/
typedef struct BiTreeNode
{
    Datatype data;
    struct BiTreeNode *lchild, *rchild;
}BiTreeNode, *BiTree;

/*三叉链表*/
typedef struct BiTreeNode
{
    Datatype data;
    struct BiTreeNode *lchild, *rchild, *parent;
}BiTreeNode, *BiTree;

2. 二叉树的遍历

//先序遍历
void PreOrder(BiTree bt)
{
    if(bt != NULL)
    {
        visit(bt->data);
        PreOrder(bt->lchild);
        PreOrder(bt->rchild);
    }
}

//中序遍历
void PreOrder(BiTree bt)
{
    if(bt != NULL)
    {
        PreOrder(bt->lchild);
        visit(bt->data);
        PreOrder(bt->rchild);
    }
}

//后序遍历
void PreOrder(BiTree bt)
{
    if(bt != NULL)
    {
        PreOrder(bt->lchild);
        PreOrder(bt->rchild);
        visit(bt->data);
    }
}

//层次遍历算法
void LevelOrder(BiTree bt)
{
    BiTreeNode Queue[MAXNODE];
    int front,rear;
    if(bt == NULL) return;
    front = -1; rear = 0;
    Queue[rear] = bt;
    while (rear != front)
    {
        front++;
        visit(Queue[front]->data);
        if (queue[front]->lchild != NULL)
        {
            rear++;
            Queue[rear] = Queue[front]->lchild;
        }
        if (queue[->rchild != NULL])
        {
            rear++;
            Queue[rear] = Queue[front]->rchild;
        }
    }
}

3. 二叉树的构建

void CreatBiTree(char preord[], char inord[], int n, BiTree root)
{  //n为二叉树结点的个数,建立的二叉树放在root中
    if (n <= 0) root = NULL;
    else PreInOrd(preord, inord, 1, n, 1, n, &root);
}
void PreInOrd(char preord[], char inord[], int i, int j, int k, int h, BiTree *t)
{  //先序序列中从i到j,中序序列从k到h,建立一棵二叉树放在t中
    int m;
    *t = new BiNode;
    (*t)->data = preord[i];
    m = k;
    while (inord[m] != preord[i]) m++;
    if (m == k) (*t)->lchild = NULL;    //左子树空
    else PreInOrd(preord, inord, i+1, i+m-k, k, m-1, &(*t)->lchild);
    if (m == h) (*t)->rchild = NULL;    //右子树空
    else PreInOrd(preord, inord, i+m-k+1, j, m+1, h, &(*t)->lchild);
}

//统计叶子结点个数
int CountLeaf(BiTree T)
{
    if (T == NULL) return 0;
    if (T->lchild == NULL && T->rchild == NULL) return 1;
    return CountLeaf(T->lchild) + CountLeaf(T->rchild);
}

//计算二叉树深度算法
int BitreeDepth (BiTree bt)
{
    if (bt == NULL) return 0;
    if (bt->lchild == NULL && bt->rchild == NULL) return 1;
    depthL = BitreeDepth(bt->lchild);
    depthR = BitreeDepth(bt->rchild);
    return 1+max(depdthL, depthR);
}

4. 二叉排序树(BST)的删除

Status DeleteBST(BiTree &T, KeyType key)
{
    if (!T) return FALSE;
    else
    {
        if (key == T->data.key)
        {  //找到关键字等于key的数据元素
            Delete(T);
            return TRUE;
        }
        else if (key < T->data.key)
            DeleteBST(T->lchild, key);
        else
            DeleteBST(T->rchild, key);
    }
}

void Delete(BiTree &p)
{  //从二叉排序树中删除结点p,并重接它的左子树或右子树
    if (!p->lchild && !p->rchild) free(&p);
    if (!p->rchild)    //只有左子树
    {
        q = p;
        p = p->lchild;
        f->lchild = p;  //两种情况,或者:f->rchild = p;
        free(q);
    }
    else if (!p->lchild)    //只有右子树
    {
        q = p;
        p = p->rchild;
        f->lchild = p;  //两种情况,或者:f->rchild = p;
        free(q);
    }
    else      //左右子树均有
    {
        q = p;
        s = p->lchild;
        while (s->rchild)
        {
            q = s;
            s = s->rchild;
        }  //s指向被删结点p的前驱,q与s同步
        p->data = s->data;
        if (q != p) q->rchild = s->lchild;
        else q->lchild = s->lchild;  //重接q的左子树
        free(s);
    }
}

5. 平衡二叉树(AVL)的插入

AvlTree Insert(ElementType X, AvlTree T)
{
    if (T == NULL)
    {  //Create and return a one node tree
        T = malloc(sizeof(struct AvlNode));
        if (T == NULL) FatalError("Out of space!!!");
        else
        {
            T->Element = X;
            T->Height = 0;
            T->Left = T->Right = NULL;
        }
    }
    else if (X < T->Element)
    {  //Handle left insertion
        T->Left = Insert(X, T->Left);
        if (Height(T->Left) - Height(T->Right) == 2)  //not balanced
            if (X < T->Left->Element)    //LL Rotation
            T = SingleRotateWithLeft(T);
            else    //LR Rotation
                T = DoubleRotateWithLeft(T);
    }
    else if (X > T->Element)
    {  //Handle right insertion
        T->Right = Insert(X, T->Right);
        if (Height(T->Right) - Height(T->Left) == 2)
            if (X > T->Right->Element)
            T = SingleRotateWithRight(T);
            else
                T = DoubleRotationWithRifht(T);
    }
    //Else X is in the tree already;we'll do nothing
    T->Height = Max(Height(T->Left), Height(T->Right)) + 1;
    return T;
}

AvlTree SingleRotateWithLeft(AvlTree T)    //LL Rotation
{
    AvlTree pT = T, pT2 = T->Left->Right;
    T = T->Left;
    T->Right = pT;
    pT->Left = pT2;
    return T;
}

6. 最优树-哈夫曼树

//哈夫曼编码的算法实现
#define MAXBIT 10
#define MAXVALUE 1000

typedef struct HNode    //结点
{
    int weight;
    int parent, lchild, rchild;
}HNode;

typedef struct HCode    //哈夫曼编码结构
{
    int bit[MAXBIT];
    int start;
}HCode;

void HuffmanCoding(HNode *HT, HCode *HC, int *w, int n)
{  //w存放n个字符的权值,构造哈夫曼树HT,并求出n个字符的哈夫曼编码HC。
    if (n <= 1) return;
    m = 2*n-1;
    HT = (HNode *)malloc(m*sizeof(HNode));  //哈夫曼树的构造
    for (p = HT, i = 1; i < n; ++i, ++p, ++w)
    {    //初始化叶子结点信息
        (*p)->weight = *w;
        (*p)->lchild = -1;
        (*p)->rchild = -1;
        (*p)->parent = -1;
    }
    for (; i < m; ++i, ++p)
    {    //初始化分支结点信息,非叶子节点
        (*p)->weight = 0;
        (*p)->lchild = -1;
        (*p)->rchild = -1;
        (*p)->parent = -1;
    }
    for (i = n; i < m; ++i)
    {  //寻找根节点权值最小和次最小的两棵子树
        m1 = m2 = MAXVALUE;
        x1 = x2 = 0;
        for (j = 0; j < i; ++j)
        {
            if (HT[j].parent == -1 && HT[j].weight < m1)
            {
                m2 = m1;
                x2 = x1;
                m1 = HT[j].weight;
                x1 = j;
            }
            else if (HT[j].parent == -1 && HT[j].weight < m2)
            {
                m2 = HT[j].weight;
                x2 = j;
            }
        }
        //合并成一棵新的子树
        HT[x1].parent = i;
        HT[x2].parent = i;
        HT[i].lchild = x1;
        HT[i].rchild = x2;
        HT[i].weight = m1 + m2;
    }
    //字符编码
    HC = (HCode *)malloc(n)*sizeof(HCNode);
    for (i = 0; i < n; ++i)
    {
        start = n - 1;  //最后一个非叶子结点的位置
        for (c = i, f = HT[i].parent; f != 1; c = f, f = HT[f].parent)
            if (HT[f].lchild = c) HC[i].bit[start--] = 0;
        else HC[i].bit[start--] = 1;
        HC[i].start = start + 1;  //记录编码的起始位置
    }
}

7. 树和森林

//树的双亲表示法
#define MAX_TREE_SIZE 100
typedef struct PTNode
{
    DataType data;
    int parent;
}PTNode;

typedef struct PTree
{
    PTNode nodes[MAX_TREE_SIZE];
    int r, n;
}PTree;
//树的孩子表示法
typedef struct CTNode
{
    int child;
    struct CTNode *next;
}CTNode;

typedef struct CTBox
{
    DataType data;
    CTNOde *firstchild;
}CTBox;

typedef struct CTree
{
    CTBox nodes[MAX_TREE_SIZE];
    int n, r;
}CTree;
//树的孩子兄弟表示法
typedef struct CSNode
{
    DataType data;
    struct CSNode *firstchild, *nextsibling;
}CSNode;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值