사이드바 열기

전북대학교 알고리즘 분할정복


검색결과에서 웹페이지의 순위를 매기기 위하여 구글이 사용하는 요소들이 100여가지가 존재한다고 합니다.

구글 페이지 랭킹에 긍정적인
영향을 미치는 조건들

    구글에서는 웹마스터 가이드라인을 제시하고 있습니다.

  • 디자인 및 콘텐츠 가이드 라인
    • 디렉토리와 텍스트 링크 구조가 명확한 사이트
    • 사용자에게 사이트맵 제공
    • 중요한 이름, 콘텐츠 또는 링크를 표시할때 이미지 대신 텍스트 사용.
    • 제목 요소와 ALT 속성이 정확
    • URL의 Query에서 매개변수의 길이는 짧게, 개수는 적게 유지
    • 한페이지의 링크는 100개 미만으로 제한
  • 기술 가이드라인
    • DHTML 혹은 플래시 같은 고급기능으로 홈페이지 전체를 구성하지 말것
    • 웹서버의 If-Modified-Since HTTP 헤더 지원여부
    • 웹서버에서 robots.txt 파일을 사용
    • 대부분의 브라우저에서의 올바른 사이트 표시
    • 사이트의 성능 모니터링과 로드시간 최적화
  • 품질 가이드라인
    • 클로킹 콘텐츠 즉 사용자를 속이거나 실제로 존재하지 않는 콘텐츠 제공하지 않음
    • 검색엔진 순위를 높이기 위한 편법 사용 금지
    • 사이트의 순위나 PageRank를 인위적으로 높이기 위해 개발된 링크 편법을 사용금지
    • 숨겨진 텍스트나 링크를 사용하지 않습니다.
    • 클로킹 또는 부적절한 리디렉션을 사용하지 않습니다.
    • 자동화된 검색어를 Google에 보내지 않습니다.
    • 페이지의 내용과 상관없는 검색어 및 키워드를 삽입하지 않습니다.
    • 대부분이 중복 콘텐츠로 채워진 다수의 페이지, 하위 도메인 또는 도메인으로 사이트를 구성하지 않습니다.
    • 피싱이나 바이러스, 트로이 목마 또는 기타 악성 소프트웨어를 설치하는 등의 악의적 행위가 이루어지는 페이지를 만들지 않습니다.
    • 검색엔진 전용 '도어웨이' 페이지 또는 독창적인 콘텐츠가 거의 없거나 전혀 없는 제휴 프로그램 등 기타 '틀에 박힌' 방식을 피합니다.
    • 사이트가 제휴 프로그램에 참여하고 있다면 해당 사이트만의 고유한 가치를 창출할 수 있어야 합니다. 사용자들이 사이트를 먼저 방문하고 싶게 만드는 고유하고 관련성 높은 콘텐츠를 제공하는 것이 그 지름길입니다.

    키워드부분

  • title Body 태그에 있는 키워드 : 타이틀태그에 있는 키워드 - 타이틀태그 시작부근에 있는 10 - 60 글자, 특수문자 제외. 플로리다업데이트는 OOP의 일환으로 이 규칙에 대한 위반에도 벌점을 주었다고 합니다. 현재 키워드 부분에서 가장 중요한 랭크포인트입니다.
  • H시리즈 태그 내의 키워드 : HTML 에는 특정 문구를 강조하기 위해 H1에서 H6까지의 태그가 존재합니다.
  • URL 에 있는 키워드 : URL에 존재하는 키워드로 연관 검색어에서 중요한 척도이었지만 너무 많이 알려저서 현재는 중요랭크포인트에서 하위권에 존재합니다.
  • 도메인명에 있는 키워드 : 도메인명에 존재 하는 키워드로 bar(-) 또는 Underbar(_)를 통해서 구분합니다.
  • img 의alt (와)과title 에 포함되는 키워드(2.6)
  • bold, strong 태그로 사용되는 키워드(2.4)
  • meta 태그의deion 그리고 사용되는 키워드(2.1)
  • meta 태그의keywords 그리고 사용되는 키워드(1.3)

    페이지 특성부분

  • 인바운드 링크(Inbound Link) : 자신의 페이지로 들어오는 링크를 말합니다. 자신의 페이지링크를 띄운 해당 페이지의 랭크에 따라 자신의 페이지 랭크 점수가 올라가게 됩니다. 예를들어 자신의 페이지를 페이지랭크 3으로 올려야 겠다고 생각하시면, 페이지랭크 1짜리의 각각의 다른페이지에서 555개의 링크를 받거나, 페이지랭크 2짜리의 각각의 다른 페이지에서 101개의 링크를 받게되면 자신의 페이지를 페이지랭크 3으로 만들수 있습니다. 가장 간단하게 페이지랭크 3을 만들려면 페이지랭크 5짜리 페이지에서 링크를 하나만 받으면 됩니다. 그 리고 페이지랭크 5를 만들려면 페이지랭크 7짜리 페이지에서 1개의 링크를 받던지 아님 6짜리 페이지에서 3개 내지는 4개의 링크를 받으면 됩니다. 페이지랭크 10짜리 페이지에서 링크를 받는다면 한번에 자신의 페이지랭크가 8로 올라갑니다.
  • 아웃바운드 링크(Outbound Link) : 자신의 홈페이지에서 타 홈페이지로 나가는 링크를 말합니다. 예를 들어 링크가 존재하는 5랭크의 페이지에서 링크의 숫자가 50개라면 15점 정도밖에 안되지만, 링크의 숫자가 10개면 77점이 됩니다. 즉 페이지의 랭크가 높다고 무조건 좋은것이 아니라 얼마나 랭크가 높으면서도 링크가 적은 페이지에서 링크를 받느냐가 중요한 것입니다. 물론 3랭크의 10개의 링크만 존재하는 페이지에서 받는것보단 5랭크의 90개 링크들 중 하나가 더 높기 때문에 1순위는 페이지 랭크입니다. 자신의 홈페이지에 적용을 한다면 외부로 나가는 링크가 얼마나 좋은 품질의 홈페이지인가에 대해 페이지랭킹에 영향을 주게 됩니다.
  • 시간의 변화에 대한 링크의 안정성 : 수시로 변하는 링크가 아닌 고정적 혹은 장기적인 링크를 받는게 좋습니다. Naver나 Daum의 경우 구글 페이지 랭킹은 7랭크이고 각각 메인화면에는 항상 각종 블로그의 링크들이 떠있습니다. 하지만 이 링크들은 수시로 변하기 때문에 해당 블로그들의 페이지 랭크에 영향을 주지 않는다는게 좋은 예입니다.
  • 문서의 나이 : 해당 페이지의 나이가 영향을 미칩니다. 랭킹전략으로 해당 페이지를 미리 만들어놓고 차차 수정해 나가는 것이 올바른 전략입니다.
  • 인덱싱 가능한 텍스트의 양 : 페이지에 너무 많은 키워드를 담고 있다면, 아웃바운드 링크와 비슷하게 해당 키워드에 대한 배점이 낮아지는 형식이기 때문에 관련된 인기 키워드들은 적은 수로 활용하는 것이 좋은 방법입니다.
  • 알고리즘으로 측정하는 문서 컨텐츠의 품질
  • 조직적/ 계층적인 문서?플로우(SiteMap)
  • 페이지의 갱신 빈도
  • URL 에 포함되는 slash의 수
  • 스펠과 문법의 정확함
  • 올바른 HTML 문서

    구글 페이지에 부정적인 영향을 미치는 요소들

  • 로봇이 빈번히 서버에 액세스 할 수 없다(3.8) 홈페이지의 대문이나 내용이 이미지이거나 Flash 혹은 그래픽으로 이루어진 경우는 이미지나 Flash 혹은 그래픽적으로 이루어진 페이지는 크롤링에서 식별 할 수 없기 때문에 아주 좋지 않은 홈페이지입니다.
  • 안좋은 홈페이지로의 아웃바운드 링크 : 구글을 검색하다보면 구글홈페이지에서 해당 페이지는 악성코드를 배포하기 때문에 들어갈 수 없습니다 라는 페이지를 표시해주는걸 보셨을 것입니다. 이러한 안좋은 홈페이지들로의 아웃바운드 링크를 걸게 된다면 페이지랭크에서 불이익을 받게 됩니다.
  • 욕설이나 비속어등의 단어
  • 많은 페이지에 중복된 타이틀이나 Meta 태그가 존재할 경우
  • 숨겨진 텍스트 : 플로리다업데이트 이후에 구글에서 검색엔진을 계속적으로 업데이트 하면서 숨겨진 텍스트를 통한 광고에 대해 벌칙을 적용하고 있는것 같습니다.
  • 이 이외에도 다른 검색 포탈과 비슷하게 페이지의 트레픽, 페이지 선정률과 클릭스 페이지에 머무는 시간, 북마크 유무등이 랭크업에 도움을 줍니다.

