二叉排序树:

定义:BST--二叉排序树,二叉搜索树 1.要么是空树,要么具有下列性质 2.如果左子树不空,则左子树的结点的值小于根结点,并且左子树也是一棵BST 3.如果右子树不空,则右子树的结点的值大于根结点,并且右子树也是一棵BST 4.按照中序遍历,则从小到大排序好的 5.最左边的孩子,一定是最小的 6.最右边的孩子,一定是最大的 7.查找方便,插入和删除也比较方便(不用大量的移动元素)

使用排序二叉树的原因:

顺序表如果按顺序存储虽然有利于查找,但是插入删除需要移动大量的元素。即使我们现在使用链表结构,但是要保证数据有序存储,插入、删除虽然不需要像线性表那样大量的移动元素,但是查找依旧很麻烦。

所以我们使用二叉排序树,依照它的特性,不仅可以将数据有序存储,插入、删除数据结点也很方便。对于查找最少1次,即是根节点,最多也就是树的深度;由于保持了链表存储结构,所以在插入、删除时只需要找到合适的位置,修改链接指针即可。(这里的删除我们使用的是替换,因为如果是单纯的删除,需要改动的链接指针较多,性能不高)

插入结点:

void BSTree::InsertBSTValue(Node*& root, int v)
{//BSTree是二叉排序树的类型,Node是结点类型
 //BSTree类中有Node类型的m_root, 还有相关的方法
    if(root == NULL)
    {
        root = new Node(v);
	}
    else if(v < root->m_value)
    {
        InsertBSTValue(root->m_left, v);
    }
    else if(v > root->m_value)
    {
        InsertBSTValue(root->m_right, v);
    }
}

int main()
{
    int num[] = { 62,88,58,47,35,73,51,99,37,93 };
    BSTree t;
    int n=sizeof(num)/sizeof(num[0]);
    for(int i=0;i<n;i++)
    {//循环插入
        t.InsertBSTValue(t.m_root,num[i])
    }
    	
    rturn 0;
}

排序:

//根据二叉排序树的特点直接中序遍历输出就是排好序的
void BSTree::Sort(Node* root)
{
    if(root!=NULL)
    {
        Sort(root->m_left);
        cout<<root->m_value<<" ";
        Sort(root->m_right);
    }
}

查找值为k的结点:

Node* BSTree::SearchValue(Node* root, int k)
{
    if(root==NULL)
        return NULL;//已经找到叶子结点的孩子了,还没有找到,即是没有
    else if(k < root->m_value)
        SearchValue(root->m_left, k);
    else if(k > root->m_value)
    {
        SearchValue(root->m_right, k);
	}
    else
    {
        return root;
    }
}

删除值为k 的结点:

分三种情况:

1、k 为根结点,直接删除即可。

2、k 只有左孩子或者右孩子,将 k 结点删除后,将它的左子树或者右子树整个移动到删除结点也就是 k 结点的位置。

3、k 既有左孩子又有右孩子,为了删除后保持二叉排序树的特点,需要用第一个左孩子的右侧孩子替换(直接前驱),或者用第一个右孩子的最左侧孩子替换(直接后继),最后将替换结点删掉即可,而替换 k 的结点肯定符合1或2的情况,很容易删掉;之所以不用删除而用替换是因为删除以后,需要对其右子树或者左子树重新插入,不仅效率不高,而且二叉排序树的结构也会发生变化,树的高度也可能会增加,这也会影响到效率。

代码:

void BSTree::DelValue(Node*& root, int k)
{
    Node* temp=NULL:
    if(root != NULL)
    {
        if(k < root->m_value)
        {
            DelValue(root->m_left, k);
        }
        else if(k > root->m_value)
        {
            DelValue(root->m_right, k);
		}
        else if(root->m_left != NULL && root->m_right != NULL)
        {
            //用第一个右孩子的最左侧孩子替换
            temp = root->m_right;
            while(temp != NULL)
            {
                temp =temp->m_left;
			}
            root->m_value=temp->m_value;
            //最后在被替换(k)结点的右子树中找到替换它的结点并删除
			DelValue(root->m_right, root->m_value);
		}
        else//1,2两种情况
		{
			temp = root;
			if (root->m_left == NULL)
				root = root->m_right;
			else
				root = root->m_left;
			delete temp;
			temp = NULL;
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值