Professional Documents
Culture Documents
DATA STRUCTURES
AND
ALGORITHMS
For M.Sc., M.C.A, & M.Tech Programmes
2014
Data Strcutures & Algorithms
UNIT - III
Sorting algorithm
A sorting algorithm is an algorithm that puts elements of a list in a certain
order. The most-used orders are numerical order and lexicographical order. Efficient sorting
is important for optimizing the use of other algorithms (such as search and merge algorithms)
which require input data to be in sorted lists; it is also often useful for canonicalizing data and
for producing human-readable output. More formally, the output must satisfy two conditions:
1. The output is in non-decreasing order (each element is no smaller than the previous
element according to the desired total order);
2. The output is a permutation (reordering) of the input.
Further, the data is often taken to be in an array, which allows random access,
rather than a list, which only allows sequential access, though often algorithms can be applied
with suitable modification to either type of data.
Since the dawn of computing, the sorting problem has attracted a great deal of
research, perhaps due to the complexity of solving it efficiently despite its simple, familiar
statement. For example, bubble sort was analyzed as early as 1956. A fundamental limit of
comparison sorting algorithms is that they require linearithmic time – O(n log n) – in the
worst case, though better performance is possible on real-world data (such as almost-sorted
data), and algorithms not based on comparison, such as counting sort, can have better
performance. Although many consider sorting a solved problem – asymptotically optimal
algorithms have been known since the mid-20th century – useful new algorithms are still
being invented, with the now widely used Timsort dating to 2002, and the library sort being
first published in 2006.
Classification
Sorting algorithms are often classified by:
Stability
An example of stable sorting on playing cards. When the cards are sorted by
rank with a stable sort, the two 5s must remain in the same order in the sorted output that they
were originally in. When they are sorted with a non-stable sort, the 5s may end up in the
opposite order in the sorted output.
When sorting some kinds of data, only part of the data is examined when
determining the sort order. For example, in the card sorting example to the right, the cards are
being sorted by their rank, and their suit is being ignored. This allows the possibility of
multiple different correctly sorted versions of the original list. Stable sorting algorithms
choose one of these, according to the following rule: if two items compare as equal, like the
two 5 cards, then their relative order will be preserved, so that if one came before the other in
the input, it will also come before the other in the output.
More formally, the data being sorted can be represented as a record or tuple of
values, and the part of the data that is used for sorting is called the key. In the card example,
cards are represented as a record (rank, suit), and the key is the rank. A sorting algorithm is
stable if whenever there are two records R and S with the same key, and R appears before S
in the original list, then R will always appear before S in the sorted list.
One application for stable sorting algorithms is sorting a list using a primary and
secondary key. For example, suppose we wish to sort a hand of cards such that the suits are in
the order clubs (♣), diamonds (♦), hearts (♥), spades (♠), and within each suit, the cards are
sorted by rank. This can be done by first sorting the cards by rank (using any sort), and then
doing a stable sort by suit:
Within each suit, the stable sort preserves the ordering by rank that was already
done. This idea can be extended to any number of keys, and is leveraged by radix sort. The
same effect can be achieved with an unstable sort by using a lexicographic key comparison,
which e.g. compares first by suits, and then compares by rank if the suits are the same.
Popular sorting algorithms
Bubble Sort:
Illustration:
Input for Bubble sort : a[1..8] = {12, 18, 42, 44, 55, 67, 94, 06}
12 18 42 44 55 67 06 94 06 18 42 44 55 67 94 12
12 18 42 44 55 06 67 94 06 12 42 44 55 67 94 18
12 18 42 44 06 55 67 94 06 12 18 44 55 67 94 42
12 18 42 06 44 55 67 94 06 12 18 42 55 67 94 44
12 18 06 42 44 55 67 94 06 12 18 42 44 67 94 55
12 06 18 42 44 55 67 94 06 12 18 42 44 55 94 67
06 12 18 42 44 55 67 94 06 12 18 42 44 55 67 94
Note:- To sort in Descending Order change the If statement in the algorithms to the new one
such as If a[i] < a[j] then, alternatively in the same algorithms print the final output in the
reverse order. We can very well verify that the least element floats to the beginning as the air
bubble floats upward in the water. If any element in the array appears more than once in
different places in the array, and while sorting if their positions are retained in the output,
then the algorithm is said to be stable.
Selection Sort:
Illustration:
Input for Selection Sort : a[1..8] = { 44, 55, 12, 42, 94, 18, 06, 67 }
Output :
Initial array : 44 55 12 42 94 18 06 67
06 55 12 42 94 18 44 67
06 12 55 42 94 18 44 67
06 12 18 42 94 55 44 67
06 12 18 42 44 55 94 67
06 12 18 42 44 55 67 94
Note: This is method is based on (i) Select an item with the least value, (ii) exchange it with
the first element in the array, and repeat these operations with remaining n-1 elements, then
with n-2 elements, until only one item – the largest – is left.
Insertion Sort:
Note: This method is widely used by card players. The items (cards) are conceptually
divided into a destination sequence a1 , a2 , ...., ai-1 an a source sequence ai , ai+1 ,..... , an. In
each step, starting with i=2 and incrementing i by unity, the i th element of the source
sequence is picked and transferred into the destination sequence by inserting it at the
appropriate place.
Illustration:
Input for Insertion Sort : a[1..8] = {44, 55, 12, 42, 94, 18, 06, 67}
Output : initially 44 55 12 42 94 18 06 67
i = 2 44 55 12 42 94 18 06 67 // no change
i = 3 12 44 55 42 94 18 06 67 // 12 is inserted
i = 4 12 42 44 55 94 18 06 67 // 42 is inserted
i = 5 12 42 44 55 94 18 06 67 // 44 is inserted
i = 6 12 18 42 44 55 94 06 67 // no change
i = 7 06 12 18 42 44 55 94 67 // 06 is inserted
i = 8 06 12 18 42 44 55 67 94 // 67 is inserted
Heap Sort:
Input for Heap Sort : a[1..8] = {06, 42, 12, 55, 94, 18, 44, 67}
Output :
12 42 18 55 94 67 44 06
18 42 44 55 94 67 12 06
42 55 44 67 94 18 12 06
44 55 94 67 42 18 12 06
55 67 94 44 42 18 12 06
67 94 55 44 42 18 12 06
94 67 55 44 42 18 12 06
An alternate algorithm is follows:
Heap Sort :
Phase – I:
(0)Construct a Binary Tree with the input given in the left list layout organizational
representation as shown in the figure (output).
(1) Process the node which is the parent of the right most node on the lowest level. If its
value is less than the value of its largest child, swap those values, otherwise do nothing.
(2) Move left on the same level. Compare the value of the parent node with the values of the
child nodes. If the parent is smaller than the largest child, swap them.
(3) When the left end of this level is reached, move up a level, and beginning with the right
most parent node, repeat step (2). Continue swapping the original parent with the largest of
its children until it is larger than its children. In effect, the original parent is being walked
down the tree in a fashion that ensures that numbers will be increasing order along the path.
(4) Repeat step (3) until all level 1 nodes have been processed (Remember that the root is at
level 0 ).
Phase – II:
(1) Compare the root node with its children, swapping it with the largest child if the largest
child is larger than the root.
(2) If a swap occurred in step (1), then continue swapping the value which was originally in
the root position until it is larger than its children. In effect, this is the original root node
value, is now being walked down a path in the tree to ensure that all paths retain values
arranged in ascending order from leaf node to root node.
(3) Swap the root node with the bottom right most child, sever the new bottom right most
child from the tree and insert it into a STACK. This is the largest value given in the input.
(4) Repeat steps (1) through (3) until only two elements are left. Then among these two
elements insert the largest element into the STACK followed by the last element which is the
least of all.
(5) Now print the elements of the STACK to get the Ascending Order of the input elements.
Illustration:
Input for Heap Sort : a[1..8] = {11, 1, 5, 7, 6, 12, 17, 8, 4, 10, 2}
1
1
5
1
7 6 1 1
2 7
4 1 2
8
0
Swap 6 & 10 1
1
5
1
7 6 1 1
2 7
4 1 2
8
0
Swap 7 & 8
11
5
1
7 10 12 17
4 6 2
8
Swap 5 & 17 1
1
5
1
1 1
8 1
2 7
0
7 4 6 0 2
Swap 1 and 10
11
17
1
8 10 12 5
4 6 2
7
Swap 1 & 6 1
1
1 1
0 7
8 1 5
1 2
4 6 2
7
Swap 11 & 17
11
17
10
8 6 12 5
4 1 2
7
Swap 11 & 12 17
11
10
8 6 12 5
4 1 2
7
Swap 12 & 11
17
12
10
8 6 11 5
4 1 2
7
Swap 2 & 17 17
12
10
8 6 11 5
2
12
10
4 1 2
7
8 6 11 5
Sever 17
4 1 17
7
10
11
12
17
The STACK contains the output.
Quick Sort:
Illustration:
Input for QuickSort : a[1..8] = {12, 18, 42, 44, 55, 67, 94, 06}
Output : 12 18 42 06 44 55 67 94
12 06 18 42 44 55 67 94
06 12 18 42 44 55 67 94
Merge sort:
In computer science, merge sort (also commonly spelled merge sort) is
an O(n log n) comparison-based sorting algorithm. Most implementations produce a stable
sort, which means that the implementation preserves the input order of equal elements in the
sorted output. Merge sort is a divide and conquer algorithm that was invented by John von
Neumann in 1945.
Merge Sort:
(1) Split the sequence (given array) a into two halves, called b and c.
(2) Merge b and c by combining single items into ordered pairs.
(3) Call the merged sequence a, and repeat steps (1) & (2), this time merging ordered pairs
into ordered quadruples.
(4) Repeat the previous steps, merging quadruples into octets, and continue doing this, each
time doubling the lengths of the merged sub-sequences, until the entire sequence is ordered.
Illustration:
Input for Merge Sort : a[1..8] = {44, 55, 12, 42, 94, 18, 06, 67}
Output :
Variants
Variants of merge sort are primarily concerned with reducing the space
complexity and the cost of copying.
A simple alternative for reducing the space overhead to n/2 is to maintain left
and right as a combined structure, copy only the left part of m into temporary space, and to
direct the merge routine to place the merged output into m.
With this version it is better to allocate the temporary space outside the merge
routine, so that only one allocation is needed. The excessive copying mentioned previously is
also mitigated, since the last pair of lines before the return result statement become
superfluous.
In-place sorting is possible, and still stable, but is more complicated, and
slightly slower, requiring non-linearithmic quasilinear time O(n log2 n). One way to sort in-
place is to merge the blocks recursively. Like the standard merge sort, in-place merge sort is
also a stable sort. Stable sorting of linked lists is simpler. In this case the algorithm does not
use more space than that already used by the list representation, but the O(log(k)) used for the
recursion trace.
A field which contains only a link will generally be smaller than an entire
record so less space will also be used. This is a standard sorting technique, not restricted to
merge sort.
Analysis
In the worst case, the number of comparisons merge sort makes is equal to or
slightly smaller than (n ⌈lg n⌉ - 2⌈lg n⌉ + 1), which is between (n lg n - n + 1) and (n lg n + n +
O(lg n)). For large n and a randomly ordered input list, merge sort's expected (average)
number of comparisons approaches α·n fewer than the worst case where
In the worst case, merge sort does about 39% fewer comparisons than quick
sort does in the average case. In terms of moves, merge sort's worst case complexity is
O(n log n)—the same complexity as quick sort's best case, and merge sort's best case takes
about half as many iterations as the worst case.
Merge sort is more efficient than quick sort for some types of lists if the data to
be sorted can only be efficiently accessed sequentially, and is thus popular in languages such
as Lisp, where sequentially accessed data structures are very common. Unlike some
(efficient) implementations of quick sort, merge sort is a stable sort. Merge sort's most
common implementation does not sort in place; therefore, the memory size of the input must
be allocated for the sorted output to be stored in (see below for versions that need only n/2
extra spaces).
Merge sort also has some demerits. One is its use of 2 n locations; the
additional n locations are commonly used because merging two sorted sets in place is more
complicated and would need more comparisons and move operations. But despite the use of
this space the algorithm still does a lot of work: The contents of m are first copied into left
and right and later into the list result on each invocation of merge_sort (variable names
according to the pseudo code above).
Merge sort type algorithms allowed large data sets to be sorted on early
computers that had small random access memories by modern standards. Records were stored
on magnetic tape and processed on banks of magnetic tape drives, such as these IBM 729s.
An external merge sort is practical to run using disk or tape drives when the data to be sorted
is too large to fit into memory. External sorting explains how merge sort is implemented with
disk drives. A typical tape drive sort uses four tape drives. All I/O is sequential (except for
rewinds at the end of each pass). A minimal implementation can get by with just 2 record
buffers and a few program variables.
Naming the four tape drives as A, B, C, D, with the original data on A, and
using only 2 record buffers, the algorithm is similar to Bottom-up implementation, using
pairs of tape drives instead of arrays in memory. The basic algorithm can be described as
follows:
Instead of starting with very short runs, usually a hybrid algorithm is used,
where the initial pass will read many records into memory, do an internal sort to create a long
run, and then distribute those long runs onto the output set. The step avoids many early
passes. For example, an internal sort of 1024 records will save 9 passes. The internal sort is
often large because it has such a benefit. In fact, there are techniques that can make the initial
runs longer than the available internal memory. A more sophisticated merge sort that
optimizes tape (and disk) drive usage is the polyphase merge sort.
Multiway Merging:
The effort involved in a sequential sort is proportional to the number of
required passes since, by definition, every pass involves the copying of the entire set of data.
One way to reduce this number is to distribute the runs onto more than two files. Merging r
runs which are equally distributed on N tapes results in a sequence of r/N runs. A second
pass reduces their number to r/N2, a third pass to r/N 3 , and after k passes there are r/N k runs
left. The total number of passes required to sort ‘n’ items by N-way merging is therefore
k= ┌ logN n ┐. Since each pass requires n copy operations, the total number of copy
operation is in the worst case M = n . ┌ log n ┐. ┌ X ┐ indicates ceiling of
N
procedure tapemergesort;
var i, j: tapeno;
el : integer; // no. Of runs distributed //
t : array [tapeno] of tapeno;
Begin // distribute initial runs to t[1], t[2], ..... t[nh] //
j = nh ; el = 0 ;
repeat if j < nh then j = j+1; else j = 1;
“ copy one run from f0 to tape j” ;
until eof(f0) ;
for i = 1 to n do t[i] = i;
repeat // merge from t[1],.....t[nh] to t[nh+1], ... t[n] //
“ rest input tapes” ;
el = 0;
j = nh + 1; // j is index of output tape //
repeat
el = el + 1;
“ merge a run from inputs to t[j] “ ;
if j < n then j = j+1 else j= nh+1 ;
until “ all inputs exhausted” ;
“ switch tapes “
until el = 1 ;
// sorted tape is t[1] //
end
Shake Sort: A careful programmer will, however, notice a peculiar asymmetry in bubble
sort: A single misplaced bubble (smallest element) in the “heavy” end of an otherwise sorted
array will shift into order in a single pass, but a misplaced item in the “light” end will sink
toward its correct position only one step in each pass. For example, the array:
12 18 42 44 55 67 94 06
will be sorted by the improved bubble sort in a single pass, but the array
94 06 12 18 42 44 55 67
will require 7 passes for sorting. This unnatural asymmetry suggests a third improvement:
alternating the direction of consecutive passes. We appropriately call the resulting algorithm
Shakesort. This algorithm is illustrated below:
Procedure shakesort;
Var j, k, el, r : index; x : item; a[1..n] : the given array of elements
begin
el = 2 ; r = n ; k = n ;
repeat
for j = r down to el do
if a[j-1] > a[j] then
begin // exchange a[j-1] and a[j] //
x = a[j-1] ; a[j-1] = a[j] ; a[j] = x ; k = j ;
end
el = k+1 ;
for j = el to r do
if a[j-1] > a[j] then
begin // exchange a[j-1] and a[j] //
x = a[j-1] ; a[j-1] = a[j] ; a[j] = x ; k = j;
end
r = k-1;
until el > r
end // shake sort //
Illustration:
Input for Shake Sort : = { 44, 55, 12, 42, 94, 18, 06, 67 }
Output :
el = 2 3 3 4 4
r= 8 8 7 7 4
44 06 06 06 06
55 44 44 12 12
12 55 12 44 18
42 12 42 18 42
94 42 55 42 44
18 94 18 55 55
06 18 67 67 67
67 67 94 94 94
The last column gives the sorted order of the input. That is, 06, 12, 18, 42, 44, 55, 67, 94
Shell Sort: A refinement of the straight insertion sort was proposed byh D. L. Shell in 1959.
The method is explained and demonstrated with an example of eight items. First, all items
which are four which are four positions apart are grouped and sorted separately. This process
is called a 4-sort,. IN this example of eight items, each group contains exactly two items.
After this first pass, the items are regrouped into groups with items two positions apart and
then sorted anew. This process is called a 2-sort. Finally, in a third pass all items are sorted
in an ordinary sort or 1-sort. One may at first wonder if the necessity of several sorting
passes, each of which involves all items, will not introduce more work than it saves.
However, each sorting step over a chain involves either relatively few items or the items are
already quite well ordered and comparatively few re-arrangements are required.
Illustration:
Input for Shell Sort: 44 55 12 42 94 18 06 67
ᵝ ᵞ ᵟ ᵠ ᵝ ᵞ ᵟ ᵠ
Output: 4-sort yields
44 18 06 42 94 55 12 67
ᵝ ᵞ ᵝ ᵞ ᵝ ᵞ ᵝ ᵞ
2-sort yields
06 18 12 42 44 55 94 67
ᵝ ᵝ ᵝ ᵝ ᵝ ᵝ ᵝ ᵝ
1-sort yields
06 12 18 42 44 55 67 94 - (Sorted Order)
The table below shows the times ( in milliseconds ) consumed by the sorting methods so far
discussed, as executed by the PASCAL system on a CDC 6400 computer. The three
columns contain the times used to sort the already ordered array, a random permutation, and
the inversely ordered array. The left figure in each column is for 256 items, the right one for
512 items.
PARALLELISM:
Parallel computers can be roughly classified according to the level at which the
hardware supports parallelism, with multi-core and multi-processor computers having
multiple processing elements within a single machine, while clusters, MPPs, and grids use
multiple computers to work on the same task. Specialized parallel computer architectures are
sometimes used alongside traditional processors, for accelerating specific tasks.
Parallel computer programs are more difficult to write than sequential ones,
because concurrency introduces several new classes of potential software bugs, of which race
conditions are the most common. Communication and synchronization between the different
subtasks are typically some of the greatest obstacles to getting good parallel program
performance. The maximum possible speed-up of a single program as a result of
parallelization is known as Amdahl's law
Types of parallelism
There are different types of Parallelisms namely: I/O Parallelism, Inter Query
Parallelism, Intra Query Parallelism, Inter Operator Parallelism, Independent Parallelism, Bit
Level Parallelism, Instruction Level Parallelism, Task Level Parallelism and Memory Level
Parallelism.
I/O Parallelism- Helps in reducing the time required to retrieve relations(data tables) from
disk by partitioning the relations on multiple disks in parallel.
Inter Query Parallelism- Queries / transactions (with reference to data base management
system) can be executed in parallel with one another. It increases transaction throughput and
it is the earliest from of parallelism to support, particularly in shared memory parallel
databases.
Bit-level parallelism
Historically, 4-bit microprocessors were replaced with 8-bit, then 16-bit, then
32-bit microprocessors. This trend generally came to an end with the introduction of 32-bit
processors, which has been a standard in general-purpose computing for two decades. Not
until recently (c. 2003–2004), with the advent of x86-64 architectures, have 64-bit processors
become commonplace.
Instruction-level parallelism
A five-stage pipelined superscalar processor, capable of issuing two instructions per cycle. It
can have two instructions in each stage of the pipeline, for a total of up to 10 instructions
(shown in green) being simultaneously executed.
In addition to instruction-level parallelism from pipelining, some processors can
issue more than one instruction at a time. These are known as superscalar processors.
Instructions can be grouped together only if there is no data dependency between them.
Score-boarding and the Tomasulo algorithm (which is similar to scoreboarding but makes use
of register renaming) are two of the most common techniques for implementing out-of-order
execution and instruction-level parallelism.
Task parallelism
Memory-level parallelism
5 2 3 8 1 6 4 5
7 11 7 9
18 16
34
The sum of all the eight given numbers is found 34 by implementing parallelism and the
time complexity of this method is found to be log2 (n).
(2) ʃ ( x2 – 3x3 + sin 12x ) dx - can be solved parallel by splitting the given problem into
three sub-problems as shown below.
ʃ x2 dx , -3ʃx3 dx and + ʃ sin 12x dx
These sub-problems can be solved parallel (simultaneously) and then the results can be added
to get the final result (answer).
(3) Web-page displaying with Multimedia data dynamically ( that is, each component of the
web-page can be designed parallel and can be displayed simultaneously.
Hardware
A logical view of a Non-Uniform Memory Access (NUMA) architecture. Processors in one directory
can access that directory's memory with less latency than they can access memory in the other
directory's memory.
Multicore computing
Symmetric multiprocessing
Distributed computing
Cluster computing
A Beowulf cluster
A cabinet from Blue Gene/L, ranked as the fourth fastest supercomputer in the world according to the
11/2008 TOP500 rankings. Blue Gene/L is a massively parallel processor. Blue Gene/L, the fifth
fastest supercomputer in the world according to the June 2009 TOP500 ranking, is a MPP.
Grid computing
Grid computing is the most distributed form of parallel computing. It makes use
of computers communicating over the Internet to work on a given problem. Because of the
low bandwidth and extremely high latency available on the Internet, distributed computing
typically deals only with embarrassingly parallel problems. Many distributed computing
applications have been created, of which SETI@home and Folding@home are the best-
known examples.
Most grid computing applications use middleware, software that sits between
the operating system and the application to manage network resources and standardize the
software interface. The most common distributed computing middleware is the Berkeley
Open Infrastructure for Network Computing (BOINC). Often, distributed computing software
makes use of "spare cycles", performing computations at times when a computer is idling.
Within parallel computing, there are specialized parallel devices that remain
niche areas of interest. While not domain-specific, they tend to be applicable to only a few
classes of parallel problems.
In the early days, GPGPU programs used the normal graphics APIs for executing
programs. However, several new programming languages and platforms have been built to do
general purpose computation on GPUs with both Nvidia and AMD releasing programming
environments with CUDA and Stream SDK respectively. Other GPU programming
languages include BrookGPU, PeakStream, and RapidMind. Nvidia has also released specific
products for computation in their Tesla series. The technology consortium Khronos Group
has released the OpenCL specification, which is a framework for writing programs that
execute across platforms consisting of CPUs and GPUs. AMD, Apple, Intel, Nvidia and
others are supporting OpenCL.
Several application-specific integrated circuit (ASIC) approaches have been devised for
dealing with parallel applications. Because an ASIC is (by definition) specific to a given
application, it can be fully optimized for that application. As a result, for a given application,
an ASIC tends to outperform a general-purpose computer. However, ASICs are created by X-
ray lithography. This process requires a mask, which can be extremely expensive. A single
mask can cost over a million US dollars. (The smaller the transistors required for the chip,
the more expensive the mask will be.) Meanwhile, performance increases in general-purpose
computing over time (as described by Moore's Law) tend to wipe out these gains in only one
or two chip generations. High initial cost, and the tendency to be overtaken by Moore's-law-
driven general-purpose computing, has rendered ASICs unfeasible for most parallel
computing applications. However, some have been built. One example is the peta-flop
RIKEN MDGRAPE-3 machine which uses custom ASICs for molecular dynamics
simulation.
Vector processors
A vector processor is a CPU or computer system that can execute the same instruction on
large sets of data. "Vector processors have high-level operations that work on linear arrays of
numbers or vectors. An example vector operation is A = B × C, where A, B, and C are each
64-element vectors of 64-bit floating-point numbers." They are closely related to Flynn's
SIMD classification.
Cray computers became famous for their vector-processing computers in the 1970s and
1980s. However, vector processors—both as CPUs and as full computer systems—have
generally disappeared. Modern processor instruction sets do include some vector processing
instructions, such as with AltiVec and Streaming SIMD Extensions (SSE).
Software
CAPS enterprise and Path scale are also coordinating their effort to make
HMPP (Hybrid Multicore Parallel Programming) directives an Open Standard called
OpenHMPP. The OpenHMPP directive-based programming model offers a syntax to
efficiently offload computations on hardware accelerators and to optimize data movement
to/from the hardware memory. OpenHMPP directives describe remote procedure call (RPC)
on an accelerator device (e.g. GPU) or more generally a set of cores. The directives annotate
C or Fortran codes to describe two sets of functionalities: the offloading of procedures
(denoted code lets) onto a remote device and the optimization of data transfers between the
CPU main memory and the accelerator memory.
Automatic parallelization
Application check-pointing
As a computer system grows in complexity, the mean time between failures
usually decreases. Application check-pointing is a technique whereby the computer system
takes a "snapshot" of the application — a record of all current resource allocations and
variable states, akin to a core dump; this information can be used to restore the program if the
computer should fail. Application check-pointing means that the program has to restart from
only its last checkpoint rather than the beginning. While check-pointing provides benefits in a
variety of situations, it is especially useful in highly parallel systems with a large number of
processors used in high performance computing.
Algorithmic methods
Fault-tolerance
The term should not be confused with buffer overflow, a condition where a
portion of memory being used as a buffer has a fixed size but is filled with more than that
amount of data. Whereas buffer overflows are usually the result of programming errors, and
thus preventable, buffer underruns are often the result of transitory issues involving the
connection which is being buffered: either a connection between two processes, with others
competing for CPU time, or a physical link, with devices competing for bandwidth.
The simplest guard against such problems is to increase the size of the buffer—if
an incoming data stream needs to be read at 1 bit per second, a buffer of 10 bits would allow
the connection to be blocked for up to 10 seconds before failing, whereas one of 60 bits
would allow a blockage of up to a minute. However, this requires more memory to be
available to the process or device, which can be expensive. It assumes that the buffer starts
full—requiring a potentially significant pause before the reading process begins—and that it
will always remain full unless the connection is currently blocked. If the data does not, on
average, arrive faster than it is needed, any blockages on the connection will be cumulative;
"dropping" one bit every minute on a hypothetical connection with a 60-bit buffer would lead
to a buffer underrun if the connection remained active for an hour. In real-time applications, a
large buffer size also increases the latency between input and output, which is undesirable in
low-latency applications such as video conferencing.
Buffer underruns can cause serious problems during CD/DVD burning, because
once the writing is started, it cannot stop and resume flawlessly; thus the pause needed by the
underrun can cause the data on the disc to become invalid. Since the buffer is generally being
filled from a relatively slow source, such as a hard disk or another CD/DVD, a heavy CPU or
memory load from other concurrent tasks can easily exhaust the capacity of a small buffer.
Therefore, a technique called buffer underrun protection was implemented by various
individual CD/DVD writer vendors, under various trademarks, such as Plextor BurnProof,
Nero UltraBuffer, Yamaha SafeBurn, JustLink, and Seamless Link. With this technique, the
laser is indeed able to stop writing for any amount of time and resume when the buffer is full
again. The gap between successive writes is extremely small. Another way to protect against
the problem, when using rewritable media (CD-RW, DVD-RW, DVD-RAM), is to use the
UDF file system, which organizes data in smaller "packets", referenced by a single, updated
address table, which can therefore be written in shorter bursts.
Multimedia playback
If the frame buffer of the graphics controller is not updated, the picture of the
computer screen will appear to hang until the buffer receives new data. Many video player
programs (e.g. MPlayer) feature the ability to drop frames if the system is overloaded,
intentionally allowing a buffer underrun to keep up the tempo.
The buffer in an audio controller is a ring buffer. If an underrun occurs and the
audio controller is not stopped, it will either keep repeating the sound contained in the buffer,
which may hold a quarter of a second, or replace by silence depending on the
implementation. Such effect is commonly referred to as "machinegun" or Max Headroom
(character) stuttering effect. This happens if the operating system hangs during audio
playback. An error handling routine (e.g. blue screen of death) may eventually stop the audio
controller.
Questions:
2 Marks:
1) State the two conditions that must be satisfied by any sorting algorithm.
5 Marks:
1) Explain the various parameters based on which the sorting algorithms are classfied.
8 Marks:
1) Tabulate the Minimum, Average, and Maximum number of Moves and Exchanges of
elements in the following sorting algorithms:
(a) Insertion sort, (b) Quick Sort, (c) Merge Sort, and (d) Heap Sort
16 Marks: