Presentation is loading. Please wait.

Presentation is loading. Please wait.

Data Structures and Algorithms What is Abstraction?

Similar presentations


Presentation on theme: "Data Structures and Algorithms What is Abstraction?"— Presentation transcript:

1

2 Data Structures and Algorithms What is Abstraction?

3 2 What is abstraction? In general terms a computer is nothing but a lot of on/off switches (i.e. 0/1). We can manipulate data by changing or evaluating state. We can perform addition, subtraction, and logic analysis. We can manipulate where data is stored thru registers and addresses.

4 3 What is abstraction? We make successive abstractions from the state of an on/off value all the way through solving complex problems. 01110100101… 0xeb\0x2a\0x89\0xcd\…. pushl EBP\popl ESI\jmp 0x2a Binary hex op code (machine instructions) assembly language int a = 3;\int b = a + 1; x = 3 + 1 High level language real world problem

5 4 Abstraction Every algorithm depends on: –Data: information manipulated by the algorithm –Control flow: order in which instructions are executed

6 5 Abstraction in Programming Naming -- using descriptive identifiers to denote variables, constants, and complicated data types. Top-Down Design -- designing an algorithm by decomposing a problem into subproblems, then decomposing each subproblem, etc. Functional Abstraction -- invoking a function to carry out a task without knowing its implementation (mechanism for accomplishing the result). Data Abstraction -- separating properties of a data type (its values and operations) from its implementation.

7 6 Abstraction Computers execute low level instructions. – Difficult to understand – Readability is non-existent – Debugging is very difficult – Based on three types of operations Unconditional Branch Conditional Branch Sub Routine call Control structures used in modern languages can implement these in terms of – if, if – else, if – then – else, and switch operations – do – while, and while operations – functions and procedures

8 7 Control Abstraction Algorithms are divided into two parts – Data Manipulation: How the data is used within the algorithm – Control Flow: The order in which the instructions are executed Two forms of control Abstraction – Control Structures: abstraction to low-level machine instructions – Functions & Procedures: abstract multiple actions as single actions. The distinction between control and data abstraction is fuzzy. The reason is that data abstractions normally include control abstraction.

9 8 Control Abstraction Control Flow -- the order in which instructions are executed. Instructions are normally executed in sequence, one after the other. To alter this, high-level languages, like C++ use special instructions called control structures for selection, looping and termination. Statement...

10 9 Compare 160 IF I >= J GO TO 163 161 LET I = I + 3 162 GO TO 160 163 LET K = 5 500 IF I <= J GO TO 503 501 LET A = 20 502 GO TO 504 503 LET A = 30 504 LET B = 2 * a 200 LET I = 0 201 LET A = 0 202 IF I >= 10 GO TO 205 203 LET A = A + 2 204 LET I = I + 1 205 GO TO 202 206 LET B = A while (i < j) i = i + 3; k = 5; if (i > j) a = 20; else a = 30; b = 2 * a; a = 0; for (i = 0;i < 10;i++) a = a + 2; b = a;

11 10 Control Structures for Selection if, if.. else, switch Looping while, for, do.. while Termination exit( ); causes immediate program termination return; terminates execution of a function break; terminates execution of a loop or switch

12 11 Choosing Loop Structures When choosing loops you should not be taken by personal likes and dislikes They exist to serve different purposes: – for loops should be used when the number of interactions is known and constant – In C++ we have a choice of 2 kinds of indefinite loops while should be used if the body of the loop may not be executed at all do – while should be used when the body has to be executed at least once – for loops in C++ can be used for undefined cases but it may make your code obscure – break inside loops should avoided. However you may encounter situations where it does make the code clearer

13 12 Functional Abstraction A powerful mechanism for expressing control abstraction A function can be used as a tool for abstraction because its behavior (what it does) can be seperated from its implementation (how it does it). Using the technique of functional decomposition a complex problem can be be decomposed into ever smaller subproblems each expressed as a function call.

14 13 Functions Software systems can contain millions of lines of code A monolithic program would be difficult to understand, validate, and maintain Waste resources since no library functions are used All major applications organize information in modular fashion Functions implement modular design

15 14 Functions Typically perform a specific task Can call other functions, themselves Similar functions are grouped into libraries Standard libraries complement C++ 1.stdlib, math Functions must be defined before they are used (called), like variables Standard library functions are declared in a header file

16 15 Functional Abstraction A function is a named subprogram that performs a specific task when it is called. The function’s specification is a description of what the function does. Functions use a parameter list for data flow from the caller to the function and from the function to the caller.

17 Parts of Function Definition int Cube ( int n ) heading { return n * n * n ; body } type of value returned name of function parameter list

18 17 Function Definition Define function header and function body Value-returning functions return-data-type function-name(parameter list) { constant declarations variable declarations other C++ statements return value }

19 18 Function Definition (cont.) Non value-returning functions void function-name(parameter list) { constant declarations variable declarations other C++ statements }

20 Parameters classified by location Always appear in a function call within the calling block. Always appear in the function heading, or function prototype. Actual Parameters Formal Parameters

21 20 The argument names in the function header are referred to as formal parameters. int FindMax(int x, int y) { int maximum; if(x>=y) maximum = x; else maximum = y; return maximum; } Function Definition (cont.)

22 21 Function Prototype Every function should have a function prototype. The function prototype specifies the type of the value that the function returns (if any) and the type, number, and order of the function's arguments. return-data-type function-name(argument data types); or void function-name(argument data types);

23 22 Function Prototype (cont.) The use of function prototypes permits error checking of data types by the compiler. It also ensures conversion of all arguments passed to the function to the declared argument data type when the function is called.

24 A prototype looks like a heading but must end with a semicolon; its parameter list just needs the type of each parameter. int Cube ( int ) ; // prototype What is a prototype?

25 24 Function naming conventions used Names of value-returning functions should be nouns (things) or phrases that describe the kind of value (or condition) returned. if (IsSeniorCitizen(thisAge)) discountRate = 0.15; squareFeet = Area(length, width); Names of non-value-returning functions should be command verbs. PrintHeading(numStars);

26 25 Calling a function A function is called by specifying its name followed by its arguments. Non-value returning functions: function-name (data passed to function); Value returning functions: results = function-name (data passed to function);

27 26 Calling a function (cont.) #include int FindMax(int, int); // function prototype int main() { int firstnum, secnum, max; cout << "\nEnter two numbers: "; cin >> firstnum >> secnum; max=FindMax(firstnum, secnum); // the function is called here cout << "The maximum is " << max << endl; return 0; } The argument names in the function call are referred to as actual parameters

28 27 Calling a function by value The function receives a copy of the actual parameter values. The function cannot change the values of the actual parameters.

29 28 Calling a function by reference Very useful when we need a function which "returns more than one value". The formal parameter becomes an alias for the actual parameter. The function can change the values of the actual parameters.

30 29 #include void newval(float&, float&); // function prototype int main() { float firstnum, secnum; cout << "Enter two numbers: "; cin >> firstnum >> secnum; newval(firstnum, secnum); cout << firstnum << secnum << endl; return 0; } void newval(float& xnum, float& ynum) { xnum = 89.5; ynum = 99.5; } Calling a function by reference (cont.)

31 30 The "const" modifier Call by reference is the preferred way to pass a large structure or class instances to functions, since the entire structure need not be copied each time it is used!! C++ provides us with protection against accidentally changing the values of variables passed by reference with the const operator function prototype: int FindMax(const int&, const int&); function header: int FindMax(const int& x, const int& y);

32 31 Parameters Default Behavior of simple types like int, char, float, double are always value parameters, unless you do something to change that. To get a reference parameter you need to place & after the type in the function heading and prototype.

33 When to use reference parameters? Reference parameters should be used when you want your function to give a value to, or change the value of, a variable from the calling block without an assignment statement in the calling block.

34 CALLING BLOCK MEMORY 25 4000 Age If you pass only a copy of 25 to a function, it is called “pass-by-value” and the function will not be able to change the contents of Age. It is still 25 when you return.

35 CALLING BLOCK MEMORY 25 4000 Age BUT, if you pass 4000, the address of Age to a function, it is called “pass-by- reference” and the function will be able to change the contents of Age. It could be 23 or 90 when you return. BUT, if you pass 4000, the address of Age to a function, it is called “pass-by- reference” and the function will be able to change the contents of Age. It could be 23 or 90 when you return.

36 Value Parameter Reference Parameter The value (25) of the actual parameter is passed to the function when it is called. The memory address (4000) of the actual parameter is passed to the function when it is called. 25 4000 Age CALLING BLOCK MEMORY

37 Pass-by-reference is also called... Pass-by-address, or Pass-by-location.

38 Pass-by-value CALLING BLOCK FUNCTION CALLED “incoming” value of actual parameter

39 Pass-by-reference CALLING BLOCK FUNCTION CALLED actual parameter has no value yet when call occurs “outgoing” new value of actual parameter

40 Pass-by-reference CALLING BLOCK FUNCTION CALLED “incoming” original value of actual parameter “outgoing” changed value of actual parameter

41 Parameters classified by purpose /* in */ one-way flow of data into the function /* out */ one-way flow of data out of the function /* inout */ two-way flow into and out of the function Parameter Data Flow

42 For all data types EXCEPT arrays-- /* in */ value /* out */ reference & after the type /* inout */ reference & after the type Data Flow Pass by Formal Parameter Needs

43 For arrays-- /* in */ reference const before the type /* out */ reference /* inout */ reference Data Flow Pass by Formal Parameter Uses

44 43 Abstraction Techniques Functional Abstraction Top-down design Data Abstraction (Central Theme of this course)

45 44 Functional Decomposition Probably the most powerful abstraction mechanism A large task is decomposed (divided) into smaller (complete) tasks which are implemented as functions (or methods) The programmer can than use these functions, make assumptions about their behaviour without worrying about implementation details – Increases software reuse – Improves software reliability as components can be tested independently and thoroughly The function specification is what the programmer needs to know

46 45 Functional Decomposition Functions can return value or not (sometimes called procedures) When designing functions we have to pay attention to data flow – One way flow into the function – One way flow out of the function – Two way flow into and out of the function

47 46 Flow into the Function The caller passes some data to the function but does not expect the function to modify the actual data. In this case parameters should be passed by value // exp must be a positive number int power(int base, int exp) { int power = 1; for (int i=0; i<exp; i++) { power = power * base; } return power } // exp must be a positive number int power(int base, int exp) { int power = 1; for (int i=0; i<exp; i++) { power = power * base; } return power }

48 47 Flow out of the Function The caller passes the location of the data as parameter (pass by reference) The functions modifies the value stored in the location without considering the value currently stored // initialize variables void initialize(float& a, float& b) { a = 1000; b = 100; } // initialize variables void initialize(float& a, float& b) { a = 1000; b = 100; }

49 48 Two-way flow into and from the Function The caller is passing the location of the date (address) as a parameter (pass by reference) The function inspect the value currently stored in the location and will possibly modify it. // initialize variables void update(float& a, float& b) { a = a + 1000; b = b + 100; } // initialize variables void update(float& a, float& b) { a = a + 1000; b = b + 100; }

50 49 Software Design: Standard Functions Problem Specification: Write a program to compute the real roots of a quadratic equation Problem Analysis: We need the three coefficients of a quadratic equation Using these coefficients we need to determine if the roots will be real or not Determine the value of the roots Recall:

51 50 Software Design: Standard Functions Data Requirements: Problem Input a (double) - square term coefficient b (double) - linear term coefficient c (double) - constant term Problem Output equation and roots if real equation and message otherwise Recall, the roots of a quadratic equation are given as:

52 51 Software Design: Standard Functions Problem Analysis, cont: Additional Program Variables radical (double) - root_one (double) - root_two (double) -

53 52 Software Design: Standard Functions Program Design: Initial Design: 1) Read square, linear, and constant terms 2) Display message if imaginary roots 3) Compute roots 4) Display real roots Step 2 refinement: 2.1) inside radical is less than or equal to zero 2.2) square coefficient (a) is zero

54 53 Software Design: Standard Functions Program Implementation:

55 54 Functions The math function sqrt takes one argument and returns a double function call: flow of control transferred to the function function interface or signature, must be specified before function is used 1) return type 2) function name 3) parameter descriptions

56 55 Functions Function prototypes are the same as the function signature with a trailing semi-colon double cos(double x); double my_function(int count, int object);

57 56 Functions Function so far have passed a single parameter and returned the desired value. What if we want to return 2 or more values? Modify the value of a function argument? Not the way we have passed parameters! Pass by value: copy of the value is made! We want to pass a reference to the parameter. A reference is essentially the memory address of the parameter

58 57 Functions Problem Specification: Rewrite the quadratic program so that the roots are determined and returned in a function. Problem Analysis: Similar to before

