数据结构与算法(三)树与二叉树

1. 树

非线性结构,层次结构
每个元素至多有一个前趋,但可以有多个后继;根结点没有前趋,其他结点有且只有一个前趋
数据元素间是一对多的关系
树、二叉树、森林

树是n(n>=0)个结点的有限集合,当n=0时为空树,否则称为非空树。
    1. 树有且仅有一个根结点
    2. 除根节点外,其余结点可分为m(m>=0)个互不相交的集合,每个集合本身又是一棵树,称为根的子树

    空树:没有任何结点的树
    最小非空树:只有一个根节点

    结点:一个元素及指向其子树的分支
    结点的度:结点拥有的子树数目(结点有几个子树分支)
    叶子、终端结点:指度为0的结点,没有子树
    分支结点、非终端结点:度不为0的结点;不为根的分支结点称为内部结点
    树的度:指树中各结点度的最大值
    结点的层次:从根结点开始,根为第一层,根的子树为第二层,依次类推
    树的深度、高度:树中结点的最大层次数
    有序树和无序树:如果将树中结点的各子树看成从左到右依次有序且不能交换,则称该树为有序树;否则称为无序树
    森林:m棵互不相交的树的集合

1.1 树的基本运算:

    置空setnull
    求根root
    求父节点parent
    求孩子child
    建树create(x,F),生成一个以x为根节点,以森林F为子树森林的树
    求右兄弟rsibling
    插入子树addchild
    删除子树delchild
    遍历操作traverse

1.2 二叉树

    每个结点至多两个子树。

二叉树的数据结构:

struct TreeNode
{
	TreeNode * lchild;	// 左子树
	TreeNode * rchild;	// 右子树
	void * data;		// 数据
}
    分类:
        满二叉树:每层含有结点数为最大值,深度为k,且含有2^k - 1个结点的二叉树
        完全二叉树:k-1层前含有结点数为最大值,k层不一定满,但全部集中在左边而空缺留在右边,子节点只可能在第k层和第k-1层出现;满二叉树一定是完全二叉树

    二叉树的存储结构
        顺序存储:
            1. 完全二叉树可根据结点编号依次存储各结点
            2. 非完全二叉树需要添加空结点使之成为完全二叉树;会造成空间浪费,最坏的情况是单右枝树(全是右结点)
        链式存储:
            双链法(二叉链表):
                在内存中存储两个子节点的存储地址;方便从根往下找;查找父节点和祖先则不方便
            三链法(三叉链表):
                在二叉链表上增加存储父节点的地址

1.3 二叉树的遍历

    非线性结构线性化
    递归算法:
        前序遍历
        中序遍历
        后序遍历
    非递归算法:
        前序遍历
        中序遍历
        后序遍历
        层次遍历
    遍历序列与二叉树的复原
        由两种遍历序列确定一颗二叉树

二叉树的遍历本质上是将一个复杂的非线性结构转换为线性结构,使每个结点都有了唯一的前驱和后继。对于二叉树的结点,查找左右子女是方便的,其前驱后继只有在遍历中得到。为了容易找到前驱和后继,有两种方法:
1. 在结点结构中增加向前和向后的指针,这种方法增加了存储开销,不可取
2. 利用二叉树的空链指针(线索二叉树)

#include <stdio.h>
/**
 * 构造一棵二叉树
 *                             15
 *                           /    \
 *                          6      18
 *                        /   \    
 *                       3     7  
 *                            /
 *                           9
 * 
 * 
*/

typedef struct sTreeNode TreeNode;

typedef struct sTreeNode
{
    TreeNode *lchild;
    TreeNode *rchild;
    int data;
} TreeNode, *PTreeNode;

// 前序遍历
void qianxu(TreeNode *root)
{
    /**
     * 跟结点为空 => 返回
     * 根结点不为空 => 输出根结点 => 左子树为根结点前序遍历 => 右子树为根结点前序遍历
     * 
     * 输出跟结点 => 递归输出左子树 => 递归输出右子树
    */

    if (NULL == root)
    {
        return;
    }

    printf("%d\t", root->data);
    qianxu(root->lchild);
    qianxu(root->rchild);
}

// 后序遍历
void houxu(TreeNode *root)
{
    /**
     * 递归输出左子树 => 递归输出右子树 => 输出跟结点
    */

    if (NULL == root)
    {
        return;
    }

    houxu(root->lchild);
    houxu(root->rchild);

    printf("%d\t", root->data);
}

// 中序遍历
void zhongxu(TreeNode *root)
{
    /**
     * 递归输出左子树 => 输出跟结点 => 递归输出右子树
    */

    if (NULL == root)
    {
        return;
    }

    zhongxu(root->lchild);
    printf("%d\t", root->data);
    zhongxu(root->rchild);
}

int main()
{
    TreeNode root, t1, t2, t3, t4, t5;
    root.lchild = root.rchild = t1.lchild = t1.rchild = t2.rchild = t2.lchild = t3.lchild = t3.rchild = t4.lchild = t5.rchild = t4.rchild = t5.lchild = NULL;

    root.data = 15;
    t1.data = 6;
    t2.data = 3;
    t3.data = 7;
    t4.data = 9;
    t5.data = 18;

    root.lchild = &t1;
    root.rchild = &t5;

    t1.lchild = &t2;
    t1.rchild = &t3;

    t3.lchild = &t4;

    printf("\nqianxu\n");
    qianxu(&root);	// 输出    15      6       3       7       9       18
    printf("\nzhongxu\n");
    zhongxu(&root); // 输出    3       6       9       7       15      18
    printf("\nhouxu\n");
    houxu(&root);	// 输出	   3       9       7       6       18      15
}

1.4 线索二叉树(Threaded BinaryTree)

加上线索的二叉树称为线索二叉树。对二叉树以某种遍历方式(如先序、中序、后序或层次等)进行遍历,使其变为线索二叉树的过程称为对二叉树进行线索化。
线索二叉树中的线索能记录每个结点前驱和后继信息。为了区别线索指针和孩子指针,在每个结点中设置标志ltag和rtag。
当tag为0时,child是指向孩子的指针;否则child是指向结点的前驱或后继的线索。
线索二叉树的结点结构:

struct ThreadedBT
{
	BYTE ltag;	// 标记lchild的目标是左子树还是前驱
	BYTE rtag;	// 标记rtag的目标是右子树还是后继
	ThreadedBT* lchild;
	ThreadedBT* lchild;
	void* data;
}

1.5 二叉搜索树/二叉查找树/二叉排序树(Binary Search Tree : BST)

