实验 二叉排序树

一、   实验目的

1. 掌握二叉树逻辑结构;

2. 掌握利用C/C++编程语言实现数据结构的编程方法;

3. 通过上机时间加强利用数据结构解决实际应用问题的能力;

二、   实验相关知识

1. 二叉树的二叉链表存储结构的实现;

2. 二叉树排序树的定义;

3. 二叉排序树的插入、构建、删除;

4. 二叉排序树的中序遍历。

三、   实验内容与要求

实现二叉排序树的结点插入、构建、遍历和元素删除( 已经提供结点删除函数实现)

四、   实现过程与结构

#include <stdio.h>
#include <string.h>
#include <algorithm>
typedef char ElemType; //二叉链表中结点元素类型
typedef struct BiTNode
{
    ElemType data;
    struct BiTNode* lchild, *rchild;
}BiTNode, *BiTree; //二叉链表的类型定义
BiTree CreateBiTree();// 利用先序遍历创建二叉树,返回根指针。
void InOrder(BiTree T);// 二叉树的中序遍历,参数:二叉树根指针T,输出:中间没有空格,末尾不换行。
int InsertNode(BiTree& T, ElemType x);//二叉排序树的插入
BiTree CreateBiTree()// 利用先序遍历创建二叉树,返回根指针。
{
    //补充代码
    BiTree T = NULL;
    int  i, n, x;
    printf_s("输入元素的个数n和n个元素:
");
    scanf_s("%d:", &n);
    for (int i = 0; i < n; i++) {
        scanf_s("%d", &x);
        InsertNode(T, x);
    }
    return T;
}

int InsertNode(BiTree &T, ElemType x)//二叉排序树的插入
{     //补充代码
    if (T == NULL) {
        T = (BiTNode*)malloc(sizeof(BiTNode));
        T->data = x;
        T->rchild = NULL;
        T->lchild = NULL;
    }
    else {
        if (T->data == x)return 0;
        if (T->data < x)
            InsertNode(T->rchild, x);
        else
            InsertNode(T->lchild, x);
    }
    return 1;
}

void InOrder(BiTree T) // 中序遍历
{   //补充代码
    if (T != NULL) {
        InOrder(T->lchild);
        printf_s("%d ",T->data);
        InOrder(T->rchild);
    }
}

BiTNode* find(BiTree& T, ElemType x)
{
    if (T == NULL)
        return NULL;
    if (T->data == x)
        return T;
    else
    {
        if (x < T->data)
            return find(T->lchild, x);
        else
            return find(T->rchild, x);
    }
}


int Delete(BiTree &p)
{
    BiTree q, s;
    //情况 1,结点 p 本身为叶子结点,直接删除即可
    if (p->lchild == NULL && p->rchild == NULL) {
        free(p);
        p = NULL;
        return 1;
    }
    if (p->lchild == NULL) { //左子树为空,右子树非空,只需用结点 p 的右子树根结点代替结点 p 即可;
        q = p;
        p = p->rchild;
        free(q);
        return 1;
    }
    else if (p->rchild == NULL) {//右子树为空,左子树非空,只需用结点 p 的左子树根结点代替结点 p 即可;
        q = p;
        p = p->lchild;//这里不是指针 p 指向左子树,而是将左子树存储的结点的地址赋值给指针变量 p
        free(q);
    }
    else {//左右子树均不为空,采用第 2 种方式
        q = p;
        s = p->lchild;
        //遍历,找到结点 p 的直接前驱
        while (s->rchild)
        {
            q = s;
            s = s->rchild;
        }
        //直接改变结点 p 的值
        p->data = s->data;
        //判断结点 p 的左子树 s 是否有右子树,分为两种情况讨论
        if (q != p) {
            q->rchild = s->lchild;//若有,则在删除直接前驱结点的同时,令前驱的左孩子结点改为 q 指向结点的孩子结点
        }
        else {
            q->lchild = s->lchild;//否则,直接将左子树上移即可
        }
        free(s);
    }
    return 1;
}
int DeleteBST(BiTree &T, int key)
{
    if (!T) {//不存在关键字等于key的数据元素
        return 0;
    }
    else
    {
        if (key == T->data) {
            Delete(T);
            return 1;
        }
        else if (key < T->data) {
            //使用递归的方式
            return DeleteBST(T->lchild, key);
        }
        else {
            return DeleteBST(T->rchild, key);
        }
    }
}

int main()
{
    BiTree T;
    T = CreateBiTree();
    while (1)
    {
        printf_s("请选择选项      
1.插入元素 
2.删除元素   
其他.结束程序
");
        InOrder(T);
        printf_s("
");
        int seleted;
        scanf_s("%d", &seleted);
        switch (seleted)
        {
        case 1:
        {
            int x;
            printf_s("输入插入的元素x=");
            scanf_s("%d", &x);
            if (InsertNode(T, x) > 0) printf_s("插入成功");
            else printf_s("元素重复,放弃插入");
            InOrder(T);
            printf_s("
");
            break;
        }
        case 2:
        {
            int x;
            printf_s("输入删除的元素x=");
            scanf_s("%d", &x);
            if (DeleteBST(T, x) > 0) printf_s("删除成功");
            else printf_s("元素不存在,放弃删除");
            InOrder(T);
            printf_s("
");
            break;
        }
        default:return 1;
        }
    }

}

原文地址:https://www.cnblogs.com/xxxsans/p/14182468.html