#include <iostream>
using namespace std;
//顺序表查找 带哨兵
int sequential(int*a,int n,int key){
//a代表数组,n代表元素个数,key代表关键字
a[0]=key;int i;
for(i=n;a[i]!=a[0];i--);//从后往前,找不到则return 0
return i;
}
//-----------------------------------------------------------------------
//二分有序查找
int binary(int*a,int n,int key){
int low,high,mid;
low=1;high=n;//从两端开始
while(low<=high){//循环结束条件为low>high
mid=(low+high)/2;//平分区间
if(key<a[mid])
high=mid-1;
else if(key>a[mid])
low=mid+1;
else return mid;
//当mid==high了再进入一次循环输出
}
return 0;
}
//--------------------------------------------------------------------------
//二叉排序树
typedef struct tree{
int data;
struct tree*lchild,*rchild;//左右孩子 左边小于根右边大于根
}*ptree;
//查找
int searchbst(ptree t,int key,ptree f,ptree&point){//需要改变传入参数则传指针或者引用
if(!t){//如果找不到
point=f;//point指向最后一个结点
return 0;
}
else if(key==t->data){// 如果找到了
point=t;
return 1;
}
//如果比结点小
else if(key<t->data)
return searchbst(t->lchild,key,t,point);
else//如果比结点大
return searchbst(t->rchild,key,t,point);
}
//插入
int insertbst(ptree&t,int key){
ptree p,s;
if(!searchbst(t,key,NULL,p)){//如果找不到
s=new tree;//建立新节点
s->data=key;
s->lchild=NULL;
s->rchild=NULL;
if(!p)//如果p指向空
t=s;
else if(p->data<key)//如果p的数据比key小
p->rchild=s;
else
p->lchild=s;
return 1;
}
return 0;
}
//删除
int delete_(ptree&t){//删除t结点并重接
ptree q,s;
if(!t->lchild){// 如果左孩子不存在
q=t;t=t->rchild;free(q);//将右孩子接上,释放节点
}
else if(!t->rchild){
q=t;t=t->lchild;free(q);
}
else{//如果左右孩子都存在,意味着不能简单重接
q=t;s=t->lchild;//q从t出发,s从t左孩子出发
while(s->rchild){//一路向右找 找到最后一个右节点
q=s;s=s->rchild;
}//q代表最后一个右节点的父母
t->data=s->data;//将s的值覆盖t的值
if(q!=t){//如果进入了循环 那么将s结点的左子树(s无右子树)接在q的右子树上
q->rchild=s->lchild;
}
//如果没有进入循环 则q和t相等 此时将s结点的左子树(s无右子树)接在q的左子树上
else q->lchild=s->lchild;
free(s);//释放s结点
}
}
int deletebst(ptree&t,int key){//类比查找
if(!t){//如果找不到
return 0;
}
else if(key==t->data){// 如果找到了
return delete_(t);
}
//如果比结点小
else if(key<t->data)
return deletebst(t->lchild,key);
else//如果比结点大
return deletebst(t->rchild,key);
}
void show(ptree&t){
if(!t)return;
cout<<t->data<<endl;
show(t->lchild);
show(t->rchild);
}
//-----------------------------------------------------------------------------
//平衡二叉树
typedef struct bitree{
int data;
int bf;
struct bitree*lchild,*rchild;//左右孩子 左边小于根右边大于根
}*pbitree;
//右旋 以t为根
void right_(pbitree&t){
pbitree l;
l=t->lchild;//令l为t的左孩子 即为新的根节点
t->lchild=l->rchild;//令l的右孩子为t的左孩子
l->rchild=t;//将t接在l右边
t=l;//更新t
}
// 左旋 以t为根
void left_(pbitree&t){
pbitree r;
r=t->rchild;//令r为t的右孩子 即为新的根节点
t->rchild=r->lchild;//令r的左孩子为t的右孩子
r->lchild=t;//将t接在r左边
t=r;//更新t
}
//左平衡
void leftbalance(pbitree&t){//t第一次不平衡
pbitree l,lr;
l=t->lchild;//l为t左孩子
switch(l->bf){//检查l的平衡度(l平衡度不可能为0 否则t不是第一次)
case 1://右旋即可
t->bf=l->bf=0;//令t和l的平衡度为0
right_(t);
break;
case -1://需要双旋
lr=l->rchild; //lr为t左节点的右节点
switch(lr->bf){//如分析
case 1:
t->bf=-1;
l->bf=0;
break;
case 0:
t->bf=l->bf=0;
break;
case -1:
t->bf=0;
l->bf=1;
break;
}
lr->bf=0;//此时lr为根节点
left_(t->lchild);
right_(t);
}
}
//右平衡
void rightbalance(pbitree&t){
pbitree r,rl;
r=t->rchild;
switch(r->bf){
case -1:
t->bf=r->bf=0;
left_(t);
break;
case 1:
rl=r->lchild;
switch(rl->bf){
case -1:
t->bf=1;
r->bf=0;
break;
case 0:
t->bf=r->bf=0;
break;
case 1:
t->bf=0;
r->bf=-1;
break;
}
rl->bf=0;
right_(t->rchild);
left_(t);
}
}
//
int insertavl(pbitree&t,int e,int*taller){
if(!t){//如果t不存在
t=new bitree;
t->data=e;
t->lchild=t->rchild=NULL;
t->bf=0;
*taller=true;//代表需要判断平衡度,长叶子
}
else{//如果找到了
if(e==t->data){
*taller=false;//代表不需要长叶子
return false;
}
if(e<t->data){//如果发现小于 则在左子树里找
if(!insertavl(t->lchild,e,taller))//如果没有插入
return false;
if(*taller){//有新增结点的话
switch(t->bf){//判断平衡度
case 1://原本左子树高 则左平衡
leftbalance(t);
*taller=false;
break;
case 0://原本一样高 左边增高
t->bf=1;
*taller=true;
break;
case -1://原本右子树高 则右平衡
t->bf=0;
*taller=false;
break;
}
}
}
else{//与上同理
if(!insertavl(t->rchild,e,taller))
return false;
if(*taller){
switch(t->bf){
case 1:
t->bf=0;
*taller=false;
break;
case 0:
t->bf=-1;
*taller=true;
break;
case -1:
rightbalance(t);
*taller=false;
break;
}
}
}
return true;
}
}
void show_(pbitree&t){
if(!t)return;
cout<<t->data<<endl;
show_(t->lchild);
show_(t->rchild);
}
int main(){
pbitree t,point;
int a[]={100,3,101,10,6,12,11};
int taller;
for(int i=0;i<=6;i++)
insertavl(t,a[i],&taller);
show_(t);
return 0;
}