NOJ-二叉排序树的插入和删除-西工大数据结构

    周二就写完了,找bug找了很长时间,今天有空了,发出来。题目如下:


    构建二叉排序树,找后继线索链表,插入都还可以,基本操作,就是这个删除比较麻烦,好多种情况,而且他居然每次都是对原二叉树进行插入删除,输出之后还得删除和插入回去,真的是闲的。

    找后继采用栈的方法就可以了,插入就和查找差不多,只不过插入是找到上一节点,查找是找到查找节点,我把这两个功能集合成一个函数了,而且我觉得只有后继很麻烦,所以把前驱和根都找出来了。

    删除需要按照节点的左右支来分情况讨论:


    以下是我的实现:

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

struct binaryTreeNode
{
    int num;
    struct binaryTreeNode *left;
    struct binaryTreeNode *right;
    struct binaryTreeNode *next;
    struct binaryTreeNode *before;
    struct binaryTreeNode *root;
};

struct binaryTree
{
    struct binaryTreeNode *root;
    struct binaryTreeNode *head;
    struct binaryTreeNode *end;
};

struct binaryTreeStack
{
    struct binaryTreeNode *L[100];
    int flag[100];
    int top ;
};

void run();
struct binaryTreeNode *createNewTree(struct binaryTreeNode *root);
struct binaryTreeNode *createNewNode();
void pushStack(struct binaryTreeNode *node);
void popStack();
void getTrackList();
int stackEmptyJudge();
struct binaryTreeNode *getNode(int num);
void putOutSection();
void cutInNode(int num);
void deletNode(int num);
void print();

struct binaryTree T;
struct binaryTreeStack S;

int main()
{
    run();
    return 0;
}

void run()
{
    int in, out;
    T.root = createNewTree(NULL);
    getTrackList();
    putOutSection();
    scanf("%d", &in);
    cutInNode(in);
    print();
    deletNode(in);
    scanf("%d", &out);
    deletNode(out);
    print();
}

struct binaryTreeNode *createNewTree(struct binaryTreeNode *root)
{
    int num;
    struct binaryTreeNode *cur;
    scanf("%d", &num);
    if (num == -1) return NULL;
    cur = createNewNode();
    cur->num = num;
    cur->left = createNewTree(cur);
    cur->right = createNewTree(cur);
    cur->root = root;
    return cur;
}

struct binaryTreeNode *createNewNode()
{
    struct binaryTreeNode *p;
    p = (struct binaryTreeNode *)malloc(sizeof(struct binaryTreeNode));
    p->num = 0;
    p->left = NULL;
    p->right = NULL;
    p->next = NULL;
    p->before = NULL;
    return p;
}

void pushStack(struct binaryTreeNode *node)
{
    ++(S.top);
    S.L[S.top] = node;
    S.flag[S.top] = 0;
}

void popStack()
{
    --(S.top);
}

void getTrackList()
{
    int i;
    struct binaryTreeNode *next;
    S.top = -1;
    pushStack(T.root);
    while(stackEmptyJudge())
    {
        next = NULL;
        switch(S.flag[S.top])
        {
            case 0 :
            {
                ++(S.flag[S.top]);
                if(S.L[S.top]->left) pushStack(S.L[S.top]->left);
                break;
            }
            case 1 :
            {
                ++(S.flag[S.top]);
                if(S.L[S.top]->right) pushStack(S.L[S.top]->right);
                break;
            }
            case 2 :
            {
                if(S.L[S.top]->right)
                {
                    next = S.L[S.top]->right;
                    while(next->left) next = next->left;
                }
                else
                {
                    i = S.top - 1;
                    while(i >= 0 && S.flag[i] == 2) i--;
                    if(i >= 0) next = S.L[i];
                }
                S.L[S.top]->next = next;
                if(next) next->before = S.L[S.top];
                popStack();
            }
        }
    }
    next = T.root;
    while(next->left) next = next->left;
    T.head = next;
    next->before = NULL;
    next = T.root;
    while(next->right) next = next->right;
    T.end = next;
    next->next = NULL;
}

int stackEmptyJudge()
{
    if(S.top == -1) return 0;
    return 1;
}