출처

http://www.impact.pe.kr/files4wiki/seo.html
http://lisence.kr/meta/test/370?PHPSESSID=9f728a772eb2031e579c335c48711ba0

Posted by LaLuna
#include <stdio.h>
#include <stdlib.h>
typedef struct  _node
{
    int             key;
    struct _node    *next;
} node;
#define success 1
#define fail    0
node    *init_node( void );     //head와 tail node의 초기화
node    *delete_all( node *head );      // head와 tail을 제외한 모든 node 삭제
node    *find_key( node *head, int s_key ); // 주어진 key값으로 node탐색
int     insert_node( node *head, int i_key );   // head와 첫번째 node사이 삽입
int     delete_node( node *node_n );    // 주어진 node의 다음 node 삭제
int     insert_key( node *head, int f_key, int i_key ); // 주어진 key값의 node 새로운 node 삽입
int     delete_key( node *head, int d_key );    // 주어진 key값의 노드삭제
void    print_node( node *head );   // node 출력

//  구현해야할 함수
//  oscending_node()   오름차순정렬
//  descending_node()   내림차순 정렬
int main( int argc, char **argv )
{
    int     result  =   0;
    node    *temp   =   NULL;
    node    *head   =   init_node();
    fputs( "Insert Node 1 to 10\n", stdout );
    insert_node( head, 10 );
    insert_node( head, 9 );
    insert_node( head, 8 );
    insert_node( head, 7 );
    insert_node( head, 6 );
    insert_node( head, 5 );
    insert_node( head, 4 );
    insert_node( head, 3 );
    insert_node( head, 2 );
    insert_node( head, 1 );
    print_node( head );
    fputs( "Finding key 5\n", stdout );
    temp    =   find_key( head, 5 );
    printf( "Finding 5 is %ssuccessful\n", temp == NULL ? "un" : "" );
    fputs( "Insert key 11 after 3\n", stdout );
    insert_key( head, 3, 11 );
    print_node( head );
    fputs( "Delete key 10\n", stdout );
    delete_key( head, 10 );
    print_node( head );
    fputs( "Finding key 3 and Delete next node\n", stdout );
    temp    =    find_key( head, 3 );
    delete_node( temp );
    print_node( head );
    fputs( "Delete key 7\n", stdout );
    delete_key( head, 7 );
    print_node( head );
    fputs( "Delete all node\n", stdout );
    delete_all( head );
    print_node( head );
    return 0;
}
node    *init_node( void )
{
    node    *head   =   (node *)malloc( sizeof(node) ); // head node initialization
    node    *tail   =   (node *)malloc( sizeof(node) ); // tail node initialization
    if( head == NULL ) // Head Node에 대해 할당에 실패했을때
    {
        fputs( "Failed to allocate for Head node\n", stdout );
        return  NULL;
    }
    if( tail == NULL ) // Tail Node에 대해 할당에 실패했을때
    {
        fputs( "Failed to allocate for tail node\n", stdout );
        free( head );  // Tail Node에 대해 할당에 실패했을 땐, Head Node를 해제
        return NULL;
    }
    head->next  =   tail;
    tail->next  =   NULL;
    return  head;
}

