二叉排序树

二叉排序树

什么是二叉排序树、

二叉排序树要么是空二叉树,要么具有如下性质:

二叉排序树中,如果其根结点有左子树,那么左子树上所有结点的值都小于根结点的值;
二叉排序树中,如果其根结点有右子树,那么右子树上所有结点的值都大于根结点的值;
二叉排序树的左右子树也要求都是二叉排序树.

例子

image
根据以上性质,我们得知二叉排序树的中序遍历是一个有序序列(升序),如上图中序遍历得到的序列为:1 2 10 14 18 20 22

结构定义

struct Node {
    int key;
    Node *lchild, *rchild;
};

节点初始化

我们定义一个函数Node* getNewNode(int key),其传入参数是一个key,返回值为一个节点地址,表示初始化一个具体key值的节点,这里是为了给插入节点函数服务所实现的。

Node *getNewNode(int key) {
    Node *p = (Node *)malloc(sizeof(Node));
    p->key = key;
    p->lchild = p->rchild = NIL;
}

插入操作

根据上面二叉排序树的性质1和性质2,当我们往一个二叉排序树种插入一个节点时,当要插入的节点的key值小于根节点的key值,则递归插入到根节点的左子树;若要插入的节点的key值大于根节点的key值,则递归插入到根节点的右子树;若二叉排序树中存在与要插入节点一样key值得节点,则不插入并返回该节点的地址。由于性质决定,插入的新节点,一定会是二叉排序树的叶子节点。

代码

Node *insert(Node *root, int key) {
    //root是空,则表明从根节点遍历到这个空节点都没有找到与参数key值一样的节点,可以在这里插入新节点,且插入后该节点为叶子节点
    if (root == NULL) {
        return getNewNode(key);
    }
    if (key == root->key) {//这里不重复插入相同key值得节点
        return root;
    }
    if (key < root->key) {//若插入key比当前节点的key小,则递归到当前节点的左子树中去插入
        root->lchild = insert(root->lchild, key);
    } else (key > root->key) {//若插入key比当前节点的key大,则递归到当前节点的右子树中去插入
        root->rchild = insert(root->rchild, key);
    }
    return root;
}

删除操作

根据删除节点的度来区分,我们可以把删除操作主要分为三个部分,:

删除度为0的节点 -> 直接删除
删除度为1的节点 -> 把删除节点的孤儿节点挂到自己的位置上
删除度为2的节点 -> 转化为删除要删除节点的前驱或者后继

对于度为2的节点:
前驱 -> 左子树的最大值
后继 -> 右子树的最小值
删除度为2的例子
比如我们想删除节点23,节点23度为2,这时候我们找到它的前驱节点19,把前驱节点的key值填到23节点的位置,再删除23的前驱节点19。
image

代码

求出某个节点前驱的代码

//传入某个节点的地址root,然后求出root节点的前驱节点的地址,并返回
Node *prodecessor(Node *root) {
    Node *p = root->lchild;
    while (p->rchild != NULL) {
        p = p->rchild;
    }
    return p;
}

删除节点代码

Node *erase(Node *root, int key) {
    //root是空,则表明从根节点遍历到这个空节点都没有找到与参数key值一样的节点,直接返回
    if (root == NULL) {
        return root;
    }
    if (key < root->key) {//key值小于当前节点的key,则要删除的点在root的左子树上
        root->lchild = erase(root->lchild, key);
    } else if (key > root->key) {//key值大于当前节点的key,则要删除的点在root的左子树上
        root->rchild = erase(root->rchild, key);
    } else {//key值与当前节点的key一样,则以度的数量开始区分删除情况。
        if (root->lchild == NULL && root->rchild == NULL) {//度为0:直接删除
            free(root);;
            return NULL;
        } else if (root->lchild == NULL || root->rchild == NULL) {//度为1:直接返回孤儿节点的地址给自身
            Node *temp = root->lchild == NULL ? root->rchild : root->lchild;
            free(root);
            return temp;
        } else {//度为2:直接转化为删除该节点的前驱节点
            Node *temp = predecessor(root);
            root->key = temp->key;
            root->lchild = erase(root->lchild, temp->key);
        }
    }
    return root;
}

遍历二叉排序树

这里我们采用中序遍历的方式遍历二叉排序树。

void in_order(Node *root) {
    if (root == NULL) {
        return ;
    }
    in_order(root->lchild);
    printf("%d ", root->key);
    in_order(root->rchild);
    return ;
}