它或者是一棵空树,或者是具有下列性质的二叉树:

  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  • 它的左、右子树也分别为二叉排序树。

对任何结点x,其左子树中的key最大不超过x.key;其右子树中的key最大不低于x.key。

二叉搜索树可以通过中序遍历将所有key有序输出。

#include <stdio.h>
#include <memory.h>

typedef struct sTreeNode TreeNode;

typedef struct sTreeNode
{
    TreeNode *lchild;
    TreeNode *rchild;
    TreeNode *parent;
    int data;
} TreeNode, *PTreeNode;

struct TreeNode *new ()
{
    PTreeNode _t = (PTreeNode)malloc(sizeof(TreeNode));

    _t->lchild = NULL;
    _t->rchild = NULL;
    _t->parent = NULL;
    _t->data = 0;

    return _t;
}

void dispose(TreeNode *_node)
{
    free(_node);
}

// 查找
struct TreeNode *search(TreeNode *root, int key)
{
    if (!root)
        return NULL;

    if (key == root->data)
        return root;

    if (root->data > key)
        return search(root->lchild, key);

    return search(root->rchild, key);
}

// 插入
struct TreeNode *insert(TreeNode *root, int key)
{
    if (!root)
    {
        TreeNode *_n = new ();
        _n->data = key;
        return _n;
    }

    if (key == root->data)
    {
        TreeNode *_n = new ();
        _n->data = key;
        _n->lchild = root->lchild;
        _n->parent = root;
        root->lchild = _n;

        return root;
    }

    if (root->data > key)
    {
        TreeNode *_n = insert(root->lchild, key);
        root->lchild = _n;
        return root;
    }
    else
    {
        TreeNode *_n = insert(root->rchild, key);
        root->rchild = _n;
        return root;
    }
}

struct TreeNode *get_min_node(TreeNode *root)
{
    if (root && root->lchild)
        return get_min_node(root->lchild);

    return root;
}

// 删除
struct TreeNode *delete (TreeNode *root, int key)
{
    if (!root)
        return NULL;

    if (key == root->data)
    {
        if (!root->rchild) // 右结点为空
        {
            // 返回左节点
            TreeNode *_n = root->lchild;
            if (_n)
            {
                _n->parent = NULL;
            }

            dispose(root); // 释放root节点

            return _n;
        }
        else
        {
            TreeNode *_n = get_min_node(root->rchild);
            _n->parent->lchild = NULL;
            _n->parent = NULL;

            _n->lchild = root->lchild;
            _n->rchild = root->rchild;

            dispose(root); // 释放root节点

            return _n;
        }
    }

    if (root->data > key)
    {
        TreeNode *_n = delete (root->lchild, key);
        if (_n)
            root->lchild = _n;
    }
    else
    {
        TreeNode *_n = delete (root->rchild, key);
        if (_n)
            root->rchild = _n;
    }

    return root;
}

// 中序遍历
void zhongxu(TreeNode *root)
{
    /**
     * 递归输出左子树 => 输出跟结点 => 递归输出右子树
    */

    if (NULL == root)
    {
        return;
    }

    zhongxu(root->lchild);
    printf("%d\t", root->data);
    zhongxu(root->rchild);
}

int main()
{
    int v[] = {1, 2, 3, 5, 6, 7, 8, 9, 22, 11, 23, 32, 0, 4};

    TreeNode *root = NULL;

    // printf("%d\r\n", sizeof(v));

    for (size_t i = 0; i < sizeof(v) / sizeof(int); i++)
    {
        root = insert(root, v[i]);
    }
    zhongxu(root);
    root = insert(root, 11);
    printf("\r\n");
    zhongxu(root);

    root = delete (root, 9);
    printf("\r\n");
    zhongxu(root);

    root = delete (root, 20);
    printf("\r\n");
    zhongxu(root);
}

1.6 平衡二叉树(AVL树:得名于它的发明者G. M. Adelson-Velsky和E. M. Landis)

又名:平衡二叉查找树

AVL树任何结点的两个子树的高度最大差为1,所以也被称为高度平衡树。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。
AVL树本质还是一棵二叉树,特点是:

  1. 是一棵二叉搜索树
  2. 带有平衡条件:每个结点的左右子树高度差绝对值(平衡因子)最多为1

AVL树本质上是带了平衡功能的二叉搜索树。

typedef struct sTreeNode TreeNode;

typedef struct sTreeNode
{
    TreeNode *lchild;
    TreeNode *rchild;
    TreeNode *parent;
    int data;
    int balance; // 平衡因子 , 0 左右子树高度相等,1 右子树比左子树高1,-1 右子树比左子树矮1
} TreeNode, *PTreeNode;

平衡二叉树的关键就是如何平衡,在插入和删除结点时,可能会破坏树的平衡状态。

  • 若结点的平衡因子小于-1,则说明左子树比右子树高;需将结点的左子树的平衡因子调整为-1(若是-1则不需要调整;若不是-1,需左旋结点的左子树),然后右旋结点。
  • 若结点的平衡因子大于1,则说明右子树比左子树高;需将结点的右子树的平衡因子调整为-1(若是-1则不需要调整;若不是-1,需右旋结点的右子树),然后左旋结点。
/**
 * AVL树:平衡二叉查找树
*/
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>

typedef struct sTreeNode TreeNode;

typedef struct sTreeNode
{
    TreeNode *lchild;
    TreeNode *rchild;
    TreeNode *parent;
    int data;
    int balance; // 平衡因子 , 0 左右子树高度相等,1 右子树比左子树高1,-1 右子树比左子树矮1
} TreeNode, *PTreeNode;

struct TreeNode *new ()
{
    int _size = sizeof(TreeNode);
    TreeNode *_t = (TreeNode *)malloc(sizeof(TreeNode));
    // if (NULL == _t) // out-of-memory
    // {
    //     return NULL;
    // }
    _t->balance = 0;
    _t->lchild = NULL;
    _t->rchild = NULL;
    _t->parent = NULL;
    _t->data = 0;

    return _t;
}

void dispose(TreeNode *_node)
{
    free(_node);
}

// 查找
struct TreeNode *search(TreeNode *root, int key)
{
    if (!root)
        return NULL;

    if (key == root->data)
        return root;

    if (root->data > key)
        return search(root->lchild, key);

    return search(root->rchild, key);
}

// 获取树高度
int height(TreeNode *root)
{
    if (!root)
        return 0;
    int lh = height(root->lchild);
    int rh = height(root->rchild);

    return lh > rh ? lh + 1 : rh + 1;
}

// 重置节点的balace值
void reset_balance_value(TreeNode *root)
{
    if (root)
        root->balance = height(root->rchild) - height(root->lchild);

    // printf("balance = %d\r\n", root->balance);
}

