나의 즐겨찾기 | 블로그홈 | 바로가기 바로가기 | 로그인
블로그  |  사진갤러리  |  동영상갤러리 방명록  |   즐겨찾기 추가
ITEDU (sdsduck)
프로필     
전체 글보기(397)
기본폴더
IT관련뉴스
Computing관련뉴스
Mobile관련뉴스
문화컨텐츠관련뉴스
통신/방송관련뉴스
Microsoft자격증
SUN자격증
ORACLE자격증
CISCO자격증
Oracle강좌
Microsoft강좌
CISCO강좌
LPIC강좌
Solaris강좌
JAVA강좌
C언어강좌
그 외 프로그램
추천사이트
개설일 : 2006/01/11
 

거품정렬(bubble sort)은 여러 정렬 알고리즘 중 가장 비 효율적인 알고리즘 중 프로그램 좀 짤 줄 아는 사람은 아무도 사용하지 않는 천덕꾸러기 알고리즘이다.   하지만 정렬을 처음 배울때 가장 쉽게 접근 할수 있는 연고로 많은 책이나 교육기관에서 가장 처음에 등장하는 알고 리즘 이기도 하다.
알아야 면장을 해먹듯이
잘 모르고 거품 정렬이 안좋네 효율이 떨어지네 하는 것은 말이 안된다.
이제 거품 정렬 정도는 눈감고도 짤수 있도록 분석 해보고 짜 보기도 하자.

1. 알고리즘
   ; 정렬 대상 자료 중 인접한 두 자료의 크기를 비교하여 맞바꾸는 방식으로 정렬한다(교환법)

예)
    30 15 40 10 20
1 round
    30 15 40 10 20       : 30 > 15 이므로 교환
    15 30 40 10 20       : 40 > 30 이므로 교환안함
    15 30 40 10 20       : 40 > 10 이므로 교환
    15 30 10 40 20       : 40 > 20 이므로 교환
    15 30 10 20 40
2 round
    15 30 10 20 40       :30 > 15 이므로 교환안함
    15 30 10 20 40       :30 > 10 이므로 교환
    15 10 30 20 40       :30 > 20 이므로 교환
    15 10 20 30 40
3 round
    15 10 20 30 40       :15 > 10 이므로 교환
    10 15 20 30 40       :20 > 15 이므로 교환안함

    10 15 20 30 40  :더이상 교환이 없음. 정렬완료!!

거품 정렬  구현 소스

#include <stdio.h>     //printf()
#include <stdlib.h>    //srand(), rand(), RAND_MAX
#include <time.h>      //time()

// 거품 정렬 함수의 프로토타입 선언
void bubble_sort(int *,int);

// 프로그램의 엔트리 포인트
void main()
{
        int nsu[10];
        int i , N=10;

       // 실행시마다 다른 계열의 난수가 발생되게 한다.
       srand(time(NULL));
       puts("\n정렬전");
      
      //10~29 사이의 난수 10개를 발생시킨다.
       for( i=0; i<N; i++)
       {
             nsu[i] = rand()*20/RAND_MAX + 10;
             printf("%d  ",nsu[i]);
        }

       bubble_sort(nsu, N);
       puts("\n정렬후");

       for( i=0; i<N; i++)
             printf("%d  ",nsu[i]);
       printf("\n");
}

        
void bubble_sort(int *a,int n)
{
        int i,j,flag,temp;

        for(i=0; i<n-1 ; i++)                   //n-1회전 비교/교환
        {
                flag=0;
                for(j=0; j<n-i-1 ; j++)        //i-1번 비교/교환
                        if(a[j] > a[j+1])      //앞에 값이 크면 교환
                        {
                                temp  =  a[j];
                                a[j]  =  a[j+1];
                                a[j+1]=  temp;
                                flag=1;           //교환 발생을 알리는 플래그
                        }
                        if(!flag)                  //교환이 한번이 발생하지 않았으면
                                return;
        }
}

 
 
