C++

[강의] 12월 12일 수업정리

k-codestudy 2024. 12. 13. 03:45

오늘은 이진 검색 트리 삭제 부분 완성과 2중 포인터를 사용하여 만든 이진 검색 트리에 대한 수업을 들었다.

 

1. 이진 검색 트리 삭제 ( 3가지 전부 )

// bst.h

#pragma once
#include <stdio.h>

class C_BST
{
private:
	struct S_NODE
	{
		int nData;

		S_NODE* pL;
		S_NODE* pR;
	};

private:
	S_NODE* m_pRoot;

private:
	void printNode(S_NODE* pNode);
	S_NODE* createNode(int nData);
	S_NODE* insertNode(S_NODE* pNode, int nData);
	void findMaxNode(S_NODE*& pMin, S_NODE* pUp);

public:
	C_BST() = default;
	bool insert(int nData);
	bool insertR(int nData);
	void earse(int nData);
	void print();
};

// bst.cpp
#include "bst.h"

void C_BST::printNode(S_NODE* pNode)
{
	if (!pNode)
		return;

	printf("%d ", pNode->nData);
	printNode(pNode->pL);
	printNode(pNode->pR);
}

C_BST::S_NODE* C_BST::createNode(int nData)
{
	S_NODE* pNode = new S_NODE{};
	pNode->nData = nData;
	pNode->pL = nullptr;
	pNode->pR = nullptr;

	return pNode;
}

bool C_BST::insert(int nData) // 문제 root를 대신할 방법이 없음
{
	if (!m_pRoot)
	{
		m_pRoot = createNode(nData);
		return true;
	}

	bool bCreate{};
	S_NODE* pNode = m_pRoot;

	while (pNode->nData != nData)
	{
		if (nData < pNode->nData)
		{
			if (pNode->pL)
			{
				pNode = pNode->pL;
			}
			else
			{
				pNode->pL = createNode(nData); 
				bCreate = true;
			}
		}

		else if (nData > pNode->nData)
		{
			if (pNode->pR)
			{
				pNode = pNode->pR;
			}
			else
			{
				pNode->pR = createNode(nData);
				bCreate = true;
			}
		}
	}

	return bCreate;
}

bool C_BST::insertR(int nData)
{
	if (!m_pRoot)
	{
		m_pRoot = createNode(nData);
		return true;
	}

	insertNode(m_pRoot, nData);
	return false;
}

void C_BST::earse(int nData)
{
	S_NODE* pFind = m_pRoot;
	S_NODE* pUp{};

	while (pFind && pFind->nData != nData) // pFind가 있고 nData가 아닐떄 까지 돌아라 
	{
		pUp = pFind; // 따라오게 만드는 것 

		if (pFind->nData > nData)
			pFind = pFind->pL;
		else if (pFind->nData < nData)
			pFind = pFind->pR;
	}

	if (!pFind)
		return;

	if (pFind->pL && pFind->pR)
	{
		S_NODE* pMinUp = pFind;
		S_NODE* pMin = pFind->pL;
		findMaxNode(pMin, pMinUp);
		//printf("up : %d, min : %d \n", pMinUp->nData, pMin->nData);

		pFind->nData = pMin->nData;
		pFind = pMin;
		pUp = pMinUp;
	}
	

	S_NODE* pNext = pFind->pL;  

	if (pFind->pR)
		pNext = pFind->pR;


	S_NODE* pDel = pFind;

	if (!pUp) // 이게 1, 2를 지우게 되면 m_pRoot를 보장해준 것 -> 그림 그려봐서 해볼 것 
		m_pRoot = pNext;
	else if (pUp->nData >= pFind->nData)
		pUp->pL = pNext;
	else
		pUp->pR = pNext;

	delete pDel;
	
}

