표준::목록 C++ 예와 함께

⚡ 스마트 요약

표준::목록 C++ 이 객체는 이중 연결 리스트로 구현된 시퀀스 컨테이너로, 요소를 비연속적인 메모리에 저장하면서 임의의 위치에 빠르게 삽입 및 삭제할 수 있고, 임의 접근이 아닌 양방향 순차 접근을 지원합니다.

  • 🔗 이중 연결 리스트: 각 요소는 이전 노드와 다음 노드에 대한 링크를 유지하므로 std::list 데이터는 연속적이지 않은 메모리 영역에 저장됩니다.
  • 빠른 삽입 및 삭제: 알려진 위치에서 요소를 추가하거나 제거하는 것은 요소가 이동하는 벡터와는 달리 상수 시간입니다.
  • 🚫 무작위 접근 불가: 요소는 양쪽 끝에서 순차적으로 탐색하여 접근할 수 있으므로 list[3]과 같은 인덱싱은 사용할 수 없습니다.
  • 🧩 생성자 : 기본 생성자, 채우기 생성자, 범위 생성자, 복사 생성자, 이동 생성자 및 초기화 목록 생성자는 서로 다른 방식으로 std::list를 생성합니다.
  • 🛠️ 멤버 기능: push_front(), push_back(), insert(), erase(), size(), reverse(), merge() 함수는 리스트의 내용을 관리합니다.
  • 🤖 AI 지원: GitHub Copilot과 같은 도우미 도구는 간단한 주석에서 std::list 선언, 반복자, 삽입 또는 삭제 로직을 구성해 줍니다.

표준::목록 C++

std::list란 무엇입니까?

In C++`std::list`는 저장 컨테이너를 의미합니다. `std::list`를 사용하면 리스트의 어느 위치에서든 항목을 삽입하고 제거할 수 있습니다. `std::list`는 이중 연결 리스트로 구현되어 있어 리스트 데이터에 양방향으로 순차적으로 접근할 수 있습니다.

표준 템플릿 라이브러리 목록은 빠른 임의 접근을 지원하지 않지만, 모든 방향에서 순차적 접근을 지원합니다.

다양한 메모리 청크에 목록 요소를 분산시킬 수 있습니다. 데이터에 대한 순차적 접근에 필요한 정보는 컨테이너에 저장됩니다. std::list는 런타임 중에 필요에 따라 양쪽 끝에서 확장 및 축소될 수 있습니다. 내부 할당자는 스토리지 요구 사항을 자동으로 충족합니다.

이러한 특징들은 실질적인 질문을 제기합니다. 과연 언제 목록을 활용해야 할까요?

std::list를 사용하는 이유는 무엇입니까?

std::list를 사용하는 이유는 다음과 같습니다.

  • std::list는 배열이나 벡터와 같은 다른 시퀀스 컨테이너에 비해 성능이 더 좋습니다.
  • 삽입, 이동 및 배출 성능이 더 우수합니다.trac어떤 위치에서든 요소를 ​​볼 수 있습니다.
  • std::list는 이러한 작업을 집중적으로 수행하는 알고리즘에서도 더 나은 성능을 발휘합니다.

이유가 명확해졌으니, 다음 단계는 이를 선언하는 구문을 작성하는 것입니다.

목록 구문

std::list를 정의하려면 다음을 가져와야 합니다. 헤더 파일. 다음은 std::list 정의 구문입니다.

template < class Type, class Alloc =allocator<T> > class list;

위의 매개변수에 대한 설명은 다음과 같습니다.

  • T – 포함된 요소의 유형을 정의합니다. T 대신 사용자 정의 유형을 포함하여 모든 데이터 유형을 사용할 수 있습니다.
  • Alloc – 할당자 객체의 유형을 정의합니다. 기본적으로 할당자 클래스 템플릿을 사용합니다. 값에 따라 달라지며 간단한 메모리 할당 모델을 사용합니다.

예제 1

#include <algorithm>
#include <iostream>
#include <list>
int main() {
	std::list<int> my_list = { 12, 5, 10, 9 };

	for (int x : my_list) {
		std::cout << x << '\n';
	}
}

출력:

std::list 생성 및 반복 예제의 출력

다음은 코드의 스크린샷입니다.

C++ for 루프를 사용하여 std::list를 생성하고 출력하는 코드입니다.

