#!/bin/sh

# 현재 디렉토리(./)에서 *.* 형태가 아닌(! -iname "*.*") 파일 찾기  
LISTS=`find ./ -type f ! -iname "*.*"`
END=0
START=0
 
for filename in $LISTS
do
        # 파일명의 길이 획득
        END=${#filename}
        START=`expr $END - 2`
 
        # 파일명의 끝 두 자리를 디렉토리명으로 지정
        DIR=${filename:$START:$END};
 
        echo "$filename ::: $DIR";
done
 
exit 0

'IT > shell 위 댄스' 카테고리의 다른 글

쉘에서 문자열 치환하기  (0) 2017.04.05
쉘에서 배열 사용하기  (0) 2017.04.03
배열 활용  (0) 2008.02.27
파일 처리  (0) 2008.02.27
awk  (0) 2008.02.27
블로그 이미지

쩐의시대

나답게 살아가고 나답게 살아가자

,

힙 (heap)

IT/알고리즘 2008. 7. 18. 16:06

1. Max Heap 소스

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
#define SIZE 20
 
void print_arr(int arr[], int size)
{
        int i = 0;
 
 
        for( i = 1; i < size; i++)
                printf("%d ", arr[i]);
 
        printf("\n");
 
}
 
void swap(int *arr, int i, int j)
{
        int tmp;
 
 
        tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
 
}
 
void heap(int *arr, int n, int m)
{
        int i;
        int j, parent;
 
 
        for( i = 2 * n; i <= m; i+=2) {
 
                j = i;
                parent = j/2; // this is parent
 
                if(arr[j] < arr[j+1]) // this is children --> 자식 중에 큰 자식을 찾는다.
                        j++;
 
                if( j == m+1)
                        j--;
 
                while( arr[parent] < arr[j]) { // parent와 자식을 비교하여 자식이 크다면 바꿔준다.
                        swap(arr, parent, j);
                        j = parent;
 
                        if( j == 1)
                                break;
 
                        parent = j/2;
                } // while
 
        } // for(i)
 
}

int main(int argc, char **argv)
{
        int arr[SIZE], i;
 
 
        arr[0] = -1;
 
        for( i = 1; i < SIZE; i++)
                arr[i] = rand() % 100;
 
        printf("------------ input data -------------\n");
        print_arr(arr, SIZE);
 
        for( i = SIZE - 1; i >= 1; i--) {
                heap(arr, 1, i); // 제일 큰 놈을 제외한 나머지 요소들로 heapify한다.
                swap(arr, 1, i); // 제일 큰 놈을 뒤로 보낸다. --> 제일 작은 놈을 앞으로 보낸다.
        }
 
 
        printf("------------ sorted data -------------\n");
        print_arr(arr, SIZE);
 
        return 0;
 
}

2. Min Heap 소스
  Max Heap 소스에서 일부만 수정
        for( i = 2 * n; i <= m; i+=2) {
 
                j = i;
                parent = j/2; // this is parent
 
                if(arr[j] > arr[j+1]) // this is children --> 자식 중에 작은 자식을 찾는다.
                        j++;
 
                if( j == m+1)
                        j--;
 
                while( arr[parent] > arr[j]) { // parent와 자식을 비교하여 자식이 작다면 바꿔준다.
                        swap(arr, parent, j);
                        j = parent;
 
                        if( j == 1)
                                break;
 
                        parent = j/2;
                } // while
 
        } // for(i)

블로그 이미지

쩐의시대

나답게 살아가고 나답게 살아가자

,
1. data가 char형인 binary search tree의 자료구조를 작성하라.
typedef struct BTREE {
     char data;
     struct BTREE *left, *right;
} BTREE;


2. 위 binary search tree의 preorder, inorder, postorder traverse를 프로그램하라.
int preorder(BTREE *t)
{
     if ( t != NULL) {
         printf("%c", t->data);
         preorder(t->left);
         preorder(t->right);
     }
}

int inorder(BTREE *t)
{
     if ( t != NULL) {
         inorder(t->left);
         printf("%c", t->data);
         inorder(t->right);
     }
}

int postorder(BTREE *t)
{
     if ( t != NULL) {
         postorder(t->left);
         postorder(t->right);
         printf("%c", t->data);
     }
}

3. swap_tree를 하나의 binary search tree에 대해 대칭이 되는 tree라고 정의할 때, 위 자료구조를 이용해서
   swap_tree를 프로그램하라.
int swap_tree(BTREE *t)
{
    BTREE *p;

    if( t == NULL)
        return NULL;
    else {
        p = (BTREE *) malloc(sizeof(BTREE));
        p->left = swap_tree(t->right);
        p->right = swap_tree(t->left);
        p->data = t->data;
        return p;
    }
}

4. 위 자료구조를 이용해서 tree를 복사하는 프로그램
int tree_copy(BTREE *t)
{
    BTREE *p;

    if( t == NULL)
        return NULL;
    else {
        p = (BTREE *) malloc(sizeof(BTREE));
        p->left = tree_copy(t->left);
        p->right = tree_copy(t->right);
        p->data = t->data;
        return p;
    }
}

5. 위 자료구조를 이용하여 tree의 max depth를 구하는 프로그램을 작성하라.
int max_depth(BTREE *t)
{
    int max = 0, depth;

    if( t == NULL)
        return 0;
    else {
         depth = max_depth(t->left) + 1;
         if( depth > max)
              max = depth;
         depth = max_depth(t->right) + 1;
         if( depth > max)
              max = depth;
         return max;
    }


}
블로그 이미지

쩐의시대

나답게 살아가고 나답게 살아가자

,
a = b-a + (b=a)
블로그 이미지

쩐의시대

나답게 살아가고 나답게 살아가자

,
** Exclusive OR 이용
    --> 양쪽 모두 같은 Bit는 0
          다른 한 쪽이 0 그리고 다른 한 쪽이 1의 비트는 1

int trans(int in)
{

    return (in ^ 0xffffffff) + 1;

}

블로그 이미지

쩐의시대

나답게 살아가고 나답게 살아가자

,
소수(솟수) : 나머지가 0이 나오고 자기자신으로만 나누어지는 수
                예)  2,  3,  5,  7,  11,  13,  17,  19,  23,  29,  31,  37,  41,
                     43,  47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,
                     107, 109, 113,  ...

#include <stdio.h>
int nextprime(int prime)
{
     int next, isprime, k;
     isprime = 1;
     if( isprime == 1)
         return 2;
     else if( isprime == 2)
         return 3;
     else {
         // 주어진 솟수에 2씩 증가시키며 솟수인지 테스트
        // 소수의 특성상 "2"를 제외한 끝자리는 항상 1, 3, 5, 7, 9 중에 하나이다.
         for( next = prime+2;   ; next += 2, isprime =1 ) {
               // 예) 소수 "13"의 반 값인 7이상으로 제산 연산할 의미가 없다.
               for( k = next/2; k >= 2; k--) {
                 if( next % k == 0 ) {
                     isprime = 0;
                     break;
                 }
             } // for(k)
             if( isprime == 1)
                 return next;
         } // for(next)
         return 0;
     } // else
}
블로그 이미지

쩐의시대

나답게 살아가고 나답게 살아가자

,

<재귀 : pivot을 배열의 중간값으로>

void qsort(int a[], int left, int right)
{
        int p, t;
        int i, j;
 
 
        if( left < right) {
                p = a[(left + right) / 2];
                i = left - 1;
                j = right + 1;
 
                while(1) {
                        while(a[++i] < p);
                        while(a[--j] > p);
 
                        if( i >= j)
                                break;
 
                        t = a[i];
                        a[i] = a[j];
                        a[j] = t;
                }
                qsort(a, left, i-1);
                qsort(a, j+1, right);
        }
 }


<재귀 : pivot을 배열의 첫 번째 값으로>

void qsort(int a[], int left, int right)
{
        int p, t;
        int i, j;
 
 
        if( left < right) {
                p = a[left];
                i = left;
                j = right + 1;
 
                while(1) {
                        while(a[++i] < p);
                        while(a[--j] > p);
 
                        if( i >= j)
                                break;
 
                        t = a[i];
                        a[i] = a[j];
                        a[j] = t;
                }
                /* pivot 값을 교환 */
                a[left] = a[j];
                a[j] = p;
 
                qsort(a, left, j-1);
                qsort(a, j+1, right);
        }
 }

 ** 재귀 함수의 문제점
    배열이 아주 클 경우 스택 오버플로우가 발생할 위험
    --> 자체 스택을 만들어 비재귀하는 방식으로 개선
    --> 구간이 작을 경우 더 이상 재귀 호출을 하지 말고 선택 정렬이나 삽입 정렬 이용


<비재귀 함수>

#include <stdio.h>
 
#define MAX_NUM 50
int stack[MAX_NUM];
int top = 0;
 
void init_stack()
{
        top = 0;
}
 
void push(int i)
{
 
        if( top >= MAX_NUM) {
                printf("stack full\n");
                return;
        }
        else
                stack[top++] = i;
}
 
int pop()
{
 
        if( top == 0)
                return 0;
        else
                return stack[--top];
 
}
 
int is_stack_empty()
{
 
        if( top == 0)
                return 1;
        else
                return 0;
 
}
void qsort(int a[], int n)
{
        int p, t;
        int i, j;
        int l, r;
 
        init_stack();  
 
        l = 0;
        r = n - 1;
 
        push(r);
        push(l);
 
        while(!is_stack_empty()) {
                l = pop();
                r = pop();
 
                if( r-l+1 > 1) {  // 종료조건 :: 남아 있는 분할의 원소 개수가 1개 이상일 경우
                        p = a[r];
                        i = l - 1;
                        j = r;
 
                        while(1) {
                                while(a[++i] < p);
                                while(a[--j] > p);
 
                                if( i >= j)
                                        break;
                       
                                t = a[i];
                                a[i] = a[j];
                                a[j] = t;
 
                        }
 
                        // pivot과 i값을 교환
                        t = a[i];
                        a[i] = a[r];
                        a[r] = t;
 
                        push(r);     // 오른쪽 분할의 오른쪽 끝
                        push(i+1);  // 오른쪽 분할의 왼쪽 끝
                        push(i-1);  // 왼쪽 분할의 오른쪽 끝
                        push(l);     // 왼쪽 분할의 왼쪽 끝
 
                } // if
        } // while
 }

** 비재귀 함수의 문제점
    재귀함수에 비해 실행시간이 약간 빠르다. 그러나, push(), pop()을 사용하므로 함수호출에 의한 오버헤드
    현상으로 속도가 확 달라지지는 않는다.
    정렬된 배열과, 역순 배열에서는 그 속도가 40배 가량 느리다. ( O(n^2) )
    ?? 가장 큰 값이나 가장 작은 값이 pivot으로 되기 때문에 속도 저하
   --> pivot 값을 난수로 지정하는 방법


< 난수 발생>

int get_random(int range)
{
 
        return rand() % range;
 
}
 
 
 
void qsort3(int a[], int n)
{
        int p, t;
        int i, j;
        int l, r;
 
 
        init_stack();  
 
        l = 0;
        r = n - 1;
 
        push(r);
        push(l);
 
        while(!is_stack_empty()) {
 
                l = pop();
                r = pop();
 
                if( r-l+1 > 1) {
                        t = get_random(r-l+1) + l; // 난수 발생
 
                        p = a[t];
                        a[t] = a[r];
                        a[r] = p;
 
                        i = l - 1;
                        j = r;
 
                        while(1) {
                                while(a[++i] < p);
                                while(a[--j] > p);
 
                                if( i >= j)
                                        break;
 
                                t = a[i];
                                a[i] = a[j];
                                a[j] = t;
 
                        }
 
                        t = a[i];
                        a[i] = a[r];
                        a[r] = t;
 
                        push(r);
                        push(i+1);
                        push(i-1);
                        push(l);
 
                } // if
        } // while
}

 이 경우는 최악의 경우가 발생하지 않는다.


<삽입정렬 추가>

void insert_sort(int a[], int n)
{
        int i, j, t;
 
 
        for( i = 1; i < n; i++) {
                t = a[i];
                j = i;
 
                while( a[j-1] > t && j > 0) {
                        a[j] = a[j-1];
                        j--;
                }
 
                a[j] = t;
        }
 
        return;
 
}
 
void qsort4(int a[], int n)
{
        int p, t;
        int i, j;
        int l, r;
 
        init_stack();
 
        l = 0;
        r = n - 1;
 
        push(r);
        push(l);
 
        while(!is_stack_empty()) {
 
                l = pop();
                r = pop();
 
                if( r-l+1 > 200) {
                        t = get_random(r-l+1) + l; // 난수 발생
 
                        p = a[t];
                        a[t] = a[r];
                        a[r] = p;
 
                        i = l - 1;
                        j = r;
 
                        while(1) {
                                while(a[++i] < p);
                                while(a[--j] > p);
 
                                if( i >= j)
                                        break;
 
                                t = a[i];
                                a[i] = a[j];
                                a[j] = t;
 
                        }
                        t = a[i];
                        a[i] = a[r];
                        a[r] = t;
 
                        push(r);
                        push(i+1);
                        push(i-1);
                        push(l);
 
                } // if
                else
                        insert_sort(a+l, r-l+1);
 
        } // while
 }



삽입 정렬은 어느 정도 정렬된 배열에서 아주 큰 효과를 내기 때문에 사용...
메모리의 소모도 줄어듬...


<세 값의 중위>