node    *delete_all( node *head )
{
    node    *navi_node  =   head->next; // 순회노드 선언 및 head 다음으로 설정
    node    *free_node  =   NULL;          // 해제노드 선언
    while( navi_node->next != NULL ) // 순회노드가 tail에 이를때까지
    {
        free_node   =   navi_node;
        navi_node   =   navi_node->next;
        free( free_node );
    }
    head->next  =   navi_node; // navi_node 가 성공적으로 루프를 종료했다면 tail
    return head;
}
node    *find_key( node *head, int s_key )
{
    node    *navi_node =   head->next; // head 다음노드로 설정
    while( navi_node->key != s_key && navi_node->next != NULL ) // key값을 찾거나 꼬리에 이를때까지
        //
    {
        navi_node   =   navi_node->next;
    }
    if( navi_node->key == s_key ) // key값을 찾았을경우
    {
        return navi_node;
    }
    else if( navi_node->next == NULL ) // 꼬리일경우
    {
        fputs( "Node is tail\n", stdout );
        return NULL;
    }
}
int     insert_node( node *head, int i_key)
{
    node    *i_node =   NULL;  // 삽입노드 선언
    i_node          =   (node *)malloc( sizeof(node) ); // 삽입노드 할당
    if( i_node == NULL )
    {
        fputs( "Failed to allocate for Insert Node\n", stdout );
        return fail;
    }
    i_node->key     =   i_key;
    i_node->next    =   head->next;
    head->next      =   i_node;
    return success;
}
int     delete_node( node *node_d)
{
    node        *delete_node    =   node_d->next; // 삭제노드 선언 및 node_next다음노드로 설정
    if( delete_node->next == NULL )
    {
        fputs( "Next node is tail.\n", stdout );
        return fail;
    }
    node_d->next    =   delete_node->next;
    free( delete_node );
    return success;
}
int     insert_key( node *head, int f_key, int i_key )
{
    node    *i_node     =   NULL;
    node    *s_node     =   head->next; // 탐색노드
    while( s_node->next != NULL && s_node->key != f_key ) // key값을 찾거나 꼬리에 도달할때까지
    {
        s_node  =   s_node->next;
    }
    if( s_node->key == f_key ) // key값일경우
    {
        i_node          =   (node *)malloc( sizeof(node) );
        if( i_node == NULL ) // 할당에 실패했을때
        {
            fputs( "Failed to allocate for Insert node\n", stdout );
            return fail;
        }
        i_node->next    =   s_node->next;
        i_node->key     =   i_key;
        s_node->next    =   i_node;
        return success;
    }
    else if( s_node->next == NULL ) // 꼬리일경우
    {
        fputs( "Search node is tail.\n", stdout );
        return fail;
    }
}
int     delete_key( node *head, int d_key )
{
    node    *s_node =   head->next; // 탐색노드
    node    *p_node =   head; // 탐색노드를 따라갈 이전노드
    while( s_node->next != NULL && s_node->key != d_key ) // key값을 찾거나 꼬리에 도달할때까지
    {
        s_node  =   s_node->next;
        p_node  =   p_node->next;
    }
    if( s_node->key == d_key ) // key값일경우
    {
        p_node->next    =   s_node->next;
        free( s_node );
        return success;
    }
    else if( s_node->next == NULL ) // 꼬리일경우
    {
        fputs( "Search node is tail.\n", stdout );
        return fail;
    }
}
void    print_node( node *head )
{
    node    *c_node =   head->next; // 탐색노드
    int     index_node  =   0; // 노드 개수
    printf("--------------------------------------------------\n");
    while( c_node->next  != NULL )
    {
        index_node++;
        fprintf(stdout, "%2dth Node key value : %2d\n", index_node, c_node->key );
        c_node  =   c_node->next;
    }
    printf("--------------------------------------------------\n");
}
}
Posted by LaLuna
 