/**
 * 结点 左旋
*/
TreeNode *turn_left(TreeNode *root)
{
    // 左旋,将父节点调整为

    if (!root)
        return NULL;

    TreeNode *_root = root->rchild;
    TreeNode *_t = _root->lchild;
    _root->parent = root->parent;
    _root->lchild = root;
    _root->lchild->rchild = _t;

    return _root;
}

/**
 * 结点 右旋
*/
TreeNode *turn_right(TreeNode *root)
{
    // 右旋,将父节点调整为右子节点(右子树的根节点,父节点和父节点的右子树组成当前节点右子树);原右子树调整为父节点的左子树

    if (!root)
        return NULL;

    TreeNode *_root = root->lchild;
    TreeNode *_t = _root->rchild;
    _root->parent = root->parent;
    _root->rchild = root;
    _root->rchild->lchild = _t;

    return _root;
}

/**
 * 重新平衡,调整平衡因子绝对值<=1
*/
struct TreeNode *rebalance(TreeNode *root)
{
    if (!root)
        return NULL;

    reset_balance_value(root);

    if (root->balance >= -1 && root->balance <= 1)
        return root;

    if (root->balance < -1) // 左子树更高,通过旋转把左子树balace调整为-1,然后右旋结点;旋转左子树,降低左子树的高度;使左子树的左子树高度大于右子树(左旋左子树),然后右旋
    {
        if (root->lchild->balance > 0) // 左子树的平衡因子<=0 左子树的左子树不比右子树低,则右旋
        {
            // 左子树的 右子树更高,左旋,然后右旋
            root->lchild = turn_left(root->lchild); // 左旋,高度差绝对值为1时,旋转后的高度不变,高度差由-1变1,1变-1
        }
        root = turn_right(root);
    }
    else // 右子树更高,通过旋转把右子树balance调整为1,然后左旋结点
    {
        if (root->rchild->balance < 0)
        {
            root->rchild = turn_right(root->rchild);
        }
        root = turn_left(root);
    }

    return rebalance(root);
}

/**
 *  插入,在bst的插入上加入rebalance操作
 *
*/
struct TreeNode *insert(TreeNode *root, int key)
{
    if (!root)
    {
        TreeNode *_n = new ();
        _n->data = key;

        return _n;
    }

    if (key == root->data)
    {
        TreeNode *_n = new ();
        _n->data = key;
        _n->lchild = root->lchild;
        _n->parent = root;
        root->lchild = _n;

        root = rebalance(root);

        return root;
    }

    if (root->data > key)
    {
        TreeNode *_n = insert(root->lchild, key);
        root->lchild = _n;
        root = rebalance(root);

        return root;
    }
    else
    {
        TreeNode *_n = insert(root->rchild, key);
        root->rchild = _n;
        root = rebalance(root);

        return root;
    }
}

struct TreeNode *get_min_node(TreeNode *root)
{
    if (root && root->lchild)
        return get_min_node(root->lchild);

    return root;
}

// 删除
struct TreeNode *delete (TreeNode *root, int key)
{
    if (!root)
        return NULL;

    if (key == root->data)
    {
        if (!root->rchild) // 右结点为空
        {
            // 返回左节点
            TreeNode *_n = root->lchild;
            if (_n)
            {
                _n->parent = NULL;
            }

            dispose(root); // 释放root节点

            _n = rebalance(_n);

            return _n;
        }
        else
        {
            TreeNode *_n = get_min_node(root->rchild);
            _n->parent->lchild = NULL;
            _n->parent = NULL;

            _n->lchild = root->lchild;
            _n->rchild = root->rchild;

            dispose(root); // 释放root节点

            _n = rebalance(_n);

            return _n;
        }
    }

    if (root->data > key)
    {
        TreeNode *_n = delete (root->lchild, key);
        if (_n)
        {
            root->lchild = _n;
            _n = rebalance(_n);
        }
    }
    else
    {
        TreeNode *_n = delete (root->rchild, key);
        if (_n)
        {
            root->rchild = _n;
            _n = rebalance(_n);
        }
    }

    return root;
}

// 中序遍历
void zhongxu(TreeNode *root)
{
    /**
     * 递归输出左子树 => 输出跟结点 => 递归输出右子树
    */

    if (NULL == root)
    {
        return;
    }

    zhongxu(root->lchild);
    printf("%d\t", root->data);
    zhongxu(root->rchild);
}

int min_size = 8;
int start = 8;

// 将数据填入数组的指定位置,无数据节点填-1;类似层次遍历
void fill(TreeNode *root, const int index, int *vl)
{
    if (!root)
    {
        vl[index] = -1;
        return;
    }

    vl[index] = root->data;
    // printf("vl[%d] = %d\r\n", index, vl[index]);

    fill(root->lchild, (2 * index) + 1, vl);
    fill(root->rchild, (2 * index) + 2, vl);
}

/**
 * 输出树形结构
*/
void show(TreeNode *root)
{
    if (!root)
    { printf("empty tree"); return;}

    int _depth = height(root);
    //TreeNode *_n = root;

    int *_vl = (int *)malloc(sizeof(int) * ((1 << (_depth + 1)) - 1));
    // 初始化
    memset(_vl, -1, sizeof(int) * ((1 << (_depth + 1)) - 1));
    // 将数据填入数组,无数据节点填-1;类似层次遍历
    fill(root, 0, _vl);

    for (size_t i = 0; i < _depth; i++)
    {
        int w = 1 << (_depth - i + 1);
        for (size_t j = ((1 << i) - 1); j < ((1 << (i + 1)) - 1); j++)
        {
            if (_vl[j] < 0)
                printf("%*c%*c", w, '-', w, ' ');
            else

                printf("%*d%*c", w, _vl[j], w, ' ');
        }

        printf("\r\n");
    }

    free(_vl);
}

int main()
{
    int v[] = {1, 2, 3, 5, 6, 7, 8, 9, 22, 11, 23, 32, 0, 4};

    TreeNode *root = NULL;

    for (size_t i = 0; i < sizeof(v) / sizeof(int); i++)
    {
        root = insert(root, v[i]);
        show(root);

        printf("\r\n\r\n################################################################################################################\r\n\r\n");
    }

    // zhongxu(root);
    // printf("\r\n");

    // show(root);
    root = insert(root, 11);
    show(root);
    printf("\r\n\r\n################################################################################################################\r\n\r\n");
    root = delete (root, 9);
    show(root);
}

1.7 红黑树(RED-BLACK TREE)

红黑树是一棵二叉查找树(AVL树:自平衡二叉查找树),它在每个结点上增加了一个存储位来表示结点的颜色,可以是红色或黑色。通过对任何一条从根到叶子的简单路径上各个结点的颜色进行约束,红黑树确保没有一条路径会比其他路径长出2倍,因而是近似平衡的。

红黑树可视化

typedef struct sRBTree
{
	RBTree * lchild;
	RBTree * rchild;
	BYTE color;		// 颜色 红或黑
	KEY key;
	void * data;
}RBTree;

红黑树性质:

  1. 每个结点或是红色或黑色
  2. 根节点是黑色
  3. 叶子结点是黑色
  4. 如果一个结点是红色,则它的两个子结点都是黑色
  5. 对于每个结点,从该结点到其所有后代叶子结点的简单路径上,均包含相同数目的黑色结点

在这里插入图片描述

/**
 * 红黑树
*/
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>

#define COLOR_BLACK 0
#define COLOR_RED 1

typedef struct sTreeNode TreeNode;

typedef struct sTreeNode
{
    TreeNode *lchild;
    TreeNode *rchild;
    TreeNode *parent;
    int data;
    int color; // 颜色 0 黑色,1 红色
} TreeNode, *PTreeNode;

struct TreeNode *new ()
{
    int _size = sizeof(TreeNode);
    TreeNode *_t = (TreeNode *)malloc(sizeof(TreeNode));
    // if (NULL == _t) // out-of-memory
    // {
    //     return NULL;
    // }
    _t->color = COLOR_RED; // 新结点都是红色的
    _t->lchild = NULL;
    _t->rchild = NULL;
    _t->parent = NULL;
    _t->data = 0;

    return _t;
}

void dispose(TreeNode *_node)
{
    free(_node);
}

// 查找,二叉排序树的查找
struct TreeNode *search(TreeNode *root, int key)
{
    if (!root)
        return NULL;

    if (key == root->data)
        return root;

    if (root->data > key)
        return search(root->lchild, key);

    return search(root->rchild, key);
}

/**
 * 结点 左旋
*/
void turn_left(TreeNode *root)
{
    // 左旋,将父节点调整为
    /**
     * 左旋需要调整4个结点共6个元素
     * 
     * 需调整4个结点:
     * 1. root
     * 2. root 结点的父节点 P
     * 3. root 节点的右子节点 RC
     * 4. RC 结点的左子节点 RC_LC
     * 
     * 需调整6个元素:
     * 1. root 的父结点指针(指向RC)
     * 2. root 的右子结点指针(指向RC_LC)
     * 
     * 3. RC 的父结点指针(指向P)
     * 4. RC 的左子结点指针(指向root)
     * 
     * 5. RC_LC 的父结点指针(指向root)
     * 6. P的左子结点指针或右子结点指针(若root为P的左子结点,则改P的左子结点指向RC,否则右子结点指向RC)
     * 
     * 
     * 
     * 
     * 
     *                P                                     P
     *                 \                                     \
     *                  root              ===>                RC
     *                 /    \                                /   \
     *                *      RC                           root    *
     *                      /  \                         /    \ 
     *                  RC_LC   *                       *      RC_LC
    */

    // 结点为NULL,或右子结点为NULL,不能左旋
    if (!root || !root->rchild)
        return;

    // root是否为其父结点的左子结点
    char root_is_left = 0;
    if (root->parent && root == root->parent->lchild)
        root_is_left = 1;

    // root的父结点
    TreeNode *P = root->parent;
    // root的右子结点
    TreeNode *RC = root->rchild;
    // RC的左子结点
    TreeNode *RC_LC = RC->lchild;

    root->parent = RC;
    root->rchild = RC_LC;

    RC->parent = P;
    RC->lchild = root;

    if (RC_LC)
        RC_LC->parent = root;

    // 调整父结点的指针
    if (P)
        if (root_is_left)
            P->lchild = RC;
        else
            P->rchild = RC;
}

/**
 * 结点 右旋
*/
void turn_right(TreeNode *root)
{
    // 右旋,将父节点调整为右子节点(右子树的根节点,父节点和父节点的右子树组成当前节点右子树);原右子树调整为父节点的左子树
    /**
     * 右旋需要调整4个结点共6个元素
     * 
     * 需调整4个结点:
     * 1. root
     * 2. root 结点的父节点 P
     * 3. root 节点的左子节点 LC
     * 4. LC 结点的右子节点 LC_RC
     * 
     * 需调整6个元素:
     * 1. root 的父结点指针(指向LC)
     * 2. root 的左子结点指针(指向LC_RC)
     * 
     * 3. LC 的父结点指针(指向P)
     * 4. LC 的右子结点指针(指向root)
     * 
     * 5. LC_RC 的父结点指针(指向root)
     * 6. P的左子结点指针或右子结点指针(若root为P的左子结点,则改P的左子结点指向LC,否则右子结点指向LC)
     * 
     * 
     * 
     * 
     * 
     *                P                                     P
     *                 \                                     \
     *                  root              ===>                LC
     *                 /    \                                /   \
     *               LC      *                              *     root
     *              /  \                                        /     \ 
     *             *    LC_RC                                 LC_RC    *
    */

    //  结点为NULL,或左子节点为NULL 不能右旋
    if (!root || !root->lchild)
        return NULL;

    // root是否为其父结点的左子结点
    char root_is_left = 0;
    if (root->parent && root == root->parent->lchild)
        root_is_left = 1;

    // root的父结点
    TreeNode *P = root->parent;
    // root的左子结点
    TreeNode *LC = root->lchild;
    // LC的右子结点
    TreeNode *LC_RC = LC->rchild;

    root->parent = LC;
    root->lchild = LC_RC;

    LC->parent = P;
    LC->rchild = root;

    if (LC_RC)
        LC_RC->parent = root;

    // 调整父结点的指针
    if (P)
        if (root_is_left)
            P->lchild = LC;
        else
            P->rchild = LC;
}

