5.4 Evaluating the Python ListWe defined several abstract data types for storing and using collections of data in the previous chapters. The next logical step is to analyze the operations of the various AD Ts to determine their efficiency. The result of this analysis depends on the efficiency of the Python list since it was the primary data structure used to implement many of the earlier abstract data types. The implementation details of the list were discussed in Chapter 3. In this section, we use those details and evaluate the efficiency of some of the more common operations. A summary of the worst case run times are shown in Table 5.4.1.
List TraversalA sequence traversal accesses the individual items, one after the other, in order to perform some operation on every item. Python provides the built-in iteration for the list structure, which accesses the items in sequential order starting with the first item. Consider the following code segment, which iterates over and computes the sum of the integer values in a list: sum = 0 for value in valueList : sum = sum + value To determine the order of complexity for this simple algorithm, we must first look at the internal implementation of the traversal. Iteration over the contiguous elements of a 1-D array, which is used to store the elements of a list, requires a count-controlled loop with an index variable whose value ranges over the indices of the subarray. The list iteration above is equivalent to the following: sum = 0 for i in range(len(valueList)) : sum = sum + valueList[i] list traversal worst-case:
Assuming the sequence contains items, it's obvious the loop performs iterations. Since all of the operations within the loop only require constant time, including the element access operation, a complete list traversal requires time. Note, this time establishes a minimum required for a complete list traversal. It can actually be higher if any operations performed during each iteration are worse than constant time, unlike this example. List AllocationCreating a list, like the creation of any object, is considered an operation whose time-complexity can be analyzed. There are two techniques commonly used to create a list: temp = list() valueList = [ 0 ] * n list allocation worst-case:
The first example creates an empty list, which can be accomplished in constant time. The second creates a list containing elements, with each element initialized to 0. The actual allocation of the elements can be done in constant time, but the initialization of the individual elements requires a list traversal. Since there are elements and a traversal requires linear time, the allocation of a vector with elements requires time. Appending to a Listlist append best-case:
worst-case:
The Creating the new larger array and destroying the old array can each be done in time. To copy the contents of the old array to the new larger array, the items have to be copied element by element, which requires time. Combining the times from the three steps yields a time of and a worst case time of . Extending a Listextend list worst-case:
The Inserting and Removing ItemsInserting a new item into a list is very similar to appending an item except the new item can be placed anywhere within the list, possibly requiring a shift in elements. An item can be removed from any element within a list, which may also involve shifting elements. Both of these operations require linear time in the worst case, the proof of which is left as an exercise.
|