기수정렬(Radix sort)에대해 질문드립니다.
한가람
제가 자료구조론을 수강하고있는대요 Radix sort에대해 알아오라고했더라고요. 교수님이 그리고 프로그램도 만들어야하는데.
기수정렬이라하겠음. 에대해 알아보니 자리수대로 비교하여 일의자리수 십의자리수 이렇게 차례대로비교하는 방법이라고
하더군요. 제가 기수정렬이대한 소스를 가져와서 분석하는데 비교될 숫자값이 어디서 입력되고 어디서 출력되는지는 알겠지만
radix_sort 부분에서 어디서 숫자들의 자릿수가 비교되는지 어떻게 순서가 정해지는지 잘모르겠네요. 프로그래밍 고수님들께
답변좀 부탁드리겠습니다. 저혼자서 기수정렬하는 프로그램을 짤수는있겠지만 먼저 이것부터 이해하고나서 만들어야겠네요
쩝.
#include stdio.h
#include stdlib.h
#define SIZE 10
#define BUCKETS 10 // 10진수
#define DIGITS 4 // 4자리 수까지 가능
#define MAX_QUEUE_SIZE 100
typedef int element;
typedef struct{
element queue[MAX_QUEUE_SIZE];
int front, rear;
}QueueType;
void error(char *message)
{
fprintf(stderr, %s\n, message);
exit(1);
}
// 초기화 함수
void init(QueueType *q)
{
q-front = q-rear = 0;
}
// 공백 상태 검출 함수
int is_empty(QueueType *q)
{
return (q-front == q-rear);
}
// 포화 상태 검출 함수
int is_full(QueueType *q)
{
return ((q-rear+1)%MAX_QUEUE_SIZE == q-front);
}
// 삽입 함수
void enqueue(QueueType *q, element item)
{
if(is_full(q))
error(큐가 포화상태입니다);
q-rear = (q-rear+1) % MAX_QUEUE_SIZE;
q-queue[q-rear] = item;
}
// 삭제 함수
element dequeue(QueueType *q)
{
if(is_empty(q))
error(큐가 공백상태입니다);
q-front = (q-front+1) % MAX_QUEUE_SIZE;
return q-queue[q-front];
}
void radix_sort(int list[], int n)
{
int i, b, d, factor=1;
QueueType queues[BUCKETS];
for(b=0; bn; b++)
init(&queues[b]); // 모든 큐 초기화
for(d=0; dDIGITS; d++)
{
for(i=0; in; i++) // 데이터들을 자리수에 따라 큐에 삽입
enqueue(&queues[(list[i]/factor)%10], list[i]);
for(b = i = 0; bBUCKETS; b++) // 버킷에서 꺼내 list로 합침
while(!is_empty(&queues[b]))
list[i++] = dequeue(&queues[b]);
factor *= 10; // 다음 자리수로 간다
}
}
// 리스트 출력 함수
void print_list(int list[])
{
int i;
for(i=0; iSIZE; i++)
printf(%d번째 값 : %d\n, i+1, list[i]);
}
///////////////////////////////////////////////////////////////////////////////////
// 메인 함수
void main()
{
int i, num=0;
int list[SIZE];
for(i=0; iSIZE; i++)
{
printf(%d번 값 : , i+1);
scanf(%d, &list[i]);
num++;
}
printf(정렬 전\n);
print_list(list);
radix_sort(list, num);
printf(정렬 후\n);
print_list(list);
}
-
소년틳터프
답변감사드립니다 그런데 아무리봐도 자리수들의 크기를비교하는 곳은 찾아볼수가없네요. 그런데도불구하고 정수를입력하면 작은순서대로 차례대로 출력되는거보니 엄청신기하네요. 어떻게 자리수들의 크기 예를들어 일의자리 5는 9보다작다 이렇게 비교하지않고도 정렬이가능할수있을까요??
-
히메
여기만 보면 버켓소팅으로 짜여진것 같은데요. 처음 자리수, num %10으로 모듈러 하죠. 그러니까 큐에 넣어서 같은 자리수에 대해 일렬로 리스트를 모읍니다. 그런다음 다시 첫번째 요소부터 마지막 요소까지 링크드 리스크를 일렬로된 리스트로 만듭니다. 그런다음 다음 자릿수로 넘어갑니다. 여기서는 100의 자리겠죠? 그럼 이만^^ㅎㅎ 자러 갑니다~^^ㅎ
-
들샘
for(i=0; in; i++) // 데이터들을 자리수에 따라 큐에 삽입
enqueue(&queues[(list[i]/factor)%10], list[i]);
for(b = i = 0; bBUCKETS; b++) // 버킷에서 꺼내 list로 합침
while(!is_empty(&queues[b]))
list[i++] = dequeue(&queues[b]);
factor *= 10; // 다음 자리수로 간다 -
슬찬
여기까지 전반적인 설명이였구요. 제가 소스 코드를 다 읽을 시간이 없어서 간단하게만 설명 드리면 % 연산이 있는 부분에서 숫자를 모듈러하고 버켓에다 넣는 것입니다. 버킷 소팅 방법은 아시겠죠? 저부분만 아신다면 나머지는 쉬우니 눈팅으로 따라가면 가능 할것이라고 봅니다. 저기가 핵심이니까요. 참고로 버킷 소팅이나 라딕스 소팅이나 거의 같습니다. 라딕스 소팅이 버킷을 이용하니까요.
-
흰양말
또한 버킷의 크기에 따라 속도가 달라짐에 유의 하시구요. 그러니까 tradeoff가 필요 합니다. 메모리를 많이 사용하면 속도가 빨라지구요. 메모리를 적게 사용하면 속도가 느려집니다. 두개의 절충점을 잘 생각해 보시구요. 또한 데이터에 둔감하죠. 양의 정수를 소팅할때 쓰이는 것이구요. 다른 좋은 소팅 알고리즘들도 많지만 양의 정수를 소팅할때는 이것만한 것도 없습니다~.
-
석죽
기수 정렬에는 직접 기수 정렬과 교환 기수 정렬이 있습니다. 둘다 아주 간단한 알고리즘으로 구현 가능하구요. 링크드 리스크로 구현할 경우 속도가 매우 느려지므로 배열로 구현 하는 것이 좋습니다.