/**
 * 重新平衡,调整插入节点root后的平衡;变色和旋转
*/
void rebalance(TreeNode *root)
{
    if (!root->parent) // root为根节点
    {
        // case 1
        root->color = COLOR_BLACK;
        return;
    }

    // 父结点
    TreeNode *_p = root->parent;
    if (COLOR_BLACK == _p->color) // 插入结点的父结点是黑色,不需要调整平衡
    {
        // case 2
        root->color = COLOR_RED;
        return;
    }

    /* 父结点为红色,则一定存在祖父结点 */

    // 祖父结点
    TreeNode *_pp = _p->parent;
    // 叔叔结点
    TreeNode *_u = NULL;

    // 父结点是祖父结点的左子结点
    char _p_is_left = 0;

    if (_p == _pp->lchild)
    {
        _u = _pp->rchild;
        _p_is_left = 1;
    }
    else
        _u = _pp->lchild;

    if (_u && COLOR_RED == _u->color)
    {
        // case 3.1
        _p->color = _u->color = COLOR_BLACK;
        _pp->color = COLOR_RED;

        rebalance(_pp);
    }
    else
    {
        // case 3.2

        // 当前结点是父结点的左子结点
        char c_is_left = 0;
        if (root == _p->lchild)
            c_is_left = 1;

        if (_p_is_left)
        {
            // case 3.2.1
            if (!c_is_left)
            {
                // case 3.2.1.2
                turn_left(_p);

                // 将父结点调整为插入结点
                TreeNode *_tmp = root;
                root = _p;
                _p = _tmp;
            }

            // case 3.2.1.1
            _p->color = COLOR_BLACK;
            _pp->color = COLOR_RED;
            turn_right(_pp);
        }
        else
        {
            // case 3.2.2

            if (c_is_left)
            {
                // case 3.2.2.2
                turn_right(_p);

                // 将父结点调整为插入结点
                TreeNode *_tmp = root;
                root = _p;
                _p = _tmp;
            }

            // case 3.2.2.1
            _p->color = COLOR_BLACK;
            _pp->color = COLOR_RED;
            turn_left(_pp);
        }
    }
}

/**
 *  插入
 *
*/
TreeNode *insert(TreeNode *root, int key)
{
    if (!root)
    {
        TreeNode *_n = new ();
        _n->data = key;
        _n->color = COLOR_BLACK;

        return _n;
    }
    else
    {
        TreeNode *_new = NULL;

        if (key == root->data)
        {
            TreeNode *_n = new ();
            _n->data = key;
            _n->lchild = root->lchild;
            _n->parent = root;
            root->lchild = _n;

            _new = _n;
        }
        else if (root->data > key)
        {
            if (root->lchild)
            {
                insert(root->lchild, key);
            }
            else
            {
                TreeNode *_n = new ();
                _n->data = key;
                _n->parent = root;
                root->lchild = _n;

                _new = _n;
            }
        }
        else
        {
            if (root->rchild)
            {
                insert(root->rchild, key);
            }
            else
            {
                TreeNode *_n = new ();
                _n->data = key;
                _n->parent = root;
                root->rchild = _n;

                _new = _n;
            }
        }

        // 插入新结点需重新平衡
        if (_new)
            rebalance(_new);
    }

    return root;
}

// 将数据填入数组的指定位置,无数据节点填-1;类似层次遍历
void fill(TreeNode *root, const int index, TreeNode **vl)
{
    if (!root)
    {
        vl[index] = NULL;
        return;
    }

    vl[index] = root;

    fill(root->lchild, (2 * index) + 1, vl);
    fill(root->rchild, (2 * index) + 2, vl);
}

// 获取树高度
int height(TreeNode *root)
{
    if (!root)
        return 0;
    int lh = height(root->lchild);
    int rh = height(root->rchild);

    return lh > rh ? lh + 1 : rh + 1;
}
/**
 * 输出树形结构
*/
void show(TreeNode *root)
{
    if (!root)
        printf("empty tree");

    int _depth = height(root);

    TreeNode *_n = root;

    TreeNode **_vl = (TreeNode *)malloc(sizeof(TreeNode *) * ((1 << (_depth + 1)) - 1));

    memset(_vl, 0, sizeof(TreeNode *) * ((1 << (_depth + 1)) - 1));

    // 将数据填入数组,无数据节点填NULL;类似层次遍历
    fill(_n, 0, _vl);

    for (size_t i = 0; i < _depth; i++)
    {
        int w = 1 << (_depth - i + 1);
        for (size_t j = ((1 << i) - 1); j < ((1 << (i + 1)) - 1); j++)
        {
            TreeNode *_tmp = _vl[j];
            if (NULL == _vl[j])
                printf("%*c%*c", w, '-', w, ' ');
            else if (COLOR_BLACK == _vl[j]->color)
                printf("\033[40;37m %*d%*c \033[0m", w - 1, _vl[j]->data, w - 1, ' ');
            else
                printf("\033[40;31m %*d%*c \033[0m", w - 1, _vl[j]->data, w - 1, ' ');
        }

        printf("\r\n");
    }

    free(_vl);
}

TreeNode *get_root(TreeNode *root)
{
    if (root->parent)
        return get_root(root->parent);
    return root;
}

// 用于调试,判断树形结构是否正确
void check(TreeNode *root)
{
    if (root)
    {
        if (root->lchild)
        {
            if (root != root->lchild->parent)
            {
                printf("error\r\n");
            }
            check(root->lchild);
        }
        if (root->rchild)
        {
            if (root != root->rchild->parent)
            {
                printf("error\r\n");
            }
            check(root->rchild);
        }
    }
}

int main()
{
    TreeNode *root = NULL;
    int vs[] = {1, 11, 5, 2, 3, 23, 32, 6, 7, 8, 9, 22, 100, 4};

    for (size_t i = 0; i < sizeof(vs) / sizeof(int); i++)
    {
        root = insert(root, vs[i]);
        root = get_root(root);
        // check(root);
        // printf("\r\n##################################################################################################################################\r\n");
        show(root);
    }

    // int v;
    // while (scanf("%d", &v))
    // {
    //     root = insert(root, v);

    //     printf("insert ok\r\n");
    //     show(root);
    // }
}

**红黑树通常用于实现map或set,所以不允许有重复值。**若是键值型数据,在插入时找到重复键则直接替换此结点的值。

1.7.1 红黑树删除平衡

/**
 * 红黑树
*/
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>

#define COLOR_BLACK 0
#define COLOR_RED 1

typedef struct sTreeNode TreeNode;

typedef struct sTreeNode
{
    TreeNode *lchild;
    TreeNode *rchild;
    TreeNode *parent;
    int data;
    int color; // 颜色 0 黑色,1 红色
} TreeNode, *PTreeNode;

struct TreeNode *new ()
{
    int _size = sizeof(TreeNode);
    TreeNode *_t = (TreeNode *)malloc(sizeof(TreeNode));
    // if (NULL == _t) // out-of-memory
    // {
    //     return NULL;
    // }
    _t->color = COLOR_RED; // 新结点都是红色的
    _t->lchild = NULL;
    _t->rchild = NULL;
    _t->parent = NULL;
    _t->data = 0;

    return _t;
}

void dispose(TreeNode *_node)
{
    free(_node);
}

