7.1 二叉搜索树

本章问题

1.中序遍历的一般形式是什么?

void InOrder(BiTree T){
    
    
	if(T){
    
    
		InOrder(T->lchild);//访问左子树
		cout<<T->data<<" ";//输出该节点的数据
		InOrder(T->rchild);//访问右子树
	}
}

先左儿子底部,然后父节点,然后右儿子的左子树底部,

img
先序遍历:GDAFEMHZ
中序遍历:ADEFGHMZ
后序遍历:AEFDHZMG

2.二叉搜索树的特点

特点: 任何一棵二叉树是二叉搜索树,当且仅当其中序遍历序列单调非降。

是一棵空树或具有以下几种性质的树:
1.若左子树不空,则左子树上所有结点的值均小于它的根结点的值
2.若右子树不空,则右子树上所有结点的值均大于它的根结点的值
3.左、右子树也分别为二叉排序树
4.没有权值相等的结点。

3.什么是等价二叉搜索树

条件:中序遍历相同
特点:“上下可变,左右不乱”,即等价二叉搜索树中各节点的垂直高度可能不同,但水平次序完全一致;

4.等价二叉搜索树的操作-旋转调整

操作 功能
zig 旋转-顺时针旋转 实现等价前提下的局部拓扑调整
zag旋转-逆时针旋转 实现等价前提下的局部拓扑调整

在下列图片之中,圆圈表示的节点,矩形表示的子树

zig旋转 -顺时针

旋转过程描述:将x和v作为c的左子树和右孩子,y和z分别作为v的左右子树

image-20210102174606946

zag旋转-逆时针

旋转过程描述:将v和z作为c的左孩子,右子树,x和y分别为作为v的左,右子树

image-20210102174606946

5.中序遍历的直接前驱和直接后继怎么获得

找后继
  1、如有右子女,后继是右子女的最左下节点;
  2、若无右子女,且是父母的左子女,则后继就是父母;
  3、若无右子女,且是父母的右子女,则一直上溯到第一个“左祖先”(定义如前
面)则后继就是这个祖先。若无这样的祖先,说明已经遍历完毕。

找前驱
  1 、如有左子女,前驱是左子女的最右下节点;
  2、若无左子女,且是父母的右子女,则前驱就是父母;
  3、若无左子女,且是父母的左子女,则一直上溯到第一个“右祖先”(定义如前
面)则前驱就是这个祖先。若无这样的祖先,说明已经遍历完毕。

6.如何插入和删除二叉搜索树节点,才能仍然保持中序遍历单调非降

这里有一个简单的想法,删除节点后,该节点的之后的直接后继依次向前移动
最右下插入节点后,依次与其直接前驱比较,然后排序,但是这样是o(n)的复杂度,这样的复杂度即使是线性结构也可以做到
没有什么体现二叉搜索树的优势
那么有什么更优化的算法么?
是有的,那么具体的方法是什么呢
插入
1.查找插入的位置,并且判断是否唯一
2.在找到的位置插入节点
查找步骤具体的描述
从树根出发,逐步的缩小查找范围,直到发现目标(成功)或缩小至空树(失败)
删除
1.查找节点和后继
2.删除节点,将节点后继连接到被删除节点的父节点
查找步骤具体的描述
来自博客:https://blog.csdn.net/hansionz/article/details/81988752
首先要确定删除节点的种类

二叉搜索树的删除大致分为以下类:
1.左子树为空
2.右子树为空
3.左右子树都为空
4.左右子树都不为空

img

对于以上的四类要删除的结点,其实我们还可以在具体一些,将一二三类归在一起,第四类是一类。
下面是两类删除结点的方法

img

7.1.1 二叉搜索树(BST)

特点: 任何一棵二叉树是二叉搜索树,当且仅当其中序遍历序列单调非降。

7.1.1.1 接口列表

操作 功能 对象
search(const T& e) 查找指定元素,返回命中节点,并返回其父亲节点 二叉搜索树
insert(const T& e) 按照二叉搜索树的结构要求插入指定元素 二叉搜索树
remove(const T& e) 按照二叉搜索树的结构要求删除元素 二叉搜索树

