탐색 (1) 용어 정리 순차 탐색 (Sequential Search) 리스트 : 하나 이상의 필드로 된 레코드의 집합

Slides:



Advertisements
Similar presentations
10-7 부동소수점 (Floating-Point) 계산  컴퓨터에서 숫자를 표기하는 방법  가수 (Fraction) : 부호화된 고정소수점 숫자 지수 (Exponent) : 소수점의 위치를 표시 ( 예 )10 진수 를 표기하면 Fraction Exponent.
Advertisements

알고리즘 기본 개념 정렬 알고리즘 탐색 알고리즘 알고리즘 복잡도.
CHAP 8:우선순위큐 C로 쉽게 풀어쓴 자료구조 Slide 1 (of 20).
제14장 동적 메모리.
연결리스트(linked list).
Report #2 - Solution 문제 #1: 다음과 같이 프로그램을 작성하라.
보고서 #7 (기한: 6/2) 2개의 스택, stk1, stk2를 이용하여 큐를 구현하라.
Chapter 10. 정렬 Chapter 10-1: 단순한 정렬 알고리즘.
제 3 장 선형 리스트 3.1 선형 리스트 3.2 연결 리스트 3.3 다항식.
정보보안 프로젝트 (Sort Algorithm) 학 부 : 컴퓨터 정보공학부, 네트워크 정보 공학부
자료구조론 11장 정렬(sort).
P150 문제를 프로그래밍 할 것 Source file (헤더파일포함), 실행화면 (학번_이름_1.txt)
빠른정렬(Quick Sort) – 개요 (1/2)
CHAP 9:정렬 C로 쉽게 풀어쓴 자료구조 생능출판사 2005.
11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const.
11.텍스트를 위한 화일.
Error Detection and Correction
제 11 장 다원 탐색 트리.
제 7 장 정렬.
자료구조: CHAP 4 리스트 (1) 순천향대학교 컴퓨터공학과 하 상 호.
자료구조: CHAP 7 트리(1) 순천향대학교 컴퓨터공학과 하 상 호.
자료구조: CHAP 4 리스트 (3) 순천향대학교 컴퓨터공학과 하 상 호.
프로그래밍 랩 – 7주 리스트.
PySpark Review 박영택.
11장. 1차원 배열.
CHAP 9: 정렬 (part 2) 순천향대학교 컴퓨터학부 하 상 호.
정렬과 합병.
CHAP 9:정렬 C로 쉽게 풀어쓴 자료구조 Slide 1 (of 44).
제 8 장 정렬.
Introduction To Data Structures Using C
11 정렬.
자기참조 구조체(1) 먼저 자신과 같은 형의 구조체를 포인트하는 포인터 멤버 필드를 갖는 구조체를 정의한다.
CHAP 9: 정렬 순천향대학교 컴퓨터학부 하 상 호.
자료구조: CHAP 7 트리 –review 순천향대학교 컴퓨터공학과 하 상 호.
27장. 모듈화 프로그래밍.
Quiz #7 다음 수들을 합병 정렬과 퀵 정렬 알고리즘을 이용하여 오름 차순으로 정렬하였을 때, 데이터 이동 회수를 각각 구하라. 여러분은 정렬 과정을 단계별로 보이면서 이동 회수를 추적해야 한다. 단, 퀵 정렬시에 피봇으로 배열의 왼쪽 첫 번째 원소를 선택한다. 5.
8장. 상호 배타적 집합의 처리.
쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express Slide 1 (of 22)
Chapter6 : JVM과 메모리 6.1 JVM의 구조와 메모리 모델 6.2 프로그램 실행과 메모리 6.3 객체생성과 메모리
알고리즘: 우선순위 큐(8장) 순천향대학교 컴퓨터 학부 하 상 호.
컴퓨터 프로그래밍 기초 - 10th : 포인터 및 구조체 -
컴퓨터 프로그래밍 기초 - 8th : 함수와 변수 / 배열 -
1. 2진 시스템.
CHAP 12: 탐색 순천향대학교 컴퓨터학부 하 상 호.
균형이진탐색트리 이진 탐색(binary search)과 이진 탐색 트리(binary search tree)와의 차이점
CHAP 12 : 탐색 C로 쉽게 풀어쓴 자료구조 Slide 1 (of 27).
조 병 규 Software Quality Lab. 한 국 교 통 대 학 교
데이터 동적 할당 Collection class.
알고리즘: 우선순위 큐(8장) 순천향대학교 컴퓨터 학부 하 상 호.
CHAP 9:정렬 C로 쉽게 풀어쓴 자료구조 생능출판사 2005.
4장. 데이터 표현 방식의 이해. 4장. 데이터 표현 방식의 이해 4-1 컴퓨터의 데이터 표현 진법에 대한 이해 n 진수 표현 방식 : n개의 문자를 이용해서 데이터를 표현 그림 4-1.
보고서 #2(제출기한: 09/23) 다음 문제를 해결하시오. (7)
DA :: 퀵 정렬 Quick Sort 퀵 정렬은 비교방식의 정렬 중 가장 빠른 정렬방법이다.
5장. 선택 알고리즘.
빠른정렬(Quick Sort) – 개요 (1/2)
7주차: Functions and Arrays
쉽게 배우는 알고리즘 2장. 점화식과 점근적 복잡도 분석
Chapter 10 데이터 검색1.
CHAP 9: 정렬 순천향대학교 컴퓨터학부 하 상 호.
컴퓨터 프로그래밍 기초 - 9th : 배열 / 포인터 -
ER-관계 사상에 의한 관계데이터베이스 설계 충북대학교 구조시스템공학과 시스템공학연구실
트리 (Logical) Data Structures Linear list Tree Graph Linear structures
컴퓨터 개론 √ 원리를 알면 IT가 맛있다 쉽게 배우는 컴퓨터 기본 원리 한빛미디어 교재출판부.
제 4 장 Record.
우선순위 큐 & Heap Ref. C로 쉽게 풀어쓴 자료구조, 생능출판사, 2005.
29장. 템플릿과 STL 01_ 템플릿 02_ STL.
빠른정렬(Quick Sort) – 개요 (1/2)
C++ Espresso 제15장 STL 알고리즘.
6 객체.
BoardGame 보드게임 따라가기.
Presentation transcript:

