二叉排序树
性质
数据结构,就是定义一种形值,并维护这种性质的数据结构
插入操作
删除操作
对于度为2的节点:
随堂练习题
按照如下顺序插入数字,画出对应的二叉搜索树
- [ 5 9 8 3 2 4 1 7 ]
- [1 2 3 4 5 ]
- [3 4 5 1 2 ]
平均查找效率:节点查找次数的期望值(假设每个节点等概率被查找) 总 次 数 节 点 数 量 \frac{总次数}{节点数量} 节点数量总次数
扩展内容
思考:快速排序与二叉排序树在思维逻辑结构上有什么相同点,对照二叉排序树的性质和快速排序算法的partition操作
代码实现
#include <stdio.h>
#include <stdlib.h>
#define KEY(root) (root ? root->key : 0)
#define SIZE(root) (root ? root->size : 0)
#define L(root) (root ? root->lchild : NULL)
typedef struct Node {
int key;
int size; // 排名问题
struct Node *lchild, *rchild;
} Node;
Node *getNewNode(int val) {
Node *p = (Node *)malloc(sizeof(Node));
p->key = val;
p->size = 1; // 排名问题
p->lchild = p->rchild = NULL;
return p;
}
int search(Node *root, int val) {
if (root == NULL) return 0;
if (root->key == val) return 1;
if (val < root->key) return search(root->lchild, val);
return search(root->rchild, val);
}
void update_size(Node *root) { // 排名问题
root->size = SIZE(root->lchild) + SIZE(root->rchild) + 1;
return ;
}
Node *insert(Node *root, int val) {
if (root == NULL) return getNewNode(val);
if (root->key == val) return root;
if (val < root->key) root->lchild = insert(root->lchild, val);
else root->rchild = insert(root->rchild, val);
update_size(root); // 排名问题
return root;
}
Node *predecessor(Node *root) {
Node *temp = root->lchild;
while (temp->rchild) temp = temp->rchild;
return temp;
}
Node *earse(Node *root, int val) {
if (root == NULL) return NULL;
if (val < root->key) {
root->lchild = earse(root->lchild, val);
} else if (val > root->key) {
root->rchild = earse(root->rchild, val);
} else {
if (root->lchild == NULL && root->rchild == NULL) {
free(root);
return NULL;
} else if (root->lchild == NULL || root->rchild == NULL) {
Node *temp = root->lchild ? root->lchild : root->rchild;
free(root);
return temp;
} else {
Node *temp = predecessor(root);
root->key = temp->key;
root->lchild = earse(root->lchild, temp->key);
}
}
update_size(root); // 排名问题
return root;
}
void output(Node *root) {
if (root == NULL) return ;
output(root->lchild);
printf("%d(%d, %d)\n", KEY(root), KEY(root->lchild), KEY(root->rchild));
output(root->rchild);
return ;
}
void pre_output(Node *root) {
if (root == NULL) return ;
printf("%d(%d, %d)\n", KEY(root), KEY(root->lchild), KEY(root->rchild));
pre_output(root->lchild);
pre_output(root->rchild);
return ;
}
int search_k(Node *root, int k) { // 排名问题
if (root == NULL) return -1;
if (SIZE(L(root)) == k - 1) return root->key;
if (k <= SIZE(L(root))) {
return search_k(root->lchild, k);
}
return search_k(root->rchild, k - SIZE(L(root)) - 1);
}
void print(Node *root) {
printf("%d(%d, %d)\n", KEY(root), KEY(root->lchild), KEY(root->rchild));
return ;
}
void output_k(Node *root, int k) { // top-k 出输前k
if (k == 0 || root == NULL) return ;
if (k <= SIZE(L(root))) {
output_k(root->lchild, k);
} else {
output(root->lchild);
print(root);
output_k(root->rchild, k - SIZE(L(root)) - 1);
}
return ;
}
void clear(Node *root) {
if (root == NULL) return ;
clear(root->lchild);
clear(root->rchild);
free(root);
return ;
}
int main() {
int op, val;
Node *root = NULL;
while (~scanf("%d%d", &op, &val)) {
switch (op) {
case 0: printf("search %d, result = %d\n", val, search(root, val)); break;
case 1: root = insert(root, val); break;
case 2: root = earse(root, val); break;
case 3:{
printf("search_k %d, result = %d\n", val, search_k(root, val));
} break;
case 4: {
printf("output_k top-%d elements\n", val);
output_k(root, val);
printf("+++++++++++++++++++++\n");
}
}
if (op == 1 || op == 2) {
output(root);
printf("-----------------------------\n");
}
}
printf("============================\n");
pre_output(root);
printf("============================\n");
clear(root);
return 0;
}