int insert_key( node *head, int f_key, int i_key )

삽입노드 선언

탐색노드 선언 head다음노드로 설정

key값을 찾거나 꼬리에 도달할때까지 반복

탐색노드를 다음노드로 이동

if( key값을 찾으면 )

삽입노드 할당 key 설정 ( 할당에 실패하면 함수 종료 )

삽입노드 다음을 탐색노드 다음으로 설정

탐색노드 다음을 삽입노드로 설정

success 반환

else if( 꼬리라면 )

에러메세지 출력

fail 반환

  1. 성공시
    • success반환
  2. 실패시
    • fail 반환
  3. 인자값
    • head : head 주소값
    • i_key : 삽입할 노드의 key

 

int  delete_key( node *head, int d_key )

탐색노드 선언 head 다음노드로 설정

탐색노드를 따라갈 이전노드 선언

탐색노드가 key값을 찾거나 꼬리에 도달할때까지 반복

이전노드를 탐색노드로 설정

탐색노드는 다음노드로 이동

if( key값을 찾았으면 )

이전노드 다음노드를 탐색노드 다음노드로 설정

탐색노드 해제

success 반환

else if( 꼬리라면 )

에러메세지 출력

fail 반환

  1. 성공시
    • success반환
  2. 실패시
    • fail 반환
  3. 인자값
    • head : head 주소값
    • int d_key : 삭제할 노드의 key

