二叉排序树
二叉排序树具有以下性质:
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值。
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值。
- 它的左、右子树也分别为二叉排序树。
我们只需要对它进行中序遍历,就可以得到一个有序的序列。并且使用二叉排序树更加方便我们查找和插入和删除结点。
为什么不直接使用链表呢?
因为在查找时,链表的时间复杂度为o(n),而二叉排序树的时间复杂度为o(log n)
代码部分
/*
* @Author: Xyh4ng
* @Date: 2022-11-26 19:28:58
* @LastEditors: Xyh4ng
* @LastEditTime: 2022-11-26 22:30:58
* @Description:
* Copyright (c) 2022 by Xyh4ng 503177404@qq.com, All Rights Reserved.
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct BSTNode
{
int data;
struct BSTNode *lchild, *rchild;
} BSTNode, *BSTree;
// 查找
int SearchBST(BSTree T, int key, BSTree f, BSTree *p)
{
if (!T)
{
*p = f;
return 0;
}
else if (key < T->data)
{
return SearchBST(T->lchild, key, T, p);
}
else if (key > T->data)
{
return SearchBST(T->rchild, key, T, p);
}
else
{
*p = T;
return 1;
}
}
// 插入
void InsertBST(BSTree *T, int key)
{
BSTree p, n;
if (SearchBST(*T, key, NULL, &p) == 0)
{
n = (BSTree)malloc(sizeof(BSTNode));
n->data = key;
n->lchild = NULL;
n->rchild = NULL;
if (!p)
*T = n;
else if (key < p->data)
p->lchild = n;
else
p->rchild = n;
}
}
void MidTraversal(BSTree T)
{
if (!T)
{
return;
}
else
{
MidTraversal(T->lchild);
printf("%d, ", T->data);
MidTraversal(T->rchild);
}
}
// 删除
void DeleteNode(BSTree *p)
{
BSTree q, s;
if (!(*p)->lchild)
{
q = *p;
*p = (*p)->rchild;
free(q);
}
else if (!(*p)->rchild)
{
q = *p;
*p = (*p)->lchild;
free(q);
}
else
{
q = *p;
s = (*p)->lchild;
while (s->rchild)
{
q = s;
s = s->rchild;
}
(*p)->data = s->data;
// 此时s指向p结点中序遍历时的前驱结点,q指向s结点的双亲结点
if (q != *p)
{
q->rchild = s->lchild;
}
else
{
q->lchild = s->lchild;
}
free(s);
}
}
void DeleteBST(BSTree *T, int key)
{
if (*T)
{
if ((*T)->data == key)
{
DeleteNode(T);
}
else if ((*T)->data < key)
{
DeleteBST(&(*T)->rchild, key);
}
else
{
DeleteBST(&(*T)->lchild, key);
}
}
}
int main()
{
int a[10] = {62, 88, 58, 47, 35, 73, 51, 99, 37, 93};
BSTree T = NULL;
for (int i = 0; i < 10; i++)
{
InsertBST(&T, a[i]);
}
MidTraversal(T);
printf("\n");
DeleteBST(&T, 88);
MidTraversal(T);
return 0;
}