CTP 250
What is a friend in C++? Why are friends used?
A friend method is used to allow access to private or protected data in a class from outside the class Normally a method which is not a member of a class cannot access such information; neither can an external class Occasionally such access will be advantageous for the programmer; then, the method or external class can be declared as a friend of the class using the keyword "friend" The method or external class will then have access to all information - public, private or protected - within the class Friends should be used with great caution Used incorrectly, the use of friends can compromise encapsulation and data security Friendship is not inherited A friend of a base
Define UML and explain why it is used.
A tool for exploration and communication during OO analysis and design A standard way to specify, construct, and document systems using OO methods Can articulate complex ideas succinctly and precisely Has its own notation, with specialized shapes and conventions Enables members of a programming team to communicate visually with one another and gain a common understanding of the system being built
What static implementation is typically used for a stack?
Array is static; i.e., it has a fixed size Therefore, the stack can get full Must prevent the push operation from adding an item to the stack if the array is full The number of items stored in the array increases and decreases as items are pushed or popped We must keep track of the current top of the stack Security with stacks Always test for full stack before pushing Always test for empty stack before popping If we use an array to model a spring-loaded stack of plates, it seems natural to let position 0 serve as the top of the stack. Let's suppose we have a stack of 8 elements, and we have pushed 70, 14, 57, 91, 21, 5, and 43:
Why are exceptions used in C++ programs? How are exceptions handled in C++? How can a main program be written to catch all exceptions a program might throw?
Exceptions: Indicate problems that occur during a program's execution Occur infrequently Exception handling Can resolve exceptions by: 1. Allowing a program to continue executing, or 2. Notifying the user of the problem and terminating the program in a controlled manner Makes programs robust and fault-tolerant Programs can Recover from exceptions Hide exceptions Pass exceptions up the "chain of command" Ignore certain exceptions and let someone else handle them Exception handling in C++ is similar to exception handling in java. Throw an exception if the situation is truly exceptional, and: The situation cannot be resolved in a reasonable manner Several resolutions exist and the client should choose the best one You detect a security issue that requires the program be halted immediately (in which case, you should throw a runtime exception)
Are recursive solutions efficient? Why or why not?
If program efficiency is essential, then it is worth the programmer's time to find an iterative solution Simulate recursion by creating a stack to keep track of all the values of local variables and parameters and the point of the call (like using the box trace method) This is tedious, and is often unnecessary, given the speed and memory capabilities of today's computers Another possibility: implement recursive solution on a computer that contains multiple processors If a function contains two recursive calls, start two other processors working on each of these calls, then put the answers together when tasks are complete In turn, each of those processors could start others, and so on, until all the calls had been completed CTP 25
What is recursive backtracking?
Many problems must be solved through careful trial-and-error (guesses) because no formula or other straightforward method exists The algorithm must be systematic and thorough, testing a uniform sequence of solutions without repeating any test Here is how it works: Make a guess at a solution If the guess leads to a dead end, then back up to that guess and make a different guess This technique of backing up when the guess doesn't work is called backtracking
Describe the 7 key themes in programming.
Modularity: dividing a program into separate software components (classes and methods) that should be cohesive (perform a single, clearly defined task) and loosely coupled (low interdependence, so changes within one component have little effect on other components). Modularity positively impacts: Constructing programs Debugging programs Reading programs Modifying programs Eliminating redundant code Good Style: Use constants for fixed values Use private data members in classes Use reference arguments properly Use methods properly Avoid global variables Check for and handle errors Use good program structure and design to improve readability Blank lines Indentation Automate documentation using Javadoc documentation comments Modifiability: Programs must be easy to modify Bug fixes Enhancements Ease of Use: Requests for user input must be very clear and precise Echo input and confirm as needed Output should be well labeled and easy to read Create a human / computer interface that is not just usable, but is userfriendly and convenient Fail-safe programming: Fail-safe programs will perform reasonably no matter how the program is used To create a fail-safe program: Test for invalid data Input values Parameter values Computed values Enforce preconditions Catch and respond to all exceptions Debugging: Systematically check program's logic to find where error occurs Tools to use while debugging: - Single-stepping - Watches - Breakpoints - cout statements Testing: Use all 4 levels of testing Unit testing Test each method independently Test each class independently Integration testing Test interactions among classes System testing Test entire application Performed by programmer who is not on development team Acceptance testing Show that system complies with requirements Conducted for customer, sometimes by customer Types:::: Open-box (white-box or glass-box) testing Test knowing the implementation Test all lines of code (decision branches, etc.) Often used for unit testing and integration testing Closed-box (black-box or functional) testing Test knowing only the specifications Often used for system testing and acceptance testing Developing test data Include boundary values Know expected results
Define software engineering and describe its benefits.
Quality of software is direct result of process we follow to create it IEEE definition of SE: Application of a systematic, disciplined, quantifiable approach to the development, operation, and maintenance of software NATO Science Committee definition of SE: Promoting the establishment of theoretical foundations and practical disciplines for software, similar to those found in the established branches of engineering Why Software Engineering? Software is costly $500 billion spent on software production in US each year $1 trillion spent on software production worldwide each year Cost of software rising 15% per year; cost of hardware decreasing As technology advances, software becomes increasingly complex Many software failures SE helps produce quality software Benefits of Using SE Techniques Proven techniques may be used to attack problem; programmers can avoid needless complexity and confusion The earlier an error is found, the cheaper it is to correct it Problems can be broken up into pieces (classes) and assigned to several people to speed up programming process Small classes are easier to understand, test and debug Fewer errors get into code, coding is speeded up, and maintenance is much easier and cheaper
What is the box trace method and why is it used?
When a function is called, execution always starts with the first statement of the function When a function ends, control returns to the statement where the call was made A Box Trace is a systematic way to trace the actions of a recursive function Each box roughly corresponds to an activation record which is automatically created on the run-time stack with each function call Activation record notes a function's local environment at the time of and as a result of the call to the function 1) Label each recursive call in the body of the recursive function. There may be several recursive calls, and it is important to distinguish between them. This will help you keep track of where to return after a function call completes. We will label the recursive calls using the letters, A, B, C, etc. 2) Represent each call to the function during the course of execution by a new box in which you note the function's local environment. Each box will contain: a) the value parameters of the formal parameter list b) the local variables c) a placeholder for the value returned by each recursive call from the current box (labeled to correspond to the labeling in step 1) d) the value of the function itself When you first create a box, you will know only the values of the parameters. The other items get filled in as you trace the execution. 3) Start by writing down the call that initiates the recursion. Create a box that represents that call, and draw an arrow from the call to the first box. Then, as you create new boxes during the tracing process for each recursive call, draw an arrow from the box that makes the call to the new box. As you draw the arrow, label it so you know which call created the box (using the labels you created in step 1.) 4) Trace the execution of the recursive subprogram, drawing a new box for each recursive call. Each reference to a function's local environment references the values in the current box, regardless of how the current box was generated. 5) On exiting the function, cross off the current box, and follow its arrow back to the box that called the function. This box is now the current box, and the label specifies the location in the function where you should continue tracing. If the recursive function returns a value, substitute the value returned by the just-terminated function call into the appropriate location in the current box.
List and describe the 5 features of object-oriented programming.
-Encapsulation: An object's data (attributes) and methods are combined into a single entity called a class Can be easily incorporated into different programs -Information Hiding: Details of how method or class performs its task(s) are hidden from rest of program -Inheritance: Acquire traits of one's predecessors Define a base class, or parent class, then define other classes (child classes or derived classes) derived from base class that inherits its properties, but has some additional properties of its own -Polymorphism: Ability to create multiple methods with same name that act differently when used with different objects Literally means many forms -Abstraction: Remove some characteristics of problem to reduce it to a set of essential characteristics Reduce complexity and increase efficiency Object is representation of original, with unwanted detail omitted
What four questions are asked when designing a recursive solution to ensure that it is a good solution?
1) How can you define the problem in terms of a smaller problem of the same type? 2) How does each recursive call diminish the size of the problem? 3) What instance of the problem can serve as the degenerate case? 4) As the problem size diminishes, will you reach this degenerate case?
What is a binary search tree (BST)? List and describe operations typically performed on a BST. Why is a BST useful?
A Binary Search Tree is a Binary Tree Requires the same operations Every node in a binary search tree has a key, for identification and comparison purposes Key values are typically unique Duplicates are allowable if it makes sense for the application, i.e. the order of the duplicates doesn't matter All keys in left subtree are smaller than (less than) the root key All keys in the right subtree are larger than (greater than) the root key The left and right subtrees are also binary search trees CTP 250 - Module 9 - Binary Trees Binary Search Trees Formal definition: a binary search tree is a set of nodes that obey the following three rules: 1. The tree is either empty or contains at least one node. 2. If the tree contains at least one node, then that node is linked to two disjoint subtrees, called the left and right subtrees of the node. Each of these subtrees is in turn a binary search tree. 3. The nodes in a left subtree contain item keys that are less in value than the root key. The nodes in a right subtree contain item keys that are greater in value than the root key.
What is a virtual method in C++? Why are virtual methods used?
A class is considered abstract if it contains one or more abstract (pure virtual) method In C++, an interface is an abstract class with only pure virtual methods. Hence, Interfaces are defined as an abstract class To declare a method as a pure virtual method, the keyword virtual is added to the beginning of the method and = 0 is placed at the end of the method header. The method is not implemented Subclass MUST provide implementation for all pure virtual methods in the abstract base class
Fully define a queue ADT, including both the definition and the operations.
A queue is a list of items one behind the other in which: Insertions are made at the back of the list Deletions and accesses are made at the front of the list Order is First In First Out (FIFO) Only the front item can be accessed; no information is available about any other item, except for the location of the last item Queues can model many things : Customers waiting in line in a bank or store Jobs waiting to be printed Planes waiting to take off at an airport Vehicles lined up at a toll booth Comparison of Stack and Queue Operations Note same task of isEmpty functions push and enqueue similar job pop and dequeue similar tasks Also peek and peekFront Differences are whether function manipulates front or back of ADT
Fully define a stack ADT, including both the definition and the operations.
A stack is an ordered collection of data items, one behind the other Items may be inserted and/or deleted only from one end, which is called the top of the stack Order is Last In First Out (LIFO) It is one-dimensional A stack can be used to model many things in real life: Plate holder in a cafeteria Cans in a row on a grocery shelf Books piled on your desk Graded assignments being returned The operations that can be performed on a stack include the following: Create an empty stack Determine if the stack is empty (contains no items) Push an item onto the stack (add an item) Pop an item from the stack (remove an item) Peek at what is currently on top of the stack (but don't change the stack) Determine if the stack is full (array implementation) Only the top item on the stack can be accessed; no information is available about the remainder of the stack The only way to count the number of items on a stack is to take each one off the top in turn and count it, doing so until the stack is empty
Fully define an ADT.
ADT: Collection of data values together with a set of operations on that data When defining the operations to be performed, it must be clear what the effect on the data will be Still not worrying about HOW to do it, but about WHAT will be done ADT specifies WHAT; data structure specifies HOW it will be implemented After ADT has been fully defined (during design), then it can be implemented by choosing a particular data structure Implementing ADT Once we understand the abstract concept, we will specify HOW we will implement the ADT Typically, no implementation can model the abstract concept exactly; we are limited by: Physical properties of the computer we are using Programming language we are using Must understand limitations of our actual implementation Often multiple ways to implement particular data structure; one specific implementation may be better for a specific application than another Data abstraction and information hiding are techniques used to implement an ADT Control how program interacts with its data structures Builds walls around data structures, so that other parts of program do not know how it is implemented Increases program security Implemented using a C++ class Separate method is created for each operation Methods for each operation can be thought of as black boxes Other parts of program know how to invoke these methods (they know the interface), but they do not know how they are implemented Implementation of data structure can be changed without affecting the remainder of the program (loose coupling) Implementation details are hidden behind a wall of ADT operations A program (client) can only access the data structure by using the ADT operations; cannot damage data structure
Fully define a list (linear list, ordered list) ADT, including both the definition and the operations.
Also called Linear List or Ordered List An ordered set of data items, one behind the other; sequential There is a first and last element Every element except the last has a unique successor Every element except the first has a unique predecessor Homogeneous (all elements are of the same data type) The ordering does not imply ascending or descending order, but it could be the order in which the data was input, or any other order One-dimensional; finite Examples of lists: list of groceries to purchase list of tasks that must be done list of appointments to keep list of students enrolled dean's list mailing list list of voters 1. Determine if the list is empty 2. Access an item on the list to examine and/or change its contents 3. Insert a new item into the list at a given position 4. Delete an item at a given position from the list 5. Make a copy of a list 6. Traverse the list, accessing and processing each element, in order 7. Determine the number of items in a list 8. Sort the items in the list into ascending or descending order, based on certain fields 9. Search the list for the occurrence of an item with a particular value in some field
What is a constructor? When is it executed in C++?
Called to create an object of a class type - called when the reference is declared
What is a copy constructor? Why is it necessary?
Copy Constructor CTP 250 - Module 6 - Stacks & Exceptions Since the default copy constructor creates a shallow copy, a copy constructor is needed for dynamic implementations to perform a deep copy The copy constructor
What is the difference between a data structure and an ADT?
Data structure: Computer manipulates large amounts of data Data must be organized and stored in order for a computer program to manipulate it A programmer uses data structures to organize and store data Data type - specifies the kind of information or data a variable may contain Data structure a collection of data objects and a set of legal operations to be performed on them typically implemented using a class ADT: ADT: Collection of data values together with a set of operations on that data When defining the operations to be performed, it must be clear what the effect on the data will be Still not worrying about HOW to do it, but about WHAT will be done ADT specifies WHAT; data structure specifies HOW it will be implemented After ADT has been fully defined (during design), then it can be implemented by choosing a particular data structure Implementing ADT Once we understand the abstract concept, we will specify HOW we will implement the ADT Typically, no implementation can model the abstract concept exactly; we are limited by: Physical properties of the computer we are using Programming language we are using Must understand limitations of our actual implementation Often multiple ways to implement particular data structure; one specific implementation may be better for a specific application than another Data abstraction and information hiding are techniques used to implement an ADT Control how program interacts with its data structures Builds walls around data structures, so that other parts of program do not know how it is implemented Increases program security Implemented using a C++ class Separate method is created for each operation Methods for each operation can be thought of as black boxes Other parts of program know how to invoke these methods (they know the interface), but they do not know how they are implemented Implementation of data structure can be changed without affecting the remainder of the program (loose coupling) Implementation details are hidden behind a wall of ADT operations A program (client) can only access the data structure by using the ADT operations; cannot damage data structure
What is a C++ destructor? When should it be used? When is it executed?
Destroys the object.
Define a full binary tree. Define a complete binary tree.
Full: A binary tree of height h with no missing nodes All leaves are at level h and all other nodes each have two children Complete: A binary tree of height h is complete if: It is full to level h - 1, and Level h is filled from left to right
Define inheritance. Describe the benefits of using inheritance. Describe the kinds of inheritance available in C++.
Inheritance A relationship among classes Allows a class to derive the behavior and structure of an existing class When a sub class overrides a method inherited from the base class, the compiler determines which version of the method to use A polymorphic method Has multiple meanings Overrides a method of the superclass Binding The association of a method with a particular class Early binding - selecting the method at compile time Late binding - selecting the method at runtime based upon the type of object
What is a circular linked list? What is a doubly linked list? What is a circular doubly linked list? Why is a dummy head node sometimes used?
Last node points to the first node Every node has a successor No node in a circular linked list contains nullptr Access to last node requires a traversal Solution: make external pointer point to last node instead of first node Can access both first and last nodes without a traversal Variations: Doubly Linked Lists Each node points to both its predecessor and its successor precede pointer and next pointer Insertions/deletions more involved than for a singly linked list Often has a dummy head node Circular doubly linked list with dummy head node precede pointer of dummy head node points to last node next pointer of last node points to dummy head node No special cases for insertions and deletions
What is operator overloading?
Operator overloading is a function where different operators are applied and depends on the arguments. Operator,-,* can be used to pass through the function , and it has their own precedence to execute.
What is recursive descent?
Parsing must be performed by compilers when the compiler is interpreting a program. The compiler must: Break the program up into its separate parts Make sure that the construction of the program is valid Translate the program into executable code A compiler must be able to recognize a number of different expressions, including arithmetic expressions The syntax rules of a language specify how basic constructs such as assignment statements and expressions are formed. These syntax rules are commonly stated as substitution rules or productions. Assume that we have the following rules for some simplified arithmetic expressions: 1) expression --> term + term | term - term | term 2) term --> factor * factor | factor / factor | factor 3) factor --> (expression) | letter | digit These rules are indirectly recursive expression is defined using term, term is defined using factor, but factor is defined using expression So, expression is defined indirectly in terms of itself Parse the expression 2 * (3 + 4) Rule 1: expression can be a term Rule 2: term can be: factor * factor Here is the partial parse tree: Apply rule 3: a factor can be a 2, and using rule 3 again, a factor can be an expression inside parentheses. So, we now have this parse tree: Apply rule 1 to evaluate expression inside the parentheses: To develop a compiler that enforces these rules, create 3 functions: check_for_expression, which applies rule 1 check_for_term, which applies rule 2 check_for_factor, which applies rule 3 this function calls check_for_expression Called recursive descent because the compiler parses large constructs by splitting them into smaller pieces, and then recursively parses each of the pieces Eventually, the compiler reaches the atomic components that cannot be split further and are directly evaluated
What is a pointer? How is a pointer declared in C++? What C++ operators are used to allocate and free memory?
Pointer: Computer memory can be visualized as a sequence of memory locations, each with a unique address Computer uses the address to access a value This is done indirectly when using ordinary variables Name of the variable refers to a particular address Instead, we can use the address directly to refer to a particular memory location Can store a value in a particular address Can retrieve the value by directly using its address Address is called a pointer Declare: int i; & is the "address of" operator &i refers to the address of I &i is a pointer Declare: int *ptr; ptr refers to the address where an int is stored; it is a pointer *ptr refers to the item pointed to by ptr We can make ptr point to i by using: ptr = &i; The integer called i can be referenced in 2 ways: by using i, or by using *ptr. This will output the value 15: i = 10; *ptr = 15; cout << i << endl;
Define a binary tree. Why is recursion often used when manipulating a binary tree?
Recursion is used to add a new node to a BST Algorithm: The assignment is done when the base case is reached and the method unwinds Base case: If the current root is empty, return the pointer to the new node for assignment Recursion: If the root is larger than the new item, the new item belongs on the left subtree. Call the method passing the left pointer as the root If the root is smaller than the new item, the new item belongs on the right subtree. Call the method passing the right pointer as the root
What is the difference between a static implementation and a dynamic implementation?
Static implementation: Remains fixed in size throughout program execution Memory is allocated when the variable is declared The same memory locations are used for that variable throughout program (or subprogram) execution Structure of variable or existence of variable cannot be changed during execution Example: array Dynamic: Dynamic Can change in size while the program is running Memory is: Allocated while the program is running Created when needed Returned when not needed Example: linked list
Define a template and explain why it is used in C++.
The C++ language uses templates to define generic data types. Templates generate class definitions based upon parameters from the client What is a template? The dictionary definition: a gauge, pattern, or mold (as a thin plate or board) used as a guide to the form of a piece being made In C++, a template can be used to: Create a family of functions that perform the same operation, but have different parameter types and/or different return types (Function Templates) Create a family of classes that operate on different data types; we will focus on this type of C++ template (Class Templates)
When is recursion a good choice for solving a problem?
Two factors contribute to the inefficiency of some recursive solutions: 1) The overhead associated with subprogram calls; can quickly eat up time because a single call to a recursive subprogram can generate many recursive calls 2) The inherent inefficiency of some recursive algorithms; some recursive algorithms repeatedly compute the same values However, recursion can greatly clarify complex programs, which often compensates for the additional overhead The true value of recursion is as a tool for solving problems for which there is no simple iterative solution Recursive solutions can be easier to understand, describe, and implement than iterative solutions In this age where a programmer's time is very expensive, it is often not worthwhile to laboriously develop a non-recursive solution when a problem is solved more naturally and more quickly using recursion If program efficiency is essential, then it is worth the programmer's time to find an iterative solution Simulate recursion by creating a stack to keep track of all the values of local variables and parameters and the point of the call (like using the box trace method) This is tedious, and is often unnecessary, given the speed and memory capabilities of today's computers Another possibility: implement recursive solution on a computer that contains multiple processors If a function contains two recursive calls, start two other processors working on each of these calls, then put the answers together when tasks are complete In turn, each of those processors could start others, and so on, until all the calls had been completed
How can a tree data structure be implemented without using pointers?
Uses an array of TreeNode objects Requires the creation of a free list that keeps track of available nodes
What is meant by traversing a tree? What is a pre-order traversal? an in-order traversal? a post-order traversal?
When working with structures such as a tree, we often need to perform an action on every member of the structure Example, printing the contents of the entire tree - each item in the tree must be displayed This process of going through the tree and performing a task for each and every member is called a "Traversal" operation Tree traversal is typically defined recursively At each node there are three things to do: visit the node traverse the left subtree traverse the right subtree The term 'visit' is used to denote an operation such as display, which is to be applied to each node of the tree CTP 250 - Module 9 - Binary Trees Binary Search Trees traversal operations Although there are many possible ways to traverse a binary tree, three ways are conventionally used: Preorder traversal: 1. Visit the node 2. Traverse the left subtree 3. Traverse the right subtree Inorder traversal: 1. Traverse the left subtree 2. Visit the node 3. Traverse the right subtree Postorder traversal: 1. Traverse the left subtree 2. Traverse the right subtree 3. Visit the node
What dynamic implementation is typically used for a stack or a queue? Fully describe how this implementation works. What operation is not usually required when a dynamic implementation is used?
linked list - not required to set the size of the ADT since the size can and will change dynamically
Define the following terms:tree root ancestor parent child subtree leaf descendant siblings degree level (Note: use the definition from the lecture, NOT the textbook definition.) height (Note: use the definition from the lecture, NOT the textbook definition.)
root node - points to 0
What is the degenerate or base case?
the case that stops the loop
Define recursion.
using a class to call itself to repeat an action