c언어

C언어 - 이진탐색트리 배열 확인 가능

pi92 2021. 3. 9. 08:43
#include <stdio.h>

#define SPACE 5

#include <stdio.h>
#include <stdlib.h>

struct tnode {
	int item;		/* number */
	struct tnode* left;	/* left child */
	struct tnode* right;	/* right child */
};

struct tnode* addtree(struct tnode*, int);  // 트리추가함수 선언
void deletetree(struct tnode**, int);      // 트리제거함수 선언
void treeprint(struct tnode*);              // 트리출력함수 선언

void draw_tree_hor(struct tnode* tree);
void draw_tree_hor2(struct tnode* tree, int depth, char* path, int right);

main()
{
	struct tnode* root;
	int cond, num;
	root = NULL;  // 초기화

	while (1) {
		printf("1 : 삽입   2 : 삭제   3 : 출력   4 : 종료\n");
		scanf_s("%d", &cond);
		if (cond == 1) {
			printf("Add Number\n");
			scanf_s("%d", &num);
			root = addtree(root, num);
		}
		else if (cond == 2) {
			printf("Delete Number\n");
			scanf_s("%d", &num);
			deletetree(&root, num);
		}
		else  if (cond == 3) {
			printf("------------출력---------\n");
			treeprint(root);
			printf("------------출력---------\n");
			draw_tree_hor(root);
		}
		else  if (cond == 4)
			break;
		else {
			printf("Wrong Input\n");
			exit(1);
		}

	}
	return 0;
}



struct tnode* addtree(struct tnode* p, int num)
{
	if (p == NULL) {
		p = (struct tnode*)malloc(sizeof(struct tnode));
		p->item = num;
		p->left = p->right = NULL;
	}
	else if (num == p->item)
		printf("존재하는 숫자 입니다\n");
	else if (num < p->item)
		p->left = addtree(p->left, num);
	else
		p->right = addtree(p->right, num);
	return p;
}


void treeprint(struct tnode* p)
{
	if (p != NULL) {
		treeprint(p->left);
		printf("%d\n", p->item);
		treeprint(p->right);
	}
}

void deletetree(struct tnode** p, int num) {

	struct tnode* deleted = *p;
	struct tnode* prev = *p;
	struct tnode* parent = NULL;
	struct tnode* move = NULL;


	if (*p == NULL) { //트리에 숫자가 없을 경우
		printf("삭제 할 수 있는 숫자가 없습니다.\n");
		return;
	}

	if (deleted->item == num) { //지울 값이 루트 값일경우

		if (deleted->left == NULL && deleted->right == NULL) { //루트 값에 자식 데이터가 없으므로 루트값만 남은 상태
			*p = NULL;
			printf("숫자가 모두 삭제되었습니다.\n");
			return; // 초기화 상태로 리턴
		}
		else if (deleted->left == NULL) { // 오른쪽 값만 존재할 경우
			*p = deleted->right;  // 구조체가 가르키는 주소를 오른쪽 값으로 변경하여 오른쪽 값이 루트가 되게만듬
		}
	}

	while ((deleted->item != num)) { //숫자 값을 찾는 반복문

		prev = deleted; // 왼쪽 주소값이 없거나 둘 다 없는경우를 해결하기 위한 값

		if (deleted->item < num)   // 작으면 왼쪽
			deleted = deleted->right;
		else
			deleted = deleted->left; // 크면 오른쪽

		if (deleted == NULL) { // 트리에 삭제 할 숫자가 존재하지 않을경우
			printf("존재하지 않는 숫자입니다.\n");
			return;
		}
	}

	if (deleted->left) { // 왼쪽을 우선 검색

		move = deleted->left; // 먼저 왼쪽 주소값으로 들어간다.

		if (move->right) { //왼쪽의 숫자중 가장 큰 숫자를 검색
			while (move->right != NULL) {
				parent = move;
				move = move->right;
			}
			parent->right = move->left;  //주소를 연결시켜주기
		}
		else
			parent = deleted;

		if (deleted == parent)
			parent->left = move->left;  //주소를 연결시켜주기
		else
			parent->right = move->left; //주소를 연결시켜주기

		deleted->item = move->item; //삭제한 데이터에 이동할 숫자 입력
	}
	else if (deleted->right)        //전 주소를 다음 주소로 연결
		prev->right = deleted->right;
	else if (prev->item > num)        //자식 숫자값이 없는경우
		prev->left = NULL;          //부모값보다 작으니 왼쪽 연결해제
	else
		prev->right = NULL;         //부모값보다 크니 오른쪽 연결해제

}


//primary fuction
void draw_tree_hor(struct tnode* tree)
{
	// should check if we don't exceed this somehow..
	char path[255] = { 0 };

	//initial depth is 0
	draw_tree_hor2(tree, 0, path, 0);
}

//secondary function
void draw_tree_hor2(struct tnode* tree, int depth, char* path, int right)
{
	// stopping condition
	if (tree == NULL)
		return;

	// increase spacing
	depth++;

	// start with right node
	draw_tree_hor2(tree->right, depth, path, 1);

	if (depth > 1)
	{
		// set | draw map
		path[depth - 2] = 0;

		if (right)
			path[depth - 2] = 1;
	}

	if (tree->left)
		path[depth - 1] = 1;

	// print root after spacing
	printf("\n");

	for (int i = 0; i < depth - 1; i++)
	{
		if (i == depth - 2)
			printf("+");
		else if (path[i])
			printf("|");
		else
			printf(" ");

		for (int j = 1; j < SPACE; j++)
			if (i < depth - 2)
				printf(" ");
			else
				printf("-");
	}

	printf("%d\n", tree->item);

	// vertical SPACErs below
	for (int i = 0; i < depth; i++)
	{
		if (path[i])
			printf("|");
		else
			printf(" ");

		for (int j = 1; j < SPACE; j++)
			printf(" ");
	}

	// go to left node
	draw_tree_hor2(tree->left, depth, path, 0);
}