SlideShare a Scribd company logo
8.1.1 Best-First Sort
A simple sorting strategy is to find the best element in the list and put that at the front.
The best element is an element for which the comparison procedure
evaluates to true when applied to that element and every other element.
For example, if the comparison function is <<, the best element is the lowest number in
the list. This element belongs at the front of the output list.
The notion of the best element in the list for a given comparison function only makes
sense if the comparison function is transitive. This means it has the property that for any
inputs a, b, and c, if (cf a b) and (cf b c) are both true, the result of (cf a c) must be
true.The << function transitive: aa<<bb and bb<<ccimplies aa<<cc foris all
numbers aa, bb, and cc.
If the comparison function does not have this property, there may be no way to arrange
the elements in a single sorted list. All of our sorting procedures require that the
procedure passed as the comparison function is transitive.
Once we can find the best element in a given list, we can sort the whole list by repeatedly
finding the best element of the remaining elements until no more elements remain.
To define our best-first sorting procedure, we first define a procedure for finding
the best element in the list, and then define a procedure for removing an element from a
list.
Finding the Best. The best element in the list is either the first element, or the best
element from the rest of the list.
Hence, we define list-find-bestrecursively. An empty list has no best element, so the base
case is for a list that has one element.
When the input list has only one element, that element is the best element. If the list has
more than one element, the best element is the better of the first element in the list and
the best element of the rest of the list.
To pick the better element from two elements, we define the pick-betterprocedure that
takes three inputs: a comparison function and two values.
(define (pick-better cf p1 p2) (if (cf p1 p2) p1 p2))
Assuming the procedure passed as cf has constant running time, the running time
of pick-better is constant.
For most of our examples, we use the &lt;procedure as the comparison function.
For arbitrary inputs, the running time of&lt; is not constant since in the worst
case performing the comparison requires examining every digit in the input numbers.
But, if the maximum value of a number in the input list is limited, then we can
consider &lt; a constant time procedure since all of the inputs passed to it are
below some fixed size.
We use pick-better to define list-find-best:
(define (list-find-bestcfp) (if (null? (cdr p)) (car p)
(pick-better cf (car p) (list-find-best cf (cdr p)))))
We use nn to represent the number of elements in the input list p. An application of list-
find-best involves n−1n−1 recursive applications since each one passes in(cdr p) as
the
new p operand and the base case stops when the list has one element left.
The running time for each application (excluding the recursive application) is constant
since it involves only applications of the constant time procedures null?, cdr, and
pick- better.
So, the total running time for list-find-best is in Θ(n)Θ(n); it scales linearly with
the length of the input list.
Deleting an Element. To implement best first sorting, we need to produce a list that
contains all the elements of the original list except for the best element, which will be
placed at the front of the output list.
We define a procedure, list-delete, that takes as inputs a List and a Value, and produces a
List that contains all the elements of the input list in the original order except for the
first element that is equal to the input value.
(define (list-deletepel) (if (null? p) null
(if (equal? (car p) el) (cdr p) ; found match,
skip this element
(cons (car p) (list-delete (cdr p) el)))))
We use the equal? procedure to check if the element matches instead of = so
thelist- delete procedure works on elements that are not just Numbers.
The equal?procedure behaves identically to = when both inputs are Numbers, but
also works sensibly on many other datatypes including Booleans, Characters, Pairs,
Lists, and Strings.
Since we assume the sizes of the inputs to equal? are bounded, we can consider equal? to
be a constant time procedure (even though it would not be constant time on arbitrary
inputs).
The worst case running time for list-delete occurs when no element in the list matches
the value of el (in the best case, the first element matches and the running time does not
depend on the length of the input list at all).
We use nn to represent the number of elements in the input list. There can be
up to nnrecursive applications of list-delete.
Each application has constant running time since all of the procedures applied (except
the recursive call) have constant running times. Hence, the total running time for list-
delete is in Θ(n)Θ(n) where nnis the length of the input list.
Best-First Sorting. We define list-sort-best-first using list-find-best andlist-delete:
(define (list-sort-best-firstcfp) (if (null? p) null
(cons (list-find-bestcfp)
(list-sort-best-first cf (list-delete p (list-find-best cf p))))))
The running time of the list-sort-best-first procedure grows quadratically with the length
of the input list.
We use nn to represent the number of elements in the input list. There are nn recursive
applications since each application of list-delete produces an output list that is one
element shorter than its input list.
In addition to the constant time procedures (null? and cons), the body of list-sort-
best- first involves two applications of list-find-best on the input list, and one application
of list- delete on the input list.
Each of these applications has running time in Θ(m)Θ(m) where mm is the length of
the input list to list-find-best and list-delete (we use mm here to avoid confusion with nn,
the length of the first list passed into list-sort-best-first).
In the first application, this input list will be a list of length nn, but in later applications
it will be involve lists of decreasing length: n−1n−1, n−2n−2, ⋯⋯, 1. Hence,
the average length of the input lists to list-find-best and list-delete is approximately n2n2.
Thus, the average running time for each of these applications is in Θ(n2)Θ(n2), which is
equivalent to Θ(n)Θ(n).
There are three applications (two of list-find-best and one of list-delete) for each
application of list-sort-best-first, so the total running time for each application
is in Θ(3n)Θ(3n), which is equivalent to Θ(n)Θ(n).
There are nn recursive applications, each with average running time in Θ(n)Θ(n),
so the running time for list-sort-best-first is in Θ(n2)Θ(n2). This means doubling the
length
of the input list quadruples the expected running time, so we predict that sorting a list of
2000 elements to take approximately four times as long as sorting a list of 1000
elements.
Let expression. Each application of the list-sort-best-first procedure involves
two
evaluations of (list-find-best cf p), a
procedure with running time in Θ(n)Θ(n) where nn is the length of the
input list.
The result of both evaluations is the same, so there is no need to evaluate this expression
twice.
We could just evaluate (list-find-best cf p) once and reuse the result. One way to do this is
to introduce a new procedure using a lambda expression and pass in the result of (list-
find-best cf p) as a parameter to this procedure so it can be used twice:
(define (list-sort-best-first-nodupcfp) (if (null? p) null
((lambda (best)
(cons best (list-sort-best-first-nodup cf (list-delete p best))))
(list-find-best cf p))))
This procedure avoids the duplicate evaluation of (list-
find-best cf p), but is quite awkward to read and
understand.
Scheme provides the let expression special form to avoid this type of duplicate
work more elegantly. The grammar for the let expression is:
The evaluation rule for the let expression is:
Evaluation Rule 6: Let expression. To evaluate a let expression, evaluate each
binding in order. To evaluate each binding, evaluate the binding expression and bind the
name to the value of that expression.
Then, the value of the let expression is the value of the body expression evaluated with
the names in the expression that match binding names substituted with their
bound values.
A let expression can be transformed into an equivalent application expression. The let
expression
(let ((NameaExpressiona) (NamebExpressionb)
cdots (NamekExpressionk))
ExpressionBody)
is equivalent to the application expression:
((lambda (Namea Nameb
Expressiona Expressionb ldots Expressionk)
ldots Namek) ExpressionBody)
The advantage of the let expression syntax is it puts the expressions next to the names to
which they are bound.
Using a let expression, we define list-sort-best-first-let to avoid the duplicate evaluations:
(define (list-sort-best-first-let cf p)
(if (null? p) null
(let ((best (list-find-best cf p))) (cons best (list-sort-best-first-let cf (list-delete p
best))))))
This runs faster than list-sort-best-first since it avoids the duplicate evaluations, but the
asymptotic asymptotic running time is still in Θ(n2)Θ(n2): there are nn recursive
applications of list-sort-best-first-let and each application involves linear
time applications of list-find-best and list-delete.
Using the let expression improves the actual running time by avoiding the
duplicate work, but does not impact the asymptotic growth rate since the duplicate work
is hidden in the constant factor.
8.1.2 Insertion Sort
The list-sort-best-first procedure seems quite inefficient. For every output element,
we are searching the whole remaining list to find the best element, but do nothing of
value with all the comparisons that were done to find the best element.
An alternate approach is to build up a sorted list as we go through the elements.
Insertion sort works by putting the first element in the list in the right place in the list
that results from sorting the rest of the elements.
First, we define the list-insert-one procedure that takes three inputs: a comparison
procedure, an element, and a List.
The input List must be sorted according to the comparison function. As output,
list- insert-one produces a List consisting of the elements of the input List, with
the input element inserts in the right place according to the comparison function.
(define (list-insert-one cf el
(if (null? p) (list el)
p) ; requires: p is sorted
el (car p)) (cons el
by cf
(if (cf
(cons (car p) (list-insert-one cf el (cdr p))))))
p)
The running time for list-insert-one is in Θ(n)Θ(n) where nn is the number of elements
in the input list. In the worst case, the input element belongs at the end of the list and it
makes nn recursive applications of list-insert-one.
Each application involves constant work so the overall running time of list-insert-one is
in Θ(n)Θ(n).
To sort the whole list, we insert each element into the list that results from sorting the
rest of the elements:
(define (list-sort-insert (if (null? p) null
(list-insert-one cf (car p) (list-sort-insert cf (cdr p)))))
cf p)
Evaluating an application of list-sort-insert on a list of length nn involves
nnrecursive
applications. The lengths of the input lists
in the recursive applications are n−1n−1,
n−2n−2, ……, 0.
Each application involves an application of list-insert-one which has linear running time.
The average length of the input list over all the applications is approximately n2n2, so
the average running time of thelist-insert-one applications is in Θ(n)Θ(n).
There are nn applications of scheme|list-insert-one|, so the total running time is
in Θ(n2)Θ(n2).
8.1.3 Quicker Sorting
Although insertion sort is typically faster than best-first sort, its running time is
still scales quadratically with the length of the list.
If it takes 100 milliseconds (one tenth of a second) to sort a list containing 1000
elements using list-sort-insert, we expect it will take four (=22=22) times as long to sort
a list containing 2000 elements, and a million times (=10002=10002) as long (over a
day!) to sort a list containing one million (1000∗10001000∗1000) elements.
Yet computers routinely need to sort lists containing many millions of elements
(for example, consider processing credit card transactions or analyzing the data
collected by a super collider).
The problem with our insertion sort is that it divides the work unevenly into inserting
one element and sorting the rest of the list.
This is a very unequal division. Any sorting procedure that works by considering
one
element at a time and putting it in the sorted position as is done by list-sort-find-
best andlist-sort-insert has a running time in Ω(n2)Ω(n2).
We cannot do better than this with this strategy since there are nn elements, and the
time required to figure out where each element goes is in Ω(n)Ω(n).