Posted by LaLuna

int insert_node( node *head, int i_key )
{
    삽입노드 선언 및 할당
    if( 할당에 실패할경우 )
    fail 반환
    삽입노드 다음노드를 head노드 다음노드로 설정
    head노드 다음노드를 삽입노드로 설정
    success 반환
}
    성공시
        success반환
    실패시
        fail 반환
    인자값
        head : head 주소값
        i_key : 삽입할 노드의 key값

int delete_node( node *node_next ) {
    삭제노드 선언
    삭제노드를 node_next 다음노드로 설정
    if( 삭제노드가 꼬리일 경우 )
    에러문장 출력fail 반환
    node_next의 다음노드를 삭제노드 다음노드로 설정
    삭제노드 할당해제
    success 반환
}


    성공시
        success반환
    실패시
        fail 반환
    인자값
        node_next : 삭제할노드의 전노드




void print_node( node *head ) {
    탐색노드 선언
    꼬리에 도착할때까지 반복
    key 값 출력
    다음노드로
}
    성공시
        없음
    실패시
        없음
    인자값
        head : head 주소값
   



Posted by LaLuna
node  *init_node( void )
{
    head node 선언 및 할당
    head node 할당 실패 시
    에러처리
    tail node의 선언 및 할당
    tail node 할당 실패 시
    head 할당해제
    에러처리
    head와 tail 연결 및 tail next 처리
    head 주소 값 반환
}

    성공시
        head 주소 반환
    실패시
        NULL 반환
    인자값
        없음.

tail->next의 처리는 3가지정도의 방법이 있다.
    1. 자기자신을 가르키게 하는경우
    2. head를 가르키게 하는경우
    3. NULL을 가르키게 하는 경우

일단 NULL을 가르키게 하는 방식으로 code 를 작성.



node *delete_all( node *head )
{
    순회노드 선언 및 head노드 다음으로 설정
    해제노드 선언
    순회노드가 tail에 이를 때까지 반복
    해제노드는 순회노드로 설정
    순회노드는 다음노드로 설정
    해제노드 할당해제
    head노드 다음노드를 tail(순회노드)로 설정
    head노드 주소값 리턴
}

    성공시
        head 주소값 반환
    실패시
        NULL 반환
    인자
        head : head 주소



node *find_key( node *head, int s_key )
{
    탐색노드 선언 및 head->next로 설정
    탐색노드가 key값을 찾거나 꼬리에 이를때까지 반복
    다음노드로 이동
    if( key값을 찾았을경우 )
        현재위치의 탐색노드 주소 반환
    else if( 꼬리일경우 )
        NULL 반환
}  

 

    성공시
        현재위치의 탐색노드주소 반환
    실패시
        NULL 반환
    인자값
        head : head 주소값
        s_key : 찾을 key값

Posted by LaLuna

구조체 정의
typedef struct  _node
{
    int             key;       // key값을 저장
    struct _node    *next;       // 다음 node의 주소
} node;

return Value definition.

#define success 1
#define fail   0
    성공할 경우 1을 return
    실패할 경우 0을 return

 

Function List

