// 이진 탐색 트리를 대상으로 데이터 저장(노드의 생성과정 포함)
void BSTInsert(BTreeNode ** pRoot, BSTData data)
{
	BTreeNode * pNode = NULL; 
	BTreeNode * cNode = *pRoot;  
	BTreeNode * nNode = NULL;   

	while (cNode != NULL)
	{
		if (GetData(cNode) == data)
			return;

		pNode = cNode;

		if (GetData(cNode) > data)
			cNode = GetLeftSubTree(cNode);
		else
			cNode = GetRightSubTree(cNode);
	}

	nNode = MakeBTreeNode();
	SetData(nNode, data);

	if (pNode != NULL)
	{
		if (GetData(pNode) > data)
			MakeLeftSubTree(pNode, nNode);
		else
			MakeRightSubTree(pNode, nNode);
	}
	else 
	{
		*pRoot = nNode;
	}
}
Exemple #2
0
int main(void) {

    BTreeNode *N1 = MakeBTreeNode();
    BTreeNode *N2 = MakeBTreeNode();
    BTreeNode *N3 = MakeBTreeNode();
    BTreeNode *N4 = MakeBTreeNode();
    BTreeNode *N5 = MakeBTreeNode();

    SetData(N1, 1);
    SetData(N2, 2);
    SetData(N3, 3);
    SetData(N4, 4);
    SetData(N5, 5);

    MakeLeftSubTree(N1, N2);
    MakeRightSubTree(N1, N3);
    MakeLeftSubTree(N3, N4);
    MakeRightSubTree(N3, N5);

    printf ( "1의 오른쪽의 왼쪽 : %d\n", GetData( GetLeftSubTree( GetRightSubTree( N1 ) ) ) );
    printf ( "1의 오른쪽의 오른쪽 : %d\n", GetData( GetRightSubTree( GetRightSubTree( N1 ) ) ) );

    printf ( "N1 후위순회.\n" );
    Traverse(N1);

    printf ( "\n\nN3 후위순회.\n" );
    Traverse(N3);

    
    return 0;
}
// LR 회전
BTreeNode * RotateLR(BTreeNode * bst)
{
	BTreeNode * pNode;
	BTreeNode * cNode;

	pNode = bst;
	cNode = GetLeftSubTree(pNode);
	
	ChangeLeftSubTree(pNode, RotateRR(cNode));   // 부분적 RR 회전
	return RotateLL(pNode);     // LL 회전
}
// LL 회전
BTreeNode * RotateLL(BTreeNode * bst)
{
	BTreeNode * pNode;
	BTreeNode * cNode;

	pNode = bst;
	cNode = GetLeftSubTree(pNode);

	ChangeLeftSubTree(pNode, GetRightSubTree(cNode));
	ChangeRightSubTree(cNode, pNode);
	return cNode;
}
BTreeNode *BSTSearch(BTreeNode *bst,BSTData target){
	BTreeNode *cNode=bst;
	BSTData cData;

	while(cNode!=NULL){
		cData=GetData(cNode);
		if(target==cData) return cNode;
		else if(target<cData) cNode=GetLeftSubTree(cNode);
		else cNode=GetRightSubTree(cNode);
	}
	return NULL;
}
// 두 서브 트리의 높이의 차를 반환
int GetHeightDiff(BTreeNode * bst)
{
	int lsh;    // left sub tree height
	int rsh;    // right sub tree height

	if(bst == NULL)
		return 0;

	lsh = GetHeight(GetLeftSubTree(bst));
	rsh = GetHeight(GetRightSubTree(bst));

	return lsh - rsh;
}
BTreeNode * BSTSearch(BTreeNode * bst, BSTData target)
{
	BTreeNode * cNode = bst;    // current node
	BSTData cd;    // current data

	while(cNode != NULL)
	{
		cd = GetData(cNode);

		if(target == cd)
			return cNode;
		else if(target < cd)
			cNode = GetLeftSubTree(cNode);
		else
			cNode = GetRightSubTree(cNode);
	}

	return NULL;
}
// 트리의 높이를 계산하여 반환
int GetHeight(BTreeNode * bst) 
{
	int leftH;		// left height
	int rightH;		// right height

	if(bst == NULL)
		return 0;

	// 왼쪽 서브 트리 높이 계산
	leftH = GetHeight(GetLeftSubTree(bst));

	// 오른쪽 서브 트리 높이 계산
	rightH = GetHeight(GetRightSubTree(bst));

	// 큰 값의 높이를 반환한다.
	if(leftH > rightH)
		return leftH + 1;
	else
		return rightH + 1;
}
// 트리의 균형을 잡는다.
BTreeNode * Rebalance(BTreeNode ** pRoot)
{
	int hDiff = GetHeightDiff(*pRoot);

	if(hDiff > 1)     // 왼쪽 서브 트리 방향으로 높이가 2 이상 크다면
	{
		if(GetHeightDiff(GetLeftSubTree(*pRoot)) > 0)
			*pRoot = RotateLL(*pRoot);
		else
			*pRoot = RotateLR(*pRoot);
	}
	
	if(hDiff < -1)     // 오른쪽 서브 트리 방향으로 2 이상 크다면
	{
		if(GetHeightDiff(GetRightSubTree(*pRoot)) < 0)
			*pRoot = RotateRR(*pRoot);
		else
			*pRoot = RotateRL(*pRoot);
	}
	
	return *pRoot;
}
void BSTInsert(BTreeNode ** pRoot, BSTData data)
{
	BTreeNode * pNode = NULL;    // parent node
	BTreeNode * cNode = *pRoot;    // current node
	BTreeNode * nNode = NULL;    // new node

	// 새로운 노드가 추가될 위치를 찾는다.
	while(cNode != NULL)
	{
		if(data == GetData(cNode))
			return;    // 키의 중복을 허용하지 않음

		pNode = cNode;

		if(GetData(cNode) > data)
			cNode = GetLeftSubTree(cNode);
		else
			cNode = GetRightSubTree(cNode);
	}
	
	// pNode의 서브 노드에 추가할 새 노드의 생성
	nNode = MakeBTreeNode();    // 새 노드의 생성
	SetData(nNode, data);    // 새 노드에 데이터 저장

	// pNode의 서브 노드에 새 노드를 추가
	if(pNode != NULL)    // 새 노드가 루트 노드가 아니라면,
	{
		if(data < GetData(pNode))
			MakeLeftSubTree(pNode, nNode);
		else
			MakeRightSubTree(pNode, nNode);
	}
	else    // 새 노드가 루트 노드라면,
	{
		*pRoot = nNode;
	}
}
BTreeNode* BSTRemove(BTreeNode** pRoot,BSTData target){
	BTreeNode *pVRoot=MakeBTreeNode();
	BTreeNode *pNode=pVRoot;
	BTreeNode *cNode=*pRoot;
	BTreeNode *dNode,*dcNode,*mNode,*mpNode;
	BSTData delData;

	//가상 노드의 오른쪽 자식이 루트노드
	ChangeRightSubTree(pVRoot,*pRoot);

	//삭제 대상 검색
	while(cNode!=NULL && GetData(cNode)!=target){
		pNode=cNode;
		if(target<GetData(cNode)) cNode=GetLeftSubTree(cNode);
		else cNode=GetRightSubTree(cNode);
	}

	if(cNode==NULL) return NULL;
	
	dNode=cNode;

	//단말 노드인 경우
	if(GetLeftSubTree(dNode)==NULL && GetRightSubTree(dNode)==NULL){
		if(GetLeftSubTree(pNode)==dNode) RemoveLeftSubTree(pNode);
		else RemoveRightSubTree(pNode);
	}
	//하나의 자식 노드를 갖는 경우
	else if(GetLeftSubTree(dNode)==NULL || GetRightSubTree(dNode)==NULL){
		if(GetLeftSubTree(dNode)!=NULL) dcNode=GetLeftSubTree(dNode);
		else dcNode=GetRightSubTree(dNode);
		if(GetLeftSubTree(pNode)==dNode) ChangeLeftSubTree(pNode,dcNode);
		else ChangeRightSubTree(pNode,dcNode);
	}
	//두 개의 자식 노드를 갖는 경우
	else{
		//삭제 노드를 대체할 노드는 삭제 노드의 오른쪽 서브트리에서의 가장 작은 값을 가진 노드
		mNode=GetRightSubTree(dNode); //대체노드
		mpNode=dNode;//대체노드의 부모노드
				
		//삭제 대상의 대체 노드를 찾음
		while(GetLeftSubTree(mNode)!=NULL){
			mpNode=mNode;
			mNode=GetLeftSubTree(mNode);
		}
		
		//대체노드에 저장된 값을 삭제할 노드에 저장
		delData=GetData(dNode); //삭제 될 노드 값 백업
		SetData(dNode,GetData(mNode));

		//대체노드의 부모노드와 자식노드를 연결
		if(GetLeftSubTree(mpNode)==mNode) ChangeLeftSubTree(mpNode,GetRightSubTree(mNode));
		else ChangeRightSubTree(mpNode,GetRightSubTree(mNode));
		
		dNode=mNode;
		SetData(dNode,delData);
	}
	//삭제된 노드가 루트노드인 경우	
	if(GetRightSubTree(pVRoot)!=*pRoot) *pRoot=GetRightSubTree(pVRoot);

	free(pVRoot);
	*pRoot=Rebalance(pRoot);
	return dNode;
}