탐색 (1) 용어 정리 순차 탐색 (Sequential Search) 리스트 : 하나 이상의 필드로 된 레코드의 집합 키(Key) : 레코드를 구분하기 위해서 사용되는 필드 순차 탐색 (Sequential Search) 레코드 리스트를 왼편에서 오른편 또는 오른편에서 왼편으로 레코드를 검사하는 것

정렬의 필요성 정렬의 두 가지 중요한 사용법 정렬 방법 (1) 탐색에서 보조로 사용 (2) 리스트의 엔트리를 비교하는 방법으로 사용 정렬 방법 (1) 내부 방법 (internal methods) 정렬할 리스트가 작아서 전체적인 정렬이 메인 메모리 상에서 실행될 수 있을 때 사용 (2) 외부 방법 (external methods) 큰 리스트에 사용

삽입 정렬 (1) 새로운 레코드를 i개의 정렬된 레코드 리스트에 끼워 넣어 크기가 i+1인 정렬된 결과 레코드 리스트를 만든다. void insert(element e, element a[], int i) {/* e를 정렬된 리스트 a[1:i]에 삽입하여 결과 리스트 a[1:i+1]도 정렬되게 한다. 배열 a는 적어도 i+2 원소를 포함할 공간을 가지고 있어야 한다. */ a[0] = e; while(e.key <a[i].key) { a[i+1] = a[i]; i--; } a[i+1] = e; 정렬된 리스트로 삽입

삽입 정렬 (2) insert(e, a, i)는 최악의 경우 삽입 전 i+1번 비교해야 함 insertionSort의 복잡도 void insertionSort(element a[], int n) {/* a[1:n]을 비감소 키 순서대로 정렬 */ int j; for(j = 2; j <= n; j++) { element temp = a[j]; insert(temp, a, j-1); } 삽입 정렬 insert(e, a, i)는 최악의 경우 삽입 전 i+1번 비교해야 함 insert의 복잡도 : O(i) insertionSort의 복잡도 i = j-1 = 1,2,...,n-1일 때 insert를 호출 복잡도 : O( ) = O(n2)

삽입 정렬 (3) 삽입 정렬의 최악의 예 n = 5, 입력 키 순서 : 5, 4, 3, 2, 1 입력 리스트가 역순이므로 새로운 레코드가 정렬된 부분에 삽입될 때마다 전체 정렬된 부분이 오른쪽으로 이동 j [1] [2] [3] [4] [5] _ 5 4 3 2 1 2 4 5 3 2 1 3 3 4 5 2 1 4 2 3 4 5 1 5 1 2 3 4 5

삽입 정렬 (4) n = 5, 입력 키 순서가 2, 3, 4, 5, 1일 경우 j = 2, 3, 4에 대한 시간 : O(1) j = 5에 대한 시간 : O(n) insertionSort는 안정적 작은 n(예를 들어, n≤30)에 대해 가장 빠른 정렬 방법 j [1] [2] [3] [4] [5] _ 2 3 4 5 1 2 2 3 4 5 1 3 2 3 4 5 1 4 2 3 4 5 1 5 1 2 3 4 5

삽입 정렬 (5) 삽입 정렬의 변형 이원 삽입 정렬 연결 삽입 정렬 insert(프로그램 7.4)에서 사용된 순차 탐색 기법 대신 이원 탐색을 사용 삽입 정렬에서 수행하는 비교 횟수를 줄인다 레코드 이동 횟수는 변하지 않음 연결 삽입 정렬 리스트의 원소들을 배열 대신 연결 리스트로 표현 링크 필드만 조정하면 되므로 레코드 이동 횟수가 0 insert에서 사용한 순차 탐색은 그대로 사용

퀵 정렬 (1) 평균 성능이 가장 좋은 정렬 방법 퀵 정렬(Quick Sort) 단계 (1) 정렬할 레코드 중 피벗(pivot:중추) 레코드를 선택 (2) 정렬할 레코드들을 다시 정돈 피벗의 왼쪽 : 피벗의 키보다 작거나 같은 레코드들을 위치 시킴 피벗의 오른쪽 : 피벗의 키보다 크거나 같은 레코드들을 위치 시킴 (3) 퀵 정렬을 순환적으로 사용 피벗의 왼쪽과 오른쪽의 레코드들은 서로 독립적으로 정렬된다

퀵 정렬 (2) 퀵 정렬 void quickSort(element a[], int left, int right) {/* a[left:right]를 비감소 키 순서대로 정렬한다. a[left].key는 피벗으로 임의로 선정한다. a[left].key≤ a[right+1].key라고 가정한다. */ int pivot, i, j; element temp; if(left < right) { i = left; j = right +1; pivot = a[left].key; do{ /* 서브리스트를 왼쪽에서 오른쪽으로 탐색하면서 left와 right 경계가 교차되거나 만날 때까지 out-of-order 원소들을 swap한다 */ do i++; while(a[i].key < pivot); do j--; while(a[j].keky > pivot); if(i < j) SWAP(a[i], a[j],temp); } while(i < j); SWAP(a[left], a[j],temp); quickSort(a, left, j-1); quickSort(a, j+1, right); } 퀵 정렬

퀵 정렬 (3) 키 (26, 5, 37, 1, 61, 11, 59, 15, 48, 19)를 가진 10개의 레코드로 된 리스트를 퀵 정렬을 사용하여 정렬 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 left right [26 5 37 1 61 11 59 15 48 19] 1 10 [11 5 19 1 15] 26 [59 61 48 37] 1 5 [ 1 5] 11 [19 15] 26 [59 61 48 37 1 2 1 5 11 [19 15] 26 [59 61 48 37] 4 5 1 5 11 15 19 26 [59 61 48 37] 7 10 1 5 11 15 19 26 [48 37] 59 [61] 7 8 1 5 11 15 19 26 37 48 59 [61] 10 10 1 5 11 15 19 26 37 48 59 61 quickSort를 호출할 때마다의 리스트 상태 대괄호는 계속해서 정렬할 서브리스트를 나타냄

퀵 정렬 (4) 평균 연산 시간 : O(nlogn) quickSort의 분석 최악의 경우 복잡도 : O(n2) 한 레코드의 위치가 정확히 정해질 때마다 그 레코드의 왼쪽과 오른쪽의 서브리스트 크기가 같을 경우 크기가 n/2인 두 개의 서브리스트를 정렬하는 작업과 같다 크기가 n인 리스트에서 한 레코드를 위치시키는 데 필요한 시간 : O(n) T(n) ≤ cn + 2T(n/2) 어떤 상수 c에 대해서 ≤ cn + 2(cn/2 + 2T(n/4)) ≤ 2cn + 4T(n/4) . ≤ cnlog2n + nT(1) = O(nlog2n) 평균 연산 시간 : O(nlogn)

퀵 정렬 (7) 퀵 정렬과 스택 공간 퀵 정렬은 순환(recursion)을 구현하기 위해 스택 공간 필요 리스트가 균등하게 나뉘는 경우 최대 순환 깊이는 log n이 되어 스택 공간으로 O(log n) 필요 최악의 경우 순환의 각 단계에서, 크기가 n-1인 왼쪽 서브 리스트와 크기가 0인 오른쪽 서브리스트로 리스트가 나뉘는 경우 순환 깊이는 n이 되어 스택 공간으로 O(n) 필요 보다 작은 크기의 서브리스트를 먼저 정렬하여 스택 공간을 점근적으로 감소시킬 수 있다.

합병 정렬 (1) 합병(Merging) 두개의 정렬된 리스트를 하나의 정렬된 리스트로 합병 합병시간 : O(n-l+1) void merge(element initList[], element mergedList[], int i, int m, int n) { /* initList[1:m]과 initList[m+1:n]는 정렬된 리스트. 이들은 정렬된 리스트 mergedList[i:n]으로 합병된다.*/ int j,k,t; j = m+1; k = i; while( i <= m && j <= n) { if (initList[i].key <= initList[j].key) mergeList[k++] = initList[i++]; else mergeList[k++] = initList[j++]; } if (i > m) /* mergedList[k:n] = initList[j:n]*/ for(t = j; t <= n; t++) mergeList[t] = initList[t]; /* mergedList[k:n] = initList[i:m] */ for(t = i; t <= m; t++) mergeListpk+t-i] = initList[t]; 합병시간 : O(n-l+1) n-l+1 : 합병될 레코드 수

합병 정렬 (2) 반복 합병 정렬(Iterative Merge Sort) 반복 합병 정렬 단계 입력 리스트를 길이가 1인 n개의 정렬된 서브리스트로 간주 반복 합병 정렬 단계 첫번째 합병 단계 : 리스트들을 쌍으로 합병하여 크기가 2인 n/2개의 리스트를 얻는다. n이 홀수이면 리스트 하나는 크기가 1 두번째 합병 단계 : n/2개의 리스트를 다시 쌍으로 합병하여 n/4개의 리스트를 얻는다. 합병 단계는 하나의 서브 리스트가 남을 때까지 계속된다. 한번 합병할 때마다 서브 리스트의 수는 반으로 줄어든다.

합병 정렬 (3) 반복 합병 정렬의 예 입력 리스트 : (26, 5, 77, 1, 61, 11, 59, 15, 48, 19) 5 26 1 77 11 61 15 59 19 48 1 5 26 77 11 15 59 61 19 48 1 5 11 15 26 59 61 77 19 48 1 5 11 15 19 26 48 59 61 77 각 단계에서 합병되는 서브리스트를 합병 트리로 나타낸 것

합병 정렬 (4) 합병 정렬은 여러 개의 합병 단계(pass)로 구현된다. 합병 패스 void mergePass(element initList[], element resultList[], int n, int s) { /* 길이가 s인 서브리스트의 인접 쌍들이 // initList에서부터 resultList로 합병된다. n은 initList에 있는 레코드 수이다. for(i = 1; i <= n-2*s+1; i+= 2*s) merge(initList, mergedList, i, i+s-1, i+2*s-1); if((i+s-1)<n) merge(initList, mergedList, i, i+s-1, n); else for(j=i; j <= n; j++) mergedList[j] = initList[j]; } 합병 패스

합병 정렬 (5) mergeSort 분석 i번째 패스 : 크기가 2i-1인 리스트를 합병 총 단계가 데이타에 적용된다. void mergeSort(element a[], int n) { int s = 1; /* 현재 segment 크기 */ element extra[MAX_SIZE]; while (s<n) mergePass(a, extra, n, s); s *= 2; mergePass(extra , a, n , s); } mergeSort 분석 i번째 패스 : 크기가 2i-1인 리스트를 합병 총 단계가 데이타에 적용된다. 합병의 각 단계에 걸리는 시간 : O(n) 총 연산 시간 : O(nlogn)

합병 정렬 (6) 순환 합병 정렬 (Recursive Merge Sort) 정렬할 리스트를 거의 똑같이 두 개로 나눈다. left 서브리스트와 right 서브리스트 서브리스트들은 순환적으로 정렬된다. 정렬된 서브리스트들은 합병된다.

합병 정렬 (7) 순환적 합병 정렬의 서브 리스트 분할 입력 리스트 : (26, 5, 77, 1, 61, 11, 59, 15, 49, 19) 26 5 77 1 61 11 59 15 48 19 5 26 11 59 5 26 77 1 61 11 15 59 19 48 1 5 26 61 77 11 15 19 48 59 1 5 11 15 19 26 48 59 61 77

합병 정렬 (7) 순환적 합병 정렬의 서브 리스트 분할 두 개의 서브리스트를 만든다 정수 배열 link[1:n]을 사용 left ~ , +1~ right 정수 배열 link[1:n]을 사용 함수 merge가 사용될 때 일어나는 레코드 복사를 제거하기 위하여 정수 포인터를 각 레코드에 연관 시키기 위함 list[i] - 정렬된 서브리스트에서 레코드 i다음에 있는 레코드 이 배열의 사용으로 레코드 복사는 링크 변경으로 대체되고 정렬 함수의 실행 시간은 레코드 크기 s에 독립적이 됨 필요한 추가 공간 : O(n) ∴ 반복적 합병 정렬은 O(snlogn) 시간과 O(sn) 추가 공간 필요 최종 체인이 결정하는 정렬 순서로 레코드들을 물리적으로 재정돈 해야하는 후처리 필요

합병 정렬 (8) 순환 합병 정렬 구현 rMergeSort의 분석 합병 정렬의 순환 버전 안정적 연산 시간 : O(nlogn) int rmergeSort(element a[], int link[], int left, int right) {// 정렬할 리스트는 a[left:right]. 초기에 link[i]는 모든 i에 대해 0이다. // rmergeSort는 정렬된 체인의 첫번째 원소의 인덱스를 반환한다. if(left >= right) return left; int mid = (left + right)/2; return listMerge(a, link, rmergeSort(a, link, left, mid), //왼쪽 반을 정렬 rmergeSort(a, link, mid+1, right)); // 오른쪽 반을 정렬 } 순환 합병 정렬 rMergeSort의 분석 합병 정렬의 순환 버전 안정적 연산 시간 : O(nlogn)

합병 정렬 (9) int listMerge(element a[], int link[], int start1, int start2) { // start1과 start2에서 시작하는 정렬된 체인이 합병된다. // link[0]가 임시 헤더로 사용된다. 합병된 체인의 시작을 반환한다. int last1, last2, lastResult=0; // 결과 체인의 마지막 레코드 for(last1 =start1, last2 = start2; last1 && last2; ) if(a[last1] <= a[last2]) { link[lastResult] = last1; lastResult = last1; last1 = link[last1]; } else { link[lastResult] = last2; lastResult = last2; last2 = link[last2]; // 나머지 레코드들을 결과 체인에 첨가 if(last1 == 0) link[lastResult] = last2; else link[lastResult] = last1; return link[0]; 정렬된 체인의 합병

합병 정렬 (10) 합병 정렬의 변형 자연 합병 정렬 (Natural Merge Sort) 입력 리스트 내에 이미 존재하고 있는 순서를 고려 이미 정렬되어 있는 레코드의 서브리스트를 식별할 수 있도록 초기 패스를 만들어야 함 26 5 26 1 61 11 59 15 48 19 5 26 77 1 11 59 61 15 19 48 1 5 11 26 59 61 77 15 19 48 1 5 11 15 19 26 48 59 61 77 자연 합병 정렬

히프 정렬 (1) 합병 정렬의 문제점 히프 정렬(heap sort) 정렬한 레코드 수에 비례하여 저장 공간이 추가로 필요 일정한 양의 저장 공간만 추가로 필요 최악의 경우 연산 시간과 평균 연산 시간 : O(nlogn) 합병 정렬보단 약간 느림 최대-히프 구조 사용 최대-히프와 연관된 삭제, 삽입 함수 : O(nlogn) 정렬 방법 adjust 함수 사용 – 최대 히프를 재조정

히프 정렬 (3) 정렬 과정 전체 연산 시간 : O(nlogn) adjust를 반복적으로 호출  최대 히프 구조를 만든다. void heapSort(element a[], int n) { int i, j; element temp; for(i=n/2; i>0; i--) adjust(a,i,n); for(i=n-1; i>0;i--) SWAP(a[1], a[i+1],temp); adjust(a, 1, i); } } 정렬 과정 adjust를 반복적으로 호출  최대 히프 구조를 만든다. 히프의 첫번째 레코드와 마지막 레코드를 교환한다. 최대 키를 가진 레코드가 정렬된 배열의 정확한 위치에 자리잡게 됨 히프의 크기를 줄인 후 히프를 재조정한다. 전체 연산 시간 : O(nlogn)

(heapSort 코드의 첫번째 for 루프를 히프 정렬 (4) 이진 트리로 변환된 배열 입력 리스트 : (26, 5, 77, 1, 61, 11, 59, 15, 48, 19) [1] [1] 77 26 [2] 61 [3] 59 [2] 5 [3] 77 [4] 48 [5] 19 11 26 [4] 1 [5] 61 11 59 [6] [7] [6] [7] 15 1 5 15 48 19 [8] [9] [10] [8] [9] [10] (a) 입력 리스트를 이진 트리로 변환한 모습 (b) 초기 히프 형태로 구성한 것 (heapSort 코드의 첫번째 for 루프를 거친 후의 최대 히프 모습)

히프 정렬 (5) [1] 61 [1] 59 [2] 48 [3] 59 [2] 48 [3] 26 [4] 15 [5] 19 11 [6] [7] [6] [7] 5 1 5 (a) 히프크기=9 Sorted = [77] (b) 히프크기=8 Sorted = [61,77] [8] [9] [8] [1] [1] 26 48 [2] 19 [3] 11 [2] 19 [3] 26 [4] 15 [5] 5 1 [4] 15 [5] 5 11 1 [6] [6] [7] (c) 히프크기=7 Sorted = [59,61,77] (d) 히프크기=6 Sorted = [48,59,61,77]

히프 정렬 (6) [1] [1] 19 15 [2] 15 [3] 11 [2] 5 [3] 11 1 5 1 [4] [5] [4] (e) 히프크기=5 Sorted = [26,48,59,61,77] 1 (f) 히프크기=5 Sorted = [19,26,48,59,61,77] [4] [5] [4] [1] 11 (g) 히프크기=3 Sorted = [15,19,26,48,59,61,77] 5 1 [2] [3]

여러 키에 의한 정렬 (3) LSD(least-significant-digit-first) 정렬 LSD가 MSD보다 더 단순 최소 유효 숫자 우선 정렬 카드 숫자 값(키 K2)에 따라 13개의 파일을 만듦 3들을 2들 위에, king들을 queen들 위에, ace들을 king들 위에 올려놓음 카드 뭉치를 거꾸로 놓고 안정된 정렬 방법을 이용하여 무늬(K1)에 따라 4개의 파일로 만듦 4개의 파일들은 각각 키 K2에 따라 정렬되게 함 4개의 파일을 합침 LSD가 MSD보다 더 단순 생성된 파일과 서브 파일을 독립적으로 정렬할 필요가 없으므로 오버헤드가 적게 든다.

여러 키에 의한 정렬 (4) 기수 (radix) 정렬 어떤 기수 r을 이용하여 정렬 키를 몇 개의 숫자로 분해 기수-r 정렬에서는 r개의 빈(bin)이 필요 (why?) 정렬되어야 하는 레코드가 R1,...,Rn일 때, 레코드의 키는 기수-r을 이용하여 분할  0~(r-1) 사이의 d개의 숫자를 가진 키가 된다. 각 빈의 레코드는 빈의 첫 레코드를 가리키는 포인터와 마지막 레코드를 가리키는 포인터를 통해 체인으로 연결되며, 체인은 큐처럼 동작

여러 키에 의한 정렬 (5) int radixSort(element a[], int link[], int d, int r, int n) { int front[r], rear[r]; int i, bin, current, first, last; first = 1; for(i = 1; i < n; i++) link[i] = i+1; link[n] = 0; for(i=d-1; i >=0; i--) for(bin = 0; bin < r; bin++) front[bin] = 0; for(current = first; current; current = link[current]) bin = digit[a[current], i, r); if(front[bin] == 0) front[bin] = current; else link[rear[bin]] = current; rear[bin] = current; } for(bin++; bin < r; bin++) if(front[bin]) {link[last] = front[bin]; last = rear[bin]; } link[last] = 0; return first; }  LSD 기수 정렬

여러 키에 의한 정렬 (6) radixSort의 분석 : 전체 연산 시간 : O(d(n+r)) d 패스를 처리하면서 각 패스의 연산 시간은 O(n+r)임 d 값은 기수 r의 선택과 가장 큰 키에 의해 정해짐 r의 선택을 달리하면 연산 시간이 달라진다.

여러 키에 의한 정렬 (7) 기수 정렬의 예 범위가 [0, 999]인 십진수를 정렬 (d=3, r=10) a[1] a[2] 179 208 306 93 859 984 55 9 271 33 (a) 초기 입력 e[0] e[1] e[2] e[3] e[4] e[5] e[6] e[7] e[8] e[9] 9 33 859 271 93 984 55 306 208 179 f[0] f[1] f[2] f[3] f[4] f[5] f[6] f[7] f[8] f[9] 179 93 33 984 55 306 208 179 859 9 (b) 첫번째-패스 큐들 (First-pass queues) 과 결과 체인

여러 키에 의한 정렬 (8) e[0] e[1] e[2] e[3] e[4] e[5] e[6] e[7] e[8] e[9] 9 208 859 179 306 33 55 271 984 93 f[0] f[1] f[2] f[3] f[4] f[5] f[6] f[7] f[8] f[9] 306 208 9 33 55 859 271 179 984 93 (c) 두 번째-패스 큐들 (Second-pass queues) 과 결과 체인

여러 키에 의한 정렬 (9) e[0] e[1] e[2] e[3] e[4] e[5] e[6] e[7] e[8] e[9] 93 55 33 271 9 179 208 306 859 984 f[0] f[1] f[2] f[3] f[4] f[5] f[6] f[7] f[8] f[9] 9 33 55 93 179 208 271 306 859 984 (d) 세 번째-패스 큐들 (Third-pass queues) 과 결과 체인