Notice
Recent Posts
Recent Comments
Link
«   2026/03   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Tags more
Archives
Today
Total
관리 메뉴

프로그래밍 공부

Lab07 AVL Tree 코드 본문

자료구조론 랩

Lab07 AVL Tree 코드

하 냥 2024. 4. 3. 19:27

 

전체 코드

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
/* (((X) > (Y)) ? (X) : (Y)) 이 아니라
   ((X) > (Y)) ? (X) : (Y) 가 되어버리면 매크로함수가 내 맘대로 잘 작동을 안한다.. 겉에 괄호 하나 더 씌워주는게 중요하네. */

struct AVLNode;
typedef struct AVLNode* Position;
typedef struct AVLNode* AVLTree;
typedef int ElementType;

typedef struct AVLNode {
	ElementType element;
	AVLTree left, right;
	int height;
}AVLNode;

AVLTree Insert(ElementType x, AVLTree T);
AVLTree Delete(ElementType x, AVLTree T);
Position SingleRotateWithLeft(Position node);
Position SingleRotateWithRight(Position node);
Position DoubleRotateWithLeft(Position node);
Position DoubleRotateWithRight(Position node);
void PrintInorder(AVLTree T);
void DeleteTree(AVLTree T);

/* 트리의 높이를 계산하는 함수 */
int HeightCalc(AVLTree T) {
	if (T == NULL)
		return -1;
	return T->height;
}

/* 값이 최소인 노드를 찾는 함수 */
AVLTree FindMin(AVLTree T) {
	if (T->left == NULL)
		return T;
	else
		return FindMin(T->left);
}

/* 값이 x인 노드가 있는지 찾는 함수 */
int FindNode(ElementType x, AVLTree T) {
	AVLTree tmp = T;

	while (tmp != NULL) {
		if (x == tmp->element)
			return 1;
		else if (x < tmp->element)
			tmp = tmp->left;
		else
			tmp = tmp->right;
	}

	return 0;
}

/* 트리의 균형을 재조정하는 함수 */
AVLTree Balancing(AVLTree T) {
	/* 트리의 균형이 왼쪽으로 2 이상 높을 경우 */
	if (HeightCalc(T->left) - HeightCalc(T->right) >= 2) {
		if (HeightCalc(T->left->left) - HeightCalc(T->left->right) >= 1)
			T = SingleRotateWithLeft(T); // LL회전
		else
			T = DoubleRotateWithLeft(T); // LR회전
	}

	/* 트리의 균형이 오른쪽으로 2 이상 높을 경우 */
	if (HeightCalc(T->right) - HeightCalc(T->left) >= 2) {
		if (HeightCalc(T->right->right) - HeightCalc(T->right->left) >= 1)
			T = SingleRotateWithRight(T); // RR회전
		else
			T = DoubleRotateWithRight(T); // RL회전
	}

	T->height = MAX(HeightCalc(T->left), HeightCalc(T->right)) + 1; // 트리의 균형을 잡은 후 T의 높이 재설정
	return T;
}

/* 값이 x인 노드를 트리에 추가하는 함수 */
AVLTree Insert(ElementType x, AVLTree T) {
	if (T == NULL) {
		T = (AVLTree)malloc(sizeof(AVLNode));

		if (T == NULL) {
			printf("Out of Space!\n");
			return -1;
		}

		T->element = x;
		T->left = T->right = NULL;
		T->height = 0;
	}
	else if (x < T->element) {
		T->left = Insert(x, T->left);
		T = Balancing(T);
	}
	else if (x > T->element) {
		T->right = Insert(x, T->right);
		T = Balancing(T);
	}

	T->height = MAX(HeightCalc(T->left), HeightCalc(T->right)) + 1;
	return T;
}

