• Selection: O(N2)
• Insertion (straight insertion): O(N2)
• Binary insertion: O(N2)
• Shell sort, conjectured: O(N1.3)
• Heapsort: O(N lg N)
• Quicksort: O(N lg N)
• Straight insertion with ordered data: O(N)
Selection and insertion (except for insertion with ordered data) are O(N2) algorithms; quicksort and heapsort are O(N lg N) algorithms.
Section 4.2 Exercises
1. In the “Hierarchy of Functional Forms” on page 78, compare each function on the list with the one that immediately follows it. For each pair of functions, show that the limiting ratio is zero as N → ∞.
Apply L’Hospital’s rule one or more times, if necessary.
2. Consider the formulas N100 and 2N. Use the approximation 210 = 103.
a) Show that for N = 100, the first formula is about 10200 while the second is about 1030. b) Show that for N = 1,000, both formulas are approximately 10300.
c) Show that for N = 10,000, the first is about 10400 while the second is about 103000. d) Which of the two formulas is asymptotically larger?
3. Suppose that two functions each have the form (lg N)k with different values of k. Show that the limiting ratio (with the smaller k value in the numerator) is zero. Do the same for two functions of the form Nα with different values of α.
4. The preceding discussion states that (lg N)k (for any fixed k such that k > 1) is less than Nα (for any fixed α such that 0 < α < 1) in the limit as N → ∞. Compare (lg N)3 with N0.2. For large N, it is easier to compare logarithms: substitute L for lg N and compare 3·lg L to 0.2·L. When N is about one million, observe that L is about 20 and lg L is between 4 and 5, so the first formula is larger than the second. Show that the “crossover point,” beyond which the second formula is larger than the first, occurs between L = 99 and L = 100 (N is about 1030). You may use the following table of base-2 logarithms:
L lg L
95 6.570
96 6.585
97 6.600
98 6.615
99 6.630
100 6.644
101 6.658
102 6.673
103 6.687
104 6.701
105 6.714
101
4.4 MATHEMATICAL INDUCTION
According to Section 3.3, the forumula tn = b·n lg n + a·(n – 1) satisfies the recurrence relation t1 = 0, tn = a + b·n + 2·tn/2 when n is a power of 2. The present section shows how to use the method of mathematical induction to verify this formula, and how to apply the method to other similar problems.
The method depends upon the Induction Principle, which states that a function of an integer argu-ment is valid for all nonnegative values of its arguargu-ment, provided that both of the following can be shown:
1. The function is valid for the argument value 0; and
2. Validity of the function for any nonnegative argument value m implies validity for m + 1.
In this particular application, the substitution n = 2k+1 gives a new independent variable k that takes on nonnegative integer values. With sk+1 = tn; sk = tn/2, it is to be shown that the function sk = b·k·2k + a·(2k– 1) satisfies the recurrence relation sk+1 = a + b·2k+1 + 2·sk with s0 = 0.
Step one of the method requires that the proposed function be verified for k = 0:
s0 = b·0·20 + a(20 – 1) = 0
Step two assumes that the proposed function is correct for an arbitrary (nonnegative) value k = m:
s(m) = b·m·2m + a·2m – a
and then uses this assumption to compute the function value for k = m + 1 from the given recurrence relation:
sm+1 = a + b·2m+1 +2·(b·m·2m + a·2m – a) = b·(m + 1)·2m+1 + a·2m+1 – a
This calculation shows that the assumption for k = m implies that the proposed function is correct for the next value k = m + 1.
Thus both requirements of the Induction Principle are satisfied and the proposed function is correct for all nonnegative values of k. The original formula in n is therefore valid whenever n is a power of 2 with a positive integer exponent.
Section 4.4 Exercises
1. Fibonacci numbers: Use mathematical induction to prove that the recurrence F0 = 0, F1 = 1, Fm+2 = Fm+1 + Fm is satisfied by the formula FN = (αN – βN)/(α – β). First, show that the formula gives the correct result when N is zero or 1. Then, assuming that the formula is correct for N = m and for N = m + 1, write out Fm+1 + Fm. Show algebraically that this sum is equal to (αm+2 – βm+2)/(α – β), using the fact that α and β are roots of the equation x2 – x – 1 = 0.
2. Shell sort interval sequence: Use mathematical induction to prove that the recurrence h0 = 1, hk+1 = 3·hk + 1 is satisfied by the formula hk = (3·k – 1) / 2.
4.4 MATHEMATICAL INDUCTION
Chapter 5 Linked Lists
Although arrays can be accessed very rapidly and efficiently, they have one major shortcoming: An array has a fixed size that cannot be changed after data has been stored in it. On the other hand, a linked list is stored dynamically and becomes larger or smaller when data is added or removed. Data can be inserted or deleted at the beginning or end of a linked list or at a specific position in the middle.
A linked list is a sequence of nodes connected with pointers. Each node is a structure, and one of its components is a pointer to the remainder of the list. For example:
type :: Node_Type
type (Info_Type) :: Info
type (Node_Type), pointer :: Next_NP end type Node_Type
The pointer in the last node of a linked list is null because the remainder of the list is empty.
A linked list is accessed through a root pointer whose target is the first node — unless the list is empty, in which case the root pointer is null. The root is declared as a variable with the pointer attribute, of the data type that has been defined for the node structures.
type (Node_Type), pointer :: Root_NP => null( )
The root is declared as a pointer variable in a main program, a subprogram, or a module. The root pointer itself is usually not a dynamically allocated object, but its target node is allocated in dynamic storage during program execution, by the following statement:
allocate( Root_NP )
Each additional node in the list is allocated dynamically as required, as the target of the pointer compo-nent in a previously allocated node.
5.1 LINKED LIST NODE OPERATIONS
Let the nodes of a linked list be structures of type Node_Type, with a data component named Info and a pointer component named Next_NP:
type :: Node_Type
type (Info_Type) :: Info
type (Node_Type), pointer :: Next_NP => null( ) end type Node_Type
The declared (target) type of the pointer component is Node_Type; this pointer provides access to the remainder of the linked list beyond the node in which it appears. Nodes are initialized with a null pointer component; thus a new node has no target until steps are taken to incorporate it into the linked list.
103
Node_Type Info_Type
Next_NP Key
Count(2) Count(1)
Info
The data component, Info, occupies a structure of type Info_Type; for simplicity, let this structure consist of a character string component named Key and an integer vector component named Data. The type definition for Info_Type specifies default initialization for the character and integer components.
type::Info_Type
character(len=S_LEN)::Key=""
integer::Data(2)=0 endtypeInfo_Type
FIGURE 5.1. Derived types for linked list nodes
The forward pointer in each node and the root pointer may be viewed as pointers to the remainder of the list, not merely to the next node. Unless the remainder of the list is empty, it is a node that contains an information component and a pointer to the (further) remainder.29