二叉查找数的实现(算法导论)

 

//定义元素最大个数
#define MAX_SIZE 100

 

#include<iostream>

using namespace std;

 

int Root=0;         //全局变量,根的索引
int now_size=0;     //定义元素当前最大的索引

//分别定义关键字,父节点,左右孩子的数组为全局变量
//结点下标从1开始,p,right,left值为0时表示为null
int key[MAX_SIZE];
int p[MAX_SIZE];
int right_child[MAX_SIZE];
int left_child[MAX_SIZE];

//查找给定的关键字,若找到,返回索引,否则返回-1
int tree_serch(int k)
{
    int x=Root;

    while(x!=0&&key[x]!=k)
    {
        if(k<key[x])
            x=left_child[x];
        else if(k>key[x])
            x=right_child[x];
        /*else
            return x;*/
    }
    if(key[x]==k)
        return x;
    else
        return -1;
}

//返回以x为根的子树的最小元素的值
int tree_min(int x)
{
    while(left_child[x]!=0)
        x=left_child[x];

    return key[x];
}

//返回以x为根的子树的最大元素的索引
int tree_max_index(int x)
{
    while(right_child[x]!=0)
        x=right_child[x];

    return x;
}

//返回以x为根的子树的最小元素的索引
int tree_min_index(int x)
{
    while(left_child[x]!=0)
        x=left_child[x];

    return x;
}

//返回以x为根的子树的最大元素的值
int tree_max(int x)
{
    while(right_child[x]!=0)
        x=right_child[x];

    return key[x];
}


//中序遍历以x为根的子树,输出各关键字
//根据二叉查找数的性质,该序列为排好序的序列
void inorder_walk(int x)
{
    //如果该数为null,返回
    if(x==0)
        return;
   
    //递归遍历左右子树

    inorder_walk(left_child[x]);
    cout<<key[x]<<" ";
    inorder_walk(right_child[x]);
   
}

//返回其后继元素的index,如果没有返回-1
int tree_successor(int x)
{
    //如果没有后继,返回-1
    if(tree_max_index(Root)==x)
        return -1;

    //如果有右子树,返回右子树中最小元素
    if(right_child[x]!=0)
        return tree_min_index(right_child[x]);
    //没有右子树,寻找其祖先,直到其祖先为其父结点的左孩子,返回其父结点
    else
    {
        int y=x;
        while(y!=0&&y==right_child[p[y]])
            y=p[y];
        return p[y];
    }
   
}

//返回其前驱元素的index,如果没有返回-1
int tree_predeecessor(int x)
{
    //如果没有前驱,返回-1
    if(tree_min_index(Root)==x)
        return -1;


    //如果有左子树,返回左子树中最大元素
    if(left_child[x]!=0)
        return tree_max_index(left_child[x]);
    //没有左子树,寻找其祖先,直到其祖先为其父结点的右孩子,返回其父结点
    else
    {
        int y=x;
        while(y!=0&&y==left_child[p[y]])
            y=p[y];
        return p[y];
    }
}


//插入关键字为k的结点
void tree_insert(int k)
{
    //初始化结点
    int index=++now_size;
    left_child[index]=0;
    right_child[index]=0;
    key[index]=k;

    //x指示查找过程中下降的路径,y始终指向x的父结点
    int y=0;
    int x=Root;

    //x下降
    while(x!=0)
    {
        y=x;
        if(k>key[x])
            x=right_child[x];
        else
            x=left_child[x];
    }
    //新结点p[]指向y
    p[index]=y;
    //如果树为空
    if(y==0)
        Root=index;
    else
    {
        //设置父结点的孩子结点
        if(k<key[y])
            left_child[y]=index;
        else
            right_child[y]=index;
    }
}

//删除索引为x的结点
void tree_delete(int x)
{
 //del为要删除的结点
 int del,del_child;
 if(left_child[x]==0||right_child[x]==0)
  del=x;
 else
  del=tree_successor(x);
 //del_child为del的非空子女,当无子女时为0
 if(left_child[del]!=0)
  del_child=left_child[del];
 else
  del_child=right_child[del];
 //如果del_child不空,其父结点为del的父结点
 if(del_child!=0)
  p[del_child]=p[del];

 //如果要删除的结点为根,根为其孩子
 if(p[del]==0)
  Root=del_child;
 else if(del==left_child[p[del]])   //如果 要删除的结点为左子树
  left_child[p[del]]=del_child;
 else
  right_child[p[del]]=del_child;

 if(x!=del)     //如果del不是x,即x有两个孩子
  key[x]=key[del];
}