node    *init_node( void );     //head와 tail node의 초기화
node    *delete_all( node *head );      // head와 tail을 제외한 모든 node 삭제
node    *find_key( node *head, int s_key ); // 주어진 key값으로 node탐색
int     insert_node( node *head, int i_key );   // head와 첫번째 node사이 삽입
int     delete_node( node *node_n );    // 주어진 node의 다음 node 삭제
int     insert_key( node *head, int f_key, int i_key ); // 주어진 key값의 node 새로운 node 삽입
int     delete_key( node *head, int d_key );    // 주어진 key값의 노드삭제
void    print_node( node *head );   // node 출력
//  구현해야할 함수
//  oscending_node()   오름차순정렬
//  descending_node()   내림차순 정렬
※ init_node를 제외한 모든 함수는 첫번째 인자로 head node를 요구한다.
Posted by LaLuna
우리가 알고 있다시피 Invariable(상수) Variable(변수)에는 Data Type이 있습니다. Data Value에 따라서 Data Type를 지정해주어야 하는데, Invariable는 그 자신의 Value에 대한 표기로 Data Type를 나타낼 수 있기 때문에 Data Type를 선언해줄 필요는 없습니다. 그러나 Variable의 경우 Value가 언제든지 바뀔 수 있기 때문에 Data type를 선언해 주어야 합니다. 그런데 모든 Variable에는 Data Type 이외에 Storage Class라는 존재합니다.

 

Storage Class란 어떠한 Variable의 기억장소에 대한 지정과 지정한 Variable의 유효범위를 결정하는 것이 Storage Class입니다. 여기서 유효범위란 어떠한 Variable Program Code의 활용범위에 따른 분류와 기억 장소를 점유하는 시간에 따른 분류를 말하는 것입니다.

Variables의 성격은 변수를 선언하는 Storage Class Specifiers(기억부류 지정자)와 선언장소(함수의 내부이냐 외부이냐)에 의하여 결정됩니다.

 

하나의 함수는 ‘{‘ 으로 시작해서 ‘}’ 으로 끝이 나며, 이 내부에서 선언된 Variables는 이 함수 안에서만 사용이 가능하며, 이것을 Local Variables라 부릅니다. 또한 모든 함수의 외부에서 선언되어 파일 안의 모든 함수에서 사용이 가능한 Variables Global Variables 이라 부릅니다.

Global Variables는 초기화를 시키지 않아도 자동적으로 0으로 정해지며, Local Variables는 초기화가 되지 않고 임의의 값(Memory가 원래 가지고 있던 쓰레기 값)을 가지게 됩니다.

 

Storage Class Speciriers에 의한 분류는 아래의 표와 같습니다.

 

Storage Class

External Variables

Automatic Variables

Static Variables

Register Variables

지 정 자

extern

auto

static

Register


저장장소

정적

데이터영역


스택

정적

데이터영역

CPU

레지스터

선언위치

함수의 외부

함수의 내부

함수의 내부

함수의 내부


통용범위

프로그램

전체


함수의 내부


함수의 내부


함수의 내부


파괴시기

프로그램

종료시


함수 종료시


프로그램 종료


함수 종료시


초 기 값


0

초기화

되지 않음


0

초기화

되지 않음

 

1. External Variables(외부 변수)

하나의 프로그램을 짜기 위해 여러 사람이 각기 다른 파일에서 작업을 하거나, 혹은 Source를 분산 시킬 필요성이 있을 경우 사용하는 지정자입니다. 전역변수는 하나의 파일 안에서 모든 함수들이 사용할 수 있지만 다른 파일은 접근이 불가능 합니다. 이런 경우 External Variables으로 선언하여 다른 파일에서 접근이 가능하도록 알려주는 역할을 합니다.

 

2. Automatic Variables(자동 변수)

우리들이 흔히 사용하는 변수는 대부분 Automatic Varibles입니다. 기본적으로 함수의 내부에서 사용되며 임시적으로 사용하는 Variable입니다. 저장장소는 스택에 위치하며, 함수의 종류시 자동적으로 없어지며, 전역으로 사용 혹은 다른 함수에서 접근이 불가능 한 변수입니다.

 

3. Static Variables(정적 변수)

기본적으로 Automatic Variables와 비슷하게 함수안에서 쓰이며, 함수가 종료되어도 없어지지 않는 특징을 가지고 있습니다. 생성은 스택이 아닌 메모리의 정적구간에 생성이 되고 프로그램 자체가 끝날 때까지 보존되어지는 정적인 의미를 지닌 Variables입니다. Static Variables의 사용은 프로그램이 끝날 때까지 존재는 하되 소속된 함수가 실행될때만 접근이 가능하다는 특징을 지니고 있습니다.

 

4. Register Variables(레지스터 변수)