More Related Content

PPT
Data Structures - Searching & sorting
PPTX
Highorderfunctions in swift
PDF
binary search
DOCX
Pi data link-2017-sp1-user-guide-es-05
PPT
Implementing External DSLs Using Scala Parser Combinators
DOCX
Selection sort lab mannual
PDF
Data structures arrays
PPT
Chap10
Data Structures - Searching & sorting
Highorderfunctions in swift
binary search
Pi data link-2017-sp1-user-guide-es-05
Implementing External DSLs Using Scala Parser Combinators
Selection sort lab mannual
Data structures arrays
Chap10

What's hot (20)

PPTX
Algorithm & data structures lec4&5
PPTX
Selection sort and insertion sort
PPTX
Searching & Sorting Algorithms
PPT
Ch05 Black Jack
PPT
Sorting
PPTX
LISP: Type specifiers in lisp
PPTX
LISP:Predicates in lisp
PPTX
Binary search
PPT
PPT
Chap03alg
PPT
Chapter 14
PDF
Python (regular expression)
PPT
Lect11 Sorting
PDF
Data Structures & Algorithm design using C
PPTX
Processing Regex Python
PPT
Hub 102 - Lesson 5 - Algorithm: Sorting & Searching
PDF
Sorting algorithm
PDF
Module 01 Stack and Recursion
PPTX
LISP: Data types in lisp
PPTX
Regular Expressions in Java
Algorithm & data structures lec4&5
Selection sort and insertion sort
Searching & Sorting Algorithms
Ch05 Black Jack
Sorting
LISP: Type specifiers in lisp
LISP:Predicates in lisp
Binary search
Chap03alg
Chapter 14
Python (regular expression)
Lect11 Sorting
Data Structures & Algorithm design using C
Processing Regex Python
Hub 102 - Lesson 5 - Algorithm: Sorting & Searching
Sorting algorithm
Module 01 Stack and Recursion
LISP: Data types in lisp
Regular Expressions in Java
Ad

Viewers also liked (18)

DOCX
Presentación del proyecto a la comunidad educativa
PDF
Ormiston education
PDF
More about health
PDF
Health matrix
PPTX
Right Sourcing Utrecht
DOC
Aids doesnt kill. your attitude kills.
PPTX
Introducción a Metodos de investigación de usuarios
PPTX
Using Visualization to Succeed with Big Data
PDF
Ifrs adoption in saudi arabia
PPTX
The Global Impact of Container Inventory Imbalance and the factors that influ...
PDF
International Accounting Standard compliance analysis on nine pharmaceutical ...
PDF
Drexel private equity guest lecture 10 20-2015
PPTX
Presentacion Derecho Penal Especial
PDF
PPTX
Recent Trends in Ship Design - 2013
PPTX
Hadoop & Cloud Storage: Object Store Integration in Production
PDF
KNIME tutorial
PDF
Having Fun Building Web Applications (Day 2 slides)
Presentación del proyecto a la comunidad educativa
Ormiston education
More about health
Health matrix
Right Sourcing Utrecht
Aids doesnt kill. your attitude kills.
Introducción a Metodos de investigación de usuarios
Using Visualization to Succeed with Big Data
Ifrs adoption in saudi arabia
The Global Impact of Container Inventory Imbalance and the factors that influ...
International Accounting Standard compliance analysis on nine pharmaceutical ...
Drexel private equity guest lecture 10 20-2015
Presentacion Derecho Penal Especial
Recent Trends in Ship Design - 2013
Hadoop & Cloud Storage: Object Store Integration in Production
KNIME tutorial
Having Fun Building Web Applications (Day 2 slides)
Ad

Similar to best first-sort (20)

PDF
PPT
Introduction
PPTX
PDF
Alg_Wks1_2.pdflklokjbhvkv jv .v.vk.hk kv h/k
PPT
Recursion.ppt
PDF
Sienna 5 decreaseandconquer
PPTX
PPT.pptx Searching and Sorting Techniques
PDF
Solution Manual for Data Structures and Algorithm Analysis in C++, 4/E 4th Ed...
DOC
Ds program-print
PPT
Algorithm Design and Analysis
PPTX
PPTX
3_Bubble Sort,Insertion Sort & Selection Sort.pptx
PPTX
366 it elective 4 (analysis of algoritm)
PPTX
searching in data structure.pptx
PPT
C Language Unit-6
PPT
Unit6 jwfiles
PPT
Unit6 C
PPT
MITP Ch 2jbhjbhjbhjbhjbhjb Sbhjblides.ppt
PPTX
Algorithms - Rocksolid Tour 2013
PDF
–PLS write program in c++Recursive Linked List OperationsWrite a.pdf
Introduction
Alg_Wks1_2.pdflklokjbhvkv jv .v.vk.hk kv h/k
Recursion.ppt
Sienna 5 decreaseandconquer
PPT.pptx Searching and Sorting Techniques
Solution Manual for Data Structures and Algorithm Analysis in C++, 4/E 4th Ed...
Ds program-print
Algorithm Design and Analysis
3_Bubble Sort,Insertion Sort & Selection Sort.pptx
366 it elective 4 (analysis of algoritm)
searching in data structure.pptx
C Language Unit-6
Unit6 jwfiles
Unit6 C
MITP Ch 2jbhjbhjbhjbhjbhjb Sbhjblides.ppt
Algorithms - Rocksolid Tour 2013
–PLS write program in c++Recursive Linked List OperationsWrite a.pdf

More from Rajendran (20)

PPT
Element distinctness lower bounds
PPT
Scheduling with Startup and Holding Costs
PPT
Divide and conquer surfing lower bounds
PPT
Red black tree
PPT
Hash table
PPT
Medians and order statistics
PPT
Proof master theorem
PPT
Recursion tree method
PPT
Recurrence theorem
PPT
Master method
PPT
Master method theorem
PPT
Hash tables
PPT
Lower bound
PPT
Master method theorem
PPT
Greedy algorithms
PPT
Longest common subsequences in Algorithm Analysis
PPT
Dynamic programming in Algorithm Analysis
PPT
Average case Analysis of Quicksort
PPT
Np completeness
PPT
computer languages
Element distinctness lower bounds
Scheduling with Startup and Holding Costs
Divide and conquer surfing lower bounds
Red black tree
Hash table
Medians and order statistics
Proof master theorem
Recursion tree method
Recurrence theorem
Master method
Master method theorem
Hash tables
Lower bound
Master method theorem
Greedy algorithms
Longest common subsequences in Algorithm Analysis
Dynamic programming in Algorithm Analysis
Average case Analysis of Quicksort
Np completeness
computer languages

Recently uploaded (20)

PPTX
CHAPTER IV. MAN AND BIOSPHERE AND ITS TOTALITY.pptx
PDF
A GUIDE TO GENETICS FOR UNDERGRADUATE MEDICAL STUDENTS
PDF
Indian roads congress 037 - 2012 Flexible pavement
PPTX
TNA_Presentation-1-Final(SAVE)) (1).pptx
PDF
What if we spent less time fighting change, and more time building what’s rig...
PDF
Black Hat USA 2025 - Micro ICS Summit - ICS/OT Threat Landscape
PDF
Computing-Curriculum for Schools in Ghana
PPTX
History, Philosophy and sociology of education (1).pptx
PDF
Vision Prelims GS PYQ Analysis 2011-2022 www.upscpdf.com.pdf
PPTX
B.Sc. DS Unit 2 Software Engineering.pptx
PDF
David L Page_DCI Research Study Journey_how Methodology can inform one's prac...
PDF
HVAC Specification 2024 according to central public works department
PDF
CISA (Certified Information Systems Auditor) Domain-Wise Summary.pdf
PDF
Weekly quiz Compilation Jan -July 25.pdf
PPTX
A powerpoint presentation on the Revised K-10 Science Shaping Paper
PDF
FOISHS ANNUAL IMPLEMENTATION PLAN 2025.pdf
PPTX
Introduction to pro and eukaryotes and differences.pptx
PDF
Paper A Mock Exam 9_ Attempt review.pdf.
PPTX
Introduction to Building Materials
PDF
IGGE1 Understanding the Self1234567891011
CHAPTER IV. MAN AND BIOSPHERE AND ITS TOTALITY.pptx
A GUIDE TO GENETICS FOR UNDERGRADUATE MEDICAL STUDENTS
Indian roads congress 037 - 2012 Flexible pavement
TNA_Presentation-1-Final(SAVE)) (1).pptx
What if we spent less time fighting change, and more time building what’s rig...
Black Hat USA 2025 - Micro ICS Summit - ICS/OT Threat Landscape
Computing-Curriculum for Schools in Ghana
History, Philosophy and sociology of education (1).pptx
Vision Prelims GS PYQ Analysis 2011-2022 www.upscpdf.com.pdf
B.Sc. DS Unit 2 Software Engineering.pptx
David L Page_DCI Research Study Journey_how Methodology can inform one's prac...
HVAC Specification 2024 according to central public works department
CISA (Certified Information Systems Auditor) Domain-Wise Summary.pdf
Weekly quiz Compilation Jan -July 25.pdf
A powerpoint presentation on the Revised K-10 Science Shaping Paper
FOISHS ANNUAL IMPLEMENTATION PLAN 2025.pdf
Introduction to pro and eukaryotes and differences.pptx
Paper A Mock Exam 9_ Attempt review.pdf.
Introduction to Building Materials
IGGE1 Understanding the Self1234567891011

best first-sort

  • 1. 8.1.1 Best-First Sort A simple sorting strategy is to find the best element in the list and put that at the front. The best element is an element for which the comparison procedure evaluates to true when applied to that element and every other element. For example, if the comparison function is <<, the best element is the lowest number in the list. This element belongs at the front of the output list. The notion of the best element in the list for a given comparison function only makes sense if the comparison function is transitive. This means it has the property that for any inputs a, b, and c, if (cf a b) and (cf b c) are both true, the result of (cf a c) must be true.The << function transitive: aa<<bb and bb<<ccimplies aa<<cc foris all numbers aa, bb, and cc. If the comparison function does not have this property, there may be no way to arrange the elements in a single sorted list. All of our sorting procedures require that the procedure passed as the comparison function is transitive. Once we can find the best element in a given list, we can sort the whole list by repeatedly finding the best element of the remaining elements until no more elements remain. To define our best-first sorting procedure, we first define a procedure for finding the best element in the list, and then define a procedure for removing an element from a list.
  • 2. Finding the Best. The best element in the list is either the first element, or the best element from the rest of the list. Hence, we define list-find-bestrecursively. An empty list has no best element, so the base case is for a list that has one element. When the input list has only one element, that element is the best element. If the list has more than one element, the best element is the better of the first element in the list and the best element of the rest of the list. To pick the better element from two elements, we define the pick-betterprocedure that takes three inputs: a comparison function and two values. (define (pick-better cf p1 p2) (if (cf p1 p2) p1 p2)) Assuming the procedure passed as cf has constant running time, the running time of pick-better is constant. For most of our examples, we use the &lt;procedure as the comparison function. For arbitrary inputs, the running time of&lt; is not constant since in the worst case performing the comparison requires examining every digit in the input numbers. But, if the maximum value of a number in the input list is limited, then we can consider &lt; a constant time procedure since all of the inputs passed to it are below some fixed size.
  • 3. We use pick-better to define list-find-best: (define (list-find-bestcfp) (if (null? (cdr p)) (car p) (pick-better cf (car p) (list-find-best cf (cdr p))))) We use nn to represent the number of elements in the input list p. An application of list- find-best involves n−1n−1 recursive applications since each one passes in(cdr p) as the new p operand and the base case stops when the list has one element left. The running time for each application (excluding the recursive application) is constant since it involves only applications of the constant time procedures null?, cdr, and pick- better. So, the total running time for list-find-best is in Θ(n)Θ(n); it scales linearly with the length of the input list. Deleting an Element. To implement best first sorting, we need to produce a list that contains all the elements of the original list except for the best element, which will be placed at the front of the output list. We define a procedure, list-delete, that takes as inputs a List and a Value, and produces a List that contains all the elements of the input list in the original order except for the first element that is equal to the input value. (define (list-deletepel) (if (null? p) null (if (equal? (car p) el) (cdr p) ; found match, skip this element (cons (car p) (list-delete (cdr p) el)))))
  • 4. We use the equal? procedure to check if the element matches instead of = so thelist- delete procedure works on elements that are not just Numbers. The equal?procedure behaves identically to = when both inputs are Numbers, but also works sensibly on many other datatypes including Booleans, Characters, Pairs, Lists, and Strings. Since we assume the sizes of the inputs to equal? are bounded, we can consider equal? to be a constant time procedure (even though it would not be constant time on arbitrary inputs). The worst case running time for list-delete occurs when no element in the list matches the value of el (in the best case, the first element matches and the running time does not depend on the length of the input list at all). We use nn to represent the number of elements in the input list. There can be up to nnrecursive applications of list-delete. Each application has constant running time since all of the procedures applied (except the recursive call) have constant running times. Hence, the total running time for list- delete is in Θ(n)Θ(n) where nnis the length of the input list.
  • 5. Best-First Sorting. We define list-sort-best-first using list-find-best andlist-delete: (define (list-sort-best-firstcfp) (if (null? p) null (cons (list-find-bestcfp) (list-sort-best-first cf (list-delete p (list-find-best cf p)))))) The running time of the list-sort-best-first procedure grows quadratically with the length of the input list. We use nn to represent the number of elements in the input list. There are nn recursive applications since each application of list-delete produces an output list that is one element shorter than its input list. In addition to the constant time procedures (null? and cons), the body of list-sort- best- first involves two applications of list-find-best on the input list, and one application of list- delete on the input list. Each of these applications has running time in Θ(m)Θ(m) where mm is the length of the input list to list-find-best and list-delete (we use mm here to avoid confusion with nn, the length of the first list passed into list-sort-best-first). In the first application, this input list will be a list of length nn, but in later applications it will be involve lists of decreasing length: n−1n−1, n−2n−2, ⋯⋯, 1. Hence, the average length of the input lists to list-find-best and list-delete is approximately n2n2. Thus, the average running time for each of these applications is in Θ(n2)Θ(n2), which is equivalent to Θ(n)Θ(n).
  • 6. There are three applications (two of list-find-best and one of list-delete) for each application of list-sort-best-first, so the total running time for each application is in Θ(3n)Θ(3n), which is equivalent to Θ(n)Θ(n). There are nn recursive applications, each with average running time in Θ(n)Θ(n), so the running time for list-sort-best-first is in Θ(n2)Θ(n2). This means doubling the length of the input list quadruples the expected running time, so we predict that sorting a list of 2000 elements to take approximately four times as long as sorting a list of 1000 elements. Let expression. Each application of the list-sort-best-first procedure involves two evaluations of (list-find-best cf p), a procedure with running time in Θ(n)Θ(n) where nn is the length of the input list. The result of both evaluations is the same, so there is no need to evaluate this expression twice. We could just evaluate (list-find-best cf p) once and reuse the result. One way to do this is to introduce a new procedure using a lambda expression and pass in the result of (list- find-best cf p) as a parameter to this procedure so it can be used twice: (define (list-sort-best-first-nodupcfp) (if (null? p) null ((lambda (best) (cons best (list-sort-best-first-nodup cf (list-delete p best)))) (list-find-best cf p)))) This procedure avoids the duplicate evaluation of (list- find-best cf p), but is quite awkward to read and understand.
  • 7. Scheme provides the let expression special form to avoid this type of duplicate work more elegantly. The grammar for the let expression is: The evaluation rule for the let expression is: Evaluation Rule 6: Let expression. To evaluate a let expression, evaluate each binding in order. To evaluate each binding, evaluate the binding expression and bind the name to the value of that expression. Then, the value of the let expression is the value of the body expression evaluated with the names in the expression that match binding names substituted with their bound values. A let expression can be transformed into an equivalent application expression. The let expression (let ((NameaExpressiona) (NamebExpressionb) cdots (NamekExpressionk)) ExpressionBody) is equivalent to the application expression:
  • 8. ((lambda (Namea Nameb Expressiona Expressionb ldots Expressionk) ldots Namek) ExpressionBody) The advantage of the let expression syntax is it puts the expressions next to the names to which they are bound. Using a let expression, we define list-sort-best-first-let to avoid the duplicate evaluations: (define (list-sort-best-first-let cf p) (if (null? p) null (let ((best (list-find-best cf p))) (cons best (list-sort-best-first-let cf (list-delete p best)))))) This runs faster than list-sort-best-first since it avoids the duplicate evaluations, but the asymptotic asymptotic running time is still in Θ(n2)Θ(n2): there are nn recursive applications of list-sort-best-first-let and each application involves linear time applications of list-find-best and list-delete. Using the let expression improves the actual running time by avoiding the duplicate work, but does not impact the asymptotic growth rate since the duplicate work is hidden in the constant factor.
  • 9. 8.1.2 Insertion Sort The list-sort-best-first procedure seems quite inefficient. For every output element, we are searching the whole remaining list to find the best element, but do nothing of value with all the comparisons that were done to find the best element. An alternate approach is to build up a sorted list as we go through the elements. Insertion sort works by putting the first element in the list in the right place in the list that results from sorting the rest of the elements. First, we define the list-insert-one procedure that takes three inputs: a comparison procedure, an element, and a List. The input List must be sorted according to the comparison function. As output, list- insert-one produces a List consisting of the elements of the input List, with the input element inserts in the right place according to the comparison function. (define (list-insert-one cf el (if (null? p) (list el) p) ; requires: p is sorted el (car p)) (cons el by cf (if (cf (cons (car p) (list-insert-one cf el (cdr p)))))) p) The running time for list-insert-one is in Θ(n)Θ(n) where nn is the number of elements in the input list. In the worst case, the input element belongs at the end of the list and it makes nn recursive applications of list-insert-one. Each application involves constant work so the overall running time of list-insert-one is in Θ(n)Θ(n).
  • 10. To sort the whole list, we insert each element into the list that results from sorting the rest of the elements: (define (list-sort-insert (if (null? p) null (list-insert-one cf (car p) (list-sort-insert cf (cdr p))))) cf p) Evaluating an application of list-sort-insert on a list of length nn involves nnrecursive applications. The lengths of the input lists in the recursive applications are n−1n−1, n−2n−2, ……, 0. Each application involves an application of list-insert-one which has linear running time. The average length of the input list over all the applications is approximately n2n2, so the average running time of thelist-insert-one applications is in Θ(n)Θ(n). There are nn applications of scheme|list-insert-one|, so the total running time is in Θ(n2)Θ(n2).
  • 11. 8.1.3 Quicker Sorting Although insertion sort is typically faster than best-first sort, its running time is still scales quadratically with the length of the list. If it takes 100 milliseconds (one tenth of a second) to sort a list containing 1000 elements using list-sort-insert, we expect it will take four (=22=22) times as long to sort a list containing 2000 elements, and a million times (=10002=10002) as long (over a day!) to sort a list containing one million (1000∗10001000∗1000) elements. Yet computers routinely need to sort lists containing many millions of elements (for example, consider processing credit card transactions or analyzing the data collected by a super collider). The problem with our insertion sort is that it divides the work unevenly into inserting one element and sorting the rest of the list. This is a very unequal division. Any sorting procedure that works by considering one element at a time and putting it in the sorted position as is done by list-sort-find- best andlist-sort-insert has a running time in Ω(n2)Ω(n2). We cannot do better than this with this strategy since there are nn elements, and the time required to figure out where each element goes is in Ω(n)Ω(n).