// 查找,二叉排序树的查找
struct TreeNode *search(TreeNode *root, int key)
{
    if (!root)
        return NULL;

    if (key == root->data)
        return root;

    if (root->data > key)
        return search(root->lchild, key);

    return search(root->rchild, key);
}

/**
 * 结点 左旋
*/
void turn_left(TreeNode *root)
{
    // 左旋,将父节点调整为
    /**
     * 左旋需要调整4个结点共6个元素
     * 
     * 需调整4个结点:
     * 1. root
     * 2. root 结点的父节点 P
     * 3. root 节点的右子节点 RC
     * 4. RC 结点的左子节点 RC_LC
     * 
     * 需调整6个元素:
     * 1. root 的父结点指针(指向RC)
     * 2. root 的右子结点指针(指向RC_LC)
     * 
     * 3. RC 的父结点指针(指向P)
     * 4. RC 的左子结点指针(指向root)
     * 
     * 5. RC_LC 的父结点指针(指向root)
     * 6. P的左子结点指针或右子结点指针(若root为P的左子结点,则改P的左子结点指向RC,否则右子结点指向RC)
     * 
     * 
     * 
     * 
     * 
     *                P                                     P
     *                 \                                     \
     *                  root              ===>                RC
     *                 /    \                                /   \
     *                *      RC                           root    *
     *                      /  \                         /    \ 
     *                  RC_LC   *                       *      RC_LC
    */

    // 结点为NULL,或右子结点为NULL,不能左旋
    if (!root || !root->rchild)
        return;

    // root是否为其父结点的左子结点
    char root_is_left = 0;
    if (root->parent && root == root->parent->lchild)
        root_is_left = 1;

    // root的父结点
    TreeNode *P = root->parent;
    // root的右子结点
    TreeNode *RC = root->rchild;
    // RC的左子结点
    TreeNode *RC_LC = RC->lchild;

    root->parent = RC;
    root->rchild = RC_LC;

    RC->parent = P;
    RC->lchild = root;

    if (RC_LC)
        RC_LC->parent = root;

    // 调整父结点的指针
    if (P)
        if (root_is_left)
            P->lchild = RC;
        else
            P->rchild = RC;
}

/**
 * 结点 右旋
*/
void turn_right(TreeNode *root)
{
    // 右旋,将父节点调整为右子节点(右子树的根节点,父节点和父节点的右子树组成当前节点右子树);原右子树调整为父节点的左子树
    /**
     * 右旋需要调整4个结点共6个元素
     * 
     * 需调整4个结点:
     * 1. root
     * 2. root 结点的父节点 P
     * 3. root 节点的左子节点 LC
     * 4. LC 结点的右子节点 LC_RC
     * 
     * 需调整6个元素:
     * 1. root 的父结点指针(指向LC)
     * 2. root 的左子结点指针(指向LC_RC)
     * 
     * 3. LC 的父结点指针(指向P)
     * 4. LC 的右子结点指针(指向root)
     * 
     * 5. LC_RC 的父结点指针(指向root)
     * 6. P的左子结点指针或右子结点指针(若root为P的左子结点,则改P的左子结点指向LC,否则右子结点指向LC)
     * 
     * 
     * 
     * 
     * 
     *                P                                     P
     *                 \                                     \
     *                  root              ===>                LC
     *                 /    \                                /   \
     *               LC      *                              *     root
     *              /  \                                        /     \ 
     *             *    LC_RC                                 LC_RC    *
    */

    //  结点为NULL,或左子节点为NULL 不能右旋
    if (!root || !root->lchild)
        return NULL;

    // root是否为其父结点的左子结点
    char root_is_left = 0;
    if (root->parent && root == root->parent->lchild)
        root_is_left = 1;

    // root的父结点
    TreeNode *P = root->parent;
    // root的左子结点
    TreeNode *LC = root->lchild;
    // LC的右子结点
    TreeNode *LC_RC = LC->rchild;

    root->parent = LC;
    root->lchild = LC_RC;

    LC->parent = P;
    LC->rchild = root;

    if (LC_RC)
        LC_RC->parent = root;

    // 调整父结点的指针
    if (P)
        if (root_is_left)
            P->lchild = LC;
        else
            P->rchild = LC;
}

/**
 * 重新平衡,调整插入节点root后的平衡;变色和旋转
*/
void rebalance(TreeNode *root)
{
    if (!root->parent) // root为根节点
    {
        // case 1
        root->color = COLOR_BLACK;
        return;
    }

    // 父结点
    TreeNode *_p = root->parent;
    if (COLOR_BLACK == _p->color) // 插入结点的父结点是黑色,不需要调整平衡
    {
        // case 2
        root->color = COLOR_RED;
        return;
    }

    /* 父结点为红色,则一定存在祖父结点 */

    // 祖父结点
    TreeNode *_pp = _p->parent;
    // 叔叔结点
    TreeNode *_u = NULL;

    // 父结点是祖父结点的左子结点
    char _p_is_left = 0;

    if (_p == _pp->lchild)
    {
        _u = _pp->rchild;
        _p_is_left = 1;
    }
    else
        _u = _pp->lchild;

    if (_u && COLOR_RED == _u->color)
    {
        // case 3.1
        _p->color = _u->color = COLOR_BLACK;
        _pp->color = COLOR_RED;

        rebalance(_pp);
    }
    else
    {
        // case 3.2

        // 当前结点是父结点的左子结点
        char c_is_left = 0;
        if (root == _p->lchild)
            c_is_left = 1;

        if (_p_is_left)
        {
            // case 3.2.1
            if (!c_is_left)
            {
                // case 3.2.1.2
                turn_left(_p);

                // 将父结点调整为插入结点
                TreeNode *_tmp = root;
                root = _p;
                _p = _tmp;
            }

            // case 3.2.1.1
            _p->color = COLOR_BLACK;
            _pp->color = COLOR_RED;
            turn_right(_pp);
        }
        else
        {
            // case 3.2.2

            if (c_is_left)
            {
                // case 3.2.2.2
                turn_right(_p);

                // 将父结点调整为插入结点
                TreeNode *_tmp = root;
                root = _p;
                _p = _tmp;
            }

            // case 3.2.2.1
            _p->color = COLOR_BLACK;
            _pp->color = COLOR_RED;
            turn_left(_pp);
        }
    }
}

