10/06/2007

Selection Sort

Algorithm Analysis
The selection sort works by selecting the smallest unsorted item remaining in the list, and then swapping it with the item in the next position to be filled. The selection sort has a complexity of O(n2).
Pros: Simple and easy to implement.Cons: Inefficient for large lists, so similar to the more efficient insertion sort that the insertion sort should be used in its place.
Source CodeBelow is the basic selection sort algorithm.
void selectionSort(int numbers[], int array_size)
{
int i, j;
int min, temp;
for (i = 0; i < array_size-1; i++)
{
min = i;
for (j = i+1; j < array_size; j++)
{
if (numbers[j] < numbers[min])
min = j;
}
temp = numbers[i];
numbers[i] = numbers[min];
numbers[min] = temp;
}
}

Quick Sort

Algorithm Analysis
The quick sort is an in-place, divide-and-conquer, massively recursive sort. As a normal person would say, it's essentially a faster in-place version of the merge sort. The quick sort algorithm is simple in theory, but very difficult to put into code (computer scientists tied themselves into knots for years trying to write a practical implementation of the algorithm, and it still has that effect on university students).
The recursive algorithm consists of four steps (which closely resemble the merge sort):
If there are one or less elements in the array to be sorted, return immediately.
Pick an element in the array to serve as a "pivot" point. (Usually the left-most element in the array is used.)
Split the array into two parts - one with elements larger than the pivot and the other with elements smaller than the pivot.
Recursively repeat the algorithm for both halves of the original array.
The efficiency of the algorithm is majorly impacted by which element is choosen as the pivot point. The worst-case efficiency of the quick sort, O(n2), occurs when the list is sorted and the left-most element is chosen. Randomly choosing a pivot point rather than using the left-most element is recommended if the data to be sorted isn't random. As long as the pivot point is chosen randomly, the quick sort has an algorithmic complexity of O(n log n).
Pros: Extremely fast.Cons: Very complex algorithm, massively recursive.
Source CodeBelow is the basic quick sort algorithm.
void quickSort(int numbers[], int array_size)
{
q_sort(numbers, 0, array_size - 1);
}
void q_sort(int numbers[], int left, int right)
{
int pivot, l_hold, r_hold;
l_hold = left;
r_hold = right;
pivot = numbers[left];
while (left < right)
{
while ((numbers[right] >= pivot) && (left < right))
right--;
if (left != right)
{
numbers[left] = numbers[right];
left++;
}
while ((numbers[left] <= pivot) && (left < right))
left++;
if (left != right)
{
numbers[right] = numbers[left];
right--;
}
}
numbers[left] = pivot;
pivot = left;
left = l_hold;
right = r_hold;
if (left < pivot)
q_sort(numbers, left, pivot-1);
if (right > pivot)
q_sort(numbers, pivot+1, right);
}

Merge Sort