59 Example of Pass-by-Reference We want to find 2 real roots for a quadratic equation ax 2 + bx + c = 0 with coefficients a, b, and c. Write a prototype for a void function named GetRoots( ) with 5 parameters. The first 3 parameters are type float. The last 2 are reference parameters of type float.

60 void GetRoots ( float, float, float, float&, float& ); This function will use 3 incoming values a, b, c from the calling block. It will calculate 2 outgoing values Root1 and Root2 for the calling block. They are the 2 real roots of the quadratic equation with coefficients a, b, c. // prototype

61 60 GetRoots() void GetRoots( float a, float b, float c, float& Root1, float& Root2 ) { float temp; temp = b * b - 4.0 * a * c; Root1 = (-b + sqrt(temp) ) / ( 2.0 * a ); Root2 = (-b - sqrt(temp) ) / ( 2.0 * a ); return; }

62 #include void GetRoots(float, float, float, float&, float&); int main ( ) { ifstream infile( "in_file"); ofstream outfile( "out_file"); float a, b, c, First, Second; int count = 0; if ( ! infile ) { cerr<<"eror: unable to open input file!\n"; return -1; } if ( ! outfile ) { cerr<<"error: unable to open output file!\n"; return -2; } while ( infile ){ infile >> a >> b >> c; GetRoots(a, b, c, First, Second); //call outfile << a<<endl << b<<endl << c<<endl << First<<endl << Second<<endl; }

63 62 Iostream manipulators setw (int w) - set width setprecision(int d) - number of places is d ios::fixed - use decimal notation for floating-point setf(ios::fixed) - sets decimal notation setfill(‘a’) - sets the fill character

64 63 Iostream manipulators cout is the standard output object cin is the standard input object methods or member functions: functions associated with objects cout and cin have associated functions input and output stream manipulators endl is an ostream manipulator iomanipulator functions are defined in the header file: iomanip

65 64 Table of Function Values Problem Specification: Write a program to list the values of various math functions in tabular form. Problem Analysis: Use log, log10, and sqrt math functions Table format: x log(x) log10(x) sqrt(x) Use a column format Use values of x as: 1->10, 20 ->100, 1000 ->100000

66 65 Table of Function Values

67 66 Table of Function Values include header files iostream: cin and cout include namespace std Eliminates std::cin and std::cout ios::fixed is an enumerated type :: the scope operator, tells which class the value comes from iomanip: setw(), setfill(), setf() setprecision() cmath: log(), log10(), sqrt()

68 67 Table of Function Values while loop: control structure Make sure each pass gets closer to loop termination => infinite loop if(): control structure if(){} else if() {}: control structure x++, ++x: post and pre increment operators x += 10 : compound assignment operator x--, --x: post and pre decrement operators x += 10 same as x = x + 10;

69 68 Table of Function Values Program output:

70 69 Top-Down Approach Programming consists of designing solutions to real world problems that can be applied to machines Specify the Problem Specify the Problem Design Top-Level Algorithm Design Top-Level Algorithm Refine algorithms into subalgorithms Refine algorithms into subalgorithms refine subalgorithms further refine subalgorithms further translate refined algorithms into program translate refined algorithms into program

71 70 Roman Numeral Evaluator Specification Description: The program should accept a simple expression using roman numerals and give the result of the expression in decimals. Input: Each line consists of two roman numerals and a operator. Roman numerals should be in upper case and operator should be (+, -, * or /) Output: The result of the operation in decimals Error Handling: If input is not correct the output should be " Bad Data "

72 71 Roman Numeral Evaluator Stepwise Refinement For each input line Convert roman numbers to decimal If operation is valid Print result of operation else Print error message For each input line Convert roman numbers to decimal If operation is valid Print result of operation else Print error message

73 72 Roman Numeral Evaluator Stepwise Refinement Prompt for input of roman number 1 While not end-of-file signal Prompt operator and roman number 2 Convert roman numbers to decimal If operation is valid Print result of operation else Print error message Prompt for input of roman number 1 While not end-of-file signal Prompt operator and roman number 2 Convert roman numbers to decimal If operation is valid Print result of operation else Print error message Prompt for input of roman number 1

74 73 Roman Numeral Evaluator Stepwise Refinement Prompt for input of roman1 While not end-of-file signal Prompt operator and roman2 decimal1 = convert roman1 to decimal decimal2 = convert roman2 to decimal If operation is valid Apply operation to decimal1 and decimal2 Print result of operation else Print error message Prompt for input of roman1 While not end-of-file signal Prompt operator and roman2 decimal1 = convert roman1 to decimal decimal2 = convert roman2 to decimal If operation is valid Apply operation to decimal1 and decimal2 Print result of operation else Print error message Prompt for input of roman1

