1. 程式人生 > >二叉查詢樹&&平衡樹基礎

二叉查詢樹&&平衡樹基礎

操作:二叉查詢樹(插入,查詢,刪除,dfs序,求最值,第k大/小)


 
//二叉查詢樹 
//特點:每個點左子樹上的點都小於該點,右子樹上的點都大於該點 
//沒有取值相同的點 任意點的左右子樹均為二叉查詢樹 
//中序遍歷嚴格單調遞增 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
struct uio{
	int num,cnt,dfs;//num取值 cnt該取值個數 dfs為dfs序 
	int l,r;//左右子節點的編號 
}bst[1001];
int n,root,ccnt=1,midcnt,ans[1000];//root為最終父節點(根節點) ccnt為輸入資料編號 midcnt為中序遍歷編號 
void get(int x)//插入 
{
	ccnt++;
	int pre=0,now=1;
	while(now!=0)
	{
		if(x==bst[now].num)
		{
			bst[now].cnt++;
			return;
		}
		if(x<bst[now].num)
		{
			pre=now;
			now=bst[now].l;
		}
		if(x>bst[now].num)
		{
			pre=now;
			now=bst[now].r;
		}
	}
	bst[ccnt].num=x;
	bst[ccnt].cnt=1;
	if(x<bst[pre].num)
		bst[pre].l=ccnt;
	else
		bst[pre].r=ccnt;
}
int search(int x)//查詢 
{
	int now=1;
	while(now!=0)
	{
		if(x==bst[now].num)
			return now;
		if(x<bst[now].num)
			now=bst[now].l;
		if(x>bst[now].num)
			now=bst[now].r;
	}
	return 0;
}
int getpre(int x) 
{
	int pre=0,now=1;
	while(now!=0)
	{
		if(x==bst[now].num)
			return pre;
		if(x<bst[now].num)
		{
			pre=now;
			now=bst[now].l;
		}
		if(x>bst[now].num)
		{
			pre=now;
			now=bst[now].r;
		}
	}
	return 0;
}
int getnxt(int x)
{
	if(bst[x].l==0)
		return x;
	return getnxt(bst[x].l);
}
void del(int x)//刪除 
{
	int pre=getpre(x);
	int now=search(x);
	if(bst[now].num>1)
	{
		bst[now].num--;
		return;
	}
	if(bst[now].l==0&&bst[now].r==0)
	{
		if(bst[pre].l==now)
			bst[pre].l=0;
		else
			bst[pre].r=0;
	}
	if(bst[now].l!=0&&bst[now].r==0)
	{
		bst[pre].l=bst[now].l;
		if(bst[pre].r==now)
			bst[pre].r=0;
	}
	if(bst[now].l==0&&bst[now].r!=0)
	{
		bst[pre].r=bst[now].r;
		if(bst[pre].l==now)
			bst[pre].l=0;
	}
	if(bst[now].l!=0&&bst[now].r!=0)
	{
		int nxt=getnxt(now);
		swap(bst[now],bst[nxt]);
		del(bst[nxt].num);
	}
}
int getmin(int x)//找最小值 返回下標 
{
	int ans=0,now=1;
	while(now!=0)
	{
		if(bst[now].num<x)
		{
			ans=now;
			now=bst[now].r;
		}
		else
			now=bst[now].l;
	}
	return ans;
}
int getmax(int x)//找最大值 返回下標
{
	int ans=0,now=1;
	if(bst[now].num>x)
	{
		ans=now;
		now=bst[now].l;
	}
	else
		now=bst[now].r;
}
int dfsnummin(int x,int y)//dfs序(升序) x起始點編號 y記序 
{
	if(bst[x].l!=0)
		dfsnummin(bst[x].l,y+1);
	if(bst[x].r!=0)
		dfsnummin(bst[x].r,y+1);
	bst[x].dfs=y;
}
int getnokmin(int x,int k)//找第k小
{
	dfsnummin(1,1);
	int now=1;
	while(now!=0)
	{
		int lsize=0;
		int lson=bst[now].l;
		int rson=bst[now].r;
		if(lson!=0)
			lsize=bst[now].dfs;
		if(x<=lsize)//x在左子樹 
			now=lson;
		else if(lsize+1<=k&&k<=lsize+bst[now].num)//x為當前節點 
			return now;
		else//x在右子樹 
		{
			x-=lsize+bst[now].num;
			now=rson; 
		}	
	}
	return 0;
}
int dfsnummax(int x,int y)//dfs序(降序) x起始點編號 y記序 
{
	if(bst[x].l!=0)
		dfsnummax(bst[x].l,y-1);
	if(bst[x].r!=0)
		dfsnummax(bst[x].r,y-1);
	bst[x].dfs=y;
}
int getnokmax(int x,int k)//找第k大 
{
	dfsnummax(1,n);
	int now=1;
	while(now!=0)
	{
		int rsize=0;
		int lson=bst[now].l;
		int rson=bst[now].r;
		if(rson!=0)
			rsize=bst[now].dfs;
		if(x<=rsize)//x在右子樹 
			now=rson;
		else if(rsize+1<=k&&k<=rsize+bst[now].num)//x為當前節點 
			return now;
		else//x在左子樹 
		{
			x-=rsize+bst[now].num;
			now=rson; 
		}	
	}
	return 0;
}
void do_something()
{
	return;
}
int main()
{
	cin>>n>>root;
	bst[1].num=root;
	bst[1].cnt=1;
	for(int i=1;i<=n;i++)
	{
		int v=0;
		cin>>v;
		get(v);
	}
	do_something(); 
	return 0;
}