Algorithm Analysis
The merge sort splits the list to be sorted into two equal halves, and places them in separate arrays. Each array is recursively sorted, and then merged back together to form the final sorted list. Like most recursive sorts, the merge sort has an algorithmic complexity of O(n log n).
Elementary implementations of the merge sort make use of three arrays - one for each half of the data set and one to store the sorted list in. The below algorithm merges the arrays in-place, so only two arrays are required. There are non-recursive versions of the merge sort, but they don't yield any significant performance enhancement over the recursive algorithm on most machines.
Pros: Marginally faster than the heap sort for larger sets.Cons: At least twice the memory requirements of the other sorts; recursive.
Source CodeBelow is the basic merge sort algorithm.
void mergeSort(int numbers[], int temp[], int array_size)
{
m_sort(numbers, temp, 0, array_size - 1);
}
void m_sort(int numbers[], int temp[], int left, int right)
{
int mid;
if (right > left)
{
mid = (right + left) / 2;
m_sort(numbers, temp, left, mid);
m_sort(numbers, temp, mid+1, right);
merge(numbers, temp, left, mid+1, right);
}
}
void merge(int numbers[], int temp[], int left, int mid, int right)
{
int i, left_end, num_elements, tmp_pos;
left_end = mid - 1;
tmp_pos = left;
num_elements = right - left + 1;
while ((left <= left_end) && (mid <= right))
{
if (numbers[left] <= numbers[mid])
{
temp[tmp_pos] = numbers[left];
tmp_pos = tmp_pos + 1;
left = left +1;
}
else
{
temp[tmp_pos] = numbers[mid];
tmp_pos = tmp_pos + 1;
mid = mid + 1;
}
}
while (left <= left_end)
{
temp[tmp_pos] = numbers[left];
left = left + 1;
tmp_pos = tmp_pos + 1;
}
while (mid <= right)
{
temp[tmp_pos] = numbers[mid];
mid = mid + 1;
tmp_pos = tmp_pos + 1;
}
for (i=0; i <= num_elements; i++)
{
numbers[right] = temp[right];
right = right - 1;
}

Insertion Sort

Algorithm AnalysisThe insertion sort works just like its name suggests - it inserts each item into its proper place in the final list. The simplest implementation of this requires two list structures - the source list and the list into which sorted items are inserted. To save memory, most implementations use an in-place sort that works by moving the current item past the already sorted items and repeatedly swapping it with the preceding item until it is in place.
Like the bubble sort, the insertion sort has a complexity of O(n2). Although it has the same complexity, the insertion sort is a little over twice as efficient as the bubble sort.
Pros: Relatively simple and easy to implement.Cons: Inefficient for large lists.
Source CodeBelow is the basic insertion sort algorithm.
void insertionSort(int numbers[], int array_size)
{
int i, j, index;
for (i=1; i < array_size; i++)
{
index = numbers[i];
j = i;
while ((j > 0) && (numbers[j-1] > index))
{
numbers[j] = numbers[j-1];
j = j - 1;
}
numbers[j] = index;
}
}

Bubble Sort

Algorithm AnalysisThe bubble sort is the oldest and simplest sort in use. Unfortunately, it's also the slowest.
The bubble sort works by comparing each item in the list with the item next to it, and swapping them if required. The algorithm repeats this process until it makes a pass all the way through the list without swapping any items (in other words, all items are in the correct order). This causes larger values to "bubble" to the end of the list while smaller values "sink" towards the beginning of the list.
The bubble sort is generally considered to be the most inefficient sorting algorithm in common usage. Under best-case conditions (the list is already sorted), the bubble sort can approach a constant O(n) level of complexity. General-case is an abysmal O(n2).
While the insertion, selection, and shell sorts also have O(n2) complexities, they are significantly more efficient than the bubble sort.
Pros: Simplicity and ease of implementation.Cons: Horribly inefficient.
Source CodeBelow is the basic bubble sort algorithm.
void bubbleSort(int numbers[], int array_size)
{
int i, j, temp;
for (i = (array_size - 1); i >= 0; i--)
{
for (j = 1; j <= i; j++)
{
if (numbers[j-1] > numbers[j])
{
temp = numbers[j-1];
numbers[j-1] = numbers[j];
numbers[j] = temp;
}
}
}
}

Matlab code example computing index for a single letter image

% %letterdemo.m
% This Matlab program takes as input
% a letter image and a letter mask image and
% illustrates the computation of the letter image statistics for
% the readability index of Scharff and Ahumada (2003).
% mask for the letter e
mask = ...
[ 0 0 0 0
0 1 1 0
1 0 0 1
1 1 1 1
1 0 0 0
1 0 0 1
0 1 1 0
0 0 0 0];

% letter e simulated luminance image
% imageY = floor(100*rand(size(mask))+50*mask);
imageY =...
[ 81 83 79 87
66 106 145 73
84 37 52 63
78 120 138 51
84 54 17 89
103 44 97 69
72 119 77 29
30 62 25 66];
%number of text pixels
nmask = sum(mask(:)); % 13
% average text pixel luminance
avetxt = sum(mask(:).*imageY(:))/nmask; % 95.1538
% variance of the text pixel luminance
vtxt = sum(mask(:).*(imageY(:)-avetxt).^2)/nmask;% 786.5917
% number of background pixels
nbck = sum(1-mask(:)); % 19
% average background luminance
avebck = sum((1-mask(:)).*imageY(:))/nbck; % 60.1579
% variance of background luminance
vbck = sum((1-mask(:)).*(imageY(:)-avebck).^2)/nbck; % 551.5014
% proportion of text pixels
pT = nmask/(nmask+nbck);
% To obtain the Global masking index of Scharff, Hill, and Ahumada (2000)
% pT = 0 ;
qT = 1-pT; % 0.4063 0.5937
% contrast of the text with respect to the background
CT = avetxt/avebck - 1;% 0.5817
% contrast of the text with respect to the image average
CA = qT*CT/(pT*CT+1); % 0.2794
% variance of the image contrast
vTB = ((pT*vtxt+qT*vbck)/avebck^2+pT*qT*CT^2)/(pT*CT+1)^2;% 0.1704
% image contrast adjusted by the masking variance relative to the
% contrast masking threshold C2
C2 = 0.05;
index = CA/sqrt(1+vTB/C2^2); %0.0336