Register Variables는 위의 Variables와 다르게 RAM에 생성되지 않고 CPU Register에 생성되어지는 특징을 가지고 있습니다. CPU Rigister RAM보다 입출력이 빠르기 때문에 프로그램중에 자주 사용하는 값을 Register에 위치해 놓음으로써 수행 속도를 높일 수 있게 하는 Variables입니다. 주의할 점은 Variable Register Variables로 지정할 때 Register에 충분한 공간이 존재한다면 Register에 생성이 되지만, 공간이 충분하지 않는다면 Automatic Variable로 취급하여 메모리의 스택에 위치하게 됩니다.

Posted by LaLuna

Analysis of Algorithm

Empirical analysis(경험적 분석)     : 알고리즘을 프로그래밍 언어로 구현을 한 뒤, 이를 실행시켜 실시간을 비교해 보는 것

Mathematical analysis(수학적 분석) : 알고리즘을 프로그래밍 언어로 구현하지 않고, 단지 알고리즘 자체만으로 수학적 분석을 하는 것

 

Best case and Worst case

Bast case  : 가장 작은 시간과 공간을 필요로 하는 경우

Worst case : 가장 많은 시간과 공간을 필요로 하는 경우

- 어떠한 알고리즘의 일반적인 경우 다른 알고리즘에 비해 매우 성능이 뛰어나나 최악의 경우에 많은 시간과 공간을 필요로 할 수 있는 현상이 있고, 어떤 알고리즘의 일반적인 경우는 다른 알고리즘에 비해 성능은 떨어지나 최악의 경우에도 일반적인 경우와 별 차이가 없는 현상이 있다.

- 최악의 경우는 알고리즘의 성능을 표현하는데 많이 쓰인다. 알고리즘의 속도를 표현할 때, 아무리 많은 시간과 공간이 필요한다 해도 최악의 경우를 넘지 않는다는 것을 보증할 때 쓰인다.

 

평균적 경우라는 개념도 존재하는데, 평균적인 경우를 사용하는 데에는 몇 가지의 문제점이 있다.

1. 평균적인 경우 자체가 수학적으로 매우 어려운 개념이라 확정짓기가 어렵다.

2. 평균적인 경우가 실제의 상황과 같지 않다는 점이다.

 

● 알고리즘의 분석의 단계

1. 알고리즘을 판단할 수 있는 입력자료 결정
2.
알고리즘을 구성하는 동작들을 추상적이고 기본적인 동작들로 분해하여 동작들의 수행시간을 계산
3.
수학적인 알고리즘 분석


 

알고리즘의 유형

 

알고리즘의 분석 결과는 입력되는 자료의 수 N에 대한 수행시간을 함수 관계로 표현

★ 1

입력자료 수에 관계없이 일정한 실행시간을 갖는 알고리즘

★ log N

입력자료 수에 따라 실행시간이 조금씩 늘어남. 주로 커다란 문제를 일정한 크기를 갖는 작은 문문제 쪼갤 때 나타는 유형

★ N

입력 자료수에 따라 선형적으로 실행시간이 걸리는 경우.

★ N log N

커다란 문제를 독립적인 작은 문제로 쪼개어 각각 해결하고 나중에 다시 하나로 합치는 경우.

★ N2

이중 루프 내에서 입력자료를 처리하는 경우.

★ N3

삼중 루프 내에서 입력자료를 처리하는 경우.

★ 2N

 입력자료의 수가 늘어남에 따라 급격한 실행시간의 증가.

 

사용자 삽입 이미지

 

Posted by LaLuna
//
//      TIMER.H : Header file for timer macro
//
//                      Programmed By Clipper
//  Copyright ⓒ 2007 LaLuna All Rights Reserved.
//

#ifndef _TIMER_H
#define _TIMER_H

#include <time.h>

#define diff_clock(t1, t2) (double)((t2)-(t1))
#define diff_second(t1, t2) ((double)((t2)-(t1)) / CLOCKS_PER_SEC)

#endif

----------------------------------------------------------------------------------------------
사용 방법은

Data Type를 clock_t 로 하여 2개의 변수를 생성, 작동시간을 받아줄 float함수를 생성.