完整代码

这里我们给出完整代码,该代码带有测试程序,首先根据提示,有选择操作的选项,输入1表示插入操作;输入2表示删除操作,选择完操作后,需要输入一个key,然后每次操作完毕,都会中序遍历输出该二叉排序树的所有节点。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define KEY(n) (n ? n->key : -1)

typedef struct Node {
    int key;
    struct Node *lchild, *rchild;
} Node;

Node *getNewNode(int key) {
    Node *p = (Node *)malloc(sizeof(Node));
    p->key = key;
    p->lchild = p->rchild = NULL;
}

void clear(Node *root) {
    if (root == NULL) {
        return ;
    }
    clear(root->lchild);
    clear(root->rchild);
    free(root);
    return ;
}

Node *insert(Node *root, int key) {
    //root是空,则表明从根节点遍历到这个空节点都没有找到与参数key值一样的节点,可以在这里插入新节点,且插入后该节点为叶子节点
    if (root == NULL) {
        return getNewNode(key);
    }
    if (root->key == key) {//这里不重复插入相同key值得节点
        return root;
    }
    if (key < root->key) {//若插入key比当前节点的key小,则递归到当前节点的左子树中去插入
        root->lchild = insert(root->lchild, key);
    } else {//若插入key比当前节点的key大,则递归到当前节点的右子树中去插入
        root->rchild = insert(root->rchild, key);
    }
    return root;
}


Node *prodecessor(Node *root) {
    Node *p = root->lchild;
    while (p->rchild != NULL) {
        p = p->rchild;
    }
    return p;
}

Node *erase(Node *root, int key) {
    //root是空,则表明从根节点遍历到这个空节点都没有找到与参数key值一样的节点,直接返回
    if (root == NULL) {
        return root;
    }
    if (key < root->key) {//key值小于当前节点的key,则要删除的点在root的左子树上
        root->lchild = erase(root->lchild, key);
    } else if (key > root->key){//key值大于当前节点的key,则要删除的点在root的左子树上
        root->rchild = erase(root->rchild, key);
    } else {//key值与当前节点的key一样,则以度的数量开始区分删除情况。
        if (root->lchild == NULL && root->rchild == NULL) {//度为0:直接删除
            free(root);
            return NULL;
        } else if (root->lchild == NULL || root->rchild == NULL) {//度为1:直接返回孤儿节点的地址给自身
            Node *p = root->lchild == NULL ? root->rchild : root->lchild;
            free(root);
            return p;
        } else {//度为2:直接转化为删除该节点的前驱节点
            Node *p = prodecessor(root);
            root->key = p->key;
            root->lchild = erase(root->lchild, p->key);
        }
    }
    return root;
}

void print_node(Node *root) {
    printf("(%d: %d, %d)\n", KEY(root), KEY(root->lchild), KEY(root->rchild));
}

void _in_order(Node *root) {
    if (root == NULL) {
        return ;
    }
    _in_order(root->lchild);
    print_node(root);
    _in_order(root->rchild);
    return ;
}

void in_order(Node *root) {
    printf("binary tree:\n");
    _in_order(root);
    printf("\n\n");
}

void menu(void) {
    printf("Please enter the operation: \n");
    printf("Press 1 to insert a node to binary search tree\n");
    printf("Press 2 to delete a node from binary search tree\n");
    printf("Press TRL + D to quit!\n");
}

int main() {
    Node *root = NULL;
    int op, key;
    menu();
    while (~scanf("%d", &op)) {
        if (op != 1 && op != 2) {
            printf("please enter the right operation!\n");
            continue;
        }
        switch (op) {
            case 1:
                printf("Enter the key you want to insert: ");
                scanf("%d", &key);
                root = insert(root, key);
            break;

            case 2:
                printf("Enter the key you want to delete: ");
                scanf("%d", &key);
                root = erase(root, key);
            break;
        }
        in_order(root);
        menu();
    }
    clear(root);
    return 0;
}