[C언어전문가과정 문의 = http://www.lesson-web.com/prom/c_main.htm]

[C/C++강좌]win32 api로 구현한 프랙탈 트리 소스

2006.02.10 13:39 | C언어강좌 | ITEDU

http://kr.blog.yahoo.com/sdsduck/402 주소복사

프랑스의 수학자 만델브로트(B. Mandelbrot)는 1967년 영국에서 발행되는
과학 잡지 [사이언스]에 느닷없이 '섬나라 영국을 둘러싸고 있는 해안선의 총
길이는 얼마인가'라는 제목의 글을 발표했다. 고도로 발달한 현대 과학이나 수
학에서 보면 초보적인 질문이기 때문에 다소 엉뚱해 보인 이 글에서, 만델브
로트는 영국의 해안선 길이는 어떤 자로 재느냐에 따라 얼마든지 달라질 수
있다고 주장했다. 1m짜리 자로 쟀을 때의 해안선 길이와 1km 단위의 자로
쟀을 때의 해안선 길이가 당연히 차이가 나듯이 만약 개미가 자기 몸에 줄자
를 달고 해안선을 돌아 길이를 잰다면 1m 단위의 자로 잰 것과는 엄청난 차
이를 낳을 것이라고 강조했다. 길이를 재는 자의 단위가 작을수록 해안선의
둘레는 그만큼 길어질 것이라는 주장이었다. 해안선의 길이는 재는 자의 길이
에 달려 있다는 것이었다. 당시엔 별 주목을 끌지 못한 만델브로트의 이 글은
오래지 않아 '프랙탈 이론'의 선구적 논문으로 지목되어 많은 과학자들로 하
여금 부랴부랴 해묵은 [사이언스]지를 뒤적이게 만들었다.
  카오스 이론, 혼돈이론, 프랙탈 이론 등으로 불리는 이 최신 이론은 최근
들어 과학자 사회에서 지지 기반을 광범위하게 넓혀 가면서 열성적인 지지자
들에 의해 상대성 이론, 양자역학과 함께 현대 과학의 3대 혁명 중의 하나로
추대되고 있다. 이전의 과학은 미시 세계, 거시 세계의 규칙성에만 주의를 기
울여 왔으나 이제는 복잡성의 세계가 새로운 과학의 주제로 떠올랐다는 것이
다.
  카오스 이론과 프랙탈 이론은 결국은 같은 말인데 굳이 엄밀하게 구분해 보
자면 겉으로는 불규칙해 보이는 현상들 가운데서도 자세히 관찰해 보면 어떤
규칙성을 찾을 수 있다는 것이 카오스(혼돈)이고 그 혼돈된 상태를 공간적인
구조로, 즉 기하학적이고 규칙적으로 표현한 것이 프랙탈이다. 프랙탈은 카오
스를 기술하는 언어인 셈이다.
  카오스 이론 하면 일반인들이 가장 먼저 떠올리는 것이 '나비 효과' 라는
애교스러운 이름일 것 같다. 오늘 서울 하늘에서 나비 한 마리가 날개 짓을
한 것이 며칠 뒤엔 뉴욕의 날씨에 영향을 끼쳐 큰 바람을 일으킬 수 있다는,
사람들의 귀를 솔깃하게 하긴 하지만 다소 과장이 섞인 이야기 말이다. 아무
튼 카오스 이론은 이처럼 겉으로 보기엔 불규칙적이고 제멋대로이기 때문에
종래의 물리학이나 수학에서 제쳐놓았던 분야들에 관심을 갖는 것에서 출발한
다.
  여태까지의 물리학이나 생물학은 기상의 변화, 동물의 번식, 난류의 흐름,
커피에 탄 프림이 어떤 운동을 하는지 등에 대해 한정적으로만 다루었다. 예
컨대 일기 예보는 기압, 바람, 온도 정도의 적은 수의 변수만 따져서 하루나
이틀 뒤, 혹은 장기적인 기상 변화를 예측하기 때문에 정확도가 떨어질뿐더러
기상 변화의 원인을 정확히 설명하지 못한다. 마찬가지로 어느 숲에서 송충이
가 번식하는데 어느 해엔 번식력이 왕성했다가 그 다음해엔 완만해진다든지,
인구 증감이 어떤 규칙성을 띠고 있는지 등에 대해 종전까지의 생물학이나 인
구학에서는 변화를 제대로 설명하지 못하거나 전망하지 못했다. 카오스 이론
에서는 복잡한 자연 현상에는 수많은 변화 요인이 있기 때문에 서너 가지의
변수만으로 그것을 설명하려는 것 자체가 무리라고 주장한다. 일식이나 월식,
혜성의 주기, 조수의 간만 등은 뉴턴 역학에서처럼 몇 가지의 변수만 가지고
도 설명이 가능하다. 즉 태양과 지구의 인력, 행성과 행성간의 인력 등만 고려
하면 되는 것이다. 그 밖의 요인들은 이들의 운동에 영향을 끼치지 않을 정도
로 사소하기 때문에 무시해도 된다고 본다. 카오스 이론은 이 '사소한 요인'들
에 주목한다. 이제까지의 일기 예보가 나비의 운동과 같은 사소한 것을 소홀
히 해 왔다면 카오스 이론에서는 그것이야말로 변화를 일으키는 동력이 될 수
있다고 주장하는 것이다. 따라서 이들은 사소한 변화에 민감한 현상들에 주의
를 모은다.
  만델브로트의 '해안선의 측정'의 예에서 보여 주듯이 우리는 상식적으로 해
안선의 길이를 측정하는 데 아주 미세한 굴곡들은 무시해도 별 상관이 없을
것처럼 생각한다. 그러나 실제로는 그 미세한 굴곡을 어떻게 처리하느냐에 따
라 하늘과 땅만큼의 차이가 난다는 것을 확인할 수 있는 것이다. 그러면 과연
해안선의 길이는 얼마까지 세밀하게 측정될 수 있는가? 1m의 자로 잰다고 하
더라도 다시 50cm 단위의 자로 재면 길이가 더 늘어날 것이고 다시 10cm의
자로 재면 또 늘어나고... 한없이 밀고 나갈 수가 있을 것이다. 결국 무한한
길이가 된다는 말인가?

 


아래의 소스는 프래탈을 이용하여 실제 나무에 가까운 모습을 재현한
소스이다.

소스의 실행 방법은 visual c++에서 win32 application으로 프로 젝트를 만들고 컴파일 하여 실행 하면 확인 할 수 있다.
*/

 

#include <windows.h>
#include <math.h>
#include <malloc.h>
#include <stdlib.h>
#include <time.h>

#define   PI    3.141592

LRESULT WndProc(HWND,UINT,WPARAM,LPARAM);

BOOL InitApp(HINSTANCE hInstance, char *cname)
{
        WNDCLASS wc;
        wc.style         = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
        wc.lpfnWndProc   = (WNDPROC)WndProc;
        wc.cbClsExtra    = 0;
        wc.cbWndExtra    = 0;
        wc.hInstance     = hInstance;
        wc.hIcon         = LoadIcon(NULL,IDI_APPLICATION);
        wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wc.lpszMenuName  = NULL;
        wc.lpszClassName  = cname;
       
        return RegisterClass(&wc);
}

void InitInst(HINSTANCE hInstance, int nCmdShow, char * cname, char *title)
{
        HWND  hWnd;

        hWnd = CreateWindow(
                        cname,
                        title,
                        WS_OVERLAPPEDWINDOW,
                        CW_USEDEFAULT,
                        CW_USEDEFAULT,
                        CW_USEDEFAULT,
                        CW_USEDEFAULT,
                        NULL,
                        NULL,
                        hInstance,
                        NULL);
        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);
}