void qsort4(int a[], int n)
{
        int p, t;
        int i, j;
        int l, r;
 
 
        init_stack();
 
        l = 0;
        r = n - 1;
 
        push(r);
        push(l);
 
        while(!is_stack_empty()) {
 
                l = pop();
                r = pop();
 
                if( r-l+1 > 200) {
                        t = (r+1) >> 1; // 나누기 2의 의미
 
                        if( a[l] > a[t]) {
                                p = a[l];
                                a[l] = a[t];
                                a[t] = p;
                        }
 
                        if( a[l] > a[r]) {
                                p = a[l];
                                a[l] = a[r];
                                a[r] = p;
                        }
 
                        if( a[t] > a[r]) {
                                p = a[t];
                                a[t] = a[r];
                                a[r] = p;
                        }
 
                        p = a[t];
                        a[t] = a[r-1];
                        a[r-1] = p;
 
                        i = l - 1;
                        j = r;
 
                        while(1) {
                                while(a[++i] < p);
                                while(a[--j] > p);
 
                                if( i >= j)
                                        break;
 
                                t = a[i];
                                a[i] = a[j];
                                a[j] = t;
 
                        }
                        t = a[i];
                        a[i] = a[r];
                        a[r] = t;
 
                        push(r);
                        push(i+1);
                        push(i-1);
                        push(l);
 
                } // if
                else
                        insert_sort(a+l, r-l+1);
 
        } // while
 
}


* 복잡도
 - Best Case
   T(n) = n + 2T(n/2)
          = n + 2(n/2 + 2T(n/4)) = 2n + 4T(n/4)
          = ...
          = n log n
 - Worst Case
   T(n) = n + T(n-1)
          = n + (n-1) + T(n-2)
          = ...
          = O(n^2)

블로그 이미지

쩐의시대

나답게 살아가고 나답게 살아가자

,
예를 들어, abc --> a, b, c, ab, bc, ac, abc

#include <stdio.h>
#include <string.h>


void swap(char *p1, char *p2)
{
     char t;

     t = *p1;
     *p1 = *p2;
     *p2 = t;
}


void perm(char *in, int st, int en)
{
    int j = 0;

    if( st == en) {
        for( j = 0; j < en; j++)
            printf("%c", in[j]);
        printf("\n");
    }
    else {
        /* in[st]에서 in[en]까지에 둘 이상의 순열이 있으면 이것을 순환적으로 생성 */
        for( j = st; j < en; j++) {
            SWAP(&in[st], &in[j]);
            perm(in, st+1, en);
            /* 인덱스 i와 인덱스 j의 데이터 위치의 위치 교환을 위해 원래 위치로 복귀*/
            SWAP(&in[st], &in[j]);
        }
    }

}
블로그 이미지

쩐의시대

나답게 살아가고 나답게 살아가자

,
주어진 Query로 각 Document가 해당 Query에 적합할 확률을 베이지언 룰을 활용하여 계산하는데,
독립가정을 전제로 베이지언 룰을 이용하여, 비연관문서 집합에서 질의가 포함될 확률에 대한
연관 집합에 포함될 확률을 계산하여 문서를 찾는 모델링이다.

장점 : 문서들이 질의에 대하여 적합할 확률의 순서에 내림 차순으로 랭크된다.
단점 : 비연관 문서와 연관 문서 집합의 초기의 결과 집합을 가정해야만 한다.
         불린 모델과 같이 가중치가 없어서 색인어의 빈도수에 대한 가중치를 부여할 수가 없다. (오카피 모델에서 적용)
       색인어들에 대한 상호 독립 가정을 전제로 한다.


블로그 이미지

쩐의시대

나답게 살아가고 나답게 살아가자

,
불리언 모델은 간결하며, 빠르지만 문서 유사도를 계산할 수 없다는 단점이 있다.
불리언 모델은 사용자 질의 처리를 위한 단순한 방법을 제공한다.
검색서비스에서도 사용자 질의 처리기는 불리언 모델을 사용해서 분석하고
검색결과는 Vector Space Model을 사용하는 형식으로 구성이 된다.

즉, Extended Boolean Model은
Boolean Model을 기반으로 해서 Vector Space Model(VSM)의 유사도 계산 기법을 이용하여 가중치를 부여할 수 없다는 단점을 해결하는데 초점이 맞추어져 있다.

Document Term Weight간의 유클리드 거리를 구해서 유사도를 찾아내며
이것은 Vector Space Model(VSM)의 TF*IDF 모델을 사용해서 구한다.

자세한 내용은 파일을 다운받아 보시길...

1. Definition
2. Boolean OR
3. Boolean AND
4. Normalized
5. P-Norm
6. AND OR 조합
7. Features

블로그 이미지

쩐의시대

나답게 살아가고 나답게 살아가자

,