PGR21.com
- PGR21 관련된 질문 및 건의는 [건의 게시판]을 이용바랍니다.
- (2013년 3월 이전) 오래된 질문글은 [이전 질문 게시판]에 있습니다.
통합 규정을 준수해 주십시오. (2015.12.25.)
Date 2019/10/03 21:58:11
Name Kaestro
Subject [질문] c++ 에서 unordered map을 pair를 key로 사용할 때 순회
문제가 지도상에 상하좌우로 증식하는 세포가 주어질 때[맵의 크기 제한 없이] 일정 시간이 지난 후 살아있는 세포의 수를 세는 문제를 풀고 있는데,

솔루션에서는 문제 상에서 숫자 제약조건 때문에 나올 수 있는 최대보다 큰 배열을 이용해서 문제를 해결했는데, 저는 실제로 map 자료구조를 이용해서 문제를 풀어보고 싶어 그렇게 문제를 풀었습니다.

c++ map을 써서 돌아가는 코드는 만들었는데, 크기가 커지면 시간 제약 조건을 통과하지 못해서, 그럼 unordered map을 쓰면 되지 않을까? 하는 생각에 unordered_map으로 자료구조를 바꿨는데 지금 insert를 하고 나서 순회를 하면 문제가 생기더라구요.

아래 코드에서 simulation에서 iterator가 breeding을 하고 나면, 저장되어있는 simulation의 구조가 변형이 되면서 아직 순회해야하는 세포는 건너뛰거나, 아까전에 순회했던 세포를 재차 순회하는 문제가 발생하고 있습니다.

이 문제를 해결하려고 map을 따로 copy 뜨는 식으로 문제도 풀어봤는데, 이건 map을 copy하는게 오래 걸려서 그런지 기존의 map을 이용한 풀이보다 속도가 떨어지더라구요.

이런 경우에 unordered_map에 새로운 노드를 추가하면서, 아직 순회하지 않은 노드를 순회하고, 기존의 unordered_map을 카피하지 않는 방법이 있을까요?

감사합니다.

void simulate() {
    for (int i = 0; i < timeLimit; ++i) {
        for (myMap::iterator it = simulation.begin(); it != simulation.end();++it) {
            if (it->second.active == DEAD || it->second.lifetime == -1) continue;
            if (it->second.active == ACTIVE) {
                const ii& pos = it->first;
                const StemCell& sc = it->second;
                breed(pos, sc);
                it = simulation.find(pos);
            }
        }

        for (myMap::iterator it = simulation.begin(); it != simulation.end(); ++it) {
            it->second.increment();
        }
    }
}

void breed(const ii& pos, const StemCell& st) {
    for (int d = 0; d < direction.size(); ++d) {
        ii nextPos = { pos.first + direction[d].first, pos.second + direction[d].second };
        myMap::iterator it = simulation.find(nextPos);
        if (it == simulation.end()) {
            simulation[nextPos] = StemCell(-1, st.healthPoint);
        } else if (it->second.lifetime == -1){
            if (it->second.healthPoint < st.healthPoint) {
            it->second.healthPoint = st.healthPoint;
            }
        }
    }
}

ps. 전에 이런 질문 올렸을 때 코드 전문을 올려달라 하신 분이 계셨어서, 링크를 달아 둡니다.
(stl map 사용) https://github.com/kaestro/algorithms/blob/master/swexpert%20academy/5653.cpp
(stl unorderd_map 사용) https://github.com/kaestro/algorithms/blob/master/swexpert%20academy/5653_unordered.cpp

통합규정 1.3 이용안내 인용

"Pgr은 '명문화된 삭제규정'이 반드시 필요하지 않은 분을 환영합니다.
법 없이도 사는 사람, 남에게 상처를 주지 않으면서 같이 이야기 나눌 수 있는 분이면 좋겠습니다."
주인없는사냥개
19/10/03 22:56
수정 아이콘
(수정됨) 지금 당장 생각나는 방법은 두 가지네요.

1. 순회 여부를 체크하는 flag를 추가해서 디폴트 값을 false로 놓고 순회 시엔 true로 바꿔서 true인 노드들은 순회를 continue로 건너뛴다.
2. 순회를 완료한 노드들을 삭제한다.

다만 2번을 하시면서 컨테이너를 순회하실거라면 for문을 이런 식으로 바꾸시는게 편할 겁니다.

for(auto it = map.begin();it != map.end();)
{
if(삭제해야함) it = map.erase(it);
else ++it;
}

다만 이건 삭제만 할 때 가능한 방법이고... insert가 같이 이루어진다면 기본적으로 작동이 잘 안될 것 같네요.
C++의 unordered_map 해쉬 맵인데 unordered라 순서가 없는 관계로
insert를 할 경우엔 한 번의 iteration에서 insert된 원소를 포함하는 모든 원소를 조회한다는 보장이 안 될 겁니다.

https://en.cppreference.com/w/cpp/container/unordered_map/insert
https://en.cppreference.com/w/cpp/container/unordered_map/erase

참조해보시길...

근데 코드보니까 제 생각엔 insert를 할 때 it를 치환했는데 for문에서 ++it가 있어서 문제가 발생하는 듯 하네요.
for문에선 제거하시고 continue 들어가는 그 부분 전에 ++it 넣어보시면 아마 삽입된 원소가 조회가 안 되는 현상은 해결이 되실 듯?
다만 기존에 있던 원소 중 건너뛰어지는 원소가 있는 문제는 발생할 것 같습니다.
19/10/03 23:32
수정 아이콘
답변 감사드립니다.
지금 삽입한 원소가 조회 안되는게 아니라 기존에 원소가 조회가 안되는게 문제였는데, 그 부분은 전반적으로 다시 문제를 해결하는 방법 밖에는 없겠네요.
말씀하신 아이디어대로 생각해서, 추가한 다음에 it = map.begin()으로 다시 초기화해서 traverse하는 방법을 일단 적용시켰는데, 이렇게하는 건 문제 해결하는 속도가 더 느려지더라구요.
다시 한 번 문제를 풀 방법을 생각해봐야될 것 같네요.
세크리
19/10/03 23:05
수정 아이콘
기본적으로 iterator 무효화 문제고요, unordered_map이 해쉬를 이용해서 아무렇게나 저장하는것이기 때문에 당연히 이 문제가 생길수밖에 없습니다. 뭐 정확이 어떤 알고리즘을 구현하고 싶으신지는 모르겠지만, iterator를 다 쓰고 나서 insert를 하던지 아니면 자료구조를 바꾸던지 해야합니다.
주인없는사냥개
19/10/03 23:08
수정 아이콘
세크리님 말에 첨언해서 iterating을 할 때 container의 원소를 추가하거나 삭제하는건 그리 권장되지 않는 방법이기도 합니다. 퍼포먼스를 위해서 포기할 때도 많이 있지만...
19/10/03 23:51
수정 아이콘
답변 감사드립니다.
unordered_map을 처음 써보는거라 insert가 되면서 이런식으로 순서가 바뀐다는걸 몰랐거든요.
제가 생각했던 건 새로 추가되는 원소가 있어도 기존의 iterator간의 앞뒤 관계는 유지가 될거라고 생각했습니다.
주인없는 사냥개님하고, 세크리님 말씀을 듣고 iterator를 다 쓰고 나서 insert를 하는 방법으로 추가할 부분만 따로 만들어내는 식으로 구현을 했는데도 속도가 충분히 빠르지 못하네요.
이런 거를 iterator 무효화라하는지 몰랐는데, 많이 배웠습니다.
주인없는사냥개
19/10/03 23:55
수정 아이콘
사실 문제 설명만 들으면 전형적인 BFS 문제로 들리는데 제가 뭐 문제를 정확하게 아는 건 아니라 더 얘기는 못해드리겠네요... 건승하시길
19/10/04 00:03
수정 아이콘
이 문제를 보고서 왜 BFS라고 생각을 못했는지 모르겠네요-_-;;
이게 BFS 변형인거군요.
그런데 단순하게 queue에다가 이어붙이기에는 이전에 넣었던 node가 틀린 값인 경우의 수가 있어서 다른 방법을 쓰긴 해야하는 것 같네요.
굉장히 도움이 많이 됐습니다. 정말 감사드립니다.
F.Nietzsche
19/10/03 23:32
수정 아이콘
순회를 해야 하는데 왜 굳이 map을...
19/10/03 23:58
수정 아이콘
순회를 할 때 map은 좋지 못한 자료구조 형태인가요?
세포가 증식하면서 필요한 공간이 계속해서 늘어나니까 늘어난 장소를 저장하기 위해 map을 사용하는 것이 좋지 않을까 생각했거든요.
기존에 있는 solution들은 아예 공간을 제약조건보다 넓게 잡고 아무것도 없는 공간도 순회하는데, map을 쓰면 세포가 존재하는 공간만 순회하니까 이게 더 효율적인 방법이 아닐까 생각했어서요.
주인없는사냥개
19/10/04 00:03
수정 아이콘
왜냐면 map은 순서가 존재하는 자료구조라 삽입 삭제가 logN에 랜덤 엑세스도 불가능해서...
말씀하신 것 들으면 그냥 구조체 배열, 혹은 정말로 최대 세포 숫자를 모른다면 리스트 정도로도 충분해보이네요
19/10/04 00:17
수정 아이콘
그래서 unordered_map을 쓰면 괜찮지 않을까 생각해서, 그리고 사실 unordered_map을 여태 한 번도 안 써봤어서 한 번 연습해보는 김에 사용해봤었는데 제가 접근 방법이 잘못됐었나보네요.크크...
감사합니다.
목록 삭게로! 맨위로
번호 제목 이름 날짜 조회
138188 [질문] 숯의 성분에 관하여 질문 드립니다. [2] 레뽀3208 19/10/04 3208
138187 [질문] 중고나라에 넷플릭스아이디공유 대량으로 하는사람들은 뭔가요? [3] 달달합니다5395 19/10/04 5395
138186 [질문] 크롬 페이지 번역 기능이 작동하지 않습니다. [3] 독수리의습격4994 19/10/04 4994
138185 [질문] [혐주의] 방안에 거미가 나왔어요. [8] 중학교일학년3701 19/10/04 3701
138184 [질문] 와이파이 속도 증가방법 질문드립니다. [5] 천우희2977 19/10/03 2977
138183 [질문] 걍 갑자기 생긴 탈모에 대한 궁금증인데요 [8] 뵈미우스3105 19/10/03 3105
138181 [질문] c++ 에서 unordered map을 pair를 key로 사용할 때 순회 [11] Kaestro3087 19/10/03 3087
138180 [질문] 놀면 뭐하니 매회 챙겨보시는 분..? [3] 치카치카2707 19/10/03 2707
138179 [질문] 종로에 있는 약국에 가면 메가트루나 임펙타민 좀 더 싸나요? [2] 마스터리3892 19/10/03 3892
138178 [질문] 임차인과의 권리금 이야기 [8] dks10wp2519 19/10/03 2519
138177 [질문] 오버워치리그 다시보기요! [2] 손나이쁜손나은2036 19/10/03 2036
138176 [질문] 이번 롤드컵은 오프닝(테마) 없나요? [2] 던져진2282 19/10/03 2282
138175 [질문] 세계적인 경제불황이 머지 않았다고 생각하시는지요...? [7] nexon3742 19/10/03 3742
138174 [질문] 이직 고민 [14] Emiyasiro3795 19/10/03 3795
138173 [질문] 차량침수 관련 [2] 외국어의 달인2085 19/10/03 2085
138172 [질문] 오늘 광화문 몇명 왔을까요? [21] Dwyane4382 19/10/03 4382
138171 [질문] 서브로 쓸 pc스피커 추천 부탁드립니다. [1] This-Plus2018 19/10/03 2018
138170 [질문] 컴퓨터 OS꺼지면서 PC 팬이 미친듯 돕니다. [7] 모찌3993 19/10/03 3993
138169 [질문] 포방터 돈까스 드셔보신분? [3] 조말론4476 19/10/03 4476
138168 [질문] 보험 리모델링 업체(?) 추천좀 부탁드립니다. 덴드로븀1887 19/10/03 1887
138167 [질문] 여수 여행 좋은 곳이나 맛집 알려 주심 감사하겠습니다 [7] 가라한3215 19/10/03 3215
138165 [질문] 육아 프로그램에서 가장 인기 많았던 아이가 누구였을까요? [24] CastorPollux3879 19/10/03 3879
138164 [질문] 새 차(기아 레이) 사는 방법 질문드립니다. [11] Aiurr4480 19/10/03 4480
목록 이전 다음
댓글

+ : 최근 1시간내에 달린 댓글
+ : 최근 2시간내에 달린 댓글
맨 위로