/* 값이 x인 노드를 트리에서 삭제하는 함수 */
AVLTree Delete(ElementType x, AVLTree T) {
	AVLTree tmp;

	if (x < T->element) {
		T->left = Delete(x, T->left);
		T = Balancing(T);
	}
	else if (x > T->element) {
		T->right = Delete(x, T->right);
		T = Balancing(T);
	}
	
	/* 삭제할 노드를 찾았을 때 밑의 else문 실행 */
	else {
		if (T->left == NULL && T->right == NULL) { // 삭제할 노드가 자식이 하나도 없을 경우
			tmp = T;
			T = NULL;
		}
		else if (T->left == NULL || T->right == NULL) { // 삭제할 노드가 자식이 하나 있을 경우
			if (T->left == NULL) {
				tmp = T->right;
				T->element = tmp->element;
				T->right = Delete(T->element, T->right);
			}
			else {
				tmp = T->left;
				T->element = tmp->element;
				T->left = Delete(T->element, T->left);
			}
		}
		else { // 삭제할 노드가 두 개의 자식이 있을 경우
			tmp = FindMin(T->right);
			T->element = tmp->element;
			T->right = Delete(T->element, T->right);
		}
		free(tmp);
	}

	if (T)
		T->height = MAX(HeightCalc(T->left), HeightCalc(T->right)) + 1;
		
	return T;
}

/* LL회전 담당 함수 */
Position SingleRotateWithLeft(Position node) {
	Position tmp;

	tmp = node->left;
	node->left = tmp->right;
	tmp->right = node;

	tmp->height = MAX(HeightCalc(tmp->left), HeightCalc(tmp->right)) + 1;
	node->height = MAX(HeightCalc(node->left), HeightCalc(node->right)) + 1;

	return tmp;
}

/* RR회전 담당 함수 */
Position SingleRotateWithRight(Position node) {
	Position tmp;

	tmp = node->right;
	node->right = tmp->left;
	tmp->left = node;

	tmp->height = MAX(HeightCalc(tmp->left), HeightCalc(tmp->right)) + 1;
	node->height = MAX(HeightCalc(node->left), HeightCalc(node->right)) + 1;

	return tmp;
}

/* LR회전 담당 함수 */
Position DoubleRotateWithLeft(Position node) {
	Position tmp;

	tmp = node->left;
	tmp = SingleRotateWithRight(tmp);
	node = SingleRotateWithLeft(node);

	return node;
}

/* RL회전 담당 함수 */
Position DoubleRotateWithRight(Position node) {
	Position tmp;

	tmp = node->right;
	tmp = SingleRotateWithLeft(tmp);
	node = SingleRotateWithRight(node);

	return node;
}

/* Inorder 형식으로 트리의 노드들을 출력하는 함수 */
void PrintInorder(AVLTree T) {
	if (T == NULL)
		return;

	PrintInorder(T->left);
	
	printf("%d", T->element);
	printf("(%d) ", T->height);

	PrintInorder(T->right);
}

/* 트리를 완전 삭제하는 함수 */
void DeleteTree(AVLTree T) {
	if (T == NULL)
		return;

	DeleteTree(T->left);
	DeleteTree(T->right);
	free(T);
}

int main(void) {
	AVLTree Tree = NULL;
	char cv;
	int key;

	while (1) {
		scanf("%c", &cv);
		switch (cv) {
		case 'i':
			scanf("%d", &key);

			if (FindNode(key, Tree)) {
				printf("insertion error : %d is already in the tree!\n", key);
				PrintInorder(Tree);
				printf("\n");
			}
			else {
				Tree = Insert(key, Tree);
				PrintInorder(Tree);
				printf("\n");
			}
			break;
		case 'd':
			scanf("%d", &key);

			if (!(FindNode(key, Tree))) {
				printf("deletion error : %d is not in the tree!\n", key);
				PrintInorder(Tree);
				printf("\n");
			}
			else {
				Tree = Delete(key, Tree);

				PrintInorder(Tree);
				printf("\n");
			}
			break;
		case 'q':
			return 0;
		}
	}

	DeleteTree(Tree);
	return 0;
}

'자료구조론 랩' 카테고리의 다른 글

Lab11 Max Heap 코드  (0) 2024.04.10
Lab08 Disjoint Set을 이용한 Maze 만들기 코드  (1) 2024.04.10
Lab06 Binary Search Tree 코드  (1) 2024.03.25