7.1.1.2 二叉搜索树-类模板

#include"binTree.h"
 
//二叉搜索树模板类
template<typename T> class bst :public binTree<T>
{
    
    
public:
	binNode<T>* _hot;   //所命中的节点的parent
	binNode<T>* connect34(   //按照3+4结构,联接3个节点及4颗树
		binNode<T>*, binNode<T>*, binNode<T>*,
		binNode<T>*, binNode<T>*, binNode<T>*, binNode<T>*
	);
	binNode<T>* rotateAt(binNode<T>* v);  //对x及父亲、祖父做统一旋转调整
 
public:
	static binNode<T>* & searchIn(binNode<T>* &v, const T& e, binNode<T>* &hot);   //在以v为根的子树中查找关键码e,并将命中节点的parent返回给hot
	virtual binNode<T>* & search(const T& e);   //查找
	virtual binNode<T>* insert(const T& e);     //插入
	virtual bool remove(const T& e);            //删除
 
	static binNode<T>* removeAt(binNode<T>* &x, binNode<T>* &hot);   //删除位置x所指的节点(以判断存在),返回值指向实际被删除者的接替者,hot指向被实际删除者的父亲
};

7.1.1.3 searchIn算法和search接口

template<typename T> binNode<T>* & bst<T>::searchIn(binNode<T>* &v, const T& e, binNode<T>* &hot)
{
    
    
	if (!v || (v->data == e))    //若v本身不存在或则直接命中,则返回v
		return v;
	hot = v;
	return searchIn((e < (v->data)) ? v->lc : v->rc, e, hot);
}
 
template<typename T> binNode<T>* & bst<T>::search(const T& e)
{
    
    
	return searchIn(_root, e, _hot = nullptr);
}  //返回时,返回值指向命中节点或假想的哨兵节点,hot指向其parent,

7.1.1.4 insert接口

template<typename T> binNode<T>* bst<T>::insert(const T& e)
{
    
    
	//首先search查询是否存在或待插入的位置
	binNode<T>* &x = search(e);
	if (x)   //若已经存在则返回
		return x;
	//否则直接插在x上,设置好前后连接关系
	x = new binNode<T>(e, _hot);
	_size++;
	updateHeightAbove(x);
	return x;
}

7.1.1.5 remove和removeAt

template<typename T> bool bst<T>::remove(const T& e)
{
    
    
	binNode<T>* succ=nullptr;  //缓存替代者节点   
	//首先搜索是否存在
	binNode<T>* &x = search(e);  //缓存将要被删除的节点
	binNode<T>* temp = x;
	if (!x)   //不存在则直接返回
		return false;
	//case 1 :命中节点至多只有一个孩子,则直接删除,孩子顶上
	if (!(x->lc))  //左孩子为空,则右孩子顶上
	{
    
    
		succ = x = x->rc;
	}
	else if(!(x->rc))
	{
    
    
		succ = x = x->lc;
	}
	//case 2 :命中节点有两个孩子,则通过succ找直接后继节点
	else
	{
    
    
		temp = temp->succ();
		swap(x->data, temp->data);   //交换数据后temp成为实际要删除的点
		binNode<T>* u = temp->parent;
		((u == x) ? u->rc : u->lc) = succ = temp->rc;  //跨过节点succ(只有一种情况是左孩子)
	}	
	_hot = temp->parent;	
	if (succ)
		succ->parent = _hot;
	delete temp;
	_size--;
	updateHeightAbove(_hot);
	return true;
}
 