75 74 Roman Numeral Evaluator Stepwise Refinement #include typedef int Boolean; const int TRUE = 1; const int FALSE = 0; // Function stubs void printValue(int,char,int); void convert(const char[], int&, Boolean&); int main() { char str1[31]; char str2[31]; char op; int dec1; int dec2; Boolean str1Valid; Boolean str2Valid; Boolean opValid; #include typedef int Boolean; const int TRUE = 1; const int FALSE = 0; // Function stubs void printValue(int,char,int); void convert(const char[], int&, Boolean&); int main() { char str1[31]; char str2[31]; char op; int dec1; int dec2; Boolean str1Valid; Boolean str2Valid; Boolean opValid;

76 75 Roman Numeral Evaluator Stepwise Refinement cout << "Roman numeral expression:\n"; while (cin >> str1) { cin >> op >> str2; convert(str1,dec1,str1Valid); convert(str2,dec2,str2Valid); opValid = (op=='+' || op=='-' || op=='*' || op=='/'); if (str1Valid && str2Valid && opValid) printValue(dec1,op,dec2); else cout << "Bad Data!"; cout << "Roman numeral expression:\n"; } return 0; } cout << "Roman numeral expression:\n"; while (cin >> str1) { cin >> op >> str2; convert(str1,dec1,str1Valid); convert(str2,dec2,str2Valid); opValid = (op=='+' || op=='-' || op=='*' || op=='/'); if (str1Valid && str2Valid && opValid) printValue(dec1,op,dec2); else cout << "Bad Data!"; cout << "Roman numeral expression:\n"; } return 0; }

77 76 Roman Numeral Evaluator What else? Draw hierarchy charts Do further refinement – Stubs should be implemented Perhaps even using further stubs! – Functions can be further divided – Functions could be implemented to be more generic Update hierarchy charts

78 Top-down Testing with Function Stubs A function stub is an unrefined function definition (with formal parameters but incomplete body) that enables you to run your program to determine if your algorithm logic is correct in the caller. The function stub body generally contains cout << “function Whatname entered”; and any /*out*/ parameter is assigned an arbitrary value.

79 Bottom-up Testing Test driver is a separate main function written just to call a new function which it will test using a test oracle (of possible input data and predicted outputs), so you can determine whether the new function meets specifications.

80 79 Bottom-up Testing As important as Top-Down Testing Instead of using stubs a "main" program is written to test the logic of the functions. This function is normally called a Test Driver A good way to write algorithms is combining top- down with bottom-up development/testing – It increases productivity – A groups of programs can test the higher level logic while another group can code and test the lower level routines The combination of both normally shorten the project time

81 80 Roman Numeral Evaluator Bottom-Up testing #include typedef int Boolean; const int TRUE = 1; const int FALSE = 0; int main() { char str[31]; int decVal; Boolean strValid; while (cin >> str) { convert(str,decVal,strValid); if (strValid) cout << "VALID"; else cout << "NOT VALID"; } return 0; } #include typedef int Boolean; const int TRUE = 1; const int FALSE = 0; int main() { char str[31]; int decVal; Boolean strValid; while (cin >> str) { convert(str,decVal,strValid); if (strValid) cout << "VALID"; else cout << "NOT VALID"; } return 0; }

82 81 Documentation On any process of developing algorithms it is very important to document your code Internal documentation is as important as design documentation. – It is used when the program need to be changed The most commonly used internal program documentation is: – Assertions – Loop Invariants – Pre Conditions – Post Conditions

83 An Assertion Is a programmer’s claim (with a value of true or false) about the contents of program variables at a particular location in program execution and is written as a comment (using English and symbols, not necessarily in C++ code).

84 83 Assertions Becoming widely accepted as documentation Shows the state of computation in a given point in the code It is like a snapshot of the internal state of the program` Should be written as a fact (something that the programmer believes to be true) An assertion has a value true of false therefore should be written as a logical statement Can be used to prove the correctness Should be placed correctly in the program and written using language-independent statements

85 84 Some Assertions // ASSERT: 1 <= month <= 13 // ASSERT: all previous values of age were <= 0 // ASSERT: total == 1 + 2 +... + (count -1) // ASSERT: sum >= 0 && count > 0 // ASSERT: 0.0 <= deptSales <= 25000.0

86 85 Examples: Assertions for (i = 0; i < 50; i++) myArray[i] = 0; // ASSERT: All myArray[0..49] == 0 for (i = 0; i < 50; i++) myArray[i] = 0; // ASSERT: All myArray[0..49] == 0 if (a < b) max = b; else max = a; // ASSERT: max has the maximum value between (a,b) if (a < b) max = b; else max = a; // ASSERT: max has the maximum value between (a,b)

87 86 Pre and Post-Conditions Used to document functions Defines the function behavior – Pre-conditions define what the function require to be "true" at the time it is called. – Post-condition define the state of computation at the time the function finishes its execution The pre and post conditions are related. If the pre- condition is guaranteed the post-condition will happen. The caller should ensure the pre-condition and the function code the post-condition

88 Preconditions and Postconditions The precondition describes every condition of formal parameters that the function requires at the moment the function is invoked. The postcondition describes the condition, particularly for reference parameters, when the function finishes execution.

89 void GetRoots( /* in */ float a, /* in */ float b, /* in */ float c, /*out */ float& Root1, /* out */ float& Root2 ) // PRE: Assigned(a) && Assigned(b) && Assigned(c) // && a != 0 && b*b - 4*a*c >= 0 // POST: Root1 and Root2 are roots of quadratic with // coefficients a, b, c { float temp; temp = b * b - 4.0 * a * c; Root1 = ( -b + sqrt ( temp ) ) / ( 2.0 * a ) ; Root2 = ( -b - sqrt ( temp ) ) / ( 2.0 * a ) ; return; }

90 int strLength ( /* in */ const char str [ ] ) //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // PRE: str is a null- terminated string // POST: FCTVAL == length of str (not counting ‘ \0 ’ ) //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { int i = 0 ; while ( str [ i ] != ‘\0’ ) i ++; return i ; }

91 90 Example: Pre/Post Conditions // PRE: assigned(ch1) && assigned(ch2) // POST: the values of ch1 and ch2 have been interchanged void swapChars (/* INOUT */ char& ch1, /* INOUT */ char& ch2) { char auxChar = ch1; ch1 = ch2; ch2 = auxChar; } // PRE: assigned(ch1) && assigned(ch2) // POST: the values of ch1 and ch2 have been interchanged void swapChars (/* INOUT */ char& ch1, /* INOUT */ char& ch2) { char auxChar = ch1; ch1 = ch2; ch2 = auxChar; } // PRE: assigned(aNumber) && aNumber >= 1 // POST: FCTVAL == aNumber * (aNumber-1) * (aNumber-2) *... * 1 int factorial (/* IN */ int aNumber) { if (aNumber == 1) return 1; else return (aNumber * factorial(anumber - 1)); } // PRE: assigned(aNumber) && aNumber >= 1 // POST: FCTVAL == aNumber * (aNumber-1) * (aNumber-2) *... * 1 int factorial (/* IN */ int aNumber) { if (aNumber == 1) return 1; else return (aNumber * factorial(anumber - 1)); }

92 91 Loop Invariants Its is a special kind of assertion but got its own name! A loop invariant is an assertion that is placed inside the loop and must be true every time the loop reaches it. Therefore it must be true: – Initially, after any interaction steps but before the loop begins – Before every iteration of the loop – After every iteration of the loop – After the loop terminates

93 While Loop Invariant The while loop invariant is true just before loop entry, just after the loop body has executed for the last time, and after every loop iteration in between. It is not necessarily true at each point inside the loop body.

94 Examples of Loop Invariants while loop condition related Invariant count = 0; while (count < 100)0 <= count <= 100 count = 4; while (count > 0)0 <= count <= 4

95 94 Where to place the loop invariant? The most useful location is immediately BEFORE the loop test. With a for or while loop, physically place the invariant at the top of the loop body, with the remark “prior to test” to indicate that the invariant is logically located BEFORE the loop test. With a do-while loop, place the loop invariant at the bottom of the loop body, immediately before the test.

96 95 While Loop Invariant sum = 0 ; count = 1 ; while ( count <= 10 ) { // INV (prior to test) : // sum == 1 + 2 +... + count-1 // && 1 <= count <= 11 sum = sum + count ; count++ ; }

97 96 For Loop Invariant sum = 0 ; for ( count = 1 ; count <= 10 ; count++ ) { // INV (after initialization, // but prior to test) : // sum == 1 + 2 +... + count-1 // && 1 <= count <= 11 sum = sum + count ; }

98 97 Do-While Loop Invariant sum = 0 ; count = 1 ; do { sum = sum + count ; count++ ; // INV: // sum == 1 + 2 +... + count-1 // && 2 <= count <= 11 } while ( count <= 10 ) ;

99 98 Case Study Sorting an Array Problem description – Input a collection of up to 100 integers from the keyboard, sort them into ascending order and print the sorted collection – If there are fewer than 100 numbers the user should use end-of-file keystroke (Ctrl-D?) By using arrays we can use algorithms that consider the size of the arrays in their logic and need to manipulate the arrays indexes. We will use selection sort

100 99 Sorting an Array-1 st Step Postpone details until later Debug the code at each level of the stepwise refinement Let us use top down testing using C++ 1. Prompt user to enter the values 2. Store the data into the array 3. Sort the array 4. Display sorted array 1. Prompt user to enter the values 2. Store the data into the array 3. Sort the array 4. Display sorted array

101 100 Sorting an Array-2 nd Step #include const int MAX_SIZE = 100; // Functions prototypes (allow the use of stubs) void inputValues (int[],int&); void sort (int[],int); void outputValues(const int[], int); int main() { int theArray[100]; int size; inputValues(theArray,size); sort(theArray,size); // ASSERT: theArray[0..size-1] is in ascending order outputValues(theArray,size); return 0; } #include const int MAX_SIZE = 100; // Functions prototypes (allow the use of stubs) void inputValues (int[],int&); void sort (int[],int); void outputValues(const int[], int); int main() { int theArray[100]; int size; inputValues(theArray,size); sort(theArray,size); // ASSERT: theArray[0..size-1] is in ascending order outputValues(theArray,size); return 0; }

102 101 Sorting an Array-3 rd Step // POST: size == number of input values // && size <= MAX_SIZE // && theArray[0..size-1] contains the input values void inputValues( /* OUT */ int theArray[], /* IN */ int& size) { cout << "INPUT FUNCTION\n"; size = 3; theArray[0] = 13; theArray[1] = 2; theArray[2] = 55; } // POST: size == number of input values // && size <= MAX_SIZE // && theArray[0..size-1] contains the input values void inputValues( /* OUT */ int theArray[], /* IN */ int& size) { cout << "INPUT FUNCTION\n"; size = 3; theArray[0] = 13; theArray[1] = 2; theArray[2] = 55; }

103 102 Sorting an Array 3 rd Step // PRE: assigned(size) && assigned(theArray[0..size-1] // POST: values of theArray[0..size-1] are rearranged in ascending // order void sort( /* INOUT */ int theArray[], /* IN */ int size) { cout << "SORT FUNCTION\n"; theArray[0] = 2; theArray[1] = 13; theArray[2] = 55; } // PRE: assigned(size) && assigned(theArray[0..size-1] // POST: values of theArray[0..size-1] are rearranged in ascending // order void sort( /* INOUT */ int theArray[], /* IN */ int size) { cout << "SORT FUNCTION\n"; theArray[0] = 2; theArray[1] = 13; theArray[2] = 55; }

104 103 Sorting an Array-3 rd Step // PRE: assigned(size) && assigned(theArray[0..size-1] // POST: values of theArray[0..size-1] are displayed void outputValues(/* IN */ const int theArray[], /* IN */ int size) { cout << "OUTPUT FUNCTION\n"; cout << theArray[0] << '\n'; cout << theArray[1] << '\n'; cout << theArray[2] << '\n'; } // PRE: assigned(size) && assigned(theArray[0..size-1] // POST: values of theArray[0..size-1] are displayed void outputValues(/* IN */ const int theArray[], /* IN */ int size) { cout << "OUTPUT FUNCTION\n"; cout << theArray[0] << '\n'; cout << theArray[1] << '\n'; cout << theArray[2] << '\n'; }

105 104 Sorting an Array-4 th Step // POST: size == number of input values // && size < 100 // && theArray[0..size-1] contains the input values void inputValues( /* OUT */ int theArray[], /* IN */ int& size) { cout << "INPUT FUNCTION\n"; size = 0; while (size > theArray[size]) // INV: theArray[0..size-1 have been input & size <= MAX_SIZE size++; } // POST: size == number of input values // && size < 100 // && theArray[0..size-1] contains the input values void inputValues( /* OUT */ int theArray[], /* IN */ int& size) { cout << "INPUT FUNCTION\n"; size = 0; while (size > theArray[size]) // INV: theArray[0..size-1 have been input & size <= MAX_SIZE size++; }

106 105 Sorting an Array-4 th Step // PRE: assigned(size) && assigned(theArray[0..size-1] // POST: values of theArray[0..size-1] are displayed void outputValues( /* IN */ const int theArray[], /* IN */ int size) { cout << "OUTPUT FUNCTION\n"; for (int i = 0; i < size; i++) // INV: theArray[0..i-1] have been output && i <= size cout << theArray[i] << '\n'; } // PRE: assigned(size) && assigned(theArray[0..size-1] // POST: values of theArray[0..size-1] are displayed void outputValues( /* IN */ const int theArray[], /* IN */ int size) { cout << "OUTPUT FUNCTION\n"; for (int i = 0; i < size; i++) // INV: theArray[0..i-1] have been output && i <= size cout << theArray[i] << '\n'; }

107 106 Sorting an Array-Selection Sort 4523125278 Bottom 8 231252745 Bottom 8231252745 Bottom 8512232745 Bottom 8512232745 Bottom 5812232745 Bottom

108 107 Sorting an Array-4 th Step // PRE: assigned(size) && assigned(theArray[0..size-1] // POST: values of theArray[0..size-1] are rearranged in ascending // order void sort( /* INOUT */ int theArray[], /* IN */ int size) { for (int bottom = size-1; bottom >=1; bottom--) { FIND THE INDEX OF LARGEST (indexLarge) NUMBER IN theArray if (indexLarge != bottom) SWAP theArray[indexLarge] and theArray[bottom] } // PRE: assigned(size) && assigned(theArray[0..size-1] // POST: values of theArray[0..size-1] are rearranged in ascending // order void sort( /* INOUT */ int theArray[], /* IN */ int size) { for (int bottom = size-1; bottom >=1; bottom--) { FIND THE INDEX OF LARGEST (indexLarge) NUMBER IN theArray if (indexLarge != bottom) SWAP theArray[indexLarge] and theArray[bottom] }

109 108 Sorting an Array-5 th Step // PRE: assigned(size) && assigned(theArray[0..size-1] // POST: values of theArray[0..size-1] are rearranged in ascending // order void sort( /* INOUT */ int theArray[], /* IN */ int size) { int indexLarge; for (int bottom = size-1; bottom >=1; bottom--) { // INV: All elements in theArray[0..bottom] <= theArray[bottom+1] // && theArray[bottom+1..size-1] are ordered // && bottom >= 0 indexLarge = 0; for (int i=1; i<=bottom;i++) // INV: theArray[indexLarge] >= all elements in theArray[0..i-1] // && i <= bottom+1 if (theArray[i] > theArray[indexLarge]) indexLarge = i; if (indexLarge != bottom) swap(theArray[indexLarge],theArray[bottom]); } // PRE: assigned(size) && assigned(theArray[0..size-1] // POST: values of theArray[0..size-1] are rearranged in ascending // order void sort( /* INOUT */ int theArray[], /* IN */ int size) { int indexLarge; for (int bottom = size-1; bottom >=1; bottom--) { // INV: All elements in theArray[0..bottom] <= theArray[bottom+1] // && theArray[bottom+1..size-1] are ordered // && bottom >= 0 indexLarge = 0; for (int i=1; i<=bottom;i++) // INV: theArray[indexLarge] >= all elements in theArray[0..i-1] // && i <= bottom+1 if (theArray[i] > theArray[indexLarge]) indexLarge = i; if (indexLarge != bottom) swap(theArray[indexLarge],theArray[bottom]); }

110 109 Sorting an Array-6 th Step // PRE: assigned(val1) && assigned(val2) // POST: values of val1 and val2 have been interchanged void swap( /* INOUT */ int& val1, /* INOUT */ int& val2) { int temp = val1; val1 = val2; val2 = temp; } // PRE: assigned(val1) && assigned(val2) // POST: values of val1 and val2 have been interchanged void swap( /* INOUT */ int& val1, /* INOUT */ int& val2) { int temp = val1; val1 = val2; val2 = temp; }


Download ppt "Data Structures and Algorithms What is Abstraction?"

Similar presentations


Ads by Google