void fractal_tree(HDC, int,double);
int      d;
LPPOINT  p;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance,
                                   LPSTR lpCmdLine, int nShowCmd)
{
        MSG msg;

        InitApp(hInstance,"fractal");
        InitInst(hInstance,nShowCmd,"fractal","fractal_tree");

        while( GetMessage(&msg, NULL,0,0))
        {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
        }
        return msg.wParam;
}

LRESULT WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
        static short c_width, c_height;
        HDC hdc;
        PAINTSTRUCT ps;

        switch(msg)
        {
        case WM_SIZE:
                c_width = LOWORD(lParam);
                c_height = HIWORD(lParam);
                break;

        case WM_PAINT:
                hdc = BeginPaint(hWnd, &ps);

                p = (LPPOINT)malloc(sizeof(POINT));
                d = 90;
                MoveToEx(hdc, c_width/2, c_height - 10, NULL);

                srand( time(NULL));
                fractal_tree(hdc, 10, c_height*0.2);
                EndPaint(hWnd,&ps);
                break;

        case WM_DESTROY:
                PostQuitMessage(0);
                break;
        default:
                return DefWindowProc(hWnd,msg,wParam,lParam);
        }
        return 0;
}

#define  rotation(gdo)  (d=(d+(gdo))%360)

void fractal_tree(HDC hdc, int n, double l)
{
        int dx, dy, x, y, left, right;
        double r;
        GetCurrentPositionEx(hdc,p);
        x = p->x;
        y = p->y;
        dx = l * cos(d*PI/180);
        dy = -l* sin(d*PI/180);

        SelectObject(hdc, CreatePen(PS_SOLID, n/2+1, 0));
        LineTo(hdc,x+dx,y+dy);
        r = 0.2*rand()/RAND_MAX + 0.7;

        if(n>0)
        {
                left = 30*rand()/RAND_MAX+30;
                rotation( left );
                fractal_tree(hdc,n-1,l*r);

                right = -70*rand()/RAND_MAX-30;
                rotation(right);
                fractal_tree(hdc,n-1,l*r);

                rotation( -(left + right) );
        }

        if(n==0)
        {
                SelectObject(hdc, CreateSolidBrush(RGB(255,0,0)));
                GetCurrentPositionEx(hdc,p);
                x = p->x;
                y = p->y;
                Ellipse(hdc, x-4, y-4, x+4, y+4);
        }

        MoveToEx(hdc,x,y,NULL);
}
               

 

 

 

 

