2010-08-15 3 views
9

여기 내 문제가 있습니다, 내가 std :: vector ints 함께 말할 수 있습니다.std :: vector에서 여러 객체 지우기?

50904090806080이라고 가정 해 봅시다.

두 번째, 다섯 번째 및 세 번째 요소를 제거해야한다는 것을 알고 있습니다. 필자는 제거 할 요소의 순서와 횟수를 항상 알 필요가 없습니다. 문제는 요소를 지우는 것입니다. 그러면 다른 요소의 색인이 변경됩니다. 따라서 어떻게 이들을 지우고 인덱스 변경을 보상 할 수 있습니까?

1. 요소의 원래 순서를 유지하지 않는 빠른 방법 :

감사

+0

"오프셋을 사용한 선형 소거는 선택 사항이 아닙니다."이유는 무엇입니까? – Niki

답변

18

나는 여러 가지 방법을 제공하고 (오프셋 (offset)와 지우기 선형 다음 옵션을하지 않는 정렬)

지울 요소에 벡터의 현재 마지막 요소를 할당 한 다음 마지막 요소를 지 웁니다. 이렇게하면 큰 움직임을 피할 수 있고 마지막 색인을 제외한 모든 색인은 일정하게 유지됩니다. 뒤에서 지우기를 시작하면 사전 계산 된 모든 색인이 정확합니다. I이 표시

void quickDelete(int idx) 
{ 
    vec[idx] = vec.back(); 
    vec.pop_back(); 
} 

본질적 ... 소거 제거 관용구의 자필 버전 Klaim으로 지적되고

2 요소의 원래 순서를 유지하는 느린 방법

1 단계 : 삭제할 벡터 요소를 모두 표시합니다 (예 : 특수 값 사용). O (삭제할 색인 |)이 있습니다.

2 단계 : v.erase(remove (v.begin(), v.end(), special_value), v.end());을 사용하여 표시된 모든 요소를 ​​지 웁니다. 이것은 O (| v |)를 가진다.

따라서 인덱스 목록이 벡터보다 짧은 경우 총 실행 시간은 O (| vector v |)입니다.

3 요소의 원래 순서 보유 느린 다른 방법

사용 술어 및 https://stackoverflow.com/a/3487742/280314에 기재된 경우 삭제한다. 이것을 효율화하고 의 요구 사항을 존중하려면 "정렬로 선형 적으로 지우기"를 선택하지 말아야합니다. 제 생각은 해시 테이블을 사용하여 술어를 구현하고 해시 테이블에 저장된 색인을 조정하여 삭제가 true를 반환 할 때 진행되도록하는 것입니다. Klaim은 제안했다.

http://www.cplusplus.com/reference/algorithm/remove_if/이 (remove-erase idiom 참조) 항목을 삭제하는 것을 잊지 마세요 참조 : 술어 당신은 당신이 원하는 것을 달성 할 수 remove_if 알고리즘을 사용하여

+0

마지막 요소가 삭제 예정된 요소 중 하나라면 어떻게 될까요? –

+0

그게 내가 생각하고있는 것 ... – jmasterx

+2

그 다음에 그 자체로 교환하는 것은 아무런 행동도하지 않고'pop_back'은 여전히 ​​올바른 일을합니다. –

14

.

당신의 술어는 단순히 각 값의 idx를 유지하여 true를 반환 할 때마다 유지하는 모든 색인을 제거하고 줄입니다.

그렇다면 제거 삭제 관용구를 사용하여 각 객체를 제거 할 수 있다면 간단하게 작업을 수행하면됩니다.

4

나는 이 아닌 요소를 이동합니다은 임시 벡터로 지우고 원래의 벡터로 바꾸고 싶습니다.

6

항목을 뒤로 지 웁니다. 즉, 가장 높은 인덱스를 먼저 지운 다음 가장 높은 인덱스를 지우십시오. 이전의 반복기 또는 인덱스를 무효화하지 않으므로 다중 지우기 호출의 명백한 접근 방식을 사용할 수 있습니다.

+0

의 설명에 그래도 난 썼다 : – jmasterx

+1

@Milo (AN 옵션을 선택하지 않습니다 오프셋 삭제 선형 다음 정렬) : 좋은 이유가없는 한 임의로 다음 확실히 옵션입니다, 더 나은 솔루션 중 하나 거부 할 수 있습니다. 왜 인덱스를 정렬 할 수 없습니까? –

1

겠습니까이 작품 :

void DeleteAll(vector<int>& data, const vector<int>& deleteIndices) 
{ 
    vector<bool> markedElements(data.size(), false); 
    vector<int> tempBuffer; 
    tempBuffer.reserve(data.size()-deleteIndices.size()); 

    for (vector<int>::const_iterator itDel = deleteIndices.begin(); itDel != deleteIndices.end(); itDel++) 
     markedElements[*itDel] = true; 

    for (size_t i=0; i<data.size(); i++) 
    { 
     if (!markedElements[i]) 
      tempBuffer.push_back(data[i]); 
    } 
    data = tempBuffer; 
} 

그것은 상관없이 삭제 얼마나 많은 요소, 오 (n)이 작동 없습니다. 벡터 인라인 순서를 재정 의하여 효율성을 얻을 수 있습니다 (하지만이 방법은 더 읽기 쉽습니다).

관련 문제