최근 이직 준비를 위해 기본기를 다시 공부하고 있습니다. 면접시 나오는 질문들에 우물쭈물 대답을 못한 적이 한두번이 아니라 ( 왜 아는 것들도 면접때면 생각이 안나게 될까요... ) 반복 복습만이 답인것 같습니다.
그래서 면접 질문시 자주 나오는 링크드 리스트를 구현해봤습니다.
밑의 것은 더블 링크드 리스트로 이전 노드를 가리키는 포인터만 없애면 싱글 링크드 리스트가 됩니다.
( 이걸 백지 코딩 하라고 하면 또 우물쭈물... )
리스트 맨뒤에 데이터를 추가하는 Push_Back 과 리스트 맨 앞에 데이터를 추가하는 Push_Front, 그리고 임의의 노드를 삭제하는 Erase 까지 구현했습니다. 임의의 위치에 데이터를 추가하는 Insert는 Erase를 살짝 바꿔주면 됩니다.
using namespace std; typedef struct _stNode { int iData; _stNode* pPrev; _stNode* pNext; } stNode; class CDoubleLinkedList { public: CDoubleLinkedList(); ~CDoubleLinkedList(); int GetNodeCount( void ) { return m_iNodeCount; } void PushBack( int iData ); void PushFront( int iData ); void Erase( int iData ); void Printf( void ); private: int m_iNodeCount; // 현재 노드 갯수 stNode* m_pHead; // 리스트의 머리 stNode* m_pTail; // 리스트의 꼬리 }; // 생성자 CDoubleLinkedList::CDoubleLinkedList() { // 초기화 m_iNodeCount = 0; m_pHead = NULL; m_pTail = NULL; } // 소멸자 CDoubleLinkedList::~CDoubleLinkedList() { // 소멸시 모든 노드 리스트 삭제 stNode* pNode = m_pHead; stNode* pTemp = pNode; while( NULL != pNode ) { pTemp = pNode; pNode = pNode->pNext; delete pTemp; } m_iNodeCount = 0; } // 리스트 맨 뒤에 추가 void CDoubleLinkedList::PushBack( int iData ) { stNode* pNode = new stNode; pNode->iData = iData; pNode->pNext = NULL; pNode->pPrev = NULL; // 머리가 없으면 처음 추가되는 것이므로, // 머리/꼬리 모두 생성된 노드로 설정. if( !m_pHead ) { m_pHead = m_pTail = pNode; ++m_iNodeCount; return; } // 마지막 노드가 새로 뒤에 추가된 노드를 가리킨다. // 새로 추가된 마지막 노드는 전 노드로 이전 마지막 노드를 가리킨다. // 새로 추가된 노드를 마지막 노드로 설정 한다. m_pTail->pNext = pNode; pNode->pPrev = m_pTail; m_pTail = pNode; ++m_iNodeCount; } // 리스트 맨 앞에 추가 void CDoubleLinkedList::PushFront( int iData ) { stNode* pNode = new stNode; pNode->iData = iData; pNode->pNext = NULL; pNode->pPrev = NULL; // 머리가 없으면 처음 추가되는 것이므로, // 머리/꼬리 모두 생성된 노드로 설정. if( !m_pHead ) { m_pHead = m_pTail = pNode; ++m_iNodeCount; return; } // 새로 첫 번째로 추가된 노드는 이전 첫 번째 노드를 가리킨다. // 이전 첫 번째 노드는 새로 추가된 첫번째 노드를 이전 노드로 가리킨다. // 새로 추가된 노드를 첫 번째 노드로 설정 한다. pNode->pNext = m_pHead; m_pHead->pPrev = pNode; m_pHead = pNode; ++m_iNodeCount; } // 임의의 데이터에 해당 하는 노드 삭제 void CDoubleLinkedList::Erase( int iData ) { stNode* pNode = m_pHead; while( pNode != NULL ) { // 지우려고 하는 데이터와 같으면 삭제 if( pNode->iData == iData ) { stNode* pPrev = pNode->pPrev; stNode* pNext = pNode->pNext; // 이전 노드가 NULL 이라면 현재 노드는 머리다. // 아니라면 이전 노드와 다음 노드를 연결해주자 if( NULL == pPrev ) m_pHead = pNext; else pPrev->pNext = pNext; // 다음 노드가 NULL 이라면 현재 노드는 꼬리다. // 아니라면 다음 노드와 이전 노드를 연결해주자 if( NULL == pNext ) m_pTail = pPrev; else pNext->pPrev = pPrev; delete pNode; --m_iNodeCount; break; } pNode = pNode->pNext; } } // 현재 노드들을 순환해서 출력 void CDoubleLinkedList::Printf( void ) { stNode* pNode = m_pHead; while( pNode != NULL ) { cout << pNode->iData << ", "; pNode = pNode->pNext; } cout << endl; } // 테스트 void main() { CDoubleLinkedList* pList = new CDoubleLinkedList; pList->PushBack( 3 ); pList->PushBack( 4 ); pList->PushBack( 5 ); pList->PushFront( 2 ); pList->PushFront( 1 ); pList->PushFront( 0 ); pList->Printf(); pList->Erase(3); pList->Printf(); pList->Erase(0); pList->Printf(); pList->PushFront( -1 ); pList->Printf(); pList->Erase(5); pList->Printf(); pList->PushBack( 6 ); pList->Printf(); delete pList; }