[C언어전문가과정 문의 = http://www.lesson-web.com/prom/c_main.htm]

 

[C/C++강좌]win32 api로 구현한 각종 정렬의 시뮬레이션

2006.02.10 13:35 | C언어강좌 | ITEDU

http://kr.blog.yahoo.com/sdsduck/401 주소복사

/* 본 소스는 이재규씨가 저술한 "C로 배우는 알고리즘"의 정렬 부분에서
    그림으로만 나온 각 정렬의 성능을 비교하는 시뮬레이션을 api를
    이용해서 실제로 구현해본 소스입니다.
   
    각 정렬의 상세 알고 리즘에 차후의 강의 에서 다룰 것이므로 생략을
    했고 시뮬레이션 소스 부분만을 설명 했습니다.
 
    기본적으로 C와 win32api의 기본 지식이 있어야 하며
    win32api는 김상형씨가 쓴책이 처음 보기에 좋습니다.
    c 책은 좋은게 워낙 많으니깐 ...

    알고리즘을 공부 할때는 딱딱한 수식이 즐비한 수학기반의
    책을 보기 보담 눈으로 바로 확인 할 수 있는 그래픽한 소스 기반
    으로 공부 하는게 질리지 않고 끝까지 할 수 있습니다.

    보통 사람들이 알고리즘을 할 때 정렬까지는 엄청 쉬운듯이 말 하지만
    정렬 알고리즘은 이 전 세대가 수 백년 동안 작성한 가장 완성도 있는
    알고리즘이라 할 수 있습니다.
 
    코드는 짧지만 이해하기는 매우 어려 우며  예제를 보지 않고 구현 하기란
    더욱 어렵습니다.

    보통 알고리즘의 기본이 되며 기본이 쉽다는것을 의미 하는것은 아닙니다.
    알고리즘의 원류를 알고 있는 사람은 어떤 문제가 닥쳐 와도 해결 할 수
    있는 능력을 보유 하고 있습니다.
*/
   

 

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>    //srand(), rand(), RAND_MAX
#include <time.h>      //time()

LRESULT WndProc(HWND,UINT,WPARAM,LPARAM);

BOOL InitApp(HINSTANCE hInstance, char *cname)
{
        WNDCLASS wc;   //윈도우의 공통적인 특성을 정의 하는 구조체
        wc.style         = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
        wc.lpfnWndProc   = (WNDPROC)WndProc;  //윈도우 프로시저 주소
        wc.cbClsExtra    = 0;
        wc.cbWndExtra    = 0;
        wc.hInstance     = hInstance;
        wc.hIcon         = LoadIcon(NULL,IDI_APPLICATION);
        wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wc.lpszMenuName  = NULL;
        wc.lpszClassName  = cname;  //구조체의 이름, 윈도우 클래스를
                                                    //유일하게 식별한다.
       
        return RegisterClass(&wc);     //운영체제에게 구조체의 주소를 등록
}

void InitInst(HINSTANCE hInstance, int nCmdShow, char * cname, char *title)
{
        HWND  hWnd;

        hWnd = CreateWindow(
                        cname,
                        title,
                        WS_OVERLAPPEDWINDOW,
                        CW_USEDEFAULT,
                        CW_USEDEFAULT,
                        CW_USEDEFAULT,
                        CW_USEDEFAULT,
                        NULL,
                        NULL,
                        hInstance,
                        NULL);
        ShowWindow(hWnd, nCmdShow);  //메모리에 있는 원도우 객체를
                                                          //화면상에 보여줌
        UpdateWindow(hWnd);                  //WM_PAINT 메시지를 생성
}

// 각 정렬 함수의 프로토타입 선언
void bubble_sort(HDC, int *,int);
void select_sort(HDC, int *,int);
void insert_sort(HDC, int *,int);
void shell_sort(HDC, int *,int);
void quick_sort(HDC, int *,int,int);
void radix_sort(HDC, int *, int, int, int);


// 프로그램의 엔트리 포인트
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance,
                                   LPSTR lpCmdLine, int nShowCmd)
{
        MSG msg;

        InitApp(hInstance,"init.h");
        InitInst(hInstance,nShowCmd,"init.h","bubble_sort");

        while( GetMessage(&msg, NULL,0,0))
        {
                TranslateMessage(&msg);  //WM_CHAR 메시지 생성
                DispatchMessage(&msg);   //프로시져 호출
        }
        return msg.wParam;
}