Code 설명 :

  1. 해당 기능을 사용하려면 알고리즘 헤더 파일을 포함하십시오.
  2. 해당 기능을 사용하려면 iostream 헤더 파일을 포함하십시오.
  3. 해당 기능을 사용하려면 목록 헤더 파일을 포함하십시오.
  4. main() 함수를 호출합니다. 프로그램 로직은 이 함수의 본문 내에 추가되어야 합니다.
  5. 4개의 정수 집합을 사용하여 my_list라는 목록을 만듭니다.
  6. 사용하십시오 for 루프 반복문 변수 x를 생성합니다. 이 변수는 리스트의 요소들을 순회하는 데 사용됩니다.
  7. 콘솔에 목록의 값을 인쇄합니다.
  8. for 루프 본문의 끝입니다.
  9. main() 함수 본문의 끝입니다.

C++ 기능 나열

일반적인 std::list 함수는 다음과 같습니다.

함수 기술설명
끼워 넣다() 이 함수는 반복자가 가리키는 위치 앞에 새 항목을 삽입합니다.
푸시백() 이 함수는 목록 끝에 새 항목을 추가합니다.
push_front() 목록 앞에 새 항목을 추가합니다.
팝프론트() 목록의 첫 번째 항목을 삭제합니다.
크기() 이 함수는 목록 요소의 수를 결정합니다.
앞쪽() 목록의 첫 번째 항목을 결정합니다.
뒤쪽에() 목록의 마지막 항목을 결정합니다.
역전() 목록 항목을 반전시킵니다.
병합() 두 개의 정렬된 목록을 병합합니다.

생성자

여기에 기능 에 의해 제공 헤더 파일:

  • 기본 생성자 std::list::list() - 요소가 XNUMX개인 빈 목록을 만듭니다.
  • 채우기 생성자 std::list::list() - n개의 요소가 포함된 목록을 만들고 각 요소에 0 값을 할당합니다.
  • 범위 생성자 std::list::list() - 처음부터 마지막까지의 범위에 있는 많은 요소가 포함된 목록을 만듭니다.
  • 복사 생성자 std::list::list()- 기존 목록에 포함된 각 요소의 복사본을 사용하여 목록을 만듭니다.
  • 이동 생성자 std::list::list() - 이동 의미를 사용하여 다른 목록의 요소로 목록을 만듭니다.
  • 초기화 목록 생성자 std::list::list() - 이동 의미를 사용하여 다른 목록의 요소로 목록을 만듭니다.

예제 2

#include <iostream>
#include <list>
using namespace std;
int main(void) {
	list<int> l;
	list<int> l1 = { 10, 20, 30 };
	list<int> l2(l1.begin(), l1.end());
	list<int> l3(move(l1));  
	cout << "Size of list l: " << l.size() << endl;
	cout << "List l2 contents: " << endl;
	for (auto it = l2.begin(); it != l2.end(); ++it)
	      cout << *it << endl;
	cout << "List l3 contents: " << endl;
	for (auto it = l3.begin(); it != l3.end(); ++it)
		cout << *it << endl;
	return 0;
}

출력:

std::list 생성자 예제의 출력 결과

다음은 코드의 스크린샷입니다.

C++ std::list의 기본 생성자, 범위 생성자 및 이동 생성자를 보여주는 코드

Code 설명 :

  1. 해당 기능을 사용하려면 iostream 헤더 파일을 포함하십시오.
  2. 해당 기능을 사용하려면 목록 헤더 파일을 포함하십시오.
  3. 클래스를 호출하지 않고 사용하려면 코드에 std 네임스페이스를 포함하세요.
  4. main() 함수를 호출합니다. 프로그램 로직은 이 함수의 본문 내에 추가되어야 합니다.
  5. l이라는 빈 목록을 만듭니다.
  6. 1개의 정수 집합으로 l3이라는 목록을 만듭니다.
  7. 처음부터 끝까지 l2이라는 목록의 모든 요소를 ​​포함하는 l1라는 목록을 만듭니다.
  8. 이동 의미론을 사용하여 l3이라는 목록을 만듭니다. 목록 l3은 목록 l2와 동일한 내용을 갖습니다.
  9. 다른 텍스트와 함께 콘솔에 l이라는 목록의 크기를 인쇄합니다.
  10. 콘솔에 일부 텍스트를 인쇄합니다.
  11. iterator라는 이름의 반복자를 만들고 이를 사용하여 l2라는 목록의 요소를 반복합니다.
  12. 콘솔에 l2라는 목록의 요소를 인쇄합니다.
  13. 콘솔에 일부 텍스트를 인쇄합니다.
  14. iterator라는 이름의 반복자를 만들고 이를 사용하여 l3라는 목록의 요소를 반복합니다.
  15. 콘솔에 l3라는 목록의 요소를 인쇄합니다.
  16. 프로그램은 성공적으로 완료되면 값을 반환해야 합니다.
  17. main() 함수 본문의 끝입니다.

