数据结构·二叉排序树(创建、插入、删除)

446 阅读3分钟

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

什么是二叉排序树:

二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree),亦称二叉搜索树。是中的一类。在一般情况下,查询效率比链表结构要高。

二叉排序树的定义:

二叉排序树要么是一颗空树要么满足以下性质:
1.若它的左子树非空,则左子树上的所有结点值都要小于它的根节点的值
2.若它的右子树非空,则右子树上的所有结点值都要小于它的根节点的值
3.它的左右子树都需要满足性质1和2

操作方向:

实现排序二叉树的创建、插入、删除结点等操作

操作思路:

  • 1.首先我们要知道的是——排序二叉树其实是二叉树的一种
  • 2.先创建一个BSTNode的结点,结点包含了数据域和指针域,指针域包含了两个指针——lchild和rchild
  • 3.排序二叉树的核心是它的创建过程,我们需要有对应的代码来实现创建的操作
  • 4.对于树的结构,很多都是递归的思想,读者需要熟悉递归的思维~

Graph:

image.png 这是一颗标准的排序二叉树,我将会以此为实例来对排序二叉树进行操作。

定义结点:

//定义二叉排序树结点
struct BSTNode
{
    int data;
    BSTNode* lchild;
    BSTNode* rchild;
};

插入函数

//插入函数
void Insert(BSTNode*& T, int data) {//因为要不断地改变指针,所以要用二级指针
    BSTNode* s;
    //如果是空树的话,直接插入到根节点
    if (!T) {
        s = new BSTNode;
        s->data = data;
	s->lchild = s->rchild = NULL;
	T = s;
    }
    else if (data < T->data) {//如果小于根节点则往左继续递归
	Insert(T->lchild, data);
    }
    else if (data > T->data) {//如果大于根节点则往右继续递归
        Insert(T->rchild, data);
    }
}

创建排序二叉树

//创建二叉树函数
void CreatBSTree(BSTNode*& T) {
    T = new BSTNode;
    T = NULL;//要先赋NULL值
    int n;
    cout << "请输入n个整数,代表二叉排序树的结点个数:";
    cin >> n;
    int data;
    for (int i = 0; i < n; i++) {
        cout << "现在请输入第" << i + 1 << "个结点的data值:";
        cin >> data;
	Insert(T, data);
    }
    cout << "二叉树创建成功!" << endl;
}

搜索函数

//搜索函数
BSTNode* SearchBST(BSTNode* T, int key) {
    if (!T || key == T->data)
	return T;
    else if (key < T->data)
	SearchBST(T->lchild, key);
    else
	SearchBST(T->rchild, key);
}

删除函数(比较难,如果只是为了创建二叉树可以忽略)

//删除函数
void DeleteBST(BSTNode* T, int key) {
    //初始化
    BSTNode* p = T;
    BSTNode* f = NULL;
    BSTNode* q = NULL;
    //循环找p->data==key的值,以及它的双亲结点
    while (p) {
	if (key == p->data)
            break;
            f = p;//f为p的双亲结点
            //在左子树找
	if (key < p->data)
            p = p->lchild;
            //在右子树找
	else
            p = p->rchild;
    }
    //如果没找到
    if (!p)
	return;
    //考虑三种情况:左右都不为空、左子树不为空、右子树不为空
    q = p;
    //1.左右都不为空
    if ((p->lchild) && (p->rchild)) {
	BSTNode* s = p->lchild;
	q = p;
	//找到左子树的最右结点,即其直接前驱
	while (s->rchild) {
            q = s;
            s = s->rchild;
	}
	p->data = s->data;//令*p的直接前驱代替*p,即s代替p
	if (q != p)
            q->rchild = s->lchild;//重接*q的右子树
	else
            q->lchild = s->lchild;//重接*q的左子树
            delete s;
	return;
    }
    //2.没有右子树
    else if (p->lchild) {
	//置换
	q = p;//q指向要删除的结点
	p = p->lchild;//p指向它的左孩子
    }
    //3.没有左子树
    else if (p->rchild) {
	//置换
	q = p;//q指向要删除的结点
	p = p->rchild;//p指向它的右孩子
    }
    //4.是叶子结点
    else if (!p->lchild && !p->rchild) {
        //置换
	q = p;
	p = NULL;
    }
    //开始重接删除结点的左孩子或右孩子
    if (!f)
	T = p;//删除的是根节点
    else if (q == f->lchild)
	f->lchild = p;
    else if (q == f->rchild)
	f->rchild = p;
    delete q;
}

测试样例:

10
66
12
5
80
1
66
30
100
71
3
30
50

代码:

由于代码篇幅比较大,请读者点击——数据结构——排序二叉树总代码部分 - 掘金 (juejin.cn)

结果演示:

image.png