#define BLACK RGB(0,0,0)       //매크로 상수를 사용하여 코드를 간단하게..
#define WHITE RGB(255,255,255)  //RGB()는 매크로 함수

LRESULT WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
        int x, nsu[2000];
        int c_width, c_height;
        HDC hdc;

        switch(msg)
        {
        case WM_SIZE:
                c_width = LOWORD(lParam);  //클라이언트 영역의 가로크기
                c_height = HIWORD(lParam);  //클라이언트 영역의 세로크기
                hdc = GetDC(hWnd);             //디바이스 컨텍스트의 핸들얻기

                for(x=0; x<c_width; x++)
                {
                       // 0 ~ c_height 사이의 랜덤 값을 생성 한다.
                       // rand()함수의 생성 범위 0~32767
                       // RAND_MAX 는 0x7fff 즉 32767의 매크로 상수임
                        nsu[x] = c_height*rand()/RAND_MAX;
                       // 세로의 픽셀 단위의 한 줄에 가로로 랜덤한 곳에 점을찍음
                        SetPixel(hdc,x,nsu[x],BLACK);
                }


//아래에 있는 함수 중 디스플레이 하고 싶은 함수만 주석을 풀고 실행한다.
//                bubble_sort(hdc,nsu,c_width);  // 거품 정렬
//                select_sort(hdc,nsu,c_width);   // 선택 정렬
//                insert_sort(hdc,nsu,c_width);    // 삽입 정렬
//                shell_sort(hdc,nsu,c_width);     // 쉘 정렬
//                quick_sort(hdc,nsu,c_width,0);  // 퀵 정렬
                radix_sort(hdc, nsu, c_width, 31, 0);  // 기수 정렬

 

                ReleaseDC(hWnd,hdc);
                break;
        case WM_DESTROY:
                PostQuitMessage(0);
                break;
        default:
                return DefWindowProc(hWnd,msg,wParam,lParam);
        }
        return 0;
}

