數據結構(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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章