12.二叉排序树.md 6.2 KB

#include<iostream>

using namespace std;
/*-----------二叉排序树的二叉链表的存储表示-----------*/
#define ENDFLAG 999
typedef int KeyType;
typedef int InfoType;
typedef struct {
    KeyType key;//关键子项
    InfoType otherinfo;//其他数据域
} ElemType;
typedef struct BSTNode {
    ElemType data;//每个结点的数据域包括关键字项和其他数据项
    struct BSTNode *lchild, *rchild;//左右孩子指针
} BSTNode, *BSTree;

/*-----------二叉排序树的查找--------------*/
BSTNode *Search_BST(BSTree &T, KeyType key) {
    while (T != NULL && key != T->data.key) {
        if (key < T->data.key) T = T->lchild;
        else T = T->rchild;
    }
    return T;
}

/*--------- 二叉排序树的递归查找-----------*/
BSTNode *SearchBST(BSTree T, KeyType key) {
    //在根指针T所指二叉排序树中递归地查找某关键字等于key的数据元素
    //若查找成功,则返回指向该数据元素结点的指针,否则返回空指针
    if ((!T) || key == T->data.key) return T;//查找结束
    else if (key < T->data.key) return SearchBST(T->lchild, key);//在左子树中继续查找
    else return SearchBST(T->rchild, key);//在右子树中继续查找
}

/*----------二叉排序树的插入------------*/
void InsertBST(BSTree &T, ElemType e) {
    if (!T) {
        BSTNode *S = new BSTNode;//生成新结点*S
        S->data = e;//新结点*S的数据域置为e
        S->lchild = S->rchild = NULL;//新结点*S作为叶子结点
        T = S;//把新结点*S链接到已找到的插入位置
    } else if (e.key < T->data.key)
        InsertBST(T->lchild, e);//将*S插入左子树
    else if (e.key > T->data.key)
        InsertBST(T->rchild, e);//将*S插入右子树
}

/*------------非递归建立二叉排序树------------*/
BSTNode *nonRecusInsertNode(BSTree &T, ElemType e) {
    BSTNode *p = T;         //用来查找
    BSTNode *q = NULL;                //用来指明当前插入位置的父节点

    //此处用来寻找插入的位置和当前插入位置的父节点
    //q记录插入位置的父节点用来连接插入的孩子
    while (p != NULL) {
        if (p->data.key == e.key) {
            return NULL;            //已经存在,插入失败
        } else if (p->data.key > e.key) {
            q = p;
            p = p->lchild;            //找到对应插入为NULL的位置
        } else {
            q = p;
            p = p->rchild;
        }
    }
    //初始化一个插入结点
    p = (BSTNode *) malloc(sizeof(BSTNode));
    p->data.key = e.key;
    p->lchild = NULL;
    p->rchild = NULL;

    //将插入结点与之父节点相连
    if (!q) {        //要插入根节点,直接用T指针相连
        T = p;
    } else if (q->data.key > e.key) {        //插入父节点的左边,将父节点的左孩子指向插入的结点
        q->lchild = p;
    } else q->rchild = p;                //插入父节点的右边,将父节点的右孩子指向插入的结点
    return p;
}

/*----------二叉排序树的创建-----------*/
void CreatBST(BSTree &T) {
    //依次读入一个关键字为key的结点,将此结点插入二叉排序树T中
    T = NULL;//将二叉排序树T初始化为空树
    ElemType e;
    int test_num[] = {6, 10, 45, 32, 55, 68, 100};

    for (int i = 0; i < sizeof(test_num) / sizeof(test_num[0]); ++i) {
        e.key = test_num[i];
        InsertBST(T, e);
    }
}

/*---------二叉排序树的删除----------*/
void DeleteBST(BSTree &T, KeyType key) {
    //从二叉排序树T中删除关键字等于key的结点
    BSTNode *p = new BSTNode;
    BSTNode *f;
    p = T;
    f = NULL;
    /*--------------下面的while循环从根开始查找关键字等于key的结点*p----------*/
    while (p) {
        if (p->data.key == key) break;//找到关键字等于key的结点*p,结束循环
        f = p;//*f为*p的双亲结点
        if (p->data.key > key) p = p->lchild;//在*p的左子树中继续查找
        else p = p->rchild;//在*p的右子树中继续查找
    }
    if (!p) return;//找不到被删结点则返回
    /*------考虑3种情况实现p所指子树内部的处理:
     * *p左右子树均空(为叶子节点)、
     * 左右子树均不空、
     * 无右子树(或无左子树)----*/

    if (p->lchild == NULL && p->rchild == NULL) {//1.*p左右子树均空(为叶子节点)
        p = NULL;
    } else if (p->lchild == NULL) {//2.1.*p左子树为空
        if (f->lchild == p)
            f->lchild = p->rchild;
        else {
            f->rchild = p->rchild;
        }
        delete p;
    } else if (p->rchild == NULL) {//2.2.*p右子树为空
        if (f->lchild == p)
            f->lchild = p->lchild;
        else {
            f->rchild = p->lchild;
        }
        delete p;
    } else {//3.左右子树均不空
        BSTNode *q = p->rchild;//*q为直接后继(*p右子树的最左节点)
        BSTNode *q_f = p;
        while (q->lchild) {
            q_f = q;//*q_f为*q的双亲结点, 如果进入while循环, *q必为*q_f的左孩子
            q = q->lchild;
        }
        p->data = q->data;//将直接后继(*p右子树的最左节点)的值赋给*p
        if (q_f == p) {
            q_f->rchild = q->rchild;//未进入while循环, 代表直接后继*q为*p的右孩子, 此结点*q必无左子树
        } else {
            q_f->lchild = q->rchild;//进入while循环, 代表直接后继为*p的右子树的最左节点, 此结点*q必无左子树
        }
        delete q;
    }

}

/*------------二叉树的中序遍历------------*/
void InorderTree(BSTree T) {
    if (T) {
        InorderTree(T->lchild);
        cout << T->data.key << " ";
        InorderTree(T->rchild);
    }
}

int main() {
    BSTree T = NULL;
    CreatBST(T);//创建一棵二叉排序树
    InorderTree(T);//中序遍历二叉树
    cout << endl;
    cout << "请输入您要查询的元素:" << endl;
    int k = 0;
    cin >> k;
    BSTree T1 = NULL;//定义T1用来接收查找结果
    T1 = SearchBST(T, k);
    if (T1) cout << "存在此元素!" << endl;
    else cout << "不存在此元素!" << endl;
    int key = 0;
    cout << "请输入您要删除的元素:" << endl;
    cin >> key;
    DeleteBST(T, key);//删除元素
    InorderTree(T);//再次中序遍历二叉树
    return 0;
}