C언어 질문
글쓴이: 익명 사용자 / 작성시간: 월, 2017/06/12 - 11:27오후
어떤 데이터에서 찾고자하는 자료를 찾을경우 FOUND 라는 출력을하고
없을경우 NOT FOUND 라는 출력을 한번만 나타나게 하려고 합니다
예시로
#include <iostream> using namespace std; void main() { int test[10]; for (int i = 0; i != 10; ++i) { test[i] = i; } for (int i = 0; i != 10; ++i) { if (test[i] == 7) { cout << "FOUND" << endl; } else { cout << "NOT FOUND" << endl; } } }
이 경우 "NOT FOUND"가 7번 출력되고 "FOUND"가 1번 출력됩니다
#include <iostream> using namespace std; void main() { int test[10]; for (int i = 0; i != 10; ++i) { test[i] = i; } int count = 0; for (int i = 0; i != 10; ++i) { if (test[i] == 7) { count++; } } if (count != 0) { cout << "FOUND" << endl; } else { cout << "NOT FOUND" << endl; } }
이 경우 "FOUND"가 한번만 출력되고 'test[i] == 11' 가 될 경우 "NOT FOUND"가 한번만 출력됩니다
두번째 코드의 출력이 제가 원하는 목표인데
저런 방법이 비효율적이라 생각되서 다른 방법이 있는지 알고 싶습니다.
Forums:
어떤 측면에서 비효율적이라고 생각하시는지는
어떤 측면에서 비효율적이라고 생각하시는지는 모르겠습니다만...
1. 규칙 없는 시퀀스에 대한 일반적인 선형 탐색 알고리즘의 시간복잡도는 O(n)입니다.
물론 정말로 에누리 없이 정확히 n에 비례하는 경우는 두 경우밖에 없는데,
1) 찾고자 하는 값이 시퀀스에 없거나.
2) 찾고자 하는 값을 마지막으로 조사한 곳에서 찾거나.
1)은 어쩔 수 없는 경우고 (시퀀스에 어떤 값이 없다는 걸 확신하려면 결국 다 찾아볼 수밖에 없습니다.)
2)는 운이 없는 경우죠.
실제로 시퀀스에 찾고자 하는 값이 단 하나 있는데 어디 있는지 전혀 단서를 찾을 수 없는 경우, 발견까지의 평균 탐색 횟수는 n/2라고 보시면 되겠습니다.
아무튼 NOT FOUND 메시지를 최종적으로 출력하기 위해서는 결국 n개의 원소를 다 볼 수밖에 없어요. 최소한 지금 널리 쓰이는 컴퓨터에서는 그렇습니다.
FOUND 메시지가 출력되는 경우에 대해서는 개선이 가능하군요. 찾고자 하는 값이 정확히 몇 개 있는지(count)를 꼭 알 필요가 없다면 루프를 끝까지 돌면서 세고 있을 이유가 없습니다. 그냥 찾자마자 빠져나오면 됩니다. 대충 아래와 같겠죠.
그래봤자 여전히 O(n)짜리 알고리즘입니다만 운이 좋아서 조금 빨리 끝나는 걸 기대해 볼 수는 있지요.
갯수를 정확히 세는 게 꼭 중요하다면 루프를 끝까지 돌리는 걸 피할 방법이 없습니다.
더 빠른 알고리즘을 바라십니까? 그러면 자료구조의 영역에 발을 들여놓아야 합니다.
https://en.wikipedia.org/wiki/Search_data_structure
시퀀스가 정렬되어 있기만 해도 이진 탐색 알고리즘을 쓰면 비용은 O(n)에서 O(log n)으로 크게 줄어들지요.
데이터가 물리 메모리 안에 무난히 다 들어올 정도의 크기라면 보통 그 정도면 충분합니다.
마침 질문자님의 코드는 배열 초기값을 오름차순으로 넣어서 이미 정렬이 되어 있네요.
이진 탐색도 이미 잘 구현된 게 있어요. C언어의 bsearch, C++의 binary_search 등.
http://en.cppreference.com/w/c/algorithm/bsearch
http://en.cppreference.com/w/cpp/algorithm/binary_search
C++의 equal_range를 쓰면 심지어 찾고자 하는 값이 정확히 몇 개 들어있는지도 O(log n)에 알 수 있지요. 원래 이진 탐색으로 가능한 거긴 한데 실제로 구현하는 건 약간 까다롭습니다.
직접 구현할 수 있으면 알고리즘 관련해서 초보딱지는 확실히 떼었다고 볼 수 있겠네요.
http://en.cppreference.com/w/cpp/algorithm/equal_range
탐색 대상이 늘었다 줄었다 하는 경우라면 일반적으로 Binary Search Tree가 있고요.
https://en.wikipedia.org/wiki/Binary_search_tree
운이 없으면 가끔 트리 균형이 안맞아서 탐색 비용이 늘어나는데 그걸 막으려면 Self-balancing binary search tree를 쓰면 됩니다.
https://en.wikipedia.org/wiki/Self-balancing_binary_search_tree
데이터 크기가 물리 메모리보다 더 커지면 이제 DBMS 개발자들이 수십년쯤 전에 연구했던 분야로 넘어갑니다. 근데 그 쯤 되면 그냥 DBMS를 쓰는 게 낫죠. sqlite 어때요? SQL 코딩도 재밌습니다.
물론 DBMS를 효율적으로 사용하는 법을 익히는 데에도 공부가 조금 필요합니다만.
https://www.sqlite.org
감사합니다
제가 질문을 애매모호하게 했는데 정확한답변을 해주셔서 이해가 잘되네요. 확장된 답변까지 달아주셔서 감사합니다. 많은 도움이 되었어요.
감사합니다
제가 질문을 애매모호하게 했는데 정확한답변을 해주셔서 이해가 잘되네요. 확장된 답변까지 달아주셔서 감사합니다. 많은 도움이 되었어요.
댓글 달기