C_BST::S_NODE* C_BST::insertNode(S_NODE* pNode, int nData)
{
	if (!pNode)
		return createNode(nData);

	if (pNode->nData > nData)
		pNode->pL = insertNode(pNode->pL, nData);

	else if (pNode->nData < nData)
		pNode->pR = insertNode(pNode->pR, nData);
	
	return pNode;
}

void C_BST::findMaxNode(S_NODE*& pMin, S_NODE* pUp)
{
	if (!pMin->pR)
		return;

	pUp = pMin;
	pMin = pMin->pR;
	findMaxNode(pMin, pUp);
}

void C_BST::print()
{
	printNode(m_pRoot);
	printf("\n");
}

2. 이중 포인터로 만든 이진 검색 트리 

// bst.h
#pragma once

#include <stdio.h>

class C_BST
{
private:
	struct S_NODE
	{
		int nData;
		S_NODE* pL;
		S_NODE* pR;
	};

private:
	S_NODE* m_pRoot;
private:
	S_NODE** findNode(S_NODE** ppNode, int nData); // 대상을 선택하는 코드 
	void printNode(S_NODE* pNode);
	S_NODE* createNode(int nData);

public:
	C_BST() = default;
	bool insert(int nData);
	bool earse(int nData);
	void earseNode(S_NODE** ppNode);
	void print();
};

// bsh.cpp
#include "bst.h"

C_BST::S_NODE** C_BST::findNode(S_NODE** ppNode, int nData) // 일부로 재귀함수로 만들 예정, 주의 -> ppNode는 절대 NULL이 되면 안됨 ( 내용물이 없을순 있지만 경로가 없을수는 없음 )
{
    if (!*ppNode)  // 있어도 return ppNode, 없어도 return ppNode;
        return ppNode;

    if ((*ppNode)->nData < nData)
        return findNode(&(*ppNode)->pL, nData);

    if ((*ppNode)->nData > nData)
        return findNode(&(*ppNode)->pR, nData);

    return ppNode;
}

void C_BST::printNode(S_NODE* pNode)
{
    if (!pNode)
        return;

    printf("%d ", pNode->nData);
    printNode(pNode->pL);
    printNode(pNode->pR);
}

C_BST::S_NODE* C_BST::createNode(int nData)
{
    S_NODE* pNode = new S_NODE{};
    pNode->nData = nData;

    return pNode;
}

bool C_BST::insert(int nData)
{
    S_NODE** ppFind = findNode(&m_pRoot, nData);

    if (*ppFind) // 있으면 중복이니까 실패임 
        return false;

    *ppFind = createNode(nData);
    return true;
}

bool C_BST::earse(int nData)
{
    S_NODE** ppFind = findNode(&m_pRoot, nData);

    if (!*ppFind) // 없으면 삭제할께 없으니 실패
        return false;

    earseNode(ppFind);

    return true;
}

void C_BST::earseNode(S_NODE** ppNode)
{
    S_NODE* pNext = (*ppNode)->pL;
    if ((*ppNode)->pR)
        pNext = (*ppNode)->pR;

    S_NODE* pDel = *ppNode;
    *ppNode = pNext;
    delete pDel;
}

void C_BST::print()
{
    printNode(m_pRoot);
    printf("\n");
}

// main.cpp
#include <iostream>

#include "bst.h"

int main()
{
	C_BST cBst{};

	cBst.insert(5);
	cBst.insert(4);
	cBst.insert(8);
	cBst.insert(9);
	cBst.insert(2);
	cBst.insert(3);
	cBst.insert(1);
	cBst.insert(6);
	cBst.insert(7);

	cBst.print();
	cBst.earse(9);
	cBst.print();
}

'C++' 카테고리의 다른 글

[강의] 12월 16일 수업정리  (0) 2024.12.16
[강의] 12월 13일 수업정리  (0) 2024.12.13
[강의] 12월 11일 수업정리  (0) 2024.12.11
[강의] 12월 10일 수업정리  (0) 2024.12.10
[강의] 12월 6일 수업정리  (1) 2024.12.06