数据结构(c++)————二叉排序树(实现map操作)

本博客是用二叉排序树实现map的查找操作。 

一:二叉排序树的性质:

(1)若它的左子树非空,则其左子树所有结点的关键字的值均小于其根结点的关键字值。

(2)若它的右子树非空,则其右子树所有结点的关键字的值均大于其根结点关键字的值。

(3)它的左右子树也分别为一棵二叉排序树。

二:二叉树的插入和建立

基本思想:(1)若二叉树为空,则新结点作为二叉排序树的根节点。

(2)若给定结点的关键字的值小于根节点关键字的值,则插入到左子树中。

(3)若给定结点的关键字的值大于根节点关键字的值,则插入到右子树中。

三:二叉树的删除(删除结点后还要保留二叉树的性质)

假设待删除的结点为*p(指向结点的指针为p),假设指针f指向结点*p的双亲,s指向结点*p的左子树中关键字值最大的结点,q指向*s的双亲。

(1)当*p为叶子结点时,即左右子树均为空。

由于删除叶子结点不破坏整棵树的结构,则值需将其双亲结点*f的lchild或rchild置空即可,然后删除结点。

(2)当*p结点只有一颗非空子树,或者是非空左子树,或者是非空右子树。

若*p结点只有右子树而无左子树,则用其右子树的根节点取代要删除的*p结点。

若*p结点只有左子树而无右子树,则用其左子树的根节点取代要删除的*p结点。

(3)当*p结点的左右子树均为空。

由图(a)可知,在删除*p结点之前,中序遍历该二叉树得到的序列为{……(CL)C……(QL)Q(SL)SP(PR)F……},在删去*p之后,为保持其他元素之间相对位置保持不变,可以令*p的直接前驱(或直接后继)替代*p,然后再从二叉排序树中删去它的直接前驱(或直接后继)。如图(b)所示,当以直接前驱*s替代*p时,由于*s只有左子树(SL),则在删去*s之后,只要令(SL)为*s的双亲*q的右子树即可。

四:具体代码:

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<set>
#include<map>
#include<cmath>
#include<string>
#include<string.h>
#include<math.h>
#include<vector>
#include<queue>
#define maxn 100010
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
struct node
{
    int a,b;
    node *left,*right,*pre;
    node()
    {
        left=NULL;
        right=NULL;
    }
};
int flag=0;
node *root=NULL;
void Add(int x,int y)
{
    node *t,*p;
    t=new node();
    t->a=x;
    t->b=y;
    p=root;
    while(1)
    {
        if(t->a < p->a)
        {
            if(p->left==NULL)
            {
                t->pre=p;
                p->left=t;
                break;
            }
            else
                p=p->left;
        }
        else if(t->a > p->a)
        {
            if(p->right == NULL)
            {
                p->pre=p;
                p->right = t;
                break;
            }
            else
                p=p->right;
        }
        else
        {
            p->b = t->b;
            break;
        }
    }
    return ;
}
void Display(node *p)//中序遍历输出这棵树
{
    if(p == NULL)
        return ;
    Display(p->left);
    cout<< p->a <<" : "<< p->b <<endl;
    Display(p->right);
}
int Query(int x)
{
    node *p=root;
    while(1)
    {
        if(x== p->a)
        {
            return p->b;
        }
        if(x > p->a)
        {
            if(p->right==NULL)
                return -1;
            p=p->right;
        }
        else
        {
            if(p->left == NULL)
                return -1;
            p=p->left;
        }
    }
}
node *ans;
node* CC(node *p,int x)//找中序遍历的后继
{
    if(p->left!=NULL)
        CC(p->left,x);
    if(flag==1)
    {
        ans=p;
        flag=0;
    }

    if(p->a==x)
        flag=1;
    if(p->right!=NULL)
        CC(p->right,x);
}
void Delete(int x)
{
    if(Query(x)==-1)
        return ;
    flag=0;
    node *p=root;
    while(1)//先找到后继这个结点
    {
        if(p->a == x)
            break;
        if(x<p->a)
            p=p->left;
        else
            p=p->right;
    }
    if(p->left==NULL && p->right == NULL)//为叶子结点
    {
        if(p->pre->left->a == x)
            p->pre->left=NULL;
        else
            p->pre->right=NULL;
        delete p;
    }
    else if(p->left == NULL || p->right == NULL)//只有一颗子树
    {
        if(p->left == NULL)
            p->pre->right=p->right;
        else
            p->pre->left=p->left;
        delete p;
    }
    else//有两颗子树
    {
        node *q;
        CC(root,x);
        q=ans;
        p->a=q->a;
        p->b=q->b;
        cout<<"q->a  : "<<x<<" "<<q->a<<endl;
        if(q->left == NULL && q->right == NULL)
        {
            if(q->pre->left->a == p->a)
                q->pre->left=NULL;
            if(q->pre->right->a== p->a)
                q->pre->right=NULL;
            delete q;
        }
        else{
            q->pre->right=q->right;
            delete q;
        }
    }
    return ;
}
int main()
{
    int x,y,n;
    cin>>n;
    for(int i=1; i<=n; i++)
    {
        cin>>x>>y;
        if(i==1)
        {
            root=new node();
            root->a = x;
            root->b = y;
        }
        else
            Add(x,y);
    }
    Display(root);
    cout<<"输入您要查询结点的值:"<<endl;
    cin>>x;
    int ans=Query(x);
    if(ans!=-1)
        cout<<ans<<endl;
    else
        cout<<"此节点不存在"<<endl;
    cout<<"输入您要删除的值:"<<endl;
    cin>>x;
    Delete(x);
    Display(root);
    return 0;
}
发布了350 篇原创文章 · 获赞 715 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/ZCY19990813/article/details/101080645
今日推荐