#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
struct pnode{ //구조체 선언
char data; //테이터 수식
int num; //트리구조의 번지
struct pnode *left; //왼쪽 노드의 포인터 변수
struct pnode *right; //오른쪽 노드의 포인터 변수
};
typedef struct pnode NODE; //이름을 노드로 정의한다.
NODE *insert(NODE *p, int num, char x) //삽입 함수
{ //포인터 변수와 번지와 데이터를 받음
NODE *temp1; //포인터 선언
NODE *temp2;
if(p==NULL) //포인터 p에 데이터가 없을 경우
{
p=(NODE *)malloc(sizeof(NODE)); //포인터 생성b
if(p==NULL)
{ //생성을 실패했을 경우 에러발생
printf("에러\n");
exit(0);
}
p->num=num; //번지를 구조체에 대입
p->data=x; //계수를 구조체에 대입
p->left=NULL; //왼쪽을 NULL지정
p->right=NULL; //오른쪽을 NULL지정
}
else //포인터 p에 데이터가 있을 경우
{
temp1 = p; //temp1에 p의 주소를 대입
while (temp1 != NULL) //temp1이 NULL 아닐때까지 반복
{
temp2 = temp1; //temp2에 temp1의 주소를 대입
if(temp1->num > num)//temp1의 번지가 입력받은 번지보다 작을 경우
{
temp1=temp1->left; //왼쪽 노드로 이동
}
else //temp1의 번지가 입력받은 번지보다 클 경우
{
temp1 =temp1->right; //오른쪽 노드로 이동
}
} //반복문의 종료되면 더 이상 하위 노드는 없다
if(temp2->num > num)//temp2의 번지가 입력받은 번지보다 작을 경우
{ //왼쪽으로 노드 생성
temp2->left = (NODE *)malloc(sizeof(NODE));
temp2 = temp2->left;
if(temp2 == NULL){ //노드 생성 실패시 에러 발생
printf("에러\n");
exit(0);
}
temp2 -> num = num; //temp2에 번지 대입
temp2 -> data = x; //tmep2에 데이터 대입
temp2 -> left = NULL; //temp2의 왼쪽과 오른쪽을 NULL 입력
temp2 -> right = NULL;
}
else{ //temp2의 번지가 입력받은 번지보다 클 경우
temp2->right = (NODE *)malloc(sizeof(NODE));
//오른쪽으로 노드 생성
temp2 =temp2 ->right;
if(temp2 == NULL){ //노드 생성 실패시 에러 발생
printf("에러\n");
exit(0);
}
temp2 -> num = num; //temp2에 번지 대입
temp2 -> data = x; //temp2에 데이터 대입
temp2 -> left = NULL; //temp2의 왼쪽과 오른쪽을 NULL입력
temp2 -> right = NULL;
}
}
return (p); //리턴 포인터 p
}
NODE *searching(NODE* p, int num, NODE **parent) //검색 함수
{
NODE* current; //노드 포인터 선언
current = p; //current에 입력받은 포인터 p의 주소 대입
*parent = NULL; //이중포인터 parent을 NULL 지정
if(current == NULL) //current가 NULL이면 에러
return(NULL); //리턴 NULL을 해줌
while(current != NULL){ //current가 NULL아닐때까지 반복
if(current->num ==num) //current의 번지가 입력 받은 번지와 같을 경우
return(current); //리턴 current
else{ //번지가 다를 경우
*parent = current; //부모포인터를 current로 지정 후
if(num < current->num) //입력 받은 번지 값보다 current의 번지 같이 클 경우
current = current->left; //current는 왼쪽 지정
else //작을 경우
current = current->right; //current는 오른쪽 지정
}
}
return(NULL);
}
NODE *deletion(NODE* p, int num) //삭제 함수
{
NODE* current, *parent, *temp; //포인터 선언
current = searching(p, num, &parent); //검색 함수를 호출
if(current == NULL) //검색되어 리턴된 값이 NULL이면 에러
{
printf("데이터번지가 없습니다.\n");
return(p);
}
else //검색된 값이 NULL 아니면
{
if(current == p) //검색된 값이 루트와 같을 경우
{
temp = current ->left; //temp에 검색된 값의 왼쪽을 대입하고
parent = current ->right; //parent에 검색된 값의 오른쪽을 대입한다.
p = temp; //p에 temp를 대입
while(temp ->right != NULL) //temp의 오른쪽 같이 NULL아닐 때까지 반복
temp = temp ->right; //temp에 temp 오른쪽 노드값을 대입
temp ->right = parent; //반복문이 끝나면 temp의 오른쪽 노드에 parent의 값을 대입
free(current); //current를 포인터를 해제한다.
return(p);
}
if(current ->left != NULL && current ->right !=NULL)
{ //검색된 값이 루트는 아니지만 양쪽다 노드를 가지고 있을 경우
if(parent ->left == current) //부모 노드의 왼쪽노드와 검색된 값이 같은 경우
{
temp = current ->left; //temp에 검색된 값의 왼쪽노드를 대입
parent ->left = current ->left; //parent의 왼쪽 노드에 검색된 왼쪽 노드를 대입
while(temp ->right != NULL) //temp의 오른쪽 노드가 NULL아닐 때까지 반복
temp = temp->right; //temp에 temp의 오른쪽 노드를 대입
temp->right = current ->right;
//반복이 끝나면 temp의 오른쪽 노드에 검색된 노드의 오른쪽 노드를 대입
current ->left=NULL; //검색된 왼쪽 노드에 NULL을 대입
current ->right=NULL; //검색된 오른쪽 노드에 NULL을 대입
}
else //부모 노드의 오른쪽노드와 검색된 값이 같은 경우
{
temp = current ->right; //temp에 검색된 값의 오른쪽노드를 대입
parent ->right = current ->right;//parent의 오른쪽 노드에 검색된 오른쪽 노드를 대입
while(temp ->left != NULL) //temp의 왼쪽 노드가 NULL아닐 때까지 반복
temp = temp->left; //temp에 temp의 오른족 노드를 대입
temp->left = current ->left;
//반복이 끝나면 temp의 왼쪽 노드에 검색된 노드의 왼쪽 노드를 대입
current ->left=NULL; //검색된 왼쪽 노드에 NULL을 대입
current ->right=NULL; //검색된 오른쪽 노드에 NULL을 대입
}
free(current); //current를 포인터를 해제한다.
return(p);
}
if(current->left == NULL && current ->right != NULL)
{ //검색된 값이 루트는 아니지만 왼쪽에는 NULL이고 오른쪽은 값을 가지고 있을 경우
if(parent ->left ==current) //부모 노드의 왼쪽노드와 검색된 겂이같은 경우
parent ->left = current ->right;//부모의 왼쪽노드와 검색된 노드의 오른쪽 노드 대입
else //부모 노드의 오른쪽 노드와 검색된 값이 같은 경우
parent ->right = current ->right;//부모의 오른쪽노드와 검색된 노드의 오른쪽 노드 대입
current ->right = NULL; //검색된 노드의 오른쪽 노드에 NULL 대입
free(current); //currenat를 포인터를 해제한다.
return(p);
}
if(current ->left != NULL && current ->right ==NULL)
{ //검색된 값이 루트는 아니지만 왼쪽에는 값이 있고 오른쪽에는 값이 NULL일 경우
if(parent ->left == current) //부모노드의 왼쪽 값이 검색된 값과 같을 경우
parent ->left = current ->left;//부모노드의 왼쪽 노드에 검색된 노드의 왼쪽 값을 대입
else //부모노드의 오른쪽 값이 검색된 값과 같을 경우
parent->right = current ->left;//부모노드의 오른쪽 노드에 검색된 노드의 왼쪽 값을 대입
current ->left = NULL; //검색된 노드의 왼쪽 값에 NULL을 대입
free(current); //current를 포인터를 해제한다.
return(p);
}
if(current ->left == NULL && current ->right == NULL)
{ //검색된 값이 루트는 아니지만 왼쪽과 오른쪽 모두 NULL인 경우
if(parent ->left == current) //부모 노드의 왼쪽 노드와 검색된 값이 같은 경우
parent ->left = NULL; //부모 노드의 왼쪽 값을 NULL로 해준다.
else //부모 노드의 오른쪽 노드와 검색된 값이 같은 경우
parent ->right = NULL; //부모 노드의 오른쪽 값을 NULL로 해준다.
free(current); //current를 포인터를 해제한다.
return(p);
}
}
return (p);
}
void preOrder(NODE *ptr){ //전위 운행법 함수
if(ptr){ //재귀적으로 호출
printf("%c ",ptr->data); //루트노드부터 출력후 왼쪽 노드부터 출력
preOrder(ptr->left); //왼쪽 서브 트리를 모두 방문
preOrder(ptr->right); //오른쪽 서브 트리들은 방문
} //모든 노드에 재귀적으로 적용 모든 노드를 한번씩 방문
}
void inOrder(NODE *ptr){ //중위 운행법 함수
if(ptr){ //재귀적으로 호출
inOrder(ptr->left); //먼저 왼쪽 서브 트리를 모두 방문
printf("%c ",ptr->data); //왼쪽 방문이 끝난 노드부터 출력
inOrder(ptr->right); //오른쪽 서브 트리들을 방문
} //모든 노드에 재귀적으로 적용 모든 노드를 한번씩 방문
}
void postOrder(NODE *ptr){ //후위 운행법 함수
if(ptr){ //재귀적으로 호출
postOrder(ptr->left); //왼쪽 서브트리를 모두 방문
postOrder(ptr->right); //오른쪽 서브트리를 모두 방문
printf("%c ",ptr->data); //자식노드가 없거나 출력된 상태이면 출력
} //모든 노드에 재귀적으로 적용 모든 노드를 한번식 방문
}
void printTree(NODE *point) //운행법을 호출 하는 함수
{
printf("\n전위 운행법으로 출력 >> ");
preOrder(point); //전위 운행법 호출
printf("\n");
printf("중위 운행법으로 출력 >> ");
inOrder(point); //중위 운행법 호출
printf("\n");
printf("후위 운행법으로 출력 >> ");
postOrder(point); //후위 운행법 호출
printf("\n");
}
void main(){ //메인 함수
int i, j, del, num; //각종 변수 선언
int k=2;
char x, yn, ny;
NODE *point = NULL;
printf("컴퓨터정보학과 2006270191 정 훈 승\n");
printf("포화 이진 트리의 원하는 레벨을 입력하세요! >> ");
scanf("%d",&j); //레벨을 입력을 받는다.
for(i=2;i<=j;i++){ //레벨 값에 맞는 포화 이진 트리의 노드를 계산
k = k * 2; //2의 k승에 빼기 1을 하면
} k = k - 1; //포화 이진 트리의 총 노드가 나온다.
for (i=1; i<=k;i++){ //총 노드수 만큼 입력을 받는다.
printf("%d번째 부터 번지와 데이터값순으로 입력하세요! >> ",i);
scanf("%d %s",&num, &x); //입력은 번지와 데이터값을 받는다.
point = insert (point, num, x); //삽입 함수를 호출한다.
}
printTree(point); //삽입 함수가 완료하면 운행법을 호출 한다.
printf("삭제를 원하시면 y 종료를 원하시면 n? >> ");
scanf("%s", &yn); //삭제 여부를 물어본다.
if(yn == 'y') //삭제를 원할 경우
{
do
{
printf("삭제할 번지를 입력하세요! >>");
scanf("%d", &del); //삭제할 번지를 입력 받는다
point = deletion(point, del); //입력받은 번지로 삭제 함수를 호출
printf("더 삭제 하실꺼면 y, 그만 삭제를 원하시면 n? >> ");
scanf("%s", &ny); //더 삭제를 원할 경우 계속 반복
if(ny == 'n') //그만 삭제를 원할경우 반복이 종료
{
break;
}
}while(1); //삭제를 원하면 무한 반복
}
else{
exit(0); //처음 삭제를 원하지 않을 경우 종료
}
printTree(point); //만약 삭제를 한번이라도 했으면 운행법 호출
}
// 참 쉽죠? ^^ 재밌게 공부하세요