template<typename T> binNode<T>* bst<T>::removeAt(binNode<T>* &x, binNode<T>* &hot)
{
    
    
	binNode<T>* w = x;   //实际被摘除的节点
	binNode<T>* succ = nullptr;  //实际被删除的节点的接替者
	if (!(x->lc))  //左孩子为空,则右孩子顶上
	{
    
    
		succ = x = x->rc;
	}
	else if (!(x->rc))//右孩子为空,则左孩子
	{
    
    
		succ = x = x->lc;
	}
	//case 2 :命中节点有两个孩子,则通过succ找直接后继节点
	else
	{
    
    
		w = w->succ();  //中序遍历的直接后继
		swap(x->data, w->data);  //交换数据
		binNode<T>* u = w->parent;//直接后继的父节点
		((u == x) ? u->rc : u->lc) = succ = w->rc;   //隔离实际删除点
        //若直接后继的父节点为自身,则直接后继父节点的左孩子
	}
	hot = w->parent;
	if (succ) succ->parent = hot;
	delete w;
	return succ;
}

7.1.1.6 connect34 3+4连接

template<typename T> binNode<T>* bst<T>::connect34(              //按照3+4结构,联接3个节点及4颗树
	binNode<T>* a, binNode<T>* b, binNode<T>* c,
	binNode<T>* T0, binNode<T>* T1, binNode<T>* T2, binNode<T>* T3)
{
    
    
	a->lc = T0; if (T0) T0->parent = a;
	a->rc = T1; if (T1) T1->parent = a;
	updateHeight(a);   //更新a的高度
	
	c->lc = T2; if (T2) T2->parent = c;
	c->rc = T3; if (T3) T3->parent = c;
	updateHeight(c);
 
	b->lc = a; a- >parent = b;
	b->rc = c; c->parent = b;
	updateHeight(b);
	return b;
}

7.1.1.7 rotateAt 3+4重平衡

template<typename T> binNode<T>* bst<T>::rotateAt(binNode<T>* v)
{
    
    
	binNode<T>* p = v->parent; binNode<T>* g = p->parent;   //首先根据v找到p和g节点
	if (g->lc == p)  //失衡是由节点删除导致的(p是g的左孩子)
	{
    
    
		if (p->lc == v) //进一步,v是p的左孩子
		{
    
    
			p->parent = g->parent;
			return connect34(v, p, g, v->lc, v->rc, p->rc, g->rc);
		}
		else
		{
    
    
			v->parent = g->parent;
			return connect34(p, v, g, p->lc, v->lc, v->rc, g->rc);
		}
	}
	else   //失衡是由节点插入造成的
	{
    
    
		if (p->rc == v)
		{
    
    
			p->parent = g->parent;
			return connect34(g, p, v, g->lc, p->lc, v->lc, v->rc);
		}
		else
		{
    
    
			v->parent = g->parent;
			return connect34(g, v, p, g->lc, v->lc, v->rc, p->rc);
		}
	}
}

7.1.2 BST.h

#pragma once
#include "bintree.h"
#include "release.h"
#include <iostream>

template<typename T> class BST:public BinTree<T>{
    
    
    protected:
        BinNodePosi(T) _hot;//“命中”节点的父亲
        BinNodePosi(T) connect34(//3+4调整
            BinNodePosi(T),BinNodePosi(T),BinNodePosi(T),
            BinNodePosi(T),BinNodePosi(T),BinNodePosi(T),BinNodePosi(T));
        BinNodePosi(T) rotateAt(BinNodePosi(T) x);//对x及父亲、祖父做统一的旋转调整
    public:
        virtual BinNodePosi(T) &search(const T& e);//查找
        virtual BinNodePosi(T) insert(const T& e);//插入
        virtual bool remove( const T& e);//删除
};


//查找调用的函数
template <typename T>
static BinNodePosi(T) & searchIn( BinNodePosi(T) & v, const T &e, BinNodePosi(T) & hot){
    
    
    if( !v || (e == v->data)) return v;
    hot = v;
    return searchIn((( e < v->data ) ? v->lc : v->rc), e , hot );
}
//查找
template <typename T> BinNodePosi(T) & BST<T>::search (const T & e)
{
    
     return searchIn( this->_root, e, _hot = nullptr);}

//插入
template <typename T> BinNodePosi(T) BST<T>::insert (const T & e){
    
    
    BinNodePosi(T) & x = search( e ); if(x) return x;
    x = new BinNode<T> ( e, _hot);
    this->_size ++;
    this->updateHeightAbove(x);
    return x;
}

//删除
template <typename T> bool BST<T>::remove( const T& e){
    
    
    BinNodePosi(T) & x = search(e); if( !x ) return false;
    removeAt( x, _hot ); this->_size --;
    this->updateHeightAbove( _hot );
    return true;
}
//删除调用的函数
template <typename T>
static BinNodePosi(T) removeAt( BinNodePosi(T)& x , BinNodePosi(T) & hot ){
    
    
    BinNodePosi(T) w = x;
    BinNodePosi(T) succ = nullptr;
    if( !HasLChild( *x ))
        succ = x = x->rc;
    else if ( !HasRChild( *x ))
        succ = x = x->lc;
    else{
    
    
        w = w->succ();
        T tmp = x->data;
        x->data = w->data;
        w->data = tmp;
        //swap ( x->data, w->data);
        BinNodePosi(T) u = w->parent;
        ((u == x) ? u->rc : u->lc) = succ = w->rc;
    }
    hot = w->parent;
    if( succ ) succ->parent = hot;
    dtl::release( w->data ); dtl::release( w ); return  succ;
}

//3+4连接
template <typename T> BinNodePosi(T) BST<T> :: connect34(
    BinNodePosi(T) a, BinNodePosi(T) b, BinNodePosi(T) c,
    BinNodePosi(T) T0, BinNodePosi(T) T1, BinNodePosi(T) T2, BinNodePosi(T) T3
){
    
    
    a->lc = T0; if( T0 ) T0->parent = a;
    a->rc = T1; if( T1 ) T1->parent = a; BinTree<T>::updateHeight(a);
    c->lc = T2; if( T2 ) T2->parent = c;
    c->rc = T3; if( T3 ) T3->parent = c; BinTree<T>::updateHeight(c);
    b->lc = a; a->parent = b;
    b->rc = c; c->parent = b; BinTree<T>::updateHeight(b);
    return b;
}
//3+4重平衡
template <typename T> BinNodePosi(T) BST<T>::rotateAt( BinNodePosi(T) v){
    
    
    BinNodePosi(T) p = v->parent; BinNodePosi(T) g = p->parent;
    if( p->data < g->data)/*zig*/
        if( v->data < p->data){
    
    /*zig-zig*/
            p->parent = g->parent;
            std::cout << v->data  << std::endl;
            return connect34( v, p, g, v->lc, v->rc, p->rc, g->rc);
        }else{
    
    /*zig-zag*/
            v->parent = g->parent;
            return connect34( p, v, g,  p->lc, v->lc, v->rc, g->rc);
        }
    else/*zag*/
        if( v->data >= p->data){
    
    /*zag-zag*/
            p->parent = g->parent;
            return connect34(g, p, v, g->lc, p->lc, v->lc, v->rc);
        }else{
    
    /*zag-zig*/
            v->parent = g->parent;
            return connect34( g, v, p, g->lc, v->lc, v->rc, p->rc);
        }

}

7.1.3 测试程序

#include "BST.h"
#include <iostream>
using namespace std;
template<typename T> void returnValue(T& a)
{
    
    
    cout << "return_value: " << a << endl;
}

int main(int argc,char* argv[])
{
    
    
	//构造树
	BST<int> bt_test;
	bt_test.insert(36);
	bt_test.insert(27);
	bt_test.insert(58);
	bt_test.insert(53);
	bt_test.insert(69);
	bt_test.insert(50);
	bt_test.insert(54);

	//测试
	cout << bt_test.search(53)->data << endl;//搜索
	bt_test.insert(59);//插入
	//bt_test.remove(50);//删除
	bt_test.insert(51);

	void (* visit)(int& ) = &returnValue;//中序遍历
	bt_test.traverse(bt_test.root(),visit);
}

/*
53
return_value: 27
return_value: 36
return_value: 50
return_value: 51
return_value: 53
return_value: 54
return_value: 58
return_value: 59
return_value: 69
*/

猜你喜欢

转载自blog.csdn.net/ZXG20000/article/details/113951391
7.1