void bubble_sort(HDC hdc, int *a,int n)
{
        int i,j,flag,temp;

        for(i=0; i<n-1 ; i++)
        {
                flag=0;
                for(j=0; j<n-i-1 ; j++)
                        if(a[j] > a[j+1])
                        {
                                SetPixel(hdc,  j, a[j],WHITE);
                                SetPixel(hdc,j+1, a[j],BLACK);

                                SetPixel(hdc, j+1, a[j+1], WHITE);
                                SetPixel(hdc, j  , a[j+1], BLACK);

                                temp  =  a[j];
                                a[j]  =  a[j+1];
                                a[j+1]=  temp;
                                flag=1;
                        }
                        if(!flag)
                                return;
                        Sleep(1);
        }
}

void select_sort(HDC hdc, int *a,int n)
{
        int i,j,chd,max;

        for(i=0; i<n-1 ; i++)
        {
                chd = i;
                max = a[i];

                for(j=i+1; j<n; j++)
                        if(a[j] > max)
                        {
                                chd = j;
                                max = a[j];
                        }
                SetPixel(hdc,  chd, a[chd],WHITE);
                SetPixel(hdc,    i, a[chd],BLACK);

                SetPixel(hdc,   i, a[i], WHITE);
                SetPixel(hdc, chd, a[i], BLACK);
                a[chd] = a[i];
                a[i] = max;

                Sleep(1);
        }
}

void insert_sort(HDC hdc, int *a,int n)
{
        int  i, j, temp;

        for(i=1; i<n; i++)
        {
                temp = a[i];
                j = i-1;

                while(j>=0 && a[j]>temp)
                {
                        SetPixel(hdc,  j, a[j],WHITE);
                        SetPixel(hdc,j+1, a[j],BLACK);

                        a[j+1]=a[j];
                        j--;
                }
                SetPixel(hdc, i, temp, WHITE);
                SetPixel(hdc, j+1  , temp, BLACK);

                a[j+1] = temp;
                Sleep(10);
        }
}

void shell_sort(HDC hdc, int *a,int n)
{
        int i, j, temp, term;
        int start;

        term = n;

        while( term > 1)
        {
                term = term/3 +1;

                for(start=0; start<term; start++)
                {
                        for(i=start; i<n; i+=term)
                        {
                                temp = a[i];
                                j = i - term;

                                while( j>=0 && a[j]>temp)
                                {
                                        SetPixel(hdc, j, a[j], WHITE);
                                        SetPixel(hdc, j+term  , a[j], BLACK);

                                        a[j+term] = a[j];
                                        j -= term;
                                }

                                SetPixel(hdc, i, temp, WHITE);
                                SetPixel(hdc, j+term  , temp, BLACK);

                                a[j+term] = temp;
                        }
                        Sleep(10);
                }

        }
}

void quick_sort(HDC hdc, int *a, int n, int x)
{
        int i,j;
        int key, temp;

        if(n > 1)
        {
                key = a[0];
                i = 0;
                j = n;

                while(1)
                {
                        while(a[++i] < key);
                        while(a[--j] > key);

                        if(i >= j)
                                break;

                        SetPixel(hdc, x+i, a[i], WHITE);
                        SetPixel(hdc, x+j, a[i], BLACK);

                        SetPixel(hdc, x+j, a[j], WHITE);
                        SetPixel(hdc, x+i, a[j], BLACK);

                        temp = a[i];
                        a[i] = a[j];
                        a[j] = temp;
                }
               
                SetPixel(hdc, x+0, key, WHITE);
                SetPixel(hdc, x+j, key, BLACK);

                SetPixel(hdc, x+j, a[j], WHITE);
                SetPixel(hdc, x+0, a[j], BLACK);

                a[0] = a[j];
                a[j] = key;

                quick_sort(hdc, a    , j    , x);
                quick_sort(hdc, a+j+1, n-j-1, x+j+1);
        }
        Sleep(10);
}

