从0开始学习数据结构-树与二叉树-二叉排序树①

113 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第23天,点击查看活动详情

二叉排序树

顾名思义,二叉排序树可以用于排序,也可以用于查找(或者称检索)。利用二叉排序树可以大大提高查找的时间效率,因此,二叉排序树也称为二叉查找树。

二叉排序树的定义

二叉排序树(binary sort tree)是一棵二叉树,若根结点的左子树不空,则左子树中所有结点的值均小于根结点的值;若根结点的右子树不空,则右子树中所有结点的值均大于或者等于根结点的值。每一棵子树也同样具有上述特性,即二叉排序树中的任何一棵子树也是一棵二叉排序树。

二叉排序树的建立(插入)

通常采用逐点插人结点的方法来构造二叉排序树。现将逐点插入法表述如下:

image.png

此插入法的表述存在一个疑问,就是,新节点插在某个叶节点的下面,成为一个新的叶节点。一定要插在叶节点下面吗?比如插在一个有左子树无右节点的节点。如下图,在10节点的右侧插入20.

image.png

很容易想到,对于给定的一个数据元素序列,若元素插入到二叉树的次序不同,则所建立的二叉排序树的形式也就不同。下面给出建立二叉排序树的非递归算法(设二叉排序树采用二叉链表存储结构)。

BTREE SORTTREE(datatype K[], int n) {
    void INSERTBST(BTREE *T, datatype item);

    BTREE T = NULL;
    if (n > 0) {
        for (int i = 0; i < n; ++i) {
            INSERTBST(&T, K[i]);
        }
    }
    return T;
}

void INSERTBST(BTREE *T, datatype item) {
    BTREE p, q;
    p = (BTREE) malloc(sizeof(BTNode));
    p->data = item;
    p->lchild = NULL;
    p->rchild = NULL;
    if ((*T) == NULL)
        *T = p;
    else {
        q = (*T);
        while (1) {
            if (item < q->data) {
                if (q->lchild != NULL)
                    q = q->lchild;
                else {
                    q->lchild = p;
                    break;
                }
            } else {
                if (q->rchild != NULL)
                    q = q->rchild;
                else {
                    q->rchild = p;
                    break;
                }
            }
        }
    }
}

递归算法:

//递归算法
void INSERTBST1(BTREE *T, datatype item) {
    if ((*T) == NULL) {
        (*T) = (BTREE) malloc(sizeof(BTNode));
        (*T)->data = item;
        (*T)->lchild = NULL;
        (*T)->rchild = NULL;
    } else if (item < (*T)->data)
        INSERTBST1(&((*T)->lchild), item);
    else
        INSERTBST1(&((*T)->rchild), item);
}

按照二叉排序树的定义,在上述插入算法中,值相同的数据元素插入到结点的右子树中。可以设想,如果这样的数据元素越多,二叉树的深度会变得越大,在后面的讨论中可以看到,这将会降低查找操作的效率。一个解决的方法是适当增加二叉树的存储空间开销,即在链结点中增加一个域以指示相同元素发生的频率。当然,如果数据元素集合只是一个更大结构的一部分,则该方法也有问题。此时可以把相同数据元素保留在一个辅助数据结构中,例如一个表或者另一棵二叉排序树中。

有趣的是,数据元素序列K一般不一定是一个按值排序的序列,但将其构造为一棵二叉排序树以后,对该二叉排序树进行中序遍历,得到的中序遍历序列却是一个按值排序的序列。这就是说,一个元素序列可以通过构造二叉排序树,然后对二叉排序树进行中序遍历而转化为一个有序序列。