Mu class (4)

Tree:
binary search tree:
a binary search tree (Binary Search Tree), (Also: a binary search tree, binary sort tree) which is either an empty tree or a binary tree with the following properties: If it's left subtree is not empty, then the value of the left sub-tree, all the nodes are less than the value of the root node; if it is not empty right subtree, the right subtree of nodes which are all greater than its root knot values of the points; its left and right sub-trees are binary sort tree.

Principle:
the discovery process binary sort trees and sub-optimal binary tree is similar to binary is usually taken as a linked list structure to store binary sort tree. The binary sort tree traversal order to obtain an ordered sequence of a key, a random sequence may be ordered into a sequence by a binary sort tree structure, the tree structure is the process of ordering random sequence process. Each time a new node is inserted is binary sort tree new leaf nodes, the insertion operation is performed without moving the other nodes, only one node pointer changes from empty to non-empty i.e. can. Search, insert, delete equal to the high complexity of the tree, O (log (n)) .

Search algorithm:
1. If the binary search tree is empty, the operation returns empty, otherwise, at operation;
2. First take root, if X is equal to the root node, return;
3. If the node is less than the root node, recursively Find the left subtree;
4. If the node is greater than the root node, recursively find the right subtree.

Node p = tree;
        while (p != null) {
            if (data < p.data) p = p.left;
            else if (data > p.data) p = p.right;
            else return p;

Insertion algorithm:
1. If the tree is empty, then directly to the new node is inserted, otherwise, perform the following steps.
2. The data to be inserted large data than the root, the right subtree to insert new data if the right subtree is empty, new data is inserted directly into the right position of the child node; not empty, then continue traversing the right subtree, find the insertion position.
3. To insert data smaller than the root node data, then the left subtree is inserted into the data, if the left subtree is empty, the new data is inserted directly into the position of the left child node; not empty, then continue traversing left child tree, find the insertion position.

if (tree == null) {
            tree = new Node(data);
            return;
        }
        
        Node p = tree;
        while (p != null) {
            if (data > p.data) {
                if (p.right == null) {
                    p.right = new Node(data);
                    return;
                }
                p = p.right;
            } else { //data < p.data
                if (p.left == null) {
                    p.left = new Node(data);
                    return;
                }
                p = p.left;
            }
        }

Deletion algorithm:
1. the first case, if you want to delete a node has no child nodes, the parent node point directly to the node you want to remove the pointer to null. For example, node 55 the way you want to delete.
2. The second case, the node if you want to delete only one node, that only left child or right child, then the parent node points to delete a node pointer to the deleted node's children can be. For example, the way you want to delete a node
3. The third case, if you want to delete a node has two children, you need to find the right child node of the smallest node in the tree or left subtree maximum node to replace it to be To delete a node on. Then delete the right sub-tree node or left the smallest sub-tree node maximum, so that you can use

 Node p = tree; //p 指向要删除的结点,初始化指向根节点
        Node pp = null; //pp 记录的是 p 的父节点
        
        while (p != null && p.data != data) {
            pp = p;
            if (data > p.data) p = p.right;
            else p = p.left;
        }
        if (p == null) return; //没有找到
        
        //要删除的节点有两个子节点
        if (p.left != null && p.right != null) {//查找右子树中最小的节点
            Node minP = p.right;
            Node minPP = p; //minPP 表示 minP 的父节点
            while (minP.left != null) {
                minPP = minP;
                minP = p.left;
            }
            p.data = minP.data; //将 minP 的数据替换到 p 中
            p = minP; //下面就变成了删除 minP 了,要结合整个删除函数来看
            pp = minPP;
        }
        
        //删除的是叶子节点或者仅有一个子节点
        Node  child; //p 的子节点
        if (p.left != null) child = p.left;
        else if (p.right != null) child = p.right;
        else child = null;
        
        if (pp == null) tree = child; // 删除的是根节点
        else if (pp.left == p) pp.left = child;
        else pp.right = child;

Balanced binary tree:

Properties:
It was a star or empty tree or a binary tree having the following properties:

Its left subtree and right subtree are balanced binary tree, and the absolute value of the difference between the depth of the left subtree and right subtree of not more than 1.
If the balance factor BF minus the depth of the node binary tree defined in its right subtree for the depth of the left subtree of the node, the binary tree balance balance factors for all the nodes may be only -1, 0,.
As long as the binary tree node has a balance factor of absolute value greater than 1, then the balanced binary tree Fengyun lost balance.

Because it will not, so the code to see someone else's blog:

#include <stdio.h>
#include <stdlib.h>
//分别定义平衡因子数
#define LH +1
#define EH  0
#define RH -1
typedef int ElemType;
typedef enum {false,true} bool;
//定义二叉排序树
typedef struct BSTNode{
    ElemType data;
    int bf;//balance flag
    struct BSTNode *lchild,*rchild;
}*BSTree,BSTNode;
//对以 p 为根结点的二叉树做右旋处理,令 p 指针指向新的树根结点
void R_Rotate(BSTree* p)
{
    //借助文章中的图 5 所示加以理解,其中结点 A 为 p 指针指向的根结点
    BSTree lc = (*p)->lchild;
    (*p)->lchild = lc->rchild;
    lc->rchild = *p;
    *p = lc;
}
////对以 p 为根结点的二叉树做左旋处理,令 p 指针指向新的树根结点
void L_Rotate(BSTree* p)
{
    //借助文章中的图 6 所示加以理解,其中结点 A 为 p 指针指向的根结点
    BSTree rc = (*p)->rchild;
    (*p)->rchild = rc->lchild;
    rc->lchild = *p;
    *p = rc;
}
//对以指针 T 所指向结点为根结点的二叉树作左子树的平衡处理,令指针 T 指向新的根结点
void LeftBalance(BSTree* T)
{
    BSTree lc,rd;
    lc = (*T)->lchild;
    //查看以 T 的左子树为根结点的子树,失去平衡的原因,如果 bf 值为 1 ,则说明添加在左子树为根结点的左子树中,需要对其进行右旋处理;反之,如果 bf 值为 -1,说明添加在以左子树为根结点的右子树中,需要进行双向先左旋后右旋的处理
    switch (lc->bf)
    {
        case LH:
            (*T)->bf = lc->bf = EH;
            R_Rotate(T);
            break;
        case RH:
            rd = lc->rchild;
            switch(rd->bf)
        {
            case LH:
                (*T)->bf = RH;
                lc->bf = EH;
                break;
            case EH:
                (*T)->bf = lc->bf = EH;
                break;
            case RH:
                (*T)->bf = EH;
                lc->bf = LH;
                break;
        }
            rd->bf = EH;
            L_Rotate(&(*T)->lchild);
            R_Rotate(T);
            break;
    }
}
//右子树的平衡处理同左子树的平衡处理完全类似
void RightBalance(BSTree* T)
{
    BSTree lc,rd;
    lc= (*T)->rchild;
    switch (lc->bf)
    {
        case RH:
            (*T)->bf = lc->bf = EH;
            L_Rotate(T);
            break;
        case LH:
            rd = lc->lchild;
            switch(rd->bf)
        {
            case LH:
                (*T)->bf = EH;
                lc->bf = RH;
                break;
            case EH:
                (*T)->bf = lc->bf = EH;
                break;
            case RH:
                (*T)->bf = EH;
                lc->bf = LH;
                break;
        }
            rd->bf = EH;
            R_Rotate(&(*T)->rchild);
            L_Rotate(T);
            break;
    }
}
int InsertAVL(BSTree* T,ElemType e,bool* taller)
{
    //如果本身为空树,则直接添加 e 为根结点
    if ((*T)==NULL)
    {
        (*T)=(BSTree)malloc(sizeof(BSTNode));
        (*T)->bf = EH;
        (*T)->data = e;
        (*T)->lchild = NULL;
        (*T)->rchild = NULL;
        *taller=true;
    }
    //如果二叉排序树中已经存在 e ,则不做任何处理
    else if (e == (*T)->data)
    {
        *taller = false;
        return 0;
    }
    //如果 e 小于结点 T 的数据域,则插入到 T 的左子树中
    else if (e < (*T)->data)
    {
        //如果插入过程,不会影响树本身的平衡,则直接结束
        if(!InsertAVL(&(*T)->lchild,e,taller))
            return 0;
        //判断插入过程是否会导致整棵树的深度 +1
        if(*taller)
        {
            //判断根结点 T 的平衡因子是多少,由于是在其左子树添加新结点的过程中导致失去平衡,所以当 T 结点的平衡因子本身为 1 时,需要进行左子树的平衡处理,否则更新树中各结点的平衡因子数
            switch ((*T)->bf)
            {
                case LH:
                    LeftBalance(T);
                    *taller = false;
                    break;
                case  EH:
                    (*T)->bf = LH;
                    *taller = true;
                    break;
                case RH:
                    (*T)->bf = EH;
                    *taller = false;
                    break;
            }
        }
    }
    //同样,当 e>T->data 时,需要插入到以 T 为根结点的树的右子树中,同样需要做和以上同样的操作
    else
    {
        if(!InsertAVL(&(*T)->rchild,e,taller))
            return 0;
        if (*taller)
        {
            switch ((*T)->bf)
            {
                case LH:
                    (*T)->bf = EH;
                    *taller = false;
                    break;
                case EH:
                    (*T)->bf = RH;
                    *taller = true;
                    break;
                case  RH:
                    RightBalance(T);
                    *taller = false;
                    break;
            }
        }
    }
    return 1;
}
//判断现有平衡二叉树中是否已经具有数据域为 e 的结点
bool FindNode(BSTree root,ElemType e,BSTree* pos)
{
    BSTree pt = root;
    (*pos) = NULL;
    while(pt)
    {
        if (pt->data == e)
        {
            //找到节点,pos指向该节点并返回true
            (*pos) = pt;
            return true;
        }
        else if (pt->data>e)
        {
            pt = pt->lchild;
        }
        else
            pt = pt->rchild;
    }
    return false;
}
//中序遍历平衡二叉树
void InorderTra(BSTree root)
{
    if(root->lchild)
        InorderTra(root->lchild);
   
    printf("%d ",root->data);
   
    if(root->rchild)
        InorderTra(root->rchild);
}
int main()
{
    int i,nArr[] = {1,23,45,34,98,9,4,35,23};
    BSTree root=NULL,pos;
    bool taller;
    //用 nArr查找表构建平衡二叉树(不断插入数据的过程)
    for (i=0;i<9;i++)
    {
        InsertAVL(&root,nArr[i],&taller);
    }
    //中序遍历输出
    InorderTra(root);
    //判断平衡二叉树中是否含有数据域为 103 的数据
    if(FindNode(root,103,&pos))
        printf("\n%d\n",pos->data);
    else
        printf("\nNot find this Node\n");
    return 0;
}
Published 13 original articles · won praise 0 · Views 343

Guess you like

Origin blog.csdn.net/JSUChengyuezhen/article/details/104407553