C++기초

220407~220411_자료구조_링크드 리스트 실행 (Linked List)

hyrule 2022. 4. 18. 14:12
#include <iostream>
#include <time.h>

#include "LinkedList.h"

#define PRINT(string) {std::cout << string << std::endl;}
#define LINESPACING {std::cout << "\n\n\n" <<std::endl;}



//ListSort 함수를 만들어 놓고 -> 리스트 헤더의 Sort 함수에서 이 함수의 주소를 인자로 받는다.
//(이후 설명은 리스트 헤더의 Sort 함수 참조)

//함수 오버로딩으로 여러가지 타입에 대한 비교 함수를 놔둘 예정.
//true = Src가 Dest보다 크다고 확인하고 서로 자리를 바꿈.
bool ListSort(const int& Src, const int& Dest)
{
	return Src > Dest;
}


int main()
{
	srand((unsigned int)time(0));
	rand();

	int LineChange = 0;





	CList<int>		list1;
	CList<float>	list2;
	
	//노드에 데이터 채우기 구현 완료.
	for (int i = 0; i < 100; ++i)
	{
		list1.push_back(i);
	}


	//하지만, 아직 우리는 리스트의 맨 앞이나 맨 뒤의 값만 볼 수 있다. 
	std::cout << "list1.front() = " << list1.front() << std::endl;
	std::cout << "list1.back() = " << list1.back() << std::endl;


	//구현한 erase 기능 작동여부 확인.
	list1.erase(80);


	//우리가 만든 iterator 클래스를 이용하여, 이런 것도 가능하다.
	CList<int>::iterator	iter;
	//CList의 iterator 클래스 iter을 만들고, 반복문을 통해 리스트 목록을 전부 조회할 수 있다.

	LINESPACING;
	PRINT("<Iterator을 이용한 List 출력 및 erase()기능 확인>");
	PRINT("80이 제거되었으면 성공.");
	for (iter = list1.begin(); iter != list1.end(); ++iter)
	{
		std::cout << *iter << ", ";
		if (++LineChange % 10 == 0)
			std::cout << std::endl;
	}


///////////////////////////////////////////////////////////////////////////////
	LINESPACING;
	PRINT("\n\n<erase()기능 구현 확인>");
	PRINT("90이 지워졌으면 성공");
	LineChange = 0;
	for (iter = list1.begin(); iter != list1.end();)
	{
		
		//for문 안에서 erase를 쓸 때는 이렇게 해야한다.
		if (90 == *iter)
		{
			iter = list1.erase(iter);
			continue;
			//continue를 쓰지 않으면, 총 사이즈는 감소했는데 iter 카운트는 그대로여서
			//존재하는 숫자 하나를 더 뛰어넘어서 조회를 해 버린다.(있는데 출력이 안됨)
		}

		std::cout << *iter << ", ";
		++iter;//++iter을 for문에서 뺴서 여기에 놔야 된다.

		//줄바꿈
		if (++LineChange % 10 == 0)
			std::cout << std::endl;
	}
	/*
	<↑ 위 코드의 치명적인 단점>
	for문을 반복할 때, 매번 확인해야 되는 조건문(iter != list1.end())
	에서 함수를 지속적으로 호출하고 있다. (end() 함수)
	이렇게 되면 매번 스택을 생성하여 함수를 실행시키고, 함수 동작이 완료되면
	스택을 정리하는 과정이 반복되기에 속도가 크게 느려진다. 

	<해결법>
	그런데, 어차피 end()함수는 계속 똑같은 값을 반환하므로, 
	end()함수의 주소를 변수에 저장해놓게 되면, 불필요한 함수의 호출이 없어져 속도가 빨라지게 된다.
	*/
	//↓해결
	LineChange = 0;
	CList<int>::iterator iterEnd = list1.end();
	for (iter = list1.begin(); iter != iterEnd; ++iter)
	{
		std::cout << *iter << ", ";

		if (++LineChange % 10 == 0)
			std::cout << std::endl;
	}




///////////////////////////////////////////////////////////////////////////////
	LINESPACING;
	PRINT("\n\n<reverse_iterator을 이용한 역순 출력>");
	//구현한 reverse_iterator을 이용한 역순으로의 출력.
	LineChange = 0;
	CList<int>::reverse_iterator	riter;
	CList<int>::reverse_iterator	riterEnd = list1.rend();
	for (riter = list1.rbegin(); riter != riterEnd; ++riter)
	{
		std::cout << *riter << std::endl;


		if (++LineChange % 10 == 0)
			std::cout << std::endl;
	}
		




///////////////////////////////////////////////////////////////////////////////
	LINESPACING;
	PRINT("\n<범위 erasse(T& a, t& b) 기능 구현 확인>");
	PRINT("10~90까지 지워지면 성공");

	CList<int> EraseTest;
	for (int i = 0; i < 100; ++i)
	{
		EraseTest.push_back(i);
	}
	CList<int>::iterator EraseStart = EraseTest.begin();
	CList<int>::iterator EraseEnd = EraseTest.end();
	for (int i = 0; i < 10; ++i)
	{
		EraseStart++;
		EraseEnd--;
	}
	EraseTest.erase(EraseStart, EraseEnd);

	LineChange = 0;
	iter = EraseTest.begin();
	CList<int>::iterator iterend = EraseTest.end();
	for (; iter != iterend; ++iter)
	{
		std::cout << *iter << ", ";


		if (++LineChange % 10 == 0)
			std::cout << std::endl;
	}





///////////////////////////////////////////////////////////////////////////////
	LINESPACING;
	PRINT("아무키나 누르면 정렬기능 구현부분으로 진행합니다.");
	system("pause");
	system("cls");
	list1.clear();

	//랜덤값을 리스트에 삽입 후 정렬이 되나 확인.
	for (int i = 0; i < 10; ++i)
	{
		list1.push_back(rand());
	}
	
	PRINT("<정렬 이전 리스트>");
	iterEnd = list1.end();
	for (iter = list1.begin(); iter != iterEnd;)
	{
		std::cout << *iter << std::endl;

		++iter;
	}

	list1.Sort(ListSort);

	
	PRINT("\n<정렬 이후 리스트>");
	for (iter = list1.begin(); iter != iterEnd;)
	{
		std::cout << *iter << std::endl;

		++iter;
	}




	return 0;
}