struct binaryTreeNode *getNode(int num)
{
    struct binaryTreeNode *p = T.root;
    while(1)
    {
        if(p->num == num) return p;
        if(p->num < num)
        {
            if(p->right) p = p->right;
            else return p;
        }
        else
        {
            if(p->left) p = p->left;
            else return p;
        }
    }
}

void putOutSection()
{
    int a, b;
    struct binaryTreeNode *p = T.head;
    scanf("%d%d", &a, &b);
    p = getNode(a);
    if(p->num <= a) p = p->next;
    while(p && p->num < b)
    {
        printf("%d ", p->num);
        p = p->next;
    }
    printf("\n");
}

void cutInNode(int num)
{
    struct binaryTreeNode *p = getNode(num), *newNode = createNewNode();
    newNode->num = num;
    newNode->root = p;
    if(num < p->num) p->left = newNode;
    else p->right = newNode;
    getTrackList();
}

void deletNode(int num)
{
    struct binaryTreeNode *p, *before, *next, *root;
    p = getNode(num);
    root = p->root;
    next = p->next;
    before = p->before;
    if(p->right == NULL && p->left == NULL)
    {
        if(root)
        {
            if(root->left == p) root->left = NULL;
            else root->right = NULL;
        }
        else T.root = NULL;
    }
    else
    {
        if(p->left && p->right)
        {
            if(p->right == next)
            {
                p->num = next->num;
                p->right = next->right;
            }
            else
            {
                 p->num = next->num;
                 next->root->left = next->right;
            }
        }
        else
        {
            if(p->right)
            {
                if(p->right == next)
                {
                    if(root)
                    {
                        if(root->right == p) root->right = next;
                        else root->left = next;
                    }
                    else T.root = next;
                }
                else
                {
                    p->num = next->num;
                    next->root->left = next->right;
                }
            }
            else
            {
                if(p->left == before)
                {
                    if(root)
                    {
                        if(root->right == p) root->right = before;
                        else root->left = before;
                    }
                    else T.root = before;
                }
                else
                {
                    p->num = before->num;
                    before->root->right = before->left;
                }
            }
        }
    }
    getTrackList();
}

void print()
{
    struct binaryTreeNode *p = T.head;
    while (p)
    {
        printf("%d ", p->num);
        p = p->next;
    }
    printf("\n");
}

    以下是各函数的注释:

void run()
{
    int in, out;
    T.root = createNewTree(NULL);//创建图
    getTrackList();//找到后继链表
    putOutSection();//输出区间
    scanf("%d", &in);
    cutInNode(in);//插入
    print();//输出插入
    deletNode(in);//删除插入
    scanf("%d", &out);
    deletNode(out);//删除
    print();//输出删除
}
struct binaryTreeNode *createNewTree(struct binaryTreeNode *root)
{
    int num;
    struct binaryTreeNode *cur;
    scanf("%d", &num);
    if (num == -1) return NULL;//结束创建
    cur = createNewNode();创建节点
    cur->num = num;
    cur->left = createNewTree(cur);//递归创建
    cur->right = createNewTree(cur);
    cur->root = root;//根节点赋值
    return cur;
}
struct binaryTreeNode *createNewNode()
{
    struct binaryTreeNode *p;
    p = (struct binaryTreeNode *)malloc(sizeof(struct binaryTreeNode));//创建节点
    p->num = 0;//初始化
    p->left = NULL;
    p->right = NULL;
    p->next = NULL;
    p->before = NULL;
    return p;
}
//栈操作
void pushStack(struct binaryTreeNode *node)
{
    ++(S.top);
    S.L[S.top] = node;
    S.flag[S.top] = 0;
}