/**
 *  插入
 *
*/
TreeNode *insert(TreeNode *root, int key)
{
    if (!root)
    {
        TreeNode *_n = new ();
        _n->data = key;
        _n->color = COLOR_BLACK;

        return _n;
    }
    else
    {
        TreeNode *_new = NULL;

        if (key == root->data)
        {
            TreeNode *_n = new ();
            _n->data = key;
            _n->lchild = root->lchild;
            _n->parent = root;
            root->lchild = _n;

            _new = _n;
        }
        else if (root->data > key)
        {
            if (root->lchild)
            {
                insert(root->lchild, key);
            }
            else
            {
                TreeNode *_n = new ();
                _n->data = key;
                _n->parent = root;
                root->lchild = _n;

                _new = _n;
            }
        }
        else
        {
            if (root->rchild)
            {
                insert(root->rchild, key);
            }
            else
            {
                TreeNode *_n = new ();
                _n->data = key;
                _n->parent = root;
                root->rchild = _n;

                _new = _n;
            }
        }

        // 插入新结点需重新平衡
        if (_new)
            rebalance(_new);
    }

    return root;
}

void reblance_del(TreeNode *node)
{
    if (!node)
        return;

    TreeNode *Tnil = new ();
    Tnil->color = COLOR_BLACK;

    TreeNode *B = NULL; //兄弟结点
    char node_is_left = 0;
    TreeNode *BL = NULL;
    TreeNode *BR = NULL;

    while (node->parent && COLOR_BLACK == node->color)
    {
        if (node == node->parent->lchild)
        {
            node_is_left = 1;
            B = node->parent->rchild;
        }
        else
        {
            node_is_left = 0;
            B = node->parent->lchild;
        }

        BL = B->lchild ? B->lchild : Tnil;
        BR = B->rchild ? B->rchild : Tnil;

        if (node_is_left)
        {
            if (COLOR_RED == B->color)
            {
                B->color = COLOR_BLACK;
                B->parent->color = COLOR_RED; // 父结点和兄弟结点互换颜色
                turn_left(B->parent);         // 兄弟结点变黑色

                B = node->parent->rchild; // 兄弟结点变了
                BL = B->lchild ? B->lchild : Tnil;
                BR = B->rchild ? B->rchild : Tnil;
            }

            if (COLOR_BLACK == BL->color && COLOR_BLACK == BR->color)
            {
                B->color = COLOR_RED; // 两兄弟黑高都-1,以父结点为新的平衡点
                node = node->parent;
            }
            else // 有子节点不为黑色
            {
                if (COLOR_BLACK == BR->color) // 左子结点是红色
                {
                    B->color = COLOR_RED;
                    BL->color = COLOR_BLACK; // B和BL交换颜色

                    turn_right(B);
                    B = node->parent->rchild; // 兄弟结点的右子结点是红色了
                    BL = B->lchild ? B->lchild : Tnil;
                    BR = B->rchild ? B->rchild : Tnil;
                }

                // 兄弟的右子结点是红色
                B->color = B->parent->color;
                B->parent->color = COLOR_BLACK; // 兄弟结点和父结点交换颜色
                BR->color = COLOR_BLACK;
                turn_left(B->parent); // 左旋父结点,完成平衡
                node = Tnil;
            }
        }
        else
        {
            if (COLOR_RED == B->color)
            {
                B->color = COLOR_BLACK;
                B->parent->color = COLOR_RED; // 父结点和兄弟结点互换颜色
                turn_right(B->parent);        // 兄弟结点变黑色

                B = node->parent->lchild; // 兄弟结点变了
                BL = B->lchild ? B->lchild : Tnil;
                BR = B->rchild ? B->rchild : Tnil;
            }

            if (COLOR_BLACK == BL->color && COLOR_BLACK == BR->color)
            {
                B->color = COLOR_RED; // 两兄弟黑高都-1,以父结点为新的平衡点
                node = node->parent;
            }
            else // 有子节点不为黑色
            {
                if (COLOR_BLACK == BL->color) // 右子结点是红色
                {
                    B->color = COLOR_RED;
                    BR->color = COLOR_BLACK; // B和BR交换颜色

                    turn_left(B);
                    B = node->parent->lchild; // 兄弟结点的左子结点是红色了
                    BL = B->lchild ? B->lchild : Tnil;
                    BR = B->rchild ? B->rchild : Tnil;
                }

                // 兄弟的左子结点是红色
                B->color = B->parent->color;
                B->parent->color = COLOR_BLACK; // 兄弟结点和父结点交换颜色
                BL->color = COLOR_BLACK;
                turn_right(B->parent); // 右旋父结点,完成平衡
                node = Tnil;
            }
        }
    }

    node->color = COLOR_BLACK;
}
TreeNode *get_replace_node(TreeNode *node)
{
    // 2. 查找替换结点
    /**
     * 2.1 无子结点,直接删除,替换结点是其本身
     * 2.2 无右子结点,替换结点是其左子结点,用替换结点再查找替换结点
     * 2.3 有右子结点,替换结点是其后继结点,用替换结点再查找替换结点
    */

    if (!node)
        return node;

    if (node->lchild && node->rchild)
    {
#if 1
        // 有右子结点
        TreeNode *_next_node = node->rchild;
        while (_next_node->lchild)
        {
            _next_node = _next_node->lchild;
        }
        return _next_node;
#else
        TreeNode *_next_node = node->lchild;
        while (_next_node->rchild)
        {
            _next_node = _next_node->rchild;
        }
        return _next_node;
#endif
    }
    return node;

#if 0

    if (!node->lchild)
    {
        return get_replace_node(node->rchild);
    }

    TreeNode *_next_node = node->lchild;
    while (_next_node->rchild)
    {
        _next_node = _next_node->rchild;
    }
    return _next_node;

#else
    // if (!node->lchild) // 左子节点为空
    //     return node->rchild;
    // // 没有右子结点
    // else if (!node->rchild)
    // {
    //     return node->lchild;
    // }

    // // 有右子结点
    // TreeNode *_next_node = node->rchild;
    // while (_next_node->lchild)
    // {
    //     _next_node = _next_node->lchild;
    // }

    // return _next_node;
#endif
}

// 将数据填入数组的指定位置,无数据节点填-1;类似层次遍历
void fill(TreeNode *root, const int index, TreeNode **vl)
{
    if (!root)
    {
        vl[index] = NULL;
        return;
    }

    vl[index] = root;

    fill(root->lchild, (2 * index) + 1, vl);
    fill(root->rchild, (2 * index) + 2, vl);
}