함수가 시작하는 부분에서 clock(); 함수로 시간을 받아주고, 끝나는 시점에서 받아준다음

끝나는시점 - 시작한시점 = 함수의 작동 시간

이 나옵니다.

예제로
        clock_t t1, t2;
        float = result;

        t1 = clock();
        for(i=0;i<LOOF;i++)
        {
            temp = get_gcd(u,v);
        }
        t2 = clock();
        result = diff_clock(t1,t2);

위와 같이 사용하시면 됩니다.
Posted by LaLuna
//
//      EUCLID1.C : Implementation of Euclid's Algorithm
//
//                      Programmed By Clipper
//  Copyright ⓒ 2007 LaLuna All Rights Reserved.
//

#include <stdio.h>
#include "timer.h"

int get_gcd(int u, int v);          //뻴셈만을 이용한 유클리드 : 최대공약수
int gcd_modulus(int u, int v);      //나머지연산을 이용한 유클리드 : 최대공약수
int gcd_recursion(int u, int v);    //재귀호출을 이용한 유클리드 : 최대공약수

#define LOOF 10000000               //함수의 성능 테스트를 위한 반복 횟수

int main(int argc, char *argv[])
{
    int u, v, temp;
    clock_t t1, t2;                 //함수 측정시간을 정하기 위한 변수
    float result1 = 0, result2 = 0, result3 = 0;//함수 측정시간을 저장하기 위한 변수
    int i;
    
    puts("\n EUCLID1 : 두 양수의 최대 공약수 찾기 ");
    puts("\n           0을 입력하면 종료");
    
    while(1)
    {
        puts("\n\n 두 양수를 입력하세요 -> ");
        scanf("%d %d", &u, &v);
        
        if(u < 0 || v < 0)//음수의 입력은 무효로 한다.
        {
            puts("음수를 입력하셨습니다. 양수를 입력하세요\n");
            continue;
        }
        if(u == 0 || v == 0)//0이 입력되면 종료한다.
        {
            puts("0을 입력하셨습니다. 프로그램을 종료하겠습니다.\n");
            break;
        }
        t1 = clock();
        for(i=0;i<LOOF;i++)
        {
            temp = get_gcd(u,v);
        }
        t2 = clock();
        result1 = diff_clock(t1,t2);//빼기, 교환 함수 시간 측정
        t1 = clock();
        for(i=0;i<:LOOF;i++)
        {
            temp = gcd_modulus(u,v);
        }
        t2 = clock();
        result2 = diff_clock(t1,t2);//나머지 함수 시간 측정

        t1 = clock();
        for(i=0;i<LOOF;i++)
        {
            temp = gcd_recursion(u,v);
        }
        t2 = clock();
        result3 = diff_clock(t1,t2);//재귀호출 시간측정
                
        printf("두 양수 %d와 %d의 최대 공약수는 %d입니다.(뺄셈과 교환)\n", u, v, get_gcd(u,v));
        printf("두 양수 %d와 %d의 최대 공약수는 %d입니다.(나머지연산)\n", u, v, gcd_modulus(u,v));
        printf("두 양수 %d와 %d의 최대 공약수는 %d입니다.(재귀호출)\n", u, v, gcd_recursion(u,v));
        printf("빼기연산 : %5.2f 나머지 연산 : %5.2f 재귀호출 연산 : %5.2f", result1, result2, result3);
    }
    system("pause");
    return 0;
}

int get_gcd(int u, int v)
{
    int temp;
    while(u)//u가 0이면 v를 리턴, 아니면 루프를 돈다.
    {
        if(u < v)//u가 v보다 작으면 교환한다.
        {
            temp = u;
            u = v;
            v = temp;
        }
        u = u - v;
    }
    return v;
}

int gcd_modulus(int u, int v)
{
    int t;
    while(v)//v가 0이면 u를 리턴, 아니면 루프를 돈다.
    {
        t = u % v;
        u = v;
        v = t;
    }
    
    return u;
}
   
int gcd_recursion(int u, int v)
{
    if(v == 0)
    {
        return u;
    }
    else
    {
        return gcd_recursion(v, u%v);//재귀호출을 이용하여 나머지 연산
    }
}

Posted by LaLuna
이전페이지 1 2 다음페이지
위로

사이드바 열기