void radix_sort(HDC hdc, int *a, int n, int b, int x)
{
        int i, j, temp;

        if(n>1 && b>=0)
        {
                i = 0 ;
                j = n-1;

                while(1)
                {
                        while( ((a[i] >> b)&1) == 0 && i<j)
                                i++;

                        while( ((a[j] >> b)&1) == 1 && i<j)
                                j--;

                        if(j <= i )
                                break;

                        SetPixel(hdc, x+i, a[i], WHITE);
                        SetPixel(hdc, x+j, a[i], BLACK);

                        SetPixel(hdc, x+j, a[j], WHITE);
                        SetPixel(hdc, x+i, a[j], BLACK);

                        temp = a[i];
                        a[i] = a[j];
                        a[j] = temp;
                }
                if( ((a[n-1] >> b)& 1) == 0)
                        j++;

                radix_sort(hdc,  a,  j,  b-1,  x);

                radix_sort(hdc,  a+j, n-j, b-1, x+j);

                Sleep(10);
        }
}
 
 

 

 


[C언어전문가과정 문의 = http://www.lesson-web.com/prom/c_main.htm]

전통적인 스와핑

main()
{
     int   a=3, b=4, t;

     t = a;
     a = b;
     b = a;
}

이렇게 하면 

  세 변수가 지역 변수 이기에 stack 메모리에 각각 4byte씩

                a        b          t
-----------------------------------
            |   3    |   4     |         |
-----------------------------------

잡히게 되며

①   t = a; 시에

                a        b          t
-----------------------------------
            |   3    |   4     |   3     |
-----------------------------------

②  a = b;

                a        b          t
-----------------------------------
            |   4    |   4     |   3     |
-----------------------------------

③ b = t;

              a        b          t
-----------------------------------
            |   4    |   3    |   3     |
-----------------------------------

이같은 일련의 과정을 통해 임시변수 t를 이용하여 a와 b의 값이 바뀌었다..

여기선 우린 이런 생각을 할수 있다....   " 왜 내가 스와핑을 하는데 제 3자가 관여를 하는거야??  기분 나쁘군"

덧셈을 이용한 스와핑

main()
{
     int   a=3, b=4;

     a = a+b;
     b = a-b;
     a = a-b;
}

이렇게 하면 

  두 변수가 지역 변수 이기에 stack 메모리에 각각 4byte씩

                a        b       
-----------------------------------
            |   3    |   4    |        
-----------------------------------

잡히게 되며

①   a = a+b; 시에

                a        b       
-----------------------------------
            |   7   |   4    |        
-----------------------------------

②  b = a-b; //7-4이므로

                a        b       
-----------------------------------
            |   7   |   3    |        
-----------------------------------

③  a = a-b; //b는 위 연산에서 3으로 바뀌었으므로 7-3이 a에 대입된다.

                a        b       
-----------------------------------
            |   4   |   3    |        
-----------------------------------


놀랍지 안은가?   이건 잔머리의 승부다....   a+b가 a의 정보와 b의 정보를
포함한다는데서 힌트를 얻을 수 있다.

그런데 문제점은  덪셈이기 때문에 오버플로우를 걱정 해야 한다. 만약
두변수의 값이 int의 양의 정수 최대 표기인 21억을 넘어가는 숫자에 대해서는 스왑을 할수가 없다.

그렇다면 곱셈을 이용한 스왑을 생각 할수도 있는데 이럴 경우 문제는 더 심각하다.

a = a*b;
b = a/b;
a = a/b;

물론 작은수에 대해서 스왑이 잘 되지만.. 덪셈보다 오버플로우가 더 심하고..
b가 0인 경우는 수학적 불능이기 때문에 스왑이 일어나지 않는다.

그래서 최종적 대안이 상호배타 비트합을 이용하는 기법이다.

X-OR를 이용한 스와핑

main()
{
     int   a=3, b=4;

     a = a^b;
     b = a^b;
     a = a^b;
}

이렇게 하면 

  두 변수가 지역 변수 이기에 stack 메모리에 각각 4byte씩

                a        b       
-----------------------------------
            |   3    |   4    |        
-----------------------------------

잡히게 되며

①   a = a^b; 시에

0011 ^ 0100 => 0111 이므로
                a        b       
-----------------------------------
            |   7   |   4    |        
-----------------------------------

②  b = a^b;

0111 ^ 0100 => 0011 이므로
                a        b       
-----------------------------------
            |   7   |   3    |        
-----------------------------------

③  a = a^b;

//b는 위 연산에서 3으로 바뀌었으므로
  0111 ^ 0011 => 0100
                a        b       
-----------------------------------
            |   4   |   3    |        
-----------------------------------

a = a^b;
b = a^b;
a = a^b;

위식의 간략화

a ^= b;
b ^= a;
a ^= b;

더 간략화

a ^= b ^= a ^= b;

캬.... 멋지지 않은가?? 한줄로 스와핑이 일어 났다...

비트의 오버플로우도 일어나지 않았고, 덧셈이나 곱셈보다 비트 필드 연산이
빠르기 빼문에 고속의 스와핑이 일어난다..

그렇다면 문제는 없는가?  문제는... 그러니까 문제는...    

a ^= b ^= a ^= b; 이식을 보고 누가 스와핑 코드인줄 알겠는가?
가독성은 프로젝트에서 엄청 중요한 문제이고 

저런 코드는 유지보수에 백해무익 하다....

또한  실수 연산에서는 사용할 수 없다.  실수의 비트열은 정수와 완전히 다르기 때문에 x-or연산을 했을시 원치않는 결과를 초래한다.

결과적으로 이 코드는 절대 수정될 일이 없는 매우 빠른 속도를 원하는 곳에
사용 하면 된다.

또한 이런 사실을 아는 사람은 이 코드가 스와핑이라는 것을 알수 있기에 이 기법을 다뤄 본다.
 
 

 

[C언어전문가과정 문의 = http://www.lesson-web.com/prom/c_main.htm]

[JAVA/SCJP강좌][JSP기초#27]태그라이브러리의 동작

2006.02.10 13:34 | JAVA강좌 | ITEDU

http://kr.blog.yahoo.com/sdsduck/399 주소복사

커스텀태그의 수행은 실제 자바클래스가 담당한다. 즉 커스텀태그를 만든다는것은 원하는 기능의 자바클래스를 설계하는 것이다.이러한 자바클래스를 Custom Tag Handler라고 한다.
기본동작
- JSP에서 태그라이브러리를 사용할려면 이를 JSP Container에게 알려야 하는데 taglib 지시자를 이용한다.
- <%@ taglib uri=“/WEB-INF/sample.tld”     prefix=“jclee” %>
        uri : 해당 커스텀태그 라이브러리에 대한 위치를 알린다.
        prefix : 사용할 태그라이브러리의 이름을 가리킨다. 접두사


- JSP콘테이너는 JSP페이지를 읽고 서블릿으로 변환할때 taglib지시자를 만나며 이때 .tld 파일이 로드되었는지 확인하며 만약 로드되지 않았다면 로드하고, 이미 로드 되었다면 넘어간다

커스텀태그 라이브러리는 TLD(Tag Linrary Descriptor)와 Custom Tag Handler로 구분 할수 있다.
TLD 파일은 JSP콘테이너가  taglib 지시자를 만났을때 제일 먼저 찾는 파일이다. 이파일에는 커스텀태그에 관한 간략한 정보들이 들어있다. 즉 TLD 파일은 JSP를 서블릿으로 컴파일할때 커스텀태그가 올바른 것인지 , 사용 문법에 맞는지등을 검사할때 이용되는 파일이다.
태그의 요청이 있다면 핸들러의 작업을 담당하는 자바클래스가 JVM에 로드되어 수행된다. 물론 로드된 클래스는 공유가 가능하다. 매 요청마다 일일이 인스턴스를 만드는것은 아니며 공유하여 사용한다.
보통 커스텀태그 라이브러리는 JAR 압축파일로 이루어져 있으며 이 파일은 태그핸들러를 구성하는 자바클래스와 수행되는 태그들의 간단한 정보와 목록이 있는 TLD 파일로 구성되어 있다.

 

 
 

[자바전문가과정 문의 = http://www.lesson-web.com/prom/java_main.htm]

[ 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 ] 다음 페이지 다음 10번째 페이지