컨테이너 속성

컨테이너 속성 목록은 다음과 같습니다.

부동산 기술설명
순서 시퀀스 컨테이너는 요소를 엄격한 선형 순서로 정렬합니다. 요소는 시퀀스의 위치에 따라 액세스됩니다.
이중 연결 목록 모든 요소에는 이전 및 다음 요소를 찾는 방법에 대한 정보가 있습니다. 이를 통해 삽입 및 삭제 작업에 일정한 시간을 할애할 수 있습니다.
할당자 인식 할당자 개체는 저장소 크기를 동적으로 수정하는 데 사용됩니다.

목록에 삽입

리스트에 값을 삽입하는 데 사용할 수 있는 다양한 함수가 있습니다. 이를 보여드리겠습니다.

예제 3

#include <algorithm>
#include <iostream>
#include <list>
int main() {
	std::list<int> my_list = { 12, 5, 10, 9 };
	my_list.push_front(11);
	my_list.push_back(18);
	auto it = std::find(my_list.begin(), my_list.end(), 10);
	if (it != my_list.end()) {
		my_list.insert(it, 21);
	}
	for (int x : my_list) {
		std::cout << x << '\n';
	}
}

출력:

std::list에 요소를 삽입한 후의 출력

다음은 코드의 스크린샷입니다.

C++ std::list에서 push_front, push_back 및 insert를 사용하는 코드

Code 설명 :

  1. 해당 기능을 사용하려면 알고리즘 헤더 파일을 포함하십시오.
  2. 해당 기능을 사용하려면 iostream 헤더 파일을 포함하십시오.
  3. 해당 기능을 사용하려면 목록 헤더 파일을 포함하십시오.
  4. main() 함수를 호출합니다. 프로그램 로직은 이 함수의 본문 내에 추가되어야 합니다.
  5. 4개의 정수 집합을 사용하여 my_list라는 목록을 만듭니다.
  6. my_list라는 목록 앞에 요소 11을 삽입합니다.
  7. my_list라는 목록의 끝에 요소 18을 삽입합니다.
  8. iterator를 생성하고 이를 사용하여 my_list 목록에서 요소 10을 찾습니다.
  9. if 문을 사용하여 위 요소가 발견되었는지 여부를 확인합니다.
  10. 요소 21이 발견된 경우 위 요소 앞에 요소 XNUMX을 삽입합니다.
  11. if 문의 본문 끝입니다.
  12. for 루프를 사용하여 루프 변수 x를 만듭니다. 이 변수는 목록 요소를 반복하는 데 사용됩니다.
  13. 콘솔에 목록의 값을 인쇄합니다.
  14. for 루프 본문의 끝입니다.
  15. main() 함수 본문의 끝입니다.

목록에 추가되는 요소는 마찬가지로 쉽게 제거할 수 있습니다.

목록에서 삭제

리스트에서 항목을 삭제하는 것이 가능합니다. erase() 함수를 사용하면 리스트에서 항목 하나 또는 여러 항목을 삭제할 수 있습니다.

  • 단일 항목을 삭제하려면 하나의 정수 위치를 전달하기만 하면 됩니다. 항목이 삭제됩니다.
  • 범위를 삭제하려면 시작 및 종료 반복자를 전달합니다. 이를 보여드리겠습니다.

예제 4

#include <algorithm>
#include <iostream>
#include <list>
using namespace std;
int main() {
	std::list<int> my_list = { 12, 5, 10, 9 };
	cout << "List elements before deletion: ";
	for (int x : my_list) {
		std::cout << x << '\n';
	}
	list<int>::iterator i = my_list.begin();
	my_list.erase(i);
	cout << "\nList elements after deletion: ";
	for (int x : my_list) {
		std::cout << x << '\n';
	}
	return 0;
}

출력:

std::list에서 요소를 삭제한 후의 출력