// 获取树高度
int height(TreeNode *root)
{
    if (!root)
        return 0;
    int lh = height(root->lchild);
    int rh = height(root->rchild);

    return lh > rh ? lh + 1 : rh + 1;
}
/**
 * 输出树形结构
*/
void show(TreeNode *root)
{
    if (!root)
        printf("empty tree");

    int _depth = height(root);

    TreeNode *_n = root;

    TreeNode **_vl = (TreeNode *)malloc(sizeof(TreeNode *) * ((1 << (_depth + 1)) - 1));

    memset(_vl, 0, sizeof(TreeNode *) * ((1 << (_depth + 1)) - 1));

    // 将数据填入数组,无数据节点填NULL;类似层次遍历
    fill(_n, 0, _vl);

    for (size_t i = 0; i < _depth; i++)
    {
        int w = 1 << (_depth - i + 1);
        for (size_t j = ((1 << i) - 1); j < ((1 << (i + 1)) - 1); j++)
        {
            TreeNode *_tmp = _vl[j];
            if (NULL == _vl[j])
                printf("%*c%*c", w, '-', w, ' ');
            else if (COLOR_BLACK == _vl[j]->color)
                printf("\033[40;37m %*d%*c \033[0m", w - 1, _vl[j]->data, w - 1, ' ');
            else
                printf("\033[40;31m %*d%*c \033[0m", w - 1, _vl[j]->data, w - 1, ' ');
        }

        printf("\r\n");
    }

    free(_vl);
}

TreeNode *get_root(TreeNode *root)
{
    if (root->parent)
        return get_root(root->parent);
    return root;
}

// 用于调试,判断树形结构是否正确
void check(TreeNode *root)
{
    if (root)
    {
        if (root->lchild)
        {
            if (root != root->lchild->parent)
            {
                printf("error\r\n");
            }
            check(root->lchild);
        }
        if (root->rchild)
        {
            if (root != root->rchild->parent)
            {
                printf("error\r\n");
            }
            check(root->rchild);
        }
    }
}

void delete (TreeNode *root, int key)
{
    /**
     * 1. 找到结点
     * 2. 找到替换结点及替换结点的接替结点
     * 3. 用替换结点数据替换删除结点数据,接替结点移到替换结点位置
     * 4. 平衡替换结点(如果替换节点是黑色,需平衡其接替结点)
    */

    // 1. 查找删除结点
    TreeNode *_node = search(root, key);
    if (!_node)
        return; // 未找到结点

    // 2. 查找替换结点
    TreeNode *_rb_node = get_replace_node(_node); // 替换结点最多只有一个子结点(无左子结点,可能有右子结点)

    // 3. 修改数据
    _node->data = _rb_node->data; // 用替换结点数据替换删除结点数据

    TreeNode *__root = get_root(_node);
    printf("\r\n##################################################################################################################################\r\n");
    show(__root);

    if (COLOR_BLACK == _rb_node->color)
        // 4. 平衡替换结点
        reblance_del(_rb_node);

    __root = get_root(_node);
    printf("\r\n##################################################################################################################################\r\n");
    show(__root);

#if 0
    // 5. 删除替换结点(替换结点一定没有左子结点,可能有右子结点)
   
    TreeNode *P = _rb_node->parent;
    TreeNode *RC = _rb_node->rchild;
    if (_rb_node == P->lchild)
    {
        P->lchild = NULL;
        if (RC)
        {
            RC->parent = P;
            P->lchild = RC;
        }
        free(_rb_node);
    }
    else
    {
        P->rchild = NULL;
        if (RC)
        {
            RC->parent = P;
            P->rchild = RC;
        }
        free(_rb_node);
    }

#else

    // 5. 删除替换结点
    TreeNode *P = _rb_node->parent;
    TreeNode *LC = _rb_node->lchild;
    TreeNode *RC = _rb_node->rchild;
    if (!P)
    {
        // 删除的是根结点,最多只有一个子结点
        if (!RC && !LC) // 没有子结点
        {
            // 删掉就没了
            root->data = -1;
        }
        else if (!LC) // 没有左子结点
        {
            /* code */

            // root->color = COLOR_BLACK;
            root->data = RC->data;
            root->lchild = NULL;
            root->rchild = NULL;
            free(RC);
        }
        else
        {
            // root->color = COLOR_BLACK;
            root->data = LC->data;
            root->lchild = NULL;
            root->rchild = NULL;
            free(LC);
        }
    }
    else if (_rb_node == P->lchild)
    {
        P->lchild = NULL;
        if (LC)
        {
            LC->parent = P;
            P->lchild = LC;
        }
        else if (RC)
        {
            RC->parent = P;
            P->lchild = RC;
        }

        free(_rb_node);
    }
    else
    {
        P->rchild = NULL;
        if (LC)
        {
            LC->parent = P;
            P->rchild = LC;
        }
        else if (RC)
        {
            RC->parent = P;
            P->rchild = RC;
        }
        free(_rb_node);
    }
#endif

    // __root = get_root(_node);
    // printf("\r\n##################################################################################################################################\r\n");
    // show(__root);
}

int main()
{
    TreeNode *root = NULL;
    int vs[] = {1, 11, 5, 2, 3, 23, 32, 6, 7, 8, 9, 22, 100, 4};

    for (size_t i = 0; i < sizeof(vs) / sizeof(int); i++)
    {
        root = insert(root, vs[i]);
        root = get_root(root);
        // check(root);
        // printf("\r\n##################################################################################################################################\r\n");
        // show(root);
    }
    show(root);
    // int v;
    // while (scanf("%d", &v))
    // {
    //     root = insert(root, v);

    //     // printf("insert ok\r\n");
    //     printf("\r\n##################################################################################################################################\r\n");
    //     show(root);
    // }

    int v;
    while (scanf("%d", &v))
    {
        delete (root, v);
        // printf("insert ok\r\n");
        root = get_root(root);
        // printf("insert ok\r\n");
        printf("\r\n##################################################################################################################################\r\n");
        show(root);
    }

    // delete (root, 7);

    // root = get_root(root);
    // // printf("insert ok\r\n");
    // printf("\r\n##################################################################################################################################\r\n");
    // show(root);
}

1.5 树和森林

1.6 哈夫曼树

    最优二叉树,带权路径长度最小的树,最适合用于做无损压缩编码(哈夫曼编码)。没有
    哈夫曼树和哈夫曼编码
  • 权越大离根结点越近
  • 没有度为1的结点(没有只有一颗子树的节点)

struct elemtype
{
    /* data */
};

// 二叉链表
struct dtreenode
{
    elemtype data;
    dtreenode *lchild; //左子节点
    dtreenode *rchild; //右子节点
};

// 二叉链表
struct ttreenode
{
    elemtype data;
    ttreenode *parent; //父节点
    ttreenode *lchild; //左子节点
    ttreenode *rchild; //右子节点
};

1.7 红黑树

1.8 平衡二叉树

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值