测试结果

Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press TRL + D to quit!
1
Enter the key you want to insert: 12
binary tree:
(12: -1, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press TRL + D to quit!
1
Enter the key you want to insert: 8
binary tree:
(8: -1, -1)
(12: 8, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press TRL + D to quit!
1
Enter the key you want to insert: 34
binary tree:
(8: -1, -1)
(12: 8, 34)
(34: -1, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press TRL + D to quit!
1
Enter the key you want to insert: 56
binary tree:
(8: -1, -1)
(12: 8, 34)
(34: -1, 56)
(56: -1, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press TRL + D to quit!
2 12
Enter the key you want to delete: binary tree:
(8: -1, 34)
(34: -1, 56)
(56: -1, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press TRL + D to quit!
1 12
Enter the key you want to insert: binary tree:
(8: -1, 34)
(12: -1, -1)
(34: 12, 56)
(56: -1, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press TRL + D to quit!

思考

如果我们分别进行两棵二叉排序树的插入构建。其中插入到这两棵树的节点的key和节点数量完全相同,唯一不同的是插入顺序不同,例如:
第一棵树按一下顺序插入6个元素: 6 9 3 2 7 5
第二棵树按以下顺序插入6个元素: 2 3 5 6 7 9
查找一个元素的时间复杂度一样吗?
这里,我们先直接画出这两棵树
第一棵
image
第二棵
image
这里的时候,第一棵二叉排序树的元素平均查找期望是(1+2*2+3*3)/6 = 5/2,大致是O(logN)级别的时间复杂度;而第二棵树的凭据查找期望是(1+2+3+4+5+6)/6 = 7/3,且这很明显,这里第二颗树已经退化成链表,这时候它的查找效率是O(N),而对比第一棵树,由于是一棵完全二叉树,其查找效率在O(logN)。由此,我们可以下定结论:

  1. 插入顺序会影响最终的树形结构
  2. 不同的树形结构,查找效率不同

为了解决以上二叉排序树会退化成链表,导致查找效率变低的情况,在二叉排序树的基础上,二叉平衡树诞生了。

拓展

二叉排序树的删除代码优化

删除掉处理度为0的代码逻辑,不影响代码整体功能

Node *erase(Node *root, int key) {
    //root是空,则表明从根节点遍历到这个空节点都没有找到与参数key值一样的节点,直接返回
    if (root == NULL) {
        return root;
    }
    if (key < root->key) {//key值小于当前节点的key,则要删除的点在root的左子树上
        root->lchild = erase(root->lchild, key);
    } else if (key > root->key) {//key值大于当前节点的key,则要删除的点在root的左子树上
        root->rchild = erase(root->rchild, key);
    } else {//key值与当前节点的key一样,则以度的数量开始区分删除情况。
        if (root->lchild == NULL || root->rchild == NULL) {//删除度为0或者1都可以这个分支。
            Node *temp = root->lchild == NULL ? root->rchild : root->lchild;
            delete root;
            return temp;
        } else {//度为2:直接转化为删除该节点的前驱节点
            Node *temp = predecessor(root);
            root->key = temp->key;
            root->lchild = erase(root->lchild, temp->key);
        }
    }
    return root;
}

如何解决排名相关的检索需求

  1. 修改二叉排序树的结构定义,增加 size 字段,记录每棵树的节点数量
  2. 若K = LS + 1,则根节点就是排名第 k 位的元素
  3. 若K <= LS,则排名第 K 位的元素在左子树中
  4. 若K > LS + 1,则排名第 k 位的元素在右子树中
    PS:LS指某个节点的左子树节点数量

带排名版本的二叉排序树

结构定义
typedef struct Node {
    int key, size;
    struct Node *lchild, *rchild;
} Node;

在结构定义中,增加了size字段名,用来记录每个子树的节点数量。

节点初始化
Node *getNewNode(int key) {
    Node *p = (Node *)malloc(sizeof(Node));
    p->key = key;
    p->size = 1;
    p->lchild = p->rchild = NULL;
}

节点初始化,由于增加了size字段,同样的,节点初始化的时候,size字段也要初始化为1.

子树节点数量更新函数
void update_size(Node *root) {
    root->size = SIZE(root->lchild) + SIZE(root->rchild) + 1;
}

每一个根节点的节点数量为其左右子树节点数的和加1。

插入
Node *insert(Node *root, int key) {
    //root是空,则表明从根节点遍历到这个空节点都没有找到与参数key值一样的节点,可以在这里插入新节点,且插入后该节点为叶子节点
    if (root == NULL) {
        return getNewNode(key);
    }
    if (root->key == key) {//这里不重复插入相同key值得节点
        return root;
    }
    if (key < root->key) {//若插入key比当前节点的key小,则递归到当前节点的左子树中去插入
        root->lchild = insert(root->lchild, key);
    } else {//若插入key比当前节点的key大,则递归到当前节点的右子树中去插入
        root->rchild = insert(root->rchild, key);
    }
    update_size(root);//更新节点数量
    return root;
}

在插入操作返回前,必须先更新节点数量。

删除
Node *erase(Node *root, int key) {
    //root是空,则表明从根节点遍历到这个空节点都没有找到与参数key值一样的节点,直接返回
    if (root == NULL) {
        return root;
    }
    if (key < root->key) {//key值小于当前节点的key,则要删除的点在root的左子树上
        root->lchild = erase(root->lchild, key);
    } else if (key > root->key){//key值大于当前节点的key,则要删除的点在root的左子树上
        root->rchild = erase(root->rchild, key);
    } else {//key值与当前节点的key一样,则以度的数量开始区分删除情况。
        if (root->lchild == NULL || root->rchild == NULL) {//删除度为0或者1都可以这个分支。
            Node *p = root->lchild == NULL ? root->rchild : root->lchild;
            free(root);
            return p;
        } else {////度为2:直接转化为删除该节点的前驱节点
            Node *p = prodecessor(root);
            root->key = p->key;
            root->lchild = erase(root->lchild, p->key);
        }
    }
    update_size(root);//更新节点数量
    return root;
}

同样的,在删除操作返回前,也要更新节点数量。

注意

无论是插入还是删除,之所以在返回root节点前更新节点数量,这是因为插入和删除只会影响到回溯时经过的节点(也就是插入节点的祖先节点)对应的子树的节点数量。

查找第K位元素
int find_k(Node *root, int k) {
    if (root == NULL || k == 0) {
        return -1;
    }
    if (k == SIZE(root->lchild) + 1) {//若root节点的左子树节点数量 + 1等于 k,则root节点就是第K个节点
        return root->key;
    }
    if (k <= SIZE(root->lchild)) {//若root节点的左子树节点数量大于等于k,则递归到左子树中去找第K个节点
        return find_k(root->lchild, k);
    }
    //若root左子树节点数量 + 1小于K,则递归到右子树中去找右子树中第K - size(L(root)) - 1个节点。
    if (k > SIZE(root->lchild) + 1) {
        return find_k(root->rchild, k - SIZE(root->lchild) - 1);
    }
}
宏定义
#define KEY(n) (n ? n->key : -1)//返回某个节点的key值
#define SIZE(n) (n ? n->size : 0)//返回某个节点对应的树的节点数量

解决 Top-K 问题(找到小于第 k 位的所有元素)

  1. 根节点就是第 k 位元素的话,就把左子树中的值全部输出出来
  2. 第 k 位在左子树中,前 k 位元素全都在左子树中
  3. 第 k 位在右子树中,说明根节点和左子树中的元素,都是前 k 位元素里面的值
void output_k(Node *root, int k) {
    if (root == NULL || k <= 0) {
        return ;
    }
    if (k == SIZE(root->lchild)) {
        _in_order(root->lchild);
    } else if (k < SIZE(root->lchild)) {
        output_k(root->lchild, k);
    } else {
        _in_order(root->lchild);
        print_node(root);
        output_k(root->rchild, k - SIZE(root->lchild) - 1);
    }
}

加上拓展后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define KEY(n) (n ? n->key : -1)
#define SIZE(n) (n ? n->size : 0)

typedef struct Node {
    int key, size;
    struct Node *lchild, *rchild;
} Node;

Node *getNewNode(int key) {
    Node *p = (Node *)malloc(sizeof(Node));
    p->key = key;
    p->size = 1;
    p->lchild = p->rchild = NULL;
}

void clear(Node *root) {
    if (root == NULL) {
        return ;
    }
    clear(root->lchild);
    clear(root->rchild);
    free(root);
    return ;
}

void update_size(Node *root) {
    root->size = SIZE(root->lchild) + SIZE(root->rchild) + 1;
}

Node *insert(Node *root, int key) {
    //root是空,则表明从根节点遍历到这个空节点都没有找到与参数key值一样的节点,可以在这里插入新节点,且插入后该节点为叶子节点
    if (root == NULL) {
        return getNewNode(key);
    }
    if (root->key == key) {//这里不重复插入相同key值得节点
        return root;
    }
    if (key < root->key) {//若插入key比当前节点的key小,则递归到当前节点的左子树中去插入
        root->lchild = insert(root->lchild, key);
    } else {//若插入key比当前节点的key大,则递归到当前节点的右子树中去插入
        root->rchild = insert(root->rchild, key);
    }
    update_size(root);
    return root;
}

Node *prodecessor(Node *root) {
    Node *p = root->lchild;
    while (p->rchild != NULL) {
        p = p->rchild;
    }
    return p;
}

Node *erase(Node *root, int key) {
    //root是空,则表明从根节点遍历到这个空节点都没有找到与参数key值一样的节点,直接返回
    if (root == NULL) {
        return root;
    }
    if (key < root->key) {//key值小于当前节点的key,则要删除的点在root的左子树上
        root->lchild = erase(root->lchild, key);
    } else if (key > root->key){//key值大于当前节点的key,则要删除的点在root的左子树上
        root->rchild = erase(root->rchild, key);
    } else {//key值与当前节点的key一样,则以度的数量开始区分删除情况。
        if (root->lchild == NULL || root->rchild == NULL) {//删除度为0或者1都可以这个分支。
            Node *p = root->lchild == NULL ? root->rchild : root->lchild;
            free(root);
            return p;
        } else {////度为2:直接转化为删除该节点的前驱节点
            Node *p = prodecessor(root);
            root->key = p->key;
            root->lchild = erase(root->lchild, p->key);
        }
    }
    update_size(root);
    return root;
}

void print_node(Node *root) {
    printf("(%d[%d]: %d, %d)\n", KEY(root), SIZE(root), KEY(root->lchild), KEY(root->rchild));
}

void _in_order(Node *root) {
    if (root == NULL) {
        return ;
    }
    _in_order(root->lchild);
    print_node(root);
    _in_order(root->rchild);
    return ;
}

void in_order(Node *root) {
    printf("binary tree:\n");
    _in_order(root);
    printf("\n\n");
}

int find_k(Node *root, int k) {
    if (root == NULL || k == 0) {
        return -1;
    }
    if (k == SIZE(root->lchild) + 1) {//若root节点的左子树节点数量 + 1等于 k,则root节点就是第K个节点
        return root->key;
    }
    if (k <= SIZE(root->lchild)) {//若root节点的左子树节点数量大于等于k,则递归到左子树中去找第K个节点
        return find_k(root->lchild, k);
    }
    //若root左子树节点数量 + 1小于K,则递归到右子树中去找右子树中第K - size(L(root)) - 1个节点。
    if (k > SIZE(root->lchild) + 1) {
        return find_k(root->rchild, k - SIZE(root->lchild) - 1);
    }
}

void menu(void) {
    printf("Please enter the operation: \n");
    printf("Press 1 to insert a node to binary search tree\n");
    printf("Press 2 to delete a node from binary search tree\n");
    printf("Press 3 to find a node from binary search tree\n");
    printf("Press 4 to output top-k sequence from binary search tree\n");
    printf("Press TRL + D to quit!\n");
}

int main() {
    Node *root = NULL;
    int op, val;
    menu();
    while (~scanf("%d", &op)) {
        if (op < 1 || op > 4) {
            printf("please enter the right operation!\n");
            continue;
        }
        switch (op) {
            case 1:
                printf("Enter the key you want to insert: ");
                scanf("%d", &val);
                root = insert(root, val);
            break;

            case 2:
                printf("Enter the key you want to delete: ");
                scanf("%d", &val);
                root = erase(root, val);
            break;

            case 3:
                printf("Enter the index you are looking for:");
                scanf("%d", &val);
                printf("Find NO.%d of the binary tree, result: %d\n\n", val, find_k(root, val));
            break;

            case 4:
                printf("Enter a k for output top-k sequence: ");
                scanf("%d", &val);
                output_k(root, val);
                printf("\n");
            break;
        }
        if (op != 3 && op != 4) {
            in_order(root);
        }
        menu();
    }
    clear(root);
    return 0;
}
测试结果
Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
1
Enter the key you want to insert: 12
binary tree:
(12[1]: -1, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
1
Enter the key you want to insert: 8
binary tree:
(8[1]: -1, -1)
(12[2]: 8, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
1
Enter the key you want to insert: 10
binary tree:
(8[2]: -1, 10)
(10[1]: -1, -1)
(12[3]: 8, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
1
Enter the key you want to insert: 9
binary tree:
(8[3]: -1, 10)
(9[1]: -1, -1)
(10[2]: 9, -1)
(12[4]: 8, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
1
Enter the key you want to insert: 34
binary tree:
(8[3]: -1, 10)
(9[1]: -1, -1)
(10[2]: 9, -1)
(12[5]: 8, 34)
(34[1]: -1, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
1
Enter the key you want to insert: 23
binary tree:
(8[3]: -1, 10)
(9[1]: -1, -1)
(10[2]: 9, -1)
(12[6]: 8, 34)
(23[1]: -1, -1)
(34[2]: 23, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
1
Enter the key you want to insert: 20
binary tree:
(8[3]: -1, 10)
(9[1]: -1, -1)
(10[2]: 9, -1)
(12[7]: 8, 34)
(20[1]: -1, -1)
(23[2]: 20, -1)
(34[3]: 23, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
1
Enter the key you want to insert: 18
binary tree:
(8[3]: -1, 10)
(9[1]: -1, -1)
(10[2]: 9, -1)
(12[8]: 8, 34)
(18[1]: -1, -1)
(20[2]: 18, -1)
(23[3]: 20, -1)
(34[4]: 23, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
1
Enter the key you want to insert: 17
binary tree:
(8[3]: -1, 10)
(9[1]: -1, -1)
(10[2]: 9, -1)
(12[9]: 8, 34)
(17[1]: -1, -1)
(18[2]: 17, -1)
(20[3]: 18, -1)
(23[4]: 20, -1)
(34[5]: 23, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
1
Enter the key you want to insert: 19
binary tree:
(8[3]: -1, 10)
(9[1]: -1, -1)
(10[2]: 9, -1)
(12[10]: 8, 34)
(17[1]: -1, -1)
(18[3]: 17, 19)
(19[1]: -1, -1)
(20[4]: 18, -1)
(23[5]: 20, -1)
(34[6]: 23, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
1
Enter the key you want to insert: 21
binary tree:
(8[3]: -1, 10)
(9[1]: -1, -1)
(10[2]: 9, -1)
(12[11]: 8, 34)
(17[1]: -1, -1)
(18[3]: 17, 19)
(19[1]: -1, -1)
(20[5]: 18, 21)
(21[1]: -1, -1)
(23[6]: 20, -1)
(34[7]: 23, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
1
Enter the key you want to insert: 25
binary tree:
(8[3]: -1, 10)
(9[1]: -1, -1)
(10[2]: 9, -1)
(12[12]: 8, 34)
(17[1]: -1, -1)
(18[3]: 17, 19)
(19[1]: -1, -1)
(20[5]: 18, 21)
(21[1]: -1, -1)
(23[7]: 20, 25)
(25[1]: -1, -1)
(34[8]: 23, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
1
Enter the key you want to insert: 28
binary tree:
(8[3]: -1, 10)
(9[1]: -1, -1)
(10[2]: 9, -1)
(12[13]: 8, 34)
(17[1]: -1, -1)
(18[3]: 17, 19)
(19[1]: -1, -1)
(20[5]: 18, 21)
(21[1]: -1, -1)
(23[8]: 20, 25)
(25[2]: -1, 28)
(28[1]: -1, -1)
(34[9]: 23, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
2
Enter the key you want to delete: 17
binary tree:
(8[3]: -1, 10)
(9[1]: -1, -1)
(10[2]: 9, -1)
(12[12]: 8, 34)
(18[2]: -1, 19)
(19[1]: -1, -1)
(20[4]: 18, 21)
(21[1]: -1, -1)
(23[7]: 20, 25)
(25[2]: -1, 28)
(28[1]: -1, -1)
(34[8]: 23, -1)


Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
3
Enter the index you are looking for:4
Find NO.4 of the binary tree, result: 12

Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
3
Enter the index you are looking for:10
Find NO.10 of the binary tree, result: 25

Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
4
Enter a k for output top-k sequence: 7
(8[3]: -1, 10)
(9[1]: -1, -1)
(10[2]: 9, -1)
(12[12]: 8, 34)
(18[2]: -1, 19)
(19[1]: -1, -1)
(20[4]: 18, 21)

Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
4
Enter a k for output top-k sequence: 3
(8[3]: -1, 10)
(9[1]: -1, -1)
(10[2]: 9, -1)

Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!
4
Enter a k for output top-k sequence: 4
(8[3]: -1, 10)
(9[1]: -1, -1)
(10[2]: 9, -1)
(12[12]: 8, 34)

Please enter the operation:
Press 1 to insert a node to binary search tree
Press 2 to delete a node from binary search tree
Press 3 to find a node from binary search tree
Press 4 to output top-k sequence from binary search tree
Press TRL + D to quit!

原创博文,转发请加上原链接

posted @ 2021-04-19 17:08  ydqun  阅读(401)  评论(0编辑  收藏  举报