다음은 코드의 스크린샷입니다.

C++ std::list에서 erase 함수를 사용하는 코드

Code 설명 :

  1. 해당 기능을 사용하려면 알고리즘 헤더 파일을 포함하십시오.
  2. 해당 기능을 사용하려면 iostream 헤더 파일을 포함하십시오.
  3. 해당 기능을 사용하려면 목록 헤더 파일을 포함하십시오.
  4. 클래스를 호출하지 않고 사용하려면 프로그램에 std 네임스페이스를 포함하세요.
  5. main() 함수를 호출합니다. 프로그램 로직은 이 함수의 본문 내에 추가되어야 합니다.
  6. 4개의 정수 집합을 사용하여 my_list라는 목록을 만듭니다.
  7. 콘솔에 일부 텍스트를 인쇄합니다.
  8. for 루프를 사용하여 루프 변수 x를 만듭니다. 이 변수는 목록 요소를 반복하는 데 사용됩니다.
  9. 콘솔에 목록의 값을 인쇄합니다.
  10. for 루프 본문의 끝입니다.
  11. 목록의 첫 번째 요소를 가리키는 반복자 i를 만듭니다.
  12. 반복자 i가 가리키는 지우기() 함수를 사용합니다.
  13. 콘솔에 일부 텍스트를 인쇄합니다.
  14. for 루프를 사용하여 루프 변수 x를 만듭니다. 이 변수는 목록 요소를 반복하는 데 사용됩니다.
  15. 콘솔에 목록의 값을 인쇄합니다. 삭제 후에 발생합니다.
  16. for 루프 본문의 끝입니다.
  17. 프로그램은 성공적으로 완료되면 값을 반환해야 합니다.
  18. main() 함수 본문의 끝입니다.

자주 묻는 질문

std::vector는 O(1)의 임의 접근 시간으로 요소를 연속적인 메모리에 저장하는 반면, std::list는 어디에서든 O(1)의 삽입 또는 삭제 시간을 제공하는 이중 연결 리스트입니다. 인덱싱에는 vector를, 중간 요소 삽입이 잦은 경우에는 list를 선택하세요.

아니요. std::list에는 임의 접근 연산자가 없으므로 list[2]는 컴파일되지 않습니다. begin() 또는 end()에서 한 번에 한 노드씩 반복하여 요소에 접근하는데, 이는 깊은 위치에 대해 선형 O(n) 시간이 소요됩니다.

std::list는 양방향으로 순회하고 push_back을 지원하는 이중 연결 리스트입니다. std::forward_list는 앞으로만 이동하는 단일 연결 리스트로, 노드당 메모리 사용량이 적고 size() 함수나 역방향 반복자를 제공하지 않습니다.

멤버 함수 my_list.sort()를 호출하세요. 이 함수는 대략 N log N 시간 복잡도로 실행되며 동일한 요소는 안정적으로 유지합니다. std::sort 알고리즘은 임의 접근 반복자가 필요하기 때문에 작동하지 않습니다. 내림차순 정렬을 위해서는 sort() 함수에 std::greater를 전달하세요.

노드를 삽입하거나 삭제하는 것은 해당 위치에 대한 반복자를 보유하면 상수 O(1) 시간입니다. 왜냐하면 인접한 포인터만 변경되기 때문입니다. 순회를 통해 해당 위치를 먼저 찾는 데는 여전히 O(n) 시간이 소요됩니다.

네. std::list는 set이 아니므로 중복된 값을 자유롭게 저장할 수 있습니다. push_back, push_front 또는 insert를 호출하면 기존 내용과 관계없이 새 노드가 추가됩니다. 중복 요소를 제거해야 하는 경우에는 std::set을 사용하세요.

예. GitHub 부조종사 std::list 선언, 반복자 루프, 삽입 또는 삭제 호출을 간단한 주석이나 함수 이름으로 작성할 수 있습니다. 작업에 연속적인 저장 공간이 더 적합한 경우 std::vector를 제안하는 경우가 많습니다.

AI 코딩 도우미는 STL 컨테이너 코드 자동 완성, 잘못된 이터레이터 사용 표시, std::list를 std::vector로 변환, 복잡도 비교 분석 등의 기능을 제공합니다. 이러한 기능은 STL 학습 속도를 향상시키지만, 모든 제안에 대한 검토는 여전히 필요합니다.

이 게시물을 요약하면 다음과 같습니다.