//输出i,key,p,left,right各值,以便测试
void output()
{
    //输出i,key,p,left,right各值
    int i;
    cout<<"i:    ";
    for(i=1;i<=now_size;i++)
    {
        cout<<i<<" ";
    }
    cout<<endl;

    cout<<"key:  ";
    for(i=1;i<=now_size;i++)
    {
        cout<<key[i]<<" ";
    }
    cout<<endl;

    cout<<"p:    ";
    for(i=1;i<=now_size;i++)
    {
        cout<<p[i]<<" ";
    }
    cout<<endl;

    cout<<"left: ";
    for(i=1;i<=now_size;i++)
    {
        cout<<left_child[i]<<" ";
    }
    cout<<endl;

    cout<<"right:";
    for(i=1;i<=now_size;i++)
    {
        cout<<right_child[i]<<" ";
    }
    cout<<endl;
 cout<<endl;

}

//测试
int main()
{
    //插入值
    tree_insert(7);
    tree_insert(2);
    tree_insert(18);
    tree_insert(4);
    tree_insert(8);
    tree_insert(5);
    tree_insert(16);
    tree_insert(9);
    tree_insert(10);
    tree_insert(20);

    output();

    /*
    以上为测试tree_insert方法,结果为:

    i:    1 2 3  4 5 6 7  8 9  10
    key:  7 2 18 4 8 5 16 9 10 20
    p:    0 1 1  2 3 4 5  7 8  3
    left: 2 0 5  0 0 0 8  0 0  0
    right:3 4 10 6 7 0 0  9 0  0

    */


    //按升序输出关键字
    cout<<"order:";
    inorder_walk(Root);
    cout<<endl;

    /*
    以上为测试inorder_walk方法,结果为:

    order:2 4 5 7 8 9 10 16 18 20

    */

    cout<<"max element:"<<tree_max(Root)<<endl;
    cout<<"min element:"<<tree_min(Root)<<endl;

    /*
    以上为测试tree_max,tree_min方法,结果为:

    max element:20
    min element:2

    */

   
    cout<<"18'index:"<<tree_serch(18)<<endl;
    cout<<"8'index:"<<tree_serch(8)<<endl;
    cout<<"2'index:"<<tree_serch(2)<<endl;
    cout<<"10'index:"<<tree_serch(10)<<endl;
    cout<<"7'index:"<<tree_serch(7)<<endl;
    cout<<"12'index:"<<tree_serch(12)<<endl;

    /*
    以上为测试tree_search方法,结果为:

    18'index:3
    8'index:5
    2'index:2
    10'index:9
    7'index:1
    12'index:-1

    */
   
    cout<<"index 1's successor is "<<tree_successor(1)<<endl;//5
    cout<<"index 5's successor is "<<tree_successor(5)<<endl;//8
    cout<<"index 9's successor is "<<tree_successor(9)<<endl;//7
    cout<<"index 10's successor is "<<tree_successor(10)<<endl;//-1

    /*
    以上为测试tree_successor方法,结果为:

    index 1's successor is 5
    index 5's successor is 8
    index 9's successor is 7
    index 10's successor is -1
    */


    cout<<"index 1's predeecessor is "<<tree_predeecessor(1)<<endl;//6
    cout<<"index 5's predeecessor is "<<tree_predeecessor(5)<<endl;//1
    cout<<"index 9's predeecessor is "<<tree_predeecessor(9)<<endl;//8
    cout<<"index 2's predeecessor is "<<tree_predeecessor(2)<<endl;//-1

    /*
    以上为测试tree_predeecessor方法,结果为:

    index 1's predeecessor is 6
    index 5's predeecessor is 1
    index 9's predeecessor is 8
    index 2's predeecessor is -1
    */

 tree_delete(9);
 output();
 /*
 以上为测试tree_delete方法,测试没有子树的情况,结果为:
 
 i:    1 2 3  4 5 6 7  8 9  10
 key:  7 2 18 4 8 5 16 9 10 20
 p:    0 1 1  2 3 4 5  7 8  3
 left: 2 0 5  0 0 0 8  0 0  0
 right:3 4 10 6 7 0 0  0 0  0
 */

 tree_delete(4);
 output();


 /*
 以上为测试tree_delete方法,测试有一个子树的情况,结果为:
 i:    1 2 3  4 5 6 7  8 9  10
 key:  7 2 18 4 8 5 16 9 10 20
 p:    0 1 1  2 3 2 5  7 8  3
 left: 2 0 5  0 0 0 8  0 0  0
 right:3 6 10 6 7 0 0  0 0  0


 */

 


 tree_delete(3);
 output();


 /*
 以上为测试tree_delete方法,测试有两个子树的情况,结果为:
 i:    1 2 3  4 5 6 7  8 9  10
 key:  7 2 20 4 8 5 16 9 10 20
 p:    0 1 1  2 3 4 5  7 8  3
 left: 2 0 5  0 0 0 8  0 0  0
 right:3 4 0  6 7 0 0  0 0  0


 */

    return 1;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值