// 이진 탐색 트리를 대상으로 데이터 저장(노드의 생성과정 포함) 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; } }
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; }