C++ 数据结构学习 ---- 伸展树

目录

1. 头文件

2. 相关函数

2.1 插入函数

2.2 删除函数

2.3 搜索函数

2.4  伸展函数

3. 完整代码

4. 代码运行结果截图


1. 头文件

需要引入C++ 数据结构学习 ---- 二叉搜索树_孤城寻欢的博客-CSDN博客的二叉搜索树文件

#include"BST.h"

template <typename T> class Splay : public BST<T> { //由BST派生的Splay树模板类
protected:
	BinNodePosi(T) splay(BinNodePosi(T) v); //将节点v伸展至根
public:
	BinNodePosi(T)& search(const T& e); //查找(重写)
	BinNodePosi(T) insert(const T& e); //插入(重写)
	bool remove(const T& e); //删除(重写)
};
//在节点*p与*lc(可能为空)之间建立父(左)子关系
template <typename NodePosi> inline void attachAsLC(NodePosi lc, NodePosi p) { p->lc = lc; if (lc) lc->parent = p; }
 //在节点*p与*rc(可能为空)之间建立父(右)子关系
template <typename NodePosi> inline void attachAsRC(NodePosi p, NodePosi rc) { p->rc = rc; if (rc) rc->parent = p; }

2. 相关函数

2.1 插入函数

//将关键码e插入伸展树中
template <typename T> BinNodePosi(T) Splay<T>::insert(const T& e) { 
	if (BST<T>::_root==NULL) { this->_size = 1; return this->_root = new BinNode<T>(e); } //原树为空
	BinNodePosi(T) t = search(e); if (e == t->data) return t; //目标节点t若存在,伸展至根
	if (t->data < e) { //在右侧嫁接
		t->parent = this->_root = new BinNode<T>(e, NULL, t, t->rc); //lc == t必非空
		if (t->rc) { t->rc->parent = this->_root; t->rc = NULL; } //rc或为空
	}
	else { //在左侧嫁接
		t->parent = this->_root = new BinNode<T>(e, NULL, t->lc, t); //rc == t必非空
		if (t->lc) { t->lc->parent = this->_root; t->lc = NULL; } //lc或为空
	}
	this->_size++; this->updateHeightAbove(t); return this->_root; //更新规模及高度,报告插入成功
} //无论e是否存在于原树中,返回时总有_root->data == e

2.2 删除函数

//从伸展树中删除关键码e
template <typename T> bool Splay<T>::remove(const T& e) { 
    if (!BST<T>::_root || (e != search(e)->data)) return false; //若目标存在,则伸展至根
    BinNodePosi(T) L = BST<T>::_root->lc;
    BinNodePosi(T) R = BST<T>::_root->rc;
    release(BST<T>::_root);//记下左、右子树L、R后,释放之
   if ( !R ) { //若R空,则
      if ( L ) L->parent = NULL; BST<T>::_root = L; //L即是余树
   } else { //否则
       BST<T>::_root = R; R->parent = NULL; search( e ); //在R中再次查找e:注定失败,但其中的最小节点必
      if (L) L->parent = BST<T>::_root; BST<T>::_root->lc = L; //伸展至根(且无左孩子),故可令其以L作为左子树
   }
   if ( --BST<T>::_size ) this->updateHeight (BST<T>::_root ); return true; //更新规模及树高,报告删除成功
}

2.3 搜索函数

//在伸展树中查找e
template <typename T> BinNodePosi(T)& Splay<T>::search(const T& e) { 
    BinNodePosi(T) p = BST<T>::search(e);
    BST<T>::_root = splay(p ? p : BST<T>::_hot); //将最后一个被访问的节点伸展至根
    return BST<T>::_root;
} //与其它BST不同,无论查找成功与否,_root都指向最后被访问的节点

2.4  伸展函数


//Splay树伸展算法:从节点v出发逐层伸展
template <typename T> BinNodePosi(T) Splay<T>::splay(BinNodePosi(T) v) { //v为因最近访问而需伸展的节点位置
    if (!v) return NULL; BinNodePosi(T) p; BinNodePosi(T) g; //*v的父亲与祖父
    while ((p = v->parent) && (g = p->parent)) { //自下而上,反复对*v做双层伸展
        BinNodePosi(T) gg = g->parent; //每轮之后*v都以原曾祖父(great-grand parent)为父
        if (IsLChild(*v))
            if (IsLChild(*p)) { //zig-zig
                std::cout << "zIg-zIg :"<<"g:"<<g->data<<" p:" << p->data<<" v:" << v->data << std::endl;
             //   printf("\tzIg-zIg :"); print(g); print(p); print(v); printf("\n");
                attachAsLC(p->rc, g); attachAsLC(v->rc, p);
                attachAsRC(p, g); attachAsRC(v, p);
            }
            else { //zig-zag
                std::cout << "zIg-zAg :" << "g:" << g->data << " p:" << p->data << " v:" << v->data << std::endl;
                //printf("\tzIg-zAg :"); print(g); print(p); print(v); printf("\n");
                attachAsLC(v->rc, p); attachAsRC(g, v->lc);
                attachAsLC(g, v); attachAsRC(v, p);
            }
        else if (IsRChild(*p)) { //zag-zag
            std::cout << "zAg-zAg :" << "g:" << g->data << " p:" << p->data << " v:" << v->data << std::endl;
            //printf("\tzAg-zAg :"); print(g); print(p); print(v); printf("\n");
            attachAsRC(g, p->lc); attachAsRC(p, v->lc);
            attachAsLC(g, p); attachAsLC(p, v);
        }
        else { //zag-zig
            std::cout << "zAg-zIg :" << "g:" << g->data << " p:" << p->data << " v:" << v->data << std::endl;
            //printf("\tzAg-zIg :"); print(g); print(p); print(v); printf("\n");
            attachAsRC(p, v->lc); attachAsLC(v->rc, g);
            attachAsRC(v, g); attachAsLC(p, v);
        }
        if (!gg) v->parent = NULL; //若*v原先的曾祖父*gg不存在,则*v现在应为树根
        else //否则,*gg此后应该以*v作为左或右孩子
            (g == gg->lc) ? attachAsLC(v, gg) : attachAsRC(gg, v);
        this->updateHeight(g); this->updateHeight(p); this->updateHeight(v);
    } //双层伸展结束时,必有g == NULL,但p可能非空
    if (p = v->parent) { //若p果真非空,则额外再做一次单旋
        if (IsLChild(*v)) {
            std::cout << "zIg :" << "p:" << p->data <<" v:"<< v->data << std::endl;
           // printf("\tzIg :"); print(p); print(v); printf("\n"); 
        }
        else {
            std::cout << "zAg :" << "p:" << p->data << " v:" << v->data << std::endl;
           // printf("\tzAg :"); print(p); print(v); printf("\n"); 
        }
        if (IsLChild(*v)) { attachAsLC(v->rc, p); attachAsRC(v, p); }
        else { attachAsRC(p, v->lc); attachAsLC(p, v); }
        this->updateHeight(p); this->updateHeight(v);
    }
    v->parent = NULL; return v;
} //调整之后新树根应为被伸展的节点,故返回该节点的位置以便上层函数更新树根

3. 完整代码



#include<iostream>
#include "SplayTree.h"

using namespace std;

int main() {
	Splay<int> sb;
	BinNodePosi(int) root = sb.insertAsRoot(5);
	sb.insert(6);
	sb.insert(4);
	sb.insert(0);
	sb.insert(7);
	sb.insert(8);
	sb.insert(9);
	sb.travLevel(root);
	sb.search(0);
	sb.travLevel(root);
	cout << endl;
	system("pause");
	return 0;
}

4. 代码运行结果截图

 以上相关代码参考邓俊辉老师的《c++语言版数据结构》!

猜你喜欢

转载自blog.csdn.net/qq_58240448/article/details/127869107