通向码农的道路(从头写stl map 基本实现)

来源:互联网 发布:学位英语考试题库软件 编辑:程序博客网 时间:2024/06/05 18:00

是不是向外科手术一样的精准,我们拿起锋利的刀子划开stl 坚韧的皮肤,在一刀下去,刨开它的肌理,掏出内脏,反复研究观察 终于掏挖除了原始的 console program 

我们终于彻底了解了无所谓的程式!

#include <iostream>

#include <map>
#include <sys/time.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <limits.h>
#include <unistd.h>
using namespace std;
#define EQ(a, b) ((a)==(b))
#define LT(a, b) ((a)<(b))
#define LQ(a, b) ((a)<=(b))
#define GT(a, b) ((a)>(b))
enum style {Pre, In, Post}; //先序,中序,后序
enum Color {Red, Black}; //红黑标志
template<typename T>
struct RBTNode
{
T data; //节点数据类型,目前默认key 为 int
Color RB;//节点颜色,比二叉链表多次节点
RBTNode<T> *lchild, *rchild; //左右孩子指针
};


#define BiTNode RBTNode
template<typename T>
class Map
{
public:
RBTNode<T> *root;

void Child(BiTNode<T>* p, BiTNode<T>* &left, BiTNode<T>* &right)const
{
 
left=p->lchild;
right=p->rchild;
}

RBTNode<T>* Uncle(RBTNode<T>* p)const
{
//初始条件: p指向二叉树中的某个节点
//操作结果: 若p的叔叔节点存在,则返回它的叔叔的指针,否则返回NULL
 
RBTNode<T> *g, *l, *r, *a=Parent(p); //a指向p的双亲
if(a!=NULL)//p存在双亲节点
{
g=Parent(a);//g指向p的祖父
Child(g, l, r); //l r 分别指向g的左右孩子
if(l==a) //a 是 g的左孩子
return r;
else //a 是 g的右孩子
return l;
}
return NULL; //p不存在双亲节点,也就不存在叔叔节点
}

BiTNode<T>* Parent(BiTNode<T>* p)const
{
//获取父亲节点,从根节点出发,寻找
if(root==p)
return NULL;
BiTNode<T> *q=root;
while(q!=NULL)
{
if(q->data.key>p->data.key)//p在左子树中
if(q->lchild==p)
return q;
else
q=q->lchild;//继续左找
else
if(q->rchild==p)
return q;
else
q=q->rchild;//继续右找
}
return NULL;
}
BiTNode<T>* Grandfather(BiTNode<T>* p)const
{  
BiTNode<T> *a=Parent(p);
if(a!=NULL)
a=Parent(a);
return a;
}

void AdjustDoubleRed(RBTNode<T>* &s, RBTNode<T>* &p)
{
//对*s和*s的双亲节点*p作递归双红调整
RBTNode<T> *u, *g, *gp;
int flag;
u=Uncle(s);//u指向s的叔叔节点
g=Grandfather(s);//g指向s的祖父节点
if(g==root) //s的祖父节点是根节点
flag=0;//g的根节点的标志
else //s的祖父节点不是根节点
{
gp=Parent(g);//gp是g的双亲(s的曾祖父)
if(g->data.key<gp->data.key)
flag=1;//g 是gp的左孩子
else
flag=2;//g 是gp的右孩子
}
if(u==NULL || u->RB==Black)//情况1,叔叔节点为黑色或空
{
if(g->data.key>p->data.key)
if(p->data.key>s->data.key)
LL_Rotate(g);//对树作ll型平衡处理
else
LR_Rotate(g);//对树作lr型平衡处理
else
if(p->data.key<s->data.key)
RR_Rotate(g);//对树g作rr型平衡处理
else
RL_Rotate(g);//对树g作rl型平衡处理
g->RB=Black;//"^"型的中间节点着黑色
g->lchild->RB=g->rchild->RB=Red; //"^"型的两边节点着红色
switch(flag)
{
case 0: root=g; break;//更新根节点
case 1: gp->lchild=g; break; //重接*g子树
case 2: gp->rchild=g;//重接*g子树
}
}
else//情况2,叔叔节点为红色
{
p->RB=u->RB=Black;//设置双亲节点和叔叔节点为黑色
if(flag>0)//祖父节点不是根节点
{
g->RB=Red;//设置祖父节点为红色
u=Parent(g);//u为祖父节点的双亲节点
if(u->RB==Red)//出现双红问题
AdjustDoubleRed(g, u);//向上作递归双红调整
}
}
}

void LL_Rotate(BiTNode<T>* &p)
{
//对*p为根的二叉树的LL型失衡,作平衡处理
BiTNode<T> *lc=p->lchild;//lc指向中值节点
p->lchild=lc->rchild;//大值节点的新左孩子为中值节点的右孩子
lc->rchild=p;//中值节点的新有孩子为大值节点
p=lc;//p指向中值节点 新的根节点
}
void RR_Rotate(BiTNode<T>* &p)
{
//对*p为根的二叉树的RR型失衡,作平衡处理
BiTNode<T> *rc=p->rchild;//rc指向中值节点
p->rchild=rc->lchild;//小值节点的新右孩子为中值节点的左孩子
rc->lchild=p;//中值节点的新左孩子为小值节点
p=rc;//p指向中值节点 
}
void LR_Rotate(BiTNode<T>* &p)
{
//对*p为根的二叉树的LR型失衡,作平衡处理
BiTNode<T> *lc=p->lchild;//lc指向小值节点
p->lchild=lc->rchild->rchild;//中值节点的右子树为大值节点的左子树
lc->rchild->rchild=p;//大值节点成为中值节点的右子树
p=lc->rchild;//根指针指向中值节点
lc->rchild=p->lchild;//中值节点的左子树成为小值节点的右子树
p->lchild=lc;//小值节点成为中值节点的左子树
}
void RL_Rotate(BiTNode<T>* &p)
{
//对*p为根的二叉树的RL型失衡,作平衡处理
BiTNode<T> *rc=p->rchild;//rc指向大值节点
p->rchild=rc->lchild->lchild;//中值节点的左子树为小值节点的右子树
rc->lchild->lchild=p;//小值节点成为中值节点的左子树
p=rc->lchild;//根指针指向中值节点
rc->lchild=p->rchild;//中值节点的右子树成为大值节点的左子树
p->rchild=rc;//大值节点成为中值节点的右子树
}




void AdjustDoubleBlack(RBTNode<T>* &pa, bool lr)
{
//由于*pa的左 lr=true 或右 lr = false 子树的黑色深度减1作双黑调整
RBTNode<T> *gp;
int flag;
if(pa==root)//pa是根节点
flag=0; //pa是根节点的标志
else //pa不是根节点
{
gp=Parent(pa);//gp是pa的双亲
if(pa->data.key<gp->data.key)
flag=1; //pa是gp的左孩子
else
flag=2; //pa是gp的右孩子
}
if(lr) //*pa的左孩子被删除
{
if(pa->lchild!=NULL && pa->lchild->RB==Red)//*pa的新左孩子存在且是红色
pa->lchild->RB=Black;//设置*pa的新左孩子为黑色
else//*pa的新左孩子不存在或是黑色
{
if(pa->rchild!=NULL && pa->rchild->RB==Black) //*pa的右孩子是黑色
{
//*pa的右孩子的右孩子是红色
if(pa->rchild->rchild!=NULL && pa->rchild->rchild->RB==Red)
//*pa的右孩子的颜色同*pa的 新根
{
pa->rchild->RB=pa->RB;
pa->RB=pa->rchild->rchild->RB=Black;//*pa和*pa的右孩子的右孩子颜色为黑
RR_Rotate(pa);//对树pa做rr型处理
switch(flag)
{
case 0: root=pa; break;
case 1: gp->lchild=pa; break;
case 2: gp->rchild=pa;
}
}
else if(pa->rchild->lchild!=NULL && pa->rchild->lchild->RB==Red)
{
//*pa的右孩子的左孩子是红色
pa->rchild->lchild->RB=pa->RB;//*pa的右孩子的左孩子新根颜色同*pa
pa->RB=pa->rchild->RB=Black;//*pa和*pa的右孩子颜色为黑
RL_Rotate(pa);//对树pa做rl型处理
switch(flag)
{
case 0: root=pa; break;
case 1: gp->lchild=pa; break;
case 2: gp->rchild=pa;
}
}
else //*pa的右孩子的左右孩子都是黑色或空
{
pa->rchild->RB=Red;
if(pa->RB==Red)
pa->RB=Black;
else
{
//递归处理*gp的双黑问题
switch(flag)
{
case 1: AdjustDoubleBlack(gp, true); break;
case 2: AdjustDoubleBlack(gp, false);
}
}
}
}
else if(pa->rchild!=NULL && pa->rchild->RB==Red)//*pa的右孩子是红色
{
pa->RB=Red;//设置*pa为红色
pa->rchild->RB=Black; //设置*pa的右孩子为黑色
RR_Rotate(pa);//对树pa作rr型平衡处理
switch(flag)
{
case 0: root=pa; break;
case 1: gp->lchild=pa; break;
case 2: gp->rchild=pa;
}
AdjustDoubleBlack(pa->lchild, true);//地柜调整
}
}
}
else//*pa的右孩子被删除
{
if(pa->rchild!=NULL && pa->rchild->RB==Red)//*pa的新孩子存在且是红色
pa->rchild->RB=Black;//设置*pa的新右孩子为黑色
else
{
if(pa->lchild!=NULL && pa->lchild->RB==Black)//*pa的左孩子是黑色
{
if(pa->lchild->lchild!=NULL && pa->lchild->lchild->RB==Red)
{
//*pa的左孩子的左孩子是红色
pa->lchild->RB=pa->RB;//*pa的左孩子的颜色同*pa的新根
pa->RB=pa->lchild->lchild->RB=Black;//*pa和*pa的左孩子的左孩子为黑
LL_Rotate(pa);//对树作ll行处理
switch(flag)
{
case 0: root=pa; break;
case 1: gp->lchild=pa; break;
case 2: gp->rchild=pa;
}
}
//*pa的左孩子的右孩子是红色
else if(pa->lchild->rchild!=NULL && pa->lchild->rchild->RB==Red)
{
//*pa的左孩子的右孩子新根颜色同*pa
pa->lchild->rchild->RB=pa->RB;
pa->RB=pa->lchild->RB=Black;//*pa和*pa的颜色为黑
LR_Rotate(pa);//对树pa作lr型平衡处理
switch(flag)
{
case 0: root=pa; break;
case 1: gp->lchild=pa; break;
case 2: gp->rchild=pa;
}
}
else
{//*pa的左孩子的左孩子都是黑色或空
pa->lchild->RB=Red;
if(pa->RB==Red)
pa->RB=Black;
else//递归处理*gp双黑问题
switch(flag)
{
case 1: AdjustDoubleBlack(gp, true); break;
case 2: AdjustDoubleBlack(gp, false);
}
}
}
else if(pa->lchild!=NULL && pa->lchild->RB==Red)//*pa的左孩子是红色
{
pa->RB=Red;//设置*pa为红色
pa->lchild->RB=Black;//设置*pa的左孩子为黑色
LL_Rotate(pa);//对树pa作ll型平衡处理
switch(flag)
{
case 0: root=pa; break;
case 1: gp->lchild=pa; break;
case 2: gp->rchild=pa;
}
AdjustDoubleBlack(pa->rchild, false);//递归调整
}
}
}
}
void Delete(RBTNode<T>* &p)
{
//从红黑树中删除p所指节点,并重接它的左或右子树
RBTNode<T> *pa, *s, *q=p; //q指向呆删除的节点
bool lr, deleflag=false;//调用双黑调整的标志,初始化为false为不调用
bool rootflag=(p==root);//p是根指针的标志
if(p->rchild==NULL || p->lchild==NULL)//*p至多有一个孩子
{
if(p->RB==Black && p!=root)//待删节点是黑色且不是根节点
{
deleflag=true;//需要调用adjustDoubleBlack()
pa=Parent(p);//pa指向待删除节点的双亲
if(p->data.key<pa->data.key)//待删节点是pa的左孩子
lr=true;
else//待删节点是pa的右孩子
lr=false;
}
if(p->rchild==NULL)//p的右子树空 待删节点是叶子也走次分支
p=p->lchild;//p指向待删除节点的右子树
else
p=p->rchild;//待删除节点是根节点且删除后树不空
if(rootflag && p!=NULL)//设置新根节点为黑色
p->RB=Black;
delete q;//释放带删除节点
}
else //p的左右子树均不空
{
s=p->lchild; //s指向待删除节点的左孩子 s由p转左
while(s->rchild!=NULL) //s有右孩子
{
q=s;
s=s->rchild;//s指向s的右孩子
}
if(s->RB==Black)//新删除节点是黑色
{
deleflag=true;//需要调用adjustdoubleblack
pa=Parent(s);//pa指向待删除节点的双亲
if(s->data.key<pa->data.key)//待删除节点是pa的左孩子
lr=true;
else //待删节点是pa的右孩子
lr=false;
}
p->data=s->data;//将待删除节点的前驱的值取代待删节点的值
if(q!=p)//待删除节点的左孩子有右子树
q->rchild=s->lchild;
else//待删节点的左孩子没有右子树
q->lchild=s->lchild;
delete s;//释放s所指节点
}
if(deleflag)
AdjustDoubleBlack(pa, lr);//作双黑调整
}

public:


//按照一定方式进行先序,中序,后序遍历
void OrderTraverse(BiTNode<T>* t,style mode,void(*visit)(BiTNode<T>*))const
{
if(t!=NULL)
{
if(mode==Pre)
visit(t);
OrderTraverse(t->lchild, mode, visit);
if(mode==In)
visit(t);
OrderTraverse(t->rchild, mode, visit);
if(mode==Post)
visit(t);
}
}

Map()
{
size = 0;
root = NULL;
}

RBTNode<T>* Find(int e)
{
if(root == NULL)
{
return NULL;
}
return FindRBTree(root,e);
}

RBTNode<T> *FindRBTree(BiTNode<T>*&p,int e)
{
if(p == NULL)
{
return NULL;
}
else
{
if EQ(p->data.key,e)
{
return p;
}
else if LT(p->data.key,e)
{
FindRBTree(p->rchild,e);
}
else
{
FindRBTree(p->lchild,e);
}

}

}
bool SearchBST(BiTNode<T>* &p, int key, BiTNode<T>* f, BiTNode<T>* &q)const
{
if(p==NULL)
{
q=f;
return false;
}
else if EQ(key, p->data.key)
{
q=p;
return true;
}
else if LT(key, p->data.key)
return SearchBST(p->lchild, key, p, q);
else
return SearchBST(p->rchild, key, p, q);
}

RBTNode<T> * Begin()
{
if(root == NULL)
{
return NULL;
}
if(size == 1)
{
return root;
}
return BeginNode(root);
}

RBTNode<T> * End()
{
if(root == NULL)
{
return NULL;
}
if(size == 1)
{
return root;
}
return EndNode(root);
}


RBTNode<T> * BeginNode(BiTNode<T>*p)
{
if(p->lchild == NULL)
{
return p;
}
else
{
BeginNode(p->lchild);
}


}


RBTNode<T> * EndNode(BiTNode<T>*p)
{
if(p->rchild == NULL)
{
return p;
}
else
{
EndNode(p->rchild);
}
}

bool Insert(T e)
{
//若红黑树中没有关键字等于e.key的元素,插入e并返回true,否则返回false
RBTNode<T> *p, *s;
if(!SearchBST(root, e.key, NULL, p))
{//查找不成功,p指向查找路径上访问的最后一个叶子节点
s=new RBTNode<T>;
s->data = e;
s->lchild=s->rchild=NULL;
if(p==NULL)
{
root=s; //待插节点*s为新根节点
s->RB=Black;//根节点着黑色
}
else//树不空
{//p指向s的父节点
if LT(e.key, p->data.key)//*s的key 小于 *p的key
p->lchild=s; //待插节点*s 为p所指节点的左孩子
else
p->rchild=s;//待插节点*s 为p所指节点的右孩子
s->RB=Red;
if(p->RB==Red)
AdjustDoubleRed(s, p);//对s 和s的双亲节点作双红调整
}
size++;
return true;
}
else //查找成功,树中已有关键字相同节点,不在插入
return false;
}
RBTNode<T> *Root()
{
return root;
}
bool Clear()
{
if(root == NULL)
{
return false;
}

return ClearTree(root);
}

bool ClearTree(BiTNode<T>*&p)
{
if(p !=NULL)
{
ClearTree(p->lchild);
ClearTree(p->rchild);
delete p;
size --;
p = NULL;
}
}

bool Erase(int key)
{
return DeleteBST(root, key);
}

bool DeleteBST(BiTNode<T>* &p, int key)
{
 
if(p==NULL)
return false;
else
{
if EQ(key, p->data.key)
{
Delete(p);
size--;
return true;
}
else if LT(key, p->data.key)
return DeleteBST(p->lchild, key);
else
return DeleteBST(p->rchild, key);
}
}
int Size()
{
return size;
}
int size;

};


template<typename T>
void VisitRB(RBTNode<T> *c)
{
cout<<c->data.key<<" ";
}


struct Test
{
int  key;
int  val;
};


int main()
{
Map<Test> rb;
int64_t t = time(0);
for(int i = 0 ; i < 5; i ++)
{
Test t;
t.key = i;
t.val = i;
bool k = rb.Insert(t);
}

auto iter = rb.Begin();
cout<<iter->data.key<<endl;
auto iterEnd = rb.End();
cout<<iterEnd->data.key<<endl;
cout<<rb.Size()<<endl;
rb.Clear();
cout<<rb.Size()<<endl;
rb.OrderTraverse(rb.Root(),In,VisitRB);
for(int i = 0; i < 1; i++)
{
auto t = rb.Find(i);
}

for(int i = 0 ; i < 1;i++)
{


bool k = rb.Erase(i);
}
return 0;
}
0 0
原创粉丝点击