티스토리 뷰
<뇌를 자극하는 알고리즘 #7>: 순차 탐색(Sequential Search) 퀴즈풀이
wisecow 2017. 7. 23. 19:14퀴즈에 등장하는 개념 요약 // 해당 도서를 읽지 않으시는 분들도 생각하고 풀어보실 수 있습니다.
# 전진 이동법
전진 이동법(Move to front method)은 어느 항목이 한 번 탐색되고 나면, 그 항목을 데이터 집합의 가장 앞(링크드 리스트에서는 헤드)에 위치시키는 방법이다. 이렇게 하면 한 번 찾은 항목을 연이어 또 찾는 경우 단번에 탐색을 완료할 수 있다. MS 워드의 '최근 문서'기능과 같은 원리로 동작한다고 생각하면 이해가 쉽다. 전진이동법의 한계는 한 번 탐색된 항목이 곧 이어 또다시 검색될 가능성이 높은 데이터 집합에서만 사용해야한다 점이다.
# 전위법
전위법(Transpose method)은 탐색된 항목을 바로 이전 항목과 교환한다는 것 말고는 기본적으로 전진 이동법과 같은 전략을 취하는 알고리즘이다. 전진 이동법은 탐색된 항목을 무조건 앞으로 옮기는데 반해, 전위법은 '자주' 탐색된 항목들이 데이터 집합의 앞쪽으로 모이게 된다. 전위법은 발견이 될 때마다 해당 데이터를 한 칸씩 데이터 집합의 앞으로 옮기기 때문이다.
Vitamin Quiz // 문제가 2개로 이루어져 있습니다.
문제 1) 기존의 단일연결리스트에 적용할 수 있던 전진 이동 순차탐색 알고리즘을 int형 배열에 사용 가능한 전진 이동 순차 탐색 코드로 재구성하라. // 기존의 코드는 바로 밑에 있는 코드다.
/*************************************************
** 전진 이동 순차 탐색 코드 (SLL ver)
*************************************************/
typedef struct Node{
int data;
struct Node *NextNode;
} Node;
Node* SLL_MoveToFront(Node **head, int target) // 단일연결리스트(SLL)용 전진이동 순차탐색 알고리즘
{
Node *current = *head;
Node *previous = NULL;
Node *match = NULL;
while (current != NULL)
{
if (current->data = target)
{
match = current; // 찾고자 하는 노드의 주소를 저장
if (previous != NULL) // 전 노드가 NULL이 아니라면
{ // current는
previous->NextNode = current->NextNode;
current->NextNode = *head;
}
break;
}
else // 찾고자 하는 값이 없을 때
{
previous = current;
current = current->NextNode;
}
return match;
}
}
/*************************************************
** End Line
*************************************************/
문제2) SLL_Tranpose( ) 함수의 배열 버전을 구현하라. 아래 단일연결리스트를 기반으로 작성되어 있는 코드를 배열 버전으로 수정하라.
/*************************************************
** 기존의 단일연결리스트(SLL) 버전의 전위법 알고리즘
*************************************************/
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node *NextNode;
} Node;
Node* SLL_Transpose(Node **head, int target)
{
Node *current = *head;
Node *pPrevious = NULL; /* 이전 노드의 이전 노드 */
Node *previous = NULL; /* 이전 노드 */
Node *match = NULL;
while (current != NULL)
{
if (current->data == target)
{
match = current;
if (previous != NULL)
{
if (pPrevious != NULL) // 2단계 전 노드가 NULL이 아닐 경우
pPrevious->NextNode = current; // 2단계 전 노드가 현재 노드를 가리키게 설정
else
*head = current;
// 이제 current는 한 칸 앞으로 전진해야하므로 더이상 previous의 다음 노드가 아니다.
// 직전 노드가 current가 아닌 다음 노드를 가리키게 수정
previous->NextNode = current->NextNode;
// current가 한 칸 앞으로 왔으므로, 이전노드가 current의 다음 노드가 된다.
current->NextNode = previous;
}
// 원하는 작업을 마쳤으니 루프를 빠져나간다.
break;
}
}
}
/*************************************************
** End Line
*************************************************/
풀이1 // 풀이1과 풀이2는 구현이 너무 간단하여 별도의 소스코드 첨부는 하지 않겠습니다.
원하는 요소를 발견하면, 일단 그 요소를 따로 저장해둔다. 0번째부터 지금 인덱스까지 한 칸 뒤로 요소들을 옮긴다. 그렇게 0번째 위치에 빈자리가 생기면, 저장해둔 정보를 옮겨주기만 하면 된다.
/*************************************************
** int형 배열을 매개변수로한 전진 이동 순차 탐색 알고리즘
*************************************************/
#include <stdio.h>
#include <stdlib.h>
void ARY_MoveToFront(int dataSet[], int target, int size)
{
int i;
int value = 0;
for (i = 0; i < size; i++)
{
if (dataSet[i] == target)
{
value = dataSet[i];
memmove(&dataSet[1], // 첫 번째 매개변수는 이사할 새로운 주소
&dataSet[0], // 두 번째 매개변수는 이사할 데이터가 어디서 부터인지를 나타내는 주소
sizeof(dataSet[0]) * i); // 세 번째 매개변수는 얼마만큼 옮길건지를 표현하는 byte
dataSet[0] = value;
}
}
}
int main()
{
int i;
int dataSet[] = { 71,5,13,1,2,48,222,136,3,15 };
int size = sizeof dataSet / sizeof dataSet[0];
ARY_MoveToFront(dataSet, 48, size);
/* 정렬된 배열 출력 */
for (i = 0; i < size; i++)
{
printf("%d ", dataSet[i]);
}
printf("\n");
}
/*************************************************
** End Line
*************************************************/
풀이2
원하는 값을 찾았다면 해당 값을 바로 직전 원소와 자리바꿈만 해주면 된다. 구현이 매우 간단하다.
/*************************************************
** 배열 버전 전위법(Transpose) 알고리즘
*************************************************/
#include <stdio.h>
#include <stdlib.h>
void ARY_Transpose(int dataSet[], int target, int size)
{
int i;
int temp; // 원소간의 값 교환시 사용될 변수
for (i = 0; i < size; i++)
{
// 만약 i가 0이라면 따로 교환해줄 필요가 없으므로 i > 0 조건 추가
if (i > 0 && dataSet[i] == target)
{
temp = dataSet[i - 1];
dataSet[i - 1] = dataSet[i];
dataSet[i] = temp;
break; // 목적을 달정했으니 빠져나온다.
}
}
}
int main()
{
int i;
int dataSet[] = { 71,5,13,1,2,48,222,136,3,15 };
int size = sizeof dataSet / sizeof dataSet[0];
for (i = 0; i < 5; i++)
{ // 48을 5번 찾았다고 가정, 48은 맨 앞으로 이동될 것이다.
ARY_Transpose(dataSet, 48, size);
}
/* 정렬된 배열 출력 */
for (i = 0; i < size; i++)
{
printf("%d ", dataSet[i]);
}
printf("\n");
}
/*************************************************
** End Line
*************************************************/
'Develop Story > Data Structure & Algorithm' 카테고리의 다른 글
| <사고력 훈련 문제 #2>: 비둘기집 원칙 (0) | 2017.07.25 |
|---|---|
| <사고력 훈련 문제 #1>: Horner의 법칙 (0) | 2017.07.25 |
| <뇌를 자극하는 알고리즘 #6>: 삽입정렬(InsertionSort) 응용 및 문제풀이 (더블링크드리스트 연동) (0) | 2017.07.23 |
| <알고리즘: 삽입정렬> 기본개념과 설명 및 코드 (0) | 2017.07.23 |
| <뇌를 자극하는 알고리즘 #5>: 버블정렬(BubbleSort) 퀴즈풀이 (0) | 2017.07.23 |
- Total
- Today
- Yesterday