void popStack()
{
    --(S.top);
}
void getTrackList()
{
    int i;
    struct binaryTreeNode *next;
    S.top = -1;
    pushStack(T.root);
    while(stackEmptyJudge())//栈不空
    {
        next = NULL;
        switch(S.flag[S.top])//按栈顶元素的标记分类
        {
            case 0 ://0次访问
            {
                ++(S.flag[S.top]);//访问次数增加
                if(S.L[S.top]->left) pushStack(S.L[S.top]->left);//压入左支
                break;
            }
            case 1 :
            {
                ++(S.flag[S.top]);//访问次数增加
                if(S.L[S.top]->right) pushStack(S.L[S.top]->right);//压入右支
                break;
            }
            case 2 :
            {
                if(S.L[S.top]->right)//若栈顶有右支
                {
                    next = S.L[S.top]->right;
                    while(next->left) next = next->left;//找到右支的最左,或右支
                }
                else//若无右支
                {
                    i = S.top - 1;
                    while(i >= 0 && S.flag[i] == 2) i--;
                    if(i >= 0) next = S.L[i];//找到栈中从顶到底的第一个一次访问节点,就是后继
                }
                S.L[S.top]->next = next;//后继连接
                if(next) next->before = S.L[S.top];前驱连接
                popStack();//两次访问后出栈
            }
        }
    }
    next = T.root;//头尾赋值
    while(next->left) next = next->left;
    T.head = next;
    next->before = NULL;
    next = T.root;
    while(next->right) next = next->right;
    T.end = next;
    next->next = NULL;
}
int stackEmptyJudge()
{
    if(S.top == -1) return 0;//判断栈是否空
    return 1;
}
struct binaryTreeNode *getNode(int num)
{
    struct binaryTreeNode *p = T.root;
    while(1)
    {
        if(p->num == num) return p;//如果找到,返回找到的节点
        if(p->num < num)//否则就找到最接近的节点,并返回,方便插入
        {
            if(p->right) p = p->right;
            else return p;
        }
        else
        {
            if(p->left) p = p->left;
            else return p;
        }
    }
}
void putOutSection()
{
    int a, b;
    struct binaryTreeNode *p = T.head;
    scanf("%d%d", &a, &b);
    p = getNode(a);//找到节点
    if(p->num <= a) p = p->next;//如果左区间的节点存在,或左区间值在找到的节点的右支(比如区间(10,15),但是只能找到9,10并不存在),就从后继开始输出
    while(p && p->num < b)//遍历输出
    {
        printf("%d ", p->num);
        p = p->next;
    }
    printf("\n");
}

void cutInNode(int num)
{
    struct binaryTreeNode *p = getNode(num), *newNode = createNewNode();
    newNode->num = num;
    newNode->root = p;
    if(num < p->num) p->left = newNode;//判断插左还是插右
    else p->right = newNode;
    getTrackList();//后继链表更新
}
void deletNode(int num)
{
    struct binaryTreeNode *p, *before, *next, *root;
    p = getNode(num);
    root = p->root;
    next = p->next;
    before = p->before;
    if(p->right == NULL && p->left == NULL)//左右都空
    {
        if(root)//如果根存在
        {
            if(root->left == p) root->left = NULL;//判断是删左还是删右
            else root->right = NULL;
        }
        else T.root = NULL;//整棵树只有一个节点,这树就空了
    }
    else
    {
        if(p->left && p->right)//左右都有
        {
            if(p->right == next)//若右支就是后继
            {
                p->num = next->num;//复制
                p->right = next->right;//把后继的右支接到p的右支上
            }
            else//
            {
                 p->num = next->num;//复制
                 next->root->left = next->right;////吧后继的右支接到后继的根的左支上
            }
        }
        else
        {
            if(p->right)//只有右
            {
                if(p->right == next)
                {
                    if(root)
                    {
                        if(root->right == p) root->right = next;
                        else root->left = next;
                    }
                    else T.root = next;
                }
                else
                {
                    p->num = next->num;
                    next->root->left = next->right;
                }
            }
            els//e只有左
            {
                if(p->left == before)
                {
                    if(root)
                    {
                        if(root->right == p) root->right = before;
                        else root->left = before;
                    }
                    else T.root = before;
                }
                else
                {
                    p->num = before->num;
                    before->root->right = before->left;
                }
            }
        }
    }
    getTrackList();//后继链表更新
}
void print()
{
    struct binaryTreeNode *p = T.head;
    while (p)//遍历输出
    {
        printf("%d ", p->num);
        p = p->next;
    }
    printf("\n");
}
我估计是还有bug但是测了好多都还行。。。







猜你喜欢

转载自blog.csdn.net/qq_30180107/article/details/80446235