검색결과 리스트
2011/03/23에 해당되는 글 3건
- 2011.03.23 원 위에 나열된 수 제거하기
- 2011.03.23 합병정렬(Merge Sort)
- 2011.03.23 다중인자를 갖는 PerformSelector 메시지
글
원 위에 나열된 수 제거하기
알고리즘.데이터구조
2011. 3. 23. 16:08
1부터 n까지의 수를 원 위에 차례로 나열하고 k 번째 수를 지워간다. k보다 적을 때까지 반복한다
입력: n, k (n > k > 0)
출력: 최종 남은 숫자들(지워진 순서로 출력, 역순으로 출력) / 지워진 숫자들
조건: 함수는 재귀적인 기법 이용 / n보다 적은 배열 하나만 이용
입력: n, k (n > k > 0)
출력: 최종 남은 숫자들(지워진 순서로 출력, 역순으로 출력) / 지워진 숫자들
조건: 함수는 재귀적인 기법 이용 / n보다 적은 배열 하나만 이용
1. 반복루프를 사용한 방법
(1) n크기의 배열을 사용. 어떤 수 n은 (n-1)배열요소에 위치한다
(2) K번째 배열요소에는 지워진 순서가 기록되고, 남아있는 수의 배열요소에는 0값을 저장하고 있다.
(3) 함수 종료 후, 기록된 순서를 통해 지워진 순서, 역순 출력을 할수 있고,
배열요소가 0인 것을 찾아 남아있는 수들을 출력 할 수 있다.
(2) K번째 배열요소에는 지워진 순서가 기록되고, 남아있는 수의 배열요소에는 0값을 저장하고 있다.
(3) 함수 종료 후, 기록된 순서를 통해 지워진 순서, 역순 출력을 할수 있고,
배열요소가 0인 것을 찾아 남아있는 수들을 출력 할 수 있다.
2. 재귀함수를 사용한 방법
(1) 단순히 위의 반복버전을 재귀함수로 변경한 버전
3. 최고 n - (n/k) 크기의 배열을 사용하는 재귀함수
(1) 첫번째, 두번째 재귀호출은 배열을 한번 순회하기 위해 루프문을 구현한 것이고,
(2) 세번째 재귀호출은 한번의 순회의 남아있는 수들로 재구성한 새 배열을 가지고, (1)과정을 재적용한다.
(3) 알고리즘이 종료하면 전역변소 $e에는 남아있는 수의 개수를 저장하고 있으면 array의 0~($e-1) 요소에 그 값이 위치한다
(2) 세번째 재귀호출은 한번의 순회의 남아있는 수들로 재구성한 새 배열을 가지고, (1)과정을 재적용한다.
(3) 알고리즘이 종료하면 전역변소 $e에는 남아있는 수의 개수를 저장하고 있으면 array의 0~($e-1) 요소에 그 값이 위치한다
3번에 대한 그림 설명
'알고리즘.데이터구조' 카테고리의 다른 글
| [알고리즘] 알고리즘 글 목록 (0) | 2013.07.08 |
|---|---|
| 프로그래밍 문제 접근법 (0) | 2011.04.26 |
| 원 위에 나열된 수 제거하기 (0) | 2011.03.23 |
| 합병정렬(Merge Sort) (0) | 2011.03.23 |
| HMAC-SHA1 (0) | 2011.03.11 |
| 문제5 그래픽편집기 (0) | 2011.02.18 |
설정
트랙백
댓글
글
합병정렬(Merge Sort)
알고리즘.데이터구조
2011. 3. 23. 15:50
n개의 아이템으로 구성된 리스트를 크기가 거의 n/3 인 3개의 부분리스트로 분할하고
각 부분리스트를 재귀적으로 정렬한 후, 그 3개의 정렬된 부분리스트를 합병하는 정렬 알고리즘을 작성하라 (n>=100)
각 부분리스트를 재귀적으로 정렬한 후, 그 3개의 정렬된 부분리스트를 합병하는 정렬 알고리즘을 작성하라 (n>=100)
=> 합병정렬(merge sort) 알고리즘을 작성하되, 3분할 방식을 사용하라~~는 말
먼저 2분할을 사용하는 합병정렬 소스는 다음과 같다
3분할을 사용하는 MergeSort (Ruby 버전)
# 배열리스트를 n/3으로 분할 후 정렬 / 병합
def merge_sort(low, high)
if (high-low >= 2)
mid1 = (high-low) /3 + low
mid2 = ((high-low)*2)/3 + low
merge_sort(low, mid1)
merge_sort(mid1+1, mid2)
merge_sort(mid2+1, high)
merge(low, mid1, mid2, high)
else
if (high-low==1 && $a[low] > $a[high])
tmp = $a[low]
$a[low] = $a[high]
$a[high] = tmp
end
end
end
def merge(low, mid1, mid2, high)
i, h, j, m, k = low, low, mid1+1, mid2+1, 0
b = []
pass = false;
while ((h<=mid1) and (j<=mid2) and (m<=high))
if ($a[h] <= $a[j] && $a[h] <= $a[m])
b[i] = $a[h]
h = h + 1
i = i + 1
next
end
if ($a[j] <= $a[h] && $a[j] <= $a[m])
b[i] = $a[j]
j = j + 1
i = i + 1
next
end
if ($a[m] <= $a[h] && $a[m] <= $a[j])
b[i] = $a[m]
m = m + 1
i = i + 1
next
end
end
# 루프가 종료하고 남은 요소들을 병합
if (h > mid1 && !pass)
pass = true
while ((j<=mid2) and (m<=high))
if ($a[j] <= $a[m])
b[i] = $a[j]
j = j + 1
else
b[i] = $a[m]
m = m + 1
end
i = i + 1
end
if (j > mid2)
for k in m..high
b[i] = $a[k]
i = i + 1
end
else
for k in j..mid2
b[i] = $a[k]
i = i + 1
end
end
end
if (j > mid2 && !pass)
pass = true
while ((h<=mid1) and (m<=high))
if ($a[h] <= $a[m])
b[i] = $a[h]
h = h + 1
else
b[i] = $a[m]
m = m + 1
end
i = i + 1
end
if h > mid1
for k in m..high
b[i] = $a[k]
i = i + 1
end
else
for k in h..mid1
b[i] = $a[k]
i = i + 1
end
end
end
if (m > high && !pass)
while ((h<=mid1) and (j<=mid2))
if ($a[h] <= $a[j])
b[i] = $a[h]
h = h + 1
else
b[i] = $a[j]
j = j + 1
end
i = i + 1
end
if (h > mid1)
for k in j..mid2
b[i] = $a[k]
i = i + 1
end
else
for k in h..mid1
b[i] = $a[k]
i = i + 1
end
end
end
# 원배열에 정련된 임시배열값을 복사
for k in low..high
$a[k] = b[k]
end
end
#$a = [1,5,4,3,2,6,9,7,8]
$a = Array.new(100)
$a.each_index { |i| $a[i] = rand(100)+1 }
$a.each { |x| print x, " " }
merge_sort(0,99)
print "결과\n"
$a.each { |x| print x, " " }
3분할을 사용하는 MergeSort (C++ 버전)
#include <iostream>
using namespace std;
void mergeSort(int * a, int low, int high);
void merge(int * a, int low, int mid1, int mid2, int high);
void print(int * arr, int size);
int * minThree(int * a, int *i, int *j, int *k);
int * minTwo(int * a, int *i, int *j);
int main()
{
int size = 100;
int * arr = new int[size];
srand(time(NULL));
// 초기화- 0~99까지 수를 랜덤으로 복사
for (int i=0; i < size; i++)
arr[i] = rand() % size;
// 정렬 전
print(arr, size);
mergeSort(arr, 0, size-1);
// 정렬 후
print(arr,size);
return 0;
}
void mergeSort(int * a, int low, int high)
{
int mid1, mid2;
if (high-low >= 2)
{
mid1 = (high-low)/3 + low;
mid2 = ((high-low)*2)/3 + low;
mergeSort(a, low, mid1);
mergeSort(a, mid1+1, mid2);
mergeSort(a, mid2+1, high);
merge(a, low, mid1, mid2, high);
}
else
{
if (high-low==1 && a[low] > a[high])
{
int tmp = a[low];
a[low] = a[high];
a[high] = tmp;
}
}
}
void merge(int * a, int low, int mid1, int mid2, int high)
{
int * b = new int[high-low+1];
bool pass = false; // 조건을 만족할 경우 나머지 if문을 통과하기 위한 변수
int i, h, j, m;
i = 0;
h = low;
j = mid1 + 1;
m = mid2 + 1;
// 세분할 배열중 하나를 다 복사할때까지 루프를 돈다
for (; h<=mid1 && j<=mid2 && m<=high; i++)
{
int * p = minThree(a, &h, &j, &m);
b[i] = a[*p];
*p = *p + 1;
}
if (h > mid1)
{
pass = true;
// 나머지 두 분할 배열중 하나를 다 복사할때까지 루프를 돈다
for (; j<=mid2 && m<=high; i++)
{
int * p = minTwo(a, &j, &m);
b[i] = a[*p];
*p = *p + 1;
}
// 나머지 하나의 분할배열을 복사한다
if (j > mid2)
for (; m<=high; i++, m++)
b[i] = a[m];
else
for (; j<=mid2; i++, j++)
b[i] = a[j];
}
if (j > mid2 && !pass)
{
pass = true;
for (; h<=mid1 && m<=high; i++)
{
int * p = minTwo(a, &h, &m);
b[i] = a[*p];
*p = *p + 1;
}
if (h > mid1)
for (; m<=high; i++, m++)
b[i] = a[m];
else
for (; h<=mid1; i++, h++)
b[i] = a[h];
}
if (m > high && !pass)
{
for (; h<=mid1 && j<=mid2; i++)
{
int * p = minTwo(a, &h, &j);
b[i] = a[*p];
*p = *p + 1;
}
if (j > mid2)
for (; h<=mid1; i++, h++)
b[i] = a[h];
else
for (; j<=mid2; i++, j++)
b[i] = a[j];
}
// 정렬된 임시배열을 원본배열에 복사한다
for (int k=low; k <= high; k++)
a[k] = b[k-low];
}
// 배열의 내용 출력
void print(int * a, int size)
{
for (int i=0; i < size; i++)
cout << a[i] << " " ;
cout << endl;
}
// 세 분할배열에 숫자 중 가장 작은수의 인덱스를 반환
int * minThree(int * a, int *i, int *j, int *k)
{
if (a[*i]<=a[*j] && a[*i]<=a[*k])
return i;
if (a[*j]<=a[*i] && a[*j]<=a[*k])
return j;
if (a[*k]<=a[*i] && a[*k]<=a[*j])
return k;
}
// 두 분할배열에 숫자 중 가장 작은수의 인덱스를 반환
int * minTwo(int * a, int * i, int * j)
{
if (a[*i]<=a[*j])
return i;
else
return j;
}
'알고리즘.데이터구조' 카테고리의 다른 글
| 프로그래밍 문제 접근법 (0) | 2011.04.26 |
|---|---|
| 원 위에 나열된 수 제거하기 (0) | 2011.03.23 |
| 합병정렬(Merge Sort) (0) | 2011.03.23 |
| HMAC-SHA1 (0) | 2011.03.11 |
| 문제5 그래픽편집기 (0) | 2011.02.18 |
| 문제4 LCD디스플레이 (0) | 2011.02.18 |
설정
트랙백
댓글
글
다중인자를 갖는 PerformSelector 메시지
Objective-C
2011. 3. 23. 15:31
이번 포스팅에서는 다중 파라미터를 갖는 Selector를 인자로 받아 별도의 쓰레드에서 처리를 해주는 비동기 메서드
구현에 대해서 알아볼 것이다.
아이폰 앱 프로젝트 진행 중 Delegate 패턴을 구현하면서 PerformSelector 류의 메서드를 사용 할 필요가 생겼다.
Cocoa Touch 프레임웍에서는 최대 2개까지의 인자를 받는 메서드(performSelector:withObject:withObject:) 만을 제공하고,
더 많은 파라미터를 전달해야 할 경우, 클래스 또는 Dictionary를 사용하여 전달해야 했다. 매번마다 파라미터를 담기위해 Dictionary를 생성하고, 데이터를 꺼내쓰는 것은 상당히 번거로운 작업이었다.
외국 블로그에서 우연히 이 문제를 깔끔하게 해결해주는 코드를 발견했다. C언어의 가변인자 리스트와 Objective-C 의
NSInvocation 메커니즘을 사용하는 방법이었다. 이 포스팅에서는 가변인자 리스트와 NSInvocation 메커니즘에 대해서는
설명하지 않겠다. 추후 Objective-C 런타임 메커니즘을 알아보면서 NSInvocation에 대해서 자세히 알아볼 것이다.
Cocoa Touch 프레임웍에서는 최대 2개까지의 인자를 받는 메서드(performSelector:withObject:withObject:) 만을 제공하고,
더 많은 파라미터를 전달해야 할 경우, 클래스 또는 Dictionary를 사용하여 전달해야 했다. 매번마다 파라미터를 담기위해 Dictionary를 생성하고, 데이터를 꺼내쓰는 것은 상당히 번거로운 작업이었다.
외국 블로그에서 우연히 이 문제를 깔끔하게 해결해주는 코드를 발견했다. C언어의 가변인자 리스트와 Objective-C 의
NSInvocation 메커니즘을 사용하는 방법이었다. 이 포스팅에서는 가변인자 리스트와 NSInvocation 메커니즘에 대해서는
설명하지 않겠다. 추후 Objective-C 런타임 메커니즘을 알아보면서 NSInvocation에 대해서 자세히 알아볼 것이다.
다음은 가변인자 리스트와 NSInvocation을 사용하여 다중 파라미터를 갖는 Selector를 호출하는 예제코드이다.
- (void)performSelector:(SEL)aSelector withContext:(void*)context,... {
if (context) {
NSMethodSignature *signature = [self methodSignatureForSelector:aSelector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation retainArguments];
NSUInteger argumentCount = [signature numberOfArguments] - 2;
[invocation setTarget:self]; // index 0
[invocation setSelector:aSelector]; // index 1
va_list arguments;
va_start(arguments, context);
// 인자의 개수는 +2가 된 상태
NSUInteger i, count = argumentCount;
void *currentValue = context;
for (i = 0; i < count; i++) {
[invocation setArgument:¤tValue atIndex:(i + 2)];
currentValue = va_arg(arguments, void*); // 다음 인자 읽기
}
va_end(arguments);
NSThread *customWorkerThread = [NSThread currentThread];
[invocation performSelector:@selector(invoke) onThread:customWorkerThread withObject:nil waitUntilDone:NO];
} else {
[self performSelectorInBackground:aSelector withObject:nil];
}
}
위 메서드를 사용하여 아래와 같이 세 개의 인자를 갖는 printArgument:andOther:andAnother: 메시지를 호출하면...
// 호출할 메서드
- (void)printArgument:(NSString*)arg1 andOther:(NSString*)arg2 andAnother:(NSString*)arg3 {
NSLog(@"%@", [NSThread currentThread]);
NSLog(@"arg1: %@", arg1);
NSLog(@"arg2: %@", arg2);
NSLog(@"arg3: %@", arg3);
}
// 요렇게 호출할 수 있다. 깔끔하지 않는가? [self performSelector:@selector(printArgument:andOther:andAnother:) withContext:@"t1", @"t2", @"t3", nil];
위 메소드를 카테고리로 정의해놓으면 아주 유용하게 사용할 수 있을 것이다.
[소스 출처]
'Objective-C' 카테고리의 다른 글
| Objective-C 문자열 조작 메서드 (0) | 2011.04.29 |
|---|---|
| 다중인자를 갖는 PerformSelector 메시지 (0) | 2011.03.23 |
| Protocol 과 Category (0) | 2011.03.22 |
| Objective-C 훑어보기 (2) | 2011.03.20 |
| [Cocoa] Cocoa Design Pattern (0) | 2011.03.20 |
| HMAC-SHA1 구현 (0) | 2011.03.03 |