Abstract Data Types. Stack ADT. Stack Model LIFO

Size: px
Start display at page:

Download "Abstract Data Types. Stack ADT. Stack Model LIFO"

Transcription

1 Abstract Data Types Data abstraction consepts have been introduced in previous courses, for example, in Chapter 7 of [Deitel]. The Abstract Data Type makes data abstraction more formal. In essence, an abstract data type (ADT) consists of the following: A collection of data A set of operations on the data or subsets of the data A set of axioms, or rules of behavior governing the interaction of operations The ADT concept is similar and related to the classical systems of mathematics, where an entity (such as a number system, group, or field) is defined in terms of operations and axioms. The ADT is also closely related to set theory, and in fact could be considered a variant of set theory. The concepts of vector, list, and deque, introduced in earlier chapters, could also be described as ADTs. Before proceeding to our primary examples of ADTs, stack and queue, let's clarify the distinction between a data structure and an ADT. A data structure is an implementation. For example, Vector, List, and Deque are data structures. An abstract data type is a system described in terms of its behavior, without regard to its implementation. The data structures Vector, List, and Deque implement the ADTs vector, list, and deque, respectively. We return to the discussion of these ADTs later in this chapter. Within the context of C++ (or most other object oriented languages such as Java and Smalltalk), an abstract data type can be defined as a class public interface with the ADT axioms stated as behavior requirements. A data structure in this context is a fully implemented class, whether or not explicit requirements have been placed on its behavior it is what it is. Of course, we often do place requirements on behavior prior to implementation, as we did for Vector, List, and Deque. The C++ language standard, in fact, places behavior and performance requirements on all of the classes in the STL. Both of these examples (our class, and the C++ STL) have thus integrated ADT concepts into the software development process: start with an ADT and then design a data structure that implements it. Conversely, any proper class can in principle be analyzed, axiomatized, and used to define a corresponding ADT, which the class implements. In this chapter we will concentrate on the stack and queue ADTs: definition, properties, uses, and implementations. The stack and queue are arguably the most important, and certainly the most often encountered, ADTs in computer science. A final comment is critically important: without the third component, the definition of ADT is vacuous of significance. For example, note that the choices of operation names are inherently meaningless, and without axioms they have no constraints on their behavior. When you see the definitions of statck and queue, a little analysis should convince you that it is only the axioms that give meaning to, and distinguish between, the two concepts. Stack ADT The stack ADT operates on a collection comprised of elements of any proper type T and, like most ADTs, inserts, removes, and manipulates data items from the collection. The stack operations are traditionally named as follows: void push (T t) void pop () T top () bool empty () unsigned int size () constructor and destructor The stack ADT has the following axioms: 1. S.size(), S.empty(), S.push(t) are always defined 2. S.pop() and S.top() are defined iff S.empty() is false 3. S.empty(), S.size(), S.top() do not change S 4. S.empty() is true iff 0 = S.size() 5. S.push(t) followed by S.pop() leaves S unchanged 6. after S.push(t), S.top() returns t 7. S.push(t) increases S.size() by 1 8. S.pop() decreases S.size() by 1 These axioms can be used to prove, among other things, that the stack is unique up to isomorphism: Given any two stacks on the same data type, there is a one to one correspondence between their elements that respects the stack operations. Another way to state this fact is that the only possible difference between two stacks on the same data type is changes in terminology; the essential functionalities are identical. Stack Model LIFO 1/22

2 The stack models the behavior called "LIFO", which stands for "last in, first out", the behavior described by axioms 5 and 6. The element most recently pushed onto the stack is the one that is at the top of the stack and is the element that is removed by the next pop operation. The slide illustrates a stack starting empty (as all stacks begin their existence) and follows the stack through three push operations and one pop operation. Derivable Behaviors (Theorems) For the following theorems, assume that S is a stack of elements of type T. Theorem. If (n = S.size()) is followed by k push operations then n + k = S.size(). Proof. Note that stack axiom 7 states the theorem in the case k = 1. Suppose that the theorem is true for the case k. Then, if we push k + 1 elements onto S, axiom 7 again states that the size is increased by one from the size after k pushes, that is, from (n + k) to (n + k) + 1 = n + k + 1, completing the induction step. Therefore the theorem is proved, by the principle of mathematical induction. Corollary: The size of a stack is non negative. Proof. If the size of S is n < 0, then we obtain a stack of size 0 by pushing n elements onto S. But S is not empty by axiom 5. This contradicts axiom 4. Theorem. If (n = S.size()) is followed by k pop operations then n k = S.size(). Proof. (Left as an exercise for the student.) Corollary. k <= n; that is, a stack of size n can be popped at most n times without intervening push operations. Proof. The size of a stack cannot be negative. Theorem. The last element of S pushed onto S is the top of S. Proof. Actually, this reiterates axiom 6. Theorem. S.pop() removes the last element of S pushed onto S. Proof. By axiom 5, S.pop() does not remove anything that was on the stack prior to the last push operation. The only other possibility is that it removes the item added by the preceding push. Theorem. Any two stacks of type T are isomorphic. This last result is beyond the scope of this course. The proof is not difficult, but it would require the development of considerable apparatus, such as defining isomorphism, and the end the result would be is difficult to appreciate, beyond the intuitive level, without dwelling longer on the various implications of isomorphism. Therefore we will skip the proof. Another point that should be addressed, if we were starting a course in the theory of ADTs, is the independence of the axioms. The axioms listed for ADT stack were assembled to make it easy to prove theorems and to accept, at least intuitively, that they characterize stack as a type. It is possible that one of these axioms could be derived from the others, however. Uses of ADT Stack Stacks (and queues) are ubiquitous in computing. Stacks, in particular, serve as a basic framework to manage general computational systems as well as in supports of specific algorithms. All modern computers have both hardware and software stacks, the former to manage calculations and the latter to manage runtime of languages such as C++. We now discuss five of the archetypical applications of the stack ADT. A widely used search process, depth first search (DFS), is implemented using a stack. The idea behind DFS, using the context of solving a maze, is to continue down paths until the way is blocked, then backtrack to the last unattempted branch path, and continue. The process ends when a goal is reached or there are no unsearched paths. A stack is used to keep track of the state of the search, pushing steps onto the stack as they are taken and popping them off during backtracking. All modern general purpose computers have a hardware supported stack for evaluating postfix expressions. To use the postfix evaluation stack effectively, computations must be converted from infix to postfix notation. This translation is part of modern compilers and interpreters and uses a software stack. C++ uses a runtime system that manages the memory requirements of an executing program. A stack, called the 2/22

3 runtime stack, is used to organize the function calls in the program. When a function is called, an activation record is pushed onto the runtime stack. When the function returns, its activation record is popped. Among other things, this system makes it straightforward for a function to call itself just push another activation record onto the runtime stack. Stack based runtime systems thus facilitate the use of recursion in programs. Queue ADT The queue ADT operates on a collection comprised of elements of any proper type T and, like most ADTs, inserts, removes, and manipulates data items from the collection. We will break from tradition and use the following names for queue operations: void push (T t) void pop () T front () bool empty () unsigned int size () constructor and destructor The queue ADT has the following axioms: 1. Q.size(), Q.empty(), Q.push(t) are always defined 2. Q.pop() and Q.front() are defined iff Q.empty() is false 3. Q.empty(), Q.size(), Q.front() do not change Q 4. Q.empty() is true iff 0 = Q.size() 5. Suppose n = Q.size() and the next element pushed onto Q is t; then, after n elements have been popped from Q, t = Q.front() 6. Q.push(t) increases Q.size() by 1 7. Q.pop() decreases Q.size() by 1 8. If t = Q.front() then Q.pop() removes t from Q These axioms can be used to prove, among other things, that the queue is unique up to isomorphism: Given any two queues on the same data type, there is a one to one correspondence between their elements that respects the queue operations. Another way to state this fact is that the only possible difference between two queues on the same data type is changes in terminology; the essential functionalities are identical. Queue Model FIFO The queue models the behavior called "FIFO", which stands for "first in, first out", the behavior described by axiom 5. The element that has been on the queue the longest is the one that is at front of the queue and is the element that is removed by the next pop operation. The slide illustrates a queue starting empty (as all queues begin their existence) and follows the queue through four push and three pop operations. Derivable Behaviors (Theorems) For the following theorems, assume that Q is a queue of elements of type T. Theorem. If (n = Q.size()) is followed by k push operations then n + k = Q.size(). Proof. Apply mathematical induction using axiom 6. Theorem. If (n = Q.size()) is followed by k pop operations then n k = Q.size(). Proof. Apply mathematical induction using axiom 7. Corollary. k <= n; that is, a queue of size n can be popped at most n times without intervening push operations. Theorem. The first element pushed onto Q (of those still in Q) is the front of Q. Proof. Axiom 5 states that the youngest element on the queue requires size pop operations to be removed. It follows that all of the older elements are popped before the youngest. (The eskimo mafia rule: the older you are, the sooner you are popped.) Theorem. Q.pop() removes the front element of Q. Theorem. Any two queues of type T are isomorphic. 3/22

4 Proof. (Beyond our scope.) Uses of ADT Queue Queues (and stacks) are ubiquitous in computing. Queues, in particular, support general computing as buffers (essential for almost any conceivable I/O), are central to algorithms such as breadth first search, and are a key concept in many simulations. Just as ADT stack is embedded in the hardware of modern CPUs to support evaluation of expressions, ADT queue, in the form of buffers, is an essential component to virtually all computer based communication. Buffers facilitate transfer of data, making it unnecessary to synchronize send with recieve, without which every computation would be hopelessly I/O bound. ADT queue is a model of actual queues of people, jobs, and processes as well. Thus queues are a natural component of many simulation models of real processes, from fast food restaurents to computer operating systems. The BFS algorithm is detailed later in this chapter. Depth First Search (DFS) Backtracking The DFS algorithm applies to any graph like structure, including directed graphs, undirected graphs, trees, and mazes. The basic idea of DFS is "go deep" whenever possible but backtrack when necessary. GoDeep: If there is an unvisited neighbor (a location adjacent to the current location), go there. BackTrack: Retreat along the path to the most recently encountered location with an unvisited neighbor. The DFS algorithm initializes at the start location and repeats "if (possible) GoDeep else BackTrack" until there are no moves left or until the goal is encountered. Our version of DFS is single goal oriented. Another version is oriented toward visiting every location, and consists of applying the goal oriented version repeatedly at every unvisited location until all locations have been visited. See Chapter VI of [Cormen]. DFS Backtracking (cont.) A stack of locations is a convenient way to organize DFS. This slide depicts a setup for DFS consisting of a graph, a starting vertex, a goal vertex, and a stack. The contents of the stack during the run of the DFS algorithm are also shown. The following is a pseudo code version of the stack based DFS algorithm. Assumptions: G is a graph with vertices start and goal. Body: DFS stack<locations> S; mark start visited; S.push(start); While (S is not empty) t = S.top(); if (t == goal) Success(S); return; if (t has unvisited neighbors) choose a next unvisited neighbor n; mark n visited; S.push(n); else BackTrack(S); 4/22

5 Failure(S); BackTrack(S) while (!S.empty() && S.top() has no unvisited neighbors) S.pop(); Success(S) cout << "Path from " << goal << " to " << start << ": "; while (!S.empty()) output (S.top()); S.pop(); Failure(S) cout << "No path from " << start << " to " << goal; while (!S.empty()) S.pop(); Outcome. If there is a path in G from start to goal, DFS finds one such path. Proof. We use mathematical induction on the number n of vertices in G. Base case (n = 1). If G has only one vertex, it must be both start and goal. There is a path, and that path is discovered by the algorithm by looking at S.top() immediately after initialization with S.push(start). Induction step. Assume that the result is true for any graph of size less than n, and consider our given graph G of size n. Suppose that there is a path in G from start to goal. Let H be the subgraph of G obtained by removing goal and the edges incident to goal. Note that H contains all vertices of G except goal, and all but the last edge of the known path from start to goal. The induction hypothesis implies that DFS finds a path in H from start to the end of this truncated path, a neighbor of goal. This neighbor of goal is thus at the top of S at the point of successfully finding this path. The algorithm runs in exactly the same way on G, either finding a path involving a different neighbor of goal or arriving at the state with a neighbor of goal at the top of S. Since goal is an unvisited neighbor of the top of S, the algorithm pushes goal onto S before any more backtracking can occur. The next cycle of the loop discovers goal at the top of S. It remains to show that the contents of the stack form a path from start to goal. Note that each time a vertex is pushed onto S, it is a neighbor of the top of S. Thus the contents of S do form a path from the bottom (start) to the top (goal). Breadth First Search (BFS) If DFS is "go deep" then BFS is "go wide". We could compare the two by solving mazes. DFS solves a maze as a single person might: search as far down a path as possible, and when blocked, retreat to the first place from which the search can continue. Stop when the goal is found or the possibilities are exhausted. BFS, on the other hand, solves a maze using a committee. The committee starts out together. Every time there is a fork in the maze, the committee breaks into subcommittees and sends a subcommittee down each path of the fork. The first subcommittee arriving at the goal blows a whistle, or else the process continues until all possibilities have been exhausted. Note that the committee arriving at the goal first has found the shortest path solving the maze, and the length of this path is the distance from the start to the goal. BFS (cont.) 5/22

6 A queue of locations is a convenient way to organize BFS. This slide depicts a setup for BFS consisting of a graph, a starting vertex, a goal vertex, and a queue. The contents of the queue during the run of the BFS algorithm are also shown. The following is a pseudo code version of the queue based BFS algorithm. Assumptions: G is a graph with vertices start and goal. Body: BFS queue<locations> Q; mark start visited; Q.push(start); While (Q is not empty) t = Q.front(); for each unvisited neighbor n of t Q.push(n); if (n == goal) Success(S); return; Q.pop(); Failure(Q); Success() // must build solution using backtrack pointers Outcome. If there is a path in G from start to goal, BFS finds a shortest such path. This version of BFS, like DFS above, is goal oriented. A broader version that searches an entire graph is discussed very thoroughly in Chapter VI of [Cormen], including proofs of correctness and runtime analysis. The algorithm above would need some embellishment to keep track of data, depending on the desired outome. We postpone further analysis of BFS and DFS to COP Evaluating Postfix Expressions Algorithm The process of evaluating expressions is an important part of most computer programs, and typically breaks into two distinct steps: 1. Translation of infix expression to postfix expression 2. Evaluation of postfix expression The first step is usually accomplished in software, either compiler or interpreter. The second step is usually accomplished with significant hardware support. However, both of these steps are facilitated with the stack ADT. We discuss the evaluation algorithm here, and discuss the translation algorithm after introducing our stack implementation later in this chapter. Both translation and evaluation use the concept of token. A token is an atomic symbol in a computer program or computation. For example, the code fragment int num1, num2; cin >> num1; num2 = num1 + 5; my_function(num2); contains the following stream of tokens (written vertically for clarity): int num1, num2 ; 6/22

7 cin >> num1 ; num2 = num1 + 5 ; my_function ( num2 ) ; and for the expression z = 25 + x*(y 5) the token stream is z = 25 + x * ( y 5 ) The postfix evaluation algorithm is described in the following pseudo code: Evaluate(postfix expression) uses stack of tokens; while (expression is not empty) t = next token; if (t is operand) push t onto stack else // t is an operator pop operands for t off stack; evaluate t on these operands; push result onto stack; // at this point, there should be exactly one operand on the stack return top of stack; Evaluating Postfix Expressions Example The slide illustrates the evaluation algorithm applied to the expression * which is the postfix translate of the prefix expression 1 + (2 + 3) * The stack operations and the stack state after each operation are shown. 7/22

8 Runtime Stack and Recursion Most modern programming languages use a runtime environment that includes a runtime stack of function activation records and a runtime heap where dynamic allocation and de allocation of memory is managed. (The latter may be automated by a garbage collection system a slow, but programmer friendly, memory management system.) As a C++ executable is loaded, a set of contiguous memory addresses is assigned to it by the operating system. This interval [bottom, top] of addresses is the address space assigned to the running program. The address space is organized as follows: [static stack >... < heap] where '[' denotes the bottom of the address space and ']' denotes the top. The static area is a fixed size and contains such things as the executable code for all program functions, locations for global variables and constants, and a symbol table in which identifiers are matched with addresses (relative to '['). The stack and heap are dynamic in size. The stack grows upward in address space and the heap grows downward. If the stack and heap collide, then memory allocated to the program has been used up and the program crashes. (With virtual memory addressing and no limits set for the program, such a crash is "virtually" impossible. But without virtual memory, or with memory limits set, this kind of crash can and often does occur.) The stack is the mechanism by which the runtime state of the program is maintained. The stack element type is AR or activation record. An activation record contains all essential information about a function, including: function name, location of function code, function parameters, function return value, and location where control is returned (location of function call). In C/C++, execution begins by pushing the activation record of main() onto the newly created stack. For every function call, a new activation record is pushed onto the runtime stack. Thus the top of the stack is always a record of the currently running function. Whenever a function returns, its activation record is popped off the stack and control is returned to the calling process (whose activation record is now at the top of the stack). Execution ends when main() returns and the stack is popped to the empty state. The runtime stack requires no restriction on which function activation records may be used at any given point in an executing program. In particular, there is no reason not to permit the same function to be activated twice or more in succession. This innocuous observation is the basis for languages such as C++ to implement recursion. In the context of programming, recursion is the phenomenon of a function calling itself as in the implementation int fib (int n) if (n <= 0) return 0; if (n == 1) return 1; return fib(n 2) + fib(n 1); or a finite sequence of functions each calling the next until the last calls the first, as in the implementation int F (int n) if (n <= 0) return 1; return G(n); int G (int n) return n * F(n 1); The number of functions involved in the circular chain of calls is the order of the recursion. (The first example above is order one recursion and the second is order two recursion.) Recursion and recursive programming are important topics to which we return in a later chapter. Adaptor Classes We will implement the ADTs stack and queue using adaptor classes. An adaptor class is a class that uses an object of another class as its primary resource for both data storage and functionality. The adaptation pattern would be something like the following: 8/22

9 class X private: Y y; public: X() : y() void F() y.f(); int G() return y.g(); ; where X is the adaptor class and Y is the adaptee class. The X methods are defined in terms of similarly named Y methods. Typically, X may present a simpler, less elaborate interface than that of Y, often focussed on a particular application or ADT. Stack and Queue Adaptor Requirements The basic implementation plan for stack and queue is to use existing structures such as Deque, List, and Vector appropriately modified via an adaptor class. To implement stack, we need a push/pop pair at the same end of the structure, and for queue we need a push/pop pair at opposite ends. To be able to use Vector for stack, we will use PushBack/PopBack to implement stack (because Vector does not have Push/Pop at the front). We will use PushBack/PopFront to implement queue. Thus Deque, List, and Vector will support stack, while only Deque and List will support queue. The slide shows the container class methods that we will adapt for use in defining the stack and queue adaptor classes. For example, suppose we have a private Deque<T> object D. Then the Pop() method could be implemented for stack and queue as and template <typename T> void stack::pop() D.PopBack(); template <typename T> void queue::pop() D.PopFront(); respectively. We can continue along this path and develop template stack and queue classes as adaptor classes for deques. The following are complete implementations using this plan: template <typename T> class Stack private: Deque<T> d; public: void Push (const T& t) d.pushback (t); void Pop () d.popback () ; T& Top () return *d.back () ; const T& Top () const return *d.back () ; // const version bool Empty () const return d.empty () ; int Size () const return d.size () ; ; // note that the const version of Top() calls the const version of d.back() template <typename T> class Queue private: Deque<T> d; public: 9/22

10 void Push (const T& t) d.pushback (t); void Pop () d.popfront () ; T& Front () return *d.front () ; const T& Front () const return *d.front () ; // const version bool Empty () const return d.empty () ; int Size () const return d.size () ; ; // note that the const version of Front() calls the const version of d.front() If a client desired to change the underlying container being adapted by TStack and TQueue, another set of adaptor classes could be defined, repeating the code above. There would also need to be some naming strategy to avoid conflicts, for example, DequeStack, VectorStack, and ListStack indicating stacks adapted from Deque, Vector, and List, respectively. We show in the next section how to avoid this repetitive definition problem using a different template parameter. Stack <T,C> We can add a second template parameter to designate a container type upon which we adapt the stack interface, as follows: template <typename T, class Container> class Stack protected: Container c_; public: typedef T ValueType; // assumption: T and Container::ValueType are the same type void Push (const ValueType& t) c_.pushback(t); void Pop () c_.popback(); // Precondition:!Empty() ValueType& Top () return c_.back(); // Precondition:!Empty() const ValueType& Top () const return c_.back(); // const version bool Empty () const return c_.empty(); unsigned int Size () const return c_.size(); void Clear () c_.clear(); ; // the const version of Top() calls the const version of c_.back() We will describe the template parameter with the keyword class instead of the keyword typename when the parameter is intended to represent a specific kind of class rather than the more general, proper type. While it is not necessary, we will also follow the STL convention and retain the typename for the elements as an explicit parameter. This makes a somewhat more readable application, and also opens the possibility of allowing the container parameter to have a default value. Thus we have now two template parameters: (1) the type of the elements of the stack and (2) the type of container on which the stack is built. It is startling that this rather audacious idea actually works. Two features of the template class definition are critical: The terminology support (typedef statement) The standardization of container class method names and syntax Template library terminology support generally consists of typedef statements that create class scope aliases that adhere to a set of standard terms, the most common being Iterator and value_type. (Both of these terms are supported by List, Vector, and Deque.) Because Stack and Queue have no iterators, there is only the need to support value_type in these cases. The C++ keyword typename is used to disambiguate the following identifier which, because it contains a scope resolution operator, could otherwise be misconstrued to mean a static class member rather than a type. Note that both of these are characteristic features of the system we have built. The kind of interoperability implied by the definition of Stack is achieved by adhering to a set of patterns of definition in our growing template library. To create a stack, the user first selects (1) an underlying container for the stack, (2) a typename for the element type of the stack, and (3) a name for the stack. For example, the user might want a List based stack of floating point numbers and name floatstack. Then the declaration would be: Stack < float, List < float > > floatstack; 10/22

11 (ignoring namespaces). Then floatstack can be used as a stack in the surrounding client program. (Note that the spacing between two '>' is necessary so as not to confuse the compiler with a misplaced right shift operator.) The practical affect of terminology support is to give clients access to the underlying element type of the container, as illustrated in the return type of Top(). Omitted from the slide are the following implementation of Display() and its use in overloading the output operator for Stack. The Display() method is provided because Stack<> has no iterator type to facilitate output of queue contents. template < typename T, class C > void Stack <T,C>:: Display(std::ostream& os, char ofc) const typename C::Iterator I; if (ofc == '\0') for (I = c_.begin(); I!= c_.end(); ++I) os << *I; else for (I = c_.begin(); I!= c_.end(); ++I) os << *I << ofc; template < typename T, class C > std::ostream& operator << (std::ostream& os, const Stack<T,C>& s) s.display(os); return os; Finally, a comment on the Stack constructor. It should not be necessary to have an explicit constructor here. The default constructor should automatically instantiate the data object Container c in the class. Some compilers have not been successful at this instantiation without the explicit call to the C constructor made in the initialization list shown. Queue <T,C> The slide shows an abbreviated version of this Queue adaptor template: template <typename T, class Container> class Queue protected: Container c_; public: typedef T ValueType; // assumption: T and Container::ValueType are the same type void Push (const ValueType& t) c_.pushback(t); void Pop () c_.popfront(); // Precondition:!Empty() ValueType& Front () return c_.front(); // Precondition:!Empty() const ValueType& Front () const return c_.front(); // const version bool Empty () const return c_.empty(); unsigned int Size () const return c_.size(); void Clear () c_.clear(); ; // the const version of Front() calls the const version of c_.front() The general remarks made above for Stack apply equally to Queue. In fact these two sitiuations are so similar it may be helpful to call attention to the differences: Pop() is implemented as PopFront() for Queue and as PopBack() for Stack Queue::Front() replaces Stack::Top() and these draw from opposite ends of the underlying container Omitted from the slide are the following implementation of Display() and its use in overloading the output operator for Stack. The Display() method is provided because Queue<> has no iterator type to facilitate output of queue contents. template < typename T, class C > void Queue <T,C>:: Display(std::ostream& os, char ofc) const 11/22

12 typename C::Iterator I; if (ofc == '\0') for (I = c_.begin(); I!= c_.end(); ++I) os << *I; else for (I = c_.begin(); I!= c_.end(); ++I) os << *I << ofc; template < typename T, class C > std::ostream& operator << (std::ostream& os, const Queue<T,C>& q) q.display(os); return os; Example Usage Testing Stack and Queue We will explore three examples of actual use of Stack and Queue: (1) functionality testing the two containers, (2) using Queue to test performance of Vector, Deque, and List, and (3) implementing the infix to postfix translation algorithm. First the testing. Functionality testing Stack and Queue Two functionality test programs, fstack.cpp and fqueue.cpp, are supplied. (See the tests directory in the code library.) Each of these provides a way to change the element type between char and String and to change to any of the appropriate supporting containers. For reference here is the code for fstack.cpp: /* */ ftstack.cpp functionality test of Stack < ValueType, ContainerType > #include <iostream> #include <stack.h> bool BATCH = 0; // choose one from group A // A1: makes stacks of char typedef char ValueType; ValueType fill = ' '; const size_t maxsize = 10; const char* vt = "char"; const char ofc = '\0'; // end A1 */ /* // A2: makes stacks of String #include <xstring.cpp> typedef fsu::string ValueType; ValueType fill = "*"; const size_t maxsize = 100; const char* vt = "String"; const char ofc = ' '; // end A2 */ /* // A3: makes stacks of int typedef int ValueType; ValueType fill = 0; const size_t maxsize = 100; const char* vt = "int"; const char ofc = ' '; // end A2 */ 12/22

13 // ===================== // ===== group B ======= // ===================== // B1: makes vector based stacks #include <vector.h> typedef fsu::vector < ValueType > ContainerType; const char* ct = "Vector"; // end B1 */ /* // B2: makes dequeue based stacks #include <deque.h> typedef fsu::deque < ValueType > ContainerType; const char* ct = "Deque"; // end B2 */ /* // B3: makes list based stacks #include <list.h> typedef fsu::list < ValueType > ContainerType; const char* ct = "List"; // end B3 */ void DisplayMenu(); template < typename T, class C > void CopyTest(fsu::Stack<T,C> s) std::cout << "CopyTest:\n"; std::cout << "Copied object size: " << s.size() << '\n' << " contents: "; s.display(std::cout, ofc); std::cout << '\n'; template < typename T, class C > void AssignTest(const fsu::stack<t,c>& s) fsu::stack<t,c> s1; s1 = s; std::cout << "AssignTest:\n"; std::cout << "Original object size: " << s.size() << '\n' << " contents: "; s.display(std::cout, ofc); std::cout << '\n'; std::cout << "Assignee object size: " << s1.size() << '\n' << " contents: "; s.display(std::cout, ofc); std::cout << '\n'; s1.push(s.top()); // OK: s1 is not const // s.push(s1.top()); // Error: s is const s1.top() = s.top(); // OK: non const = const // s.top() = s1.top(); // Error: const = non const int main() std::cout << "This is a Stack < " << vt << ", " << ct << " < " << vt << " > > test program\n"; DisplayMenu(); fsu::stack < ValueType, ContainerType > q; ValueType Tval; char option; do std::cout << "Enter [command][argument] ('M' for menu, 'Q' to quit): "; std::cin >> option; if (BATCH) std::cout << option; switch (option) 13/22

14 case '=': // CC and = if (BATCH) std::cout << '\n'; CopyTest(q); AssignTest(q); break; case '+': // void Push(T) std::cin >> Tval; if (BATCH) std::cout << Tval << '\n'; q.push(tval); break; case ' ': // void Pop() if (BATCH) std::cout << '\n'; if (!q.empty()) q.pop(); else std::cout << "Stack is empty\n"; break; case 'c': case 'C': // void clear() if (BATCH) std::cout << '\n'; q.clear(); break; case 't': case 'T': // T Top() if (BATCH) std::cout << '\n'; if (!q.empty()) Tval = q.top(); std::cout << "Top of Stack: " << Tval << '\n'; else std::cout << "Stack is empty\n"; break; case 'e': case 'E': // int Empty() if (BATCH) std::cout << '\n'; std::cout << "Stack is "; if (!q.empty()) std::cout << "not "; std::cout << "empty\n"; break; case 's': case 'S': // size_t Size() if (BATCH) std::cout << '\n'; std::cout << "Stack size = " << q.size() << '\n'; break; case 'd': case 'D': // display contents of stack if (BATCH) std::cout << '\n'; std::cout << "Stack contents: "; q.display(std::cout,ofc); std::cout << '\n'; break; case 'm': case 'M': // display menu if (BATCH) std::cout << '\n'; DisplayMenu(); break; case 'q': case 'Q': case 'x': case 'X': if (BATCH) std::cout << '\n'; 14/22

15 option = 'q'; break; default: if (BATCH) std::cout << '\n'; std::cout << "** Unrecognized command please try again.\n"; while (option!= 'q'); std::cout << "\nhave a nice day." << std::endl; return EXIT_FAILURE; void DisplayMenu() std::cout << "Push(Tval)... +\n" << "Pop()... \n" << "Clear()... C\n" << "Top()... T\n" << "Empty()... E\n" << "Size()... S\n" << "Copies... =\n" << "Display entire stack... D\n" << "Display this menu... M\n"; Performance Testing Several related issues may be investigated using performance testing, including the relative efficiency of various implementations of stacks and queues. Performance testing in this context is relative: we set up a fair test of two or more different data structures, run the test for each data structure, and keep track of the time required for each to complete the test. Faster completion times mean more efficient implementations in terms of runtime. To set up such a test, we need a notion of timer and a notion of side by side comparison of competing implementations. /* dragstrip.h Definition of DragStrip, a framework for measuring and comparing runtime for two classes DS1, DS2 [typically, these are container classes "DS" is for "Data Structure"]. */ DrapStrip3 is for comparing 3 different classes DS1, DS2, DS3 DrapStrip4 is for comparing 4 different classes DS1, DS2, DS3, DS4... #ifndef _DRAGSTRIP_H #define _DRAGSTRIP_H #include <timer.h> #include <xran.h> #include <timer.cpp> // in lieu of makefile #include <xran.cpp> // in lieu of makefile namespace dragstrip /* DragStrip2 */ template <class DS1, class DS2, class RandomClass> class DragStrip public: DragStrip (); virtual ~DragStrip (); void RunTest (unsigned long numtrials); virtual void Trial1 (unsigned long numtrials) = 0; 15/22

16 virtual void Trial2 (unsigned long numtrials) = 0; DS1 DS2 fsu::timer RandomClass fsu::random_int fsu::instant double ds1_; ds2_; clock_; ranobj_; ranint_; time1_, time2_; // defined in xtime.h rate1_, rate2_; // trials/msec private: DragStrip (const DragStrip& ); DragStrip& operator = (const DragStrip& ); ; template <class DS1, class DS2, class RandomClass> DragStrip<DS1,DS2,RandomClass>::DragStrip() : ds1_(), ds2_(), ranobj_(), ranint_(), time1_(), time2_(), rate1_(0.0), rate2_(0.0), clock_() std::cout << "event clock started" << std::endl; template <class DS1, class DS2, class RandomClass> DragStrip<DS1,DS2,RandomClass>::~DragStrip() std::cout << "event clock stopped with alive time " << clock_.alivetime() << std::endl; template <class DS1, class DS2, class RandomClass> void DragStrip<DS1,DS2,RandomClass>::RunTest(unsigned long numtrials) std::cout << "starting event 1" << std::endl; clock_.splitreset(); Trial1(numtrials); time1_ = clock_.splittime(); std::cout << "event 1 stopped with split time " << time1_ << std::endl; std::cout << "starting event 2" << std::endl; clock_.splitreset(); Trial2(numtrials); time2_ = clock_.splittime(); std::cout << "event 2 stopped with split time " << time2_ << std::endl; double msec; msec = ((double)time1_.sec_) * ((double)time1_.usec_) / ; rate1_ = ((double)numtrials) / msec; msec = ((double)time2_.sec_) * ((double)time2_.usec_) / ; rate2_ = ((double)numtrials) / msec; /* DragStrip3 */... // namespace fsu #endif /* timer.h Defining classes Instant and Timer These support the timing of processes using the unix clock. The metaphor is that of a stopwatch in a sports context: events start and stop, and split 16/22

17 */ times can be gathered between intermediate points between start and stop. #ifndef _TIMER_H #define _TIMER_H #include <iostream.h> // Instant is a gussied up version of Unix/C struct timeval; see XTime.cpp class Instant public: Instant& operator += (const Instant& i2); Instant& operator = (const Instant& i2); Instant& operator = (const Instant& i2); Instant (); Instant (long s, long u); Instant (const Instant& i); void write_mseconds (ostream& os, int p = 0) const; // msec as float void write_seconds (ostream& os, int p = 0) const; // sec as float void write_minutes (ostream& os, int p = 0) const; // min as float void write_hours (ostream& os, int p = 0) const; // hrs as float void write_time (ostream& os, int p = 0) const; // hrs:mins:secs void normalize (); ; long sec, usec; // seconds // microseconds == sec/ Instant operator + (const Instant& i1, const Instant& i2); Instant operator (const Instant& i1, const Instant& i2); int operator == (const Instant& i1, const Instant& i2); int operator!= (const Instant& i1, const Instant& i2); int operator < (const Instant& i1, const Instant& i2); int operator <= (const Instant& i1, const Instant& i2); int operator > (const Instant& i1, const Instant& i2); int operator >= (const Instant& i1, const Instant& i2); ostream& operator << (ostream& os, const Instant& i); istream& operator >> (istream& is, Instant& i); class Timer public: Timer(); // the default copy constructior, assignment and destructor will work fine ; Instant alive_time(); Instant event_time(); Instant split_time(); void event_reset(); void split_reset(); private: // data const Instant birth_t; Instant event_t, split_t, curr_t; #endif // get current time static Instant gettime(); /* qrace.cpp 17/22

18 Runtime contest among Queue<Vector<>>, Queue<Deque<>>, Queue<RingBuff<>>, Queue<List<>> Uses the dragstrip framework Uses specific definitions of trials in qtriala.cpp and qtrialb.cpp */ qtriala.cpp: unlimited random operations qtrialb.cpp: random selection of sequences of repeated ops, weighted to pop/push away from max/min #include <iostream> #include <dragstrp.h> #include <deque.h> #include <list.h> #include <vector_nonstd.h> #include <ringbuff.h> #include <queue.h> namespace dragstrip const unsigned long numtrials = ; const unsigned int max_size = 2000; const unsigned int min_size = 500; const unsigned int streak_length = 20; typedef fsu::queue < char, alt::vector < char > > DS1; const char* DS1name = "Queue < char, alt::vector < char > >"; typedef fsu::queue < char, fsu::deque < char > > DS2; const char* DS2name = "Queue < char, fsu::deque < char > >"; typedef fsu::queue < char, fsu::list < char > > DS3; const char* DS3name = "Queue < char, fsu::list < char > >"; typedef fsu::queue < char, fsu::ringbuffer < char > > DS4; const char* DS4name = "Queue < char, fsu::ringbuffer < char > >"; typedef fsu::random_letter random_class; class Race : public dragstrip::dragstrip4 <DS1, DS2, DS3, DS4, random_class> public: Race(); virtual void Trial1 (unsigned long numtrials); virtual void Trial2 (unsigned long numtrials); virtual void Trial3 (unsigned long numtrials); virtual void Trial4 (unsigned long numtrials); ; Race::Race() : DragStrip4 <DS1, DS2, DS3, DS4, random_class> () // namespace dragstrip int main() dragstrip::race race; race.runtest(dragstrip::numtrials); std::cout << std::fixed << std::setprecision(4) << "After " << dragstrip::numtrials << " trials,\n" << dragstrip::ds1name << " speed == " << race.rate1 << " trials/msec\n" << dragstrip::ds2name << " speed == " << race.rate2 << " trials/msec\n" << dragstrip::ds3name << " speed == " << race.rate3 << " trials/msec\n" << dragstrip::ds4name << " speed == " << race.rate4 << " trials/msec\n"; return 0; 18/22

19 // #include "qtriala.cpp" #include "qtrialb.cpp" xi[~]>qrace4.x event clock started starting event 1 event 1 stopped with split time 0:2:57.02 starting event 2 event 2 stopped with split time 0:0:15.78 starting event 3 event 3 stopped with split time 0:0:22.85 After trials, Queue < Vector < char > > speed == ops/msec Queue < Deque < char > > speed == ops/msec Queue < List < char > > speed == ops/msec event clock stopped with alive time 0:3:35.66 xi> Converting Infix to Postfix /* in2post.cpp */ convert infix expression to postfix expression this example only works for single letter operands #include <iostream> #include <queue.h> #include <stack.h> const unsigned int colsize = 25; class token // an operator, a parenthesis, or an operand friend std::ostream& operator << (std::ostream& os, token& t) os << t.ch; return os; friend int operator == (token t1, token t2) return t1.ch == t2.ch; friend int operator!= (token t1, token t2) return t1.ch!= t2.ch; friend int operator >= (token t1, token t2); // operator precedance NOT a total ordering friend int operator <= (token t1, token t2) return (t2 >= t1); friend int operator < (token t1, token t2) return (t2 >= t1 && t1!= t2); 19/22

20 friend int operator > (token t1, token t2) return (t2 > t1); public: int Operator (); // am I an operator? unsigned char ch; ; // class token int operator >= (token t1, token t2) int returnval = 0; if (t1.ch == t2.ch) returnval = 1; else switch (t1.ch) case '*': case '/': case '%': switch (t2.ch) case '+': case ' ': returnval = 1; break; break; return returnval; // end operator >=() int token::operator () int returnval = 0; if (ch == '+' ch == ' ' ch == '*' ch == '/' ch == '%') returnval = 1; return returnval; // end Operator() typedef fsu::queue < token > tokenqueue; typedef fsu::stack < token > tokenstack; void DisplayHeader (std::ostream& os = std::cout) unsigned int i; os << "S"; for (i = 0; i < colsize 1; ++i) os << ' '; os << "Q1"; for (i = 0; i < colsize 2; ++i) os << ' '; os << "Q2\n"; os << " "; for (i = 0; i < colsize 2; ++i) os << ' '; os << " "; for (i = 0; i < colsize 2; ++i) os << ' '; os << " \n"; // end DisplayHeader() void Display (tokenstack& S, tokenqueue& Q1, tokenqueue& Q2, std::ostream& os = std::cout) unsigned int i; if (!S.Empty()) os << S; for (i = 0; i < colsize S.Size(); ++i) os << ' '; else os << "NULL"; for (i = 0; i < colsize 4; ++i) os << ' '; if (!Q1.Empty()) 20/22

21 os << Q1; for (i = 0; i < colsize Q1.Size(); ++i) os << ' '; else os << "NULL"; for (i = 0; i < colsize 4; ++i) os << ' '; if (!Q2.Empty()) os << Q2; else os << "NULL"; os << std::endl; // end Display() int i2p (tokenqueue & Q1, tokenqueue & Q2) // converts infix expression in Q1 to postfix expression in Q2 token L, R; L.ch = '('; R.ch = ')'; tokenstack S; Q2.Clear(); DisplayHeader(); Display(S, Q1, Q2); while (!Q1.Empty()) if (Q1.Front() == L) // push '(' to mark beginning of a parenthesized expression S.Push(Q1.Front()); Q1.Pop(); Display(S, Q1, Q2); else if (Q1.Front().Operator()) // pop previous operators of equal or higher precedence to output while (!S.Empty() && S.Top() >= Q1.Front()) Q2.Push(S.Top()); S.Pop(); Display(S, Q1, Q2); // then push new operator onto stack S.Push(Q1.Front()); Q1.Pop(); Display(S, Q1, Q2); else if (Q1.Front() == R) // regurgitate operators for the parenthesized expression while (!S.Empty() &&!(S.Top() == L)) Q2.Push(S.Top()); S.Pop(); Display(S, Q1, Q2); if (S.Empty()) // unbalanced parentheses std::cout << "** error: too many right parens\n"; return 0; S.Pop(); // discard '(' 21/22

22 Q1.Pop(); // discard ')' Display(S, Q1, Q2); else // t should be an operand // send operand directly to output Q2.Push(Q1.Front()); Q1.Pop(); Display(S, Q1, Q2); // end while() // regurgitate remaining operators while (!S.Empty()) if (S.Top() == L) // unbalanced parentheses std::cout << "** error: too many left parens\n"; return 0; Q2.Push(S.Top()); S.Pop(); Display(S, Q1, Q2); return 1; // end i2p() int main() char c; tokenqueue Q1, Q2; token t; while(1) std::cout << "Enter infix expression (0 to quit): "; std::cin.get(c); if (c == '0') break; while (c!= '\n') t.ch = c; Q1.Push(t); std::cin.get(c); std::cout << '\n'; if (i2p(q1, Q2)) std::cout << "\n postfix conversion: " << Q2 << std::endl; else std::cout << "\n** syntax error in infix expression" << std::endl; // end while() return 0; 22/22

Abstract Data Types. Stack ADT

Abstract Data Types. Stack ADT Abstract Data Types Data abstraction consepts have been introduced in previous courses, for example, in Chapter 7 of [Deitel]. The Abstract Data Type makes data abstraction more formal. In essence, an

More information

Data Structures and Algorithms

Data Structures and Algorithms Data Structures and Algorithms Alice E. Fischer Lecture 6: Stacks 2018 Alice E. Fischer Data Structures L5, Stacks... 1/29 Lecture 6: Stacks 2018 1 / 29 Outline 1 Stacks C++ Template Class Functions 2

More information

IV. Stacks. A. Introduction 1. Consider the 4 problems on pp (1) Model the discard pile in a card game. (2) Model a railroad switching yard

IV. Stacks. A. Introduction 1. Consider the 4 problems on pp (1) Model the discard pile in a card game. (2) Model a railroad switching yard IV. Stacks 1 A. Introduction 1. Consider the problems on pp. 170-1 (1) Model the discard pile in a card game (2) Model a railroad switching yard (3) Parentheses checker () Calculate and display base-two

More information

Short Notes of CS201

Short Notes of CS201 #includes: Short Notes of CS201 The #include directive instructs the preprocessor to read and include a file into a source code file. The file name is typically enclosed with < and > if the file is a system

More information

CS201 - Introduction to Programming Glossary By

CS201 - Introduction to Programming Glossary By CS201 - Introduction to Programming Glossary By #include : The #include directive instructs the preprocessor to read and include a file into a source code file. The file name is typically enclosed with

More information

List, Stack, and Queues

List, Stack, and Queues List, Stack, and Queues R. J. Renka Department of Computer Science & Engineering University of North Texas 02/24/2010 3.1 Abstract Data Type An Abstract Data Type (ADT) is a set of objects with a set of

More information

Preface... (vii) CHAPTER 1 INTRODUCTION TO COMPUTERS

Preface... (vii) CHAPTER 1 INTRODUCTION TO COMPUTERS Contents Preface... (vii) CHAPTER 1 INTRODUCTION TO COMPUTERS 1.1. INTRODUCTION TO COMPUTERS... 1 1.2. HISTORY OF C & C++... 3 1.3. DESIGN, DEVELOPMENT AND EXECUTION OF A PROGRAM... 3 1.4 TESTING OF PROGRAMS...

More information

Abstract Data Types 1

Abstract Data Types 1 Abstract Data Types 1 Purpose Abstract Data Types (ADTs) Lists Stacks Queues 2 Abstract Data Types (ADTs) ADT is a set of objects together with a set of operations. Abstract in that implementation of operations

More information

Lists, Stacks, and Queues. (Lists, Stacks, and Queues ) Data Structures and Programming Spring / 50

Lists, Stacks, and Queues. (Lists, Stacks, and Queues ) Data Structures and Programming Spring / 50 Lists, Stacks, and Queues (Lists, Stacks, and Queues ) Data Structures and Programming Spring 2016 1 / 50 Abstract Data Types (ADT) Data type a set of objects + a set of operations Example: integer set

More information

This chapter serves mainly to gather and organize information about iterators. Some new concepts are also introduced for completeness.

This chapter serves mainly to gather and organize information about iterators. Some new concepts are also introduced for completeness. Iterators Overview We have introduced, used, built, and studied iterators in several contexts, including List, TDeque, and TVector. We have seen that ordinary pointers also can be thought of as iterators

More information

Abstract Data Types. CptS 223 Advanced Data Structures. Larry Holder School of Electrical Engineering and Computer Science Washington State University

Abstract Data Types. CptS 223 Advanced Data Structures. Larry Holder School of Electrical Engineering and Computer Science Washington State University Abstract Data Types CptS 223 Advanced Data Structures Larry Holder School of Electrical Engineering and Computer Science Washington State University 1 Purpose Abstract Data Types (ADTs) Lists Stacks Queues

More information

CE221 Programming in C++ Part 1 Introduction

CE221 Programming in C++ Part 1 Introduction CE221 Programming in C++ Part 1 Introduction 06/10/2017 CE221 Part 1 1 Module Schedule There are two lectures (Monday 13.00-13.50 and Tuesday 11.00-11.50) each week in the autumn term, and a 2-hour lab

More information

CMSC 341 Lecture 6 Templates, Stacks & Queues. Based on slides by Shawn Lupoli & Katherine Gibson at UMBC

CMSC 341 Lecture 6 Templates, Stacks & Queues. Based on slides by Shawn Lupoli & Katherine Gibson at UMBC CMSC 341 Lecture 6 Templates, Stacks & Queues Based on slides by Shawn Lupoli & Katherine Gibson at UMBC Today s Topics Data types in C++ Overloading functions Templates How to implement them Possible

More information

Bits and Bytes. Bit Operators in C/C++

Bits and Bytes. Bit Operators in C/C++ Bits and Bytes The byte is generally the smallest item of storage that is directly accessible in modern computers, and symbiotically the byte is the smallest item of storage used by modern programming

More information

STACKS AND QUEUES. Problem Solving with Computers-II

STACKS AND QUEUES. Problem Solving with Computers-II STACKS AND QUEUES Problem Solving with Computers-II 2 Stacks container class available in the C++ STL Container class that uses the Last In First Out (LIFO) principle Methods i. push() ii. iii. iv. pop()

More information

Appendix. Grammar. A.1 Introduction. A.2 Keywords. There is no worse danger for a teacher than to teach words instead of things.

Appendix. Grammar. A.1 Introduction. A.2 Keywords. There is no worse danger for a teacher than to teach words instead of things. A Appendix Grammar There is no worse danger for a teacher than to teach words instead of things. Marc Block Introduction keywords lexical conventions programs expressions statements declarations declarators

More information

Programming Abstractions

Programming Abstractions Programming Abstractions C S 1 0 6 B Cynthia Lee Today s Topics ADTs Stack Example: Reverse-Polish Notation calculator Queue Example: Mouse Events Stacks New ADT: Stack stack.h template

More information

Introduction to C++ Systems Programming

Introduction to C++ Systems Programming Introduction to C++ Systems Programming Introduction to C++ Syntax differences between C and C++ A Simple C++ Example C++ Input/Output C++ Libraries C++ Header Files Another Simple C++ Example Inline Functions

More information

ADTs: Stacks and Queues

ADTs: Stacks and Queues Introduction to the Stack ADTs: Stack: a data structure that holds a collection of elements of the same type. - The elements are accessed according to LIFO order: last in, first out - No random access

More information

COP4530 Data Structures, Algorithms and Generic Programming Recitation 4 Date: September 14/18-, 2008

COP4530 Data Structures, Algorithms and Generic Programming Recitation 4 Date: September 14/18-, 2008 COP4530 Data Structures, Algorithms and Generic Programming Recitation 4 Date: September 14/18-, 2008 Lab topic: 1) Take Quiz 4 2) Discussion on Assignment 2 Discussion on Assignment 2. Your task is to

More information

Lecture Notes. char myarray [ ] = {0, 0, 0, 0, 0 } ; The memory diagram associated with the array can be drawn like this

Lecture Notes. char myarray [ ] = {0, 0, 0, 0, 0 } ; The memory diagram associated with the array can be drawn like this Lecture Notes Array Review An array in C++ is a contiguous block of memory. Since a char is 1 byte, then an array of 5 chars is 5 bytes. For example, if you execute the following C++ code you will allocate

More information

CS 270 Algorithms. Oliver Kullmann. Binary search. Lists. Background: Pointers. Trees. Implementing rooted trees. Tutorial

CS 270 Algorithms. Oliver Kullmann. Binary search. Lists. Background: Pointers. Trees. Implementing rooted trees. Tutorial Week 7 General remarks Arrays, lists, pointers and 1 2 3 We conclude elementary data structures by discussing and implementing arrays, lists, and trees. Background information on pointers is provided (for

More information

Abstract Data Types 1

Abstract Data Types 1 Abstract Data Types 1 Purpose Abstract Data Types (ADTs) Lists Stacks Queues 2 Primitive vs. Abstract Data Types Primitive DT: programmer ADT: programmer Interface (API) data Implementation (methods) Data

More information

Stacks and their Applications

Stacks and their Applications Stacks and their Applications Lecture 23 Sections 18.1-18.2 Robb T. Koether Hampden-Sydney College Fri, Mar 16, 2018 Robb T. Koether Hampden-Sydney College) Stacks and their Applications Fri, Mar 16, 2018

More information

12 Abstract Data Types

12 Abstract Data Types 12 Abstract Data Types 12.1 Foundations of Computer Science Cengage Learning Objectives After studying this chapter, the student should be able to: Define the concept of an abstract data type (ADT). Define

More information

March 13/2003 Jayakanth Srinivasan,

March 13/2003 Jayakanth Srinivasan, Statement Effort MergeSort(A, lower_bound, upper_bound) begin T(n) if (lower_bound < upper_bound) Θ(1) mid = (lower_bound + upper_bound)/ 2 Θ(1) MergeSort(A, lower_bound, mid) T(n/2) MergeSort(A, mid+1,

More information

ADVANCED DATA STRUCTURES USING C++ ( MT-CSE-110 )

ADVANCED DATA STRUCTURES USING C++ ( MT-CSE-110 ) ADVANCED DATA STRUCTURES USING C++ ( MT-CSE-110 ) Unit - 2 By: Gurpreet Singh Dean Academics & H.O.D. (C.S.E. / I.T.) Yamuna Institute of Engineering & Technology, Gadholi What is a Stack? A stack is a

More information

Introduction to Programming

Introduction to Programming Introduction to Programming session 6 Instructor: Reza Entezari-Maleki Email: entezari@ce.sharif.edu 1 Spring 2011 These slides are created using Deitel s slides Sharif University of Technology Outlines

More information

Topics. Trees Vojislav Kecman. Which graphs are trees? Terminology. Terminology Trees as Models Some Tree Theorems Applications of Trees CMSC 302

Topics. Trees Vojislav Kecman. Which graphs are trees? Terminology. Terminology Trees as Models Some Tree Theorems Applications of Trees CMSC 302 Topics VCU, Department of Computer Science CMSC 302 Trees Vojislav Kecman Terminology Trees as Models Some Tree Theorems Applications of Trees Binary Search Tree Decision Tree Tree Traversal Spanning Trees

More information

III. Classes (Chap. 3)

III. Classes (Chap. 3) III. Classes III-1 III. Classes (Chap. 3) As we have seen, C++ data types can be classified as: Fundamental (or simple or scalar): A data object of one of these types is a single object. int, double, char,

More information

CSCI 136 Data Structures & Advanced Programming. Lecture 14 Fall 2018 Instructor: Bills

CSCI 136 Data Structures & Advanced Programming. Lecture 14 Fall 2018 Instructor: Bills CSCI 136 Data Structures & Advanced Programming Lecture 14 Fall 2018 Instructor: Bills Announcements Mid-Term Review Session Monday (10/15), 7:00-8:00 pm in TPL 203 No prepared remarks, so bring questions!

More information

Lecture 24 Notes Search in Graphs

Lecture 24 Notes Search in Graphs Lecture 24 Notes Search in Graphs 15-122: Principles of Imperative Computation (Spring 2016) Frank Pfenning, André Platzer, Rob Simmons, Penny Anderson 1 Introduction In this lecture, we will discuss the

More information

Chapter 15 - C++ As A "Better C"

Chapter 15 - C++ As A Better C Chapter 15 - C++ As A "Better C" Outline 15.1 Introduction 15.2 C++ 15.3 A Simple Program: Adding Two Integers 15.4 C++ Standard Library 15.5 Header Files 15.6 Inline Functions 15.7 References and Reference

More information

DATA STRUCTURE : A MCQ QUESTION SET Code : RBMCQ0305

DATA STRUCTURE : A MCQ QUESTION SET Code : RBMCQ0305 Q.1 If h is any hashing function and is used to hash n keys in to a table of size m, where n

More information

Topic Binary Trees (Non-Linear Data Structures)

Topic Binary Trees (Non-Linear Data Structures) Topic Binary Trees (Non-Linear Data Structures) CIS210 1 Linear Data Structures Arrays Linked lists Skip lists Self-organizing lists CIS210 2 Non-Linear Data Structures Hierarchical representation? Trees

More information

Programming Languages Third Edition. Chapter 7 Basic Semantics

Programming Languages Third Edition. Chapter 7 Basic Semantics Programming Languages Third Edition Chapter 7 Basic Semantics Objectives Understand attributes, binding, and semantic functions Understand declarations, blocks, and scope Learn how to construct a symbol

More information

1. Describe History of C++? 2. What is Dev. C++? 3. Why Use Dev. C++ instead of C++ DOS IDE?

1. Describe History of C++? 2. What is Dev. C++? 3. Why Use Dev. C++ instead of C++ DOS IDE? 1. Describe History of C++? The C++ programming language has a history going back to 1979, when Bjarne Stroustrup was doing work for his Ph.D. thesis. One of the languages Stroustrup had the opportunity

More information

CSE 230 Intermediate Programming in C and C++

CSE 230 Intermediate Programming in C and C++ CSE 230 Intermediate Programming in C and C++ Structures and List Processing Fall 2017 Stony Brook University Instructor: Shebuti Rayana http://www3.cs.stonybrook.edu/~cse230/ Self-referential Structure

More information

Interview Questions of C++

Interview Questions of C++ Interview Questions of C++ Q-1 What is the full form of OOPS? Ans: Object Oriented Programming System. Q-2 What is a class? Ans: Class is a blue print which reflects the entities attributes and actions.

More information

Lecture 24 Search in Graphs

Lecture 24 Search in Graphs Lecture 24 Search in Graphs 15-122: Principles of Imperative Computation (Fall 2018) Frank Pfenning, André Platzer, Rob Simmons, Penny Anderson, Iliano Cervesato In this lecture, we will discuss the question

More information

CS242 COMPUTER PROGRAMMING

CS242 COMPUTER PROGRAMMING CS242 COMPUTER PROGRAMMING I.Safa a Alawneh Variables Outline 2 Data Type C++ Built-in Data Types o o o o bool Data Type char Data Type int Data Type Floating-Point Data Types Variable Declaration Initializing

More information

DATA STRUCTURES AND ALGORITHMS

DATA STRUCTURES AND ALGORITHMS DATA STRUCTURES AND ALGORITHMS For COMPUTER SCIENCE DATA STRUCTURES &. ALGORITHMS SYLLABUS Programming and Data Structures: Programming in C. Recursion. Arrays, stacks, queues, linked lists, trees, binary

More information

An Introduction to Trees

An Introduction to Trees An Introduction to Trees Alice E. Fischer Spring 2017 Alice E. Fischer An Introduction to Trees... 1/34 Spring 2017 1 / 34 Outline 1 Trees the Abstraction Definitions 2 Expression Trees 3 Binary Search

More information

EC8393FUNDAMENTALS OF DATA STRUCTURES IN C Unit 3

EC8393FUNDAMENTALS OF DATA STRUCTURES IN C Unit 3 UNIT 3 LINEAR DATA STRUCTURES 1. Define Data Structures Data Structures is defined as the way of organizing all data items that consider not only the elements stored but also stores the relationship between

More information

Chapter 18 - C++ Operator Overloading

Chapter 18 - C++ Operator Overloading Chapter 18 - C++ Operator Overloading Outline 18.1 Introduction 18.2 Fundamentals of Operator Overloading 18.3 Restrictions on Operator Overloading 18.4 Operator Functions as Class Members vs. as friend

More information

infix expressions (review)

infix expressions (review) Outline infix, prefix, and postfix expressions queues queue interface queue applications queue implementation: array queue queue implementation: linked queue application of queues and stacks: data structure

More information

Problem with Scanning an Infix Expression

Problem with Scanning an Infix Expression Operator Notation Consider the infix expression (X Y) + (W U), with parentheses added to make the evaluation order perfectly obvious. This is an arithmetic expression written in standard form, called infix

More information

nptr = new int; // assigns valid address_of_int value to nptr std::cin >> n; // assigns valid int value to n

nptr = new int; // assigns valid address_of_int value to nptr std::cin >> n; // assigns valid int value to n Static and Dynamic Memory Allocation In this chapter we review the concepts of array and pointer and the use of the bracket operator for both arrays and pointers. We also review (or introduce) pointer

More information

Tail Calls. CMSC 330: Organization of Programming Languages. Tail Recursion. Tail Recursion (cont d) Names and Binding. Tail Recursion (cont d)

Tail Calls. CMSC 330: Organization of Programming Languages. Tail Recursion. Tail Recursion (cont d) Names and Binding. Tail Recursion (cont d) CMSC 330: Organization of Programming Languages Tail Calls A tail call is a function call that is the last thing a function does before it returns let add x y = x + y let f z = add z z (* tail call *)

More information

Queue Implementations

Queue Implementations Queue Implementations 1 Circular Queues buffer of fixed capacity improvements and cost estimates 2 Deques the double ended queue queue as double linked circular list MCS 360 Lecture 17 Introduction to

More information

Object Oriented Programming COP3330 / CGS5409

Object Oriented Programming COP3330 / CGS5409 Object Oriented Programming COP3330 / CGS5409 Intro to Data Structures Vectors Linked Lists Queues Stacks C++ has some built-in methods of storing compound data in useful ways, like arrays and structs.

More information

Programming Abstractions

Programming Abstractions Programming Abstractions C S 1 0 6 B Cynthia Lee Today s Topics HW Tips QT Creator dos & don ts ADTs Stack Example: Reverse-Polish Notation calculator Queue Event queues QT Creator A F E W W A R N I N

More information

DEEPIKA KAMBOJ UNIT 2. What is Stack?

DEEPIKA KAMBOJ UNIT 2. What is Stack? What is Stack? UNIT 2 Stack is an important data structure which stores its elements in an ordered manner. You must have seen a pile of plates where one plate is placed on top of another. Now, when you

More information

the Queue queue ADT using the STL queue designing the simulation simulation with STL queue using STL list as queue using STL vector as queue

the Queue queue ADT using the STL queue designing the simulation simulation with STL queue using STL list as queue using STL vector as queue the Queue 1 The Queue Abstract Data Type queue ADT using the STL queue 2 Simulating a Printer Queue designing the simulation simulation with STL queue 3 adapting STL list and vector using STL list as queue

More information

Containers: Stack. Jordi Cortadella and Jordi Petit Department of Computer Science

Containers: Stack. Jordi Cortadella and Jordi Petit Department of Computer Science Containers: Stack Jordi Cortadella and Jordi Petit Department of Computer Science The Stack ADT A stack is a list of objects in which insertions and deletions can only be performed at the top of the list.

More information

CS 216 Exam 1 Fall SOLUTION

CS 216 Exam 1 Fall SOLUTION CS 216 Exam 1 Fall 2004 - SOLUTION Name: Lab Section: Email Address: Student ID # This exam is closed note, closed book. You will have an hour and fifty minutes total to complete the exam. You may NOT

More information

CS201 Some Important Definitions

CS201 Some Important Definitions CS201 Some Important Definitions For Viva Preparation 1. What is a program? A program is a precise sequence of steps to solve a particular problem. 2. What is a class? We write a C++ program using data

More information

INSTITUTE OF AERONAUTICAL ENGINEERING

INSTITUTE OF AERONAUTICAL ENGINEERING INSTITUTE OF AERONAUTICAL ENGINEERING (Autonomous) Dundigal, Hyderabad - 500 043 COMPUTER SCIENCE AND ENGINEERING TUTORIAL QUESTION BANK Course Name Course Code Class Branch DATA STRUCTURES ACS002 B. Tech

More information

Stating the obvious, people and computers do not speak the same language.

Stating the obvious, people and computers do not speak the same language. 3.4 SYSTEM SOFTWARE 3.4.3 TRANSLATION SOFTWARE INTRODUCTION Stating the obvious, people and computers do not speak the same language. People have to write programs in order to instruct a computer what

More information

Algorithms: Lecture 10. Chalmers University of Technology

Algorithms: Lecture 10. Chalmers University of Technology Algorithms: Lecture 10 Chalmers University of Technology Today s Topics Basic Definitions Path, Cycle, Tree, Connectivity, etc. Graph Traversal Depth First Search Breadth First Search Testing Bipartatiness

More information

CSC 222: Computer Programming II. Spring 2004

CSC 222: Computer Programming II. Spring 2004 CSC 222: Computer Programming II Spring 2004 Stacks and recursion stack ADT push, pop, top, empty, size vector-based implementation, library application: parenthesis/delimiter matching run-time

More information

Containers: Stack. The Stack ADT. The Stack ADT. The Stack ADT

Containers: Stack. The Stack ADT. The Stack ADT. The Stack ADT Containers: Stack The Stack ADT A stack is a list of objects in which insertions and deletions can only be performed at the top of the list. Also known as LIFO Last In, First Out) push insert an element

More information

Lecture Data Structure Stack

Lecture Data Structure Stack Lecture Data Structure Stack 1.A stack :-is an abstract Data Type (ADT), commonly used in most programming languages. It is named stack as it behaves like a real-world stack, for example a deck of cards

More information

Operator Overloading in C++ Systems Programming

Operator Overloading in C++ Systems Programming Operator Overloading in C++ Systems Programming Operator Overloading Fundamentals of Operator Overloading Restrictions on Operator Overloading Operator Functions as Class Members vs. Global Functions Overloading

More information

The Stack and Queue Types

The Stack and Queue Types The Stack and Queue Types Hartmut Kaiser hkaiser@cct.lsu.edu http://www.cct.lsu.edu/ hkaiser/fall_2012/csc1254.html 2 Programming Principle of the Day Do the simplest thing that could possibly work A good

More information

CSE143 Exam with answers Problem numbering may differ from the test as given. Midterm #2 February 16, 2001

CSE143 Exam with answers Problem numbering may differ from the test as given. Midterm #2 February 16, 2001 CSE143 Exam with answers Problem numbering may differ from the test as given. All multiple choice questions are equally weighted. You can generally assume that code shown in the questions is intended to

More information

use static size for this buffer

use static size for this buffer Software Design (C++) 4. Templates and standard library (STL) Juha Vihavainen University of Helsinki Overview Introduction to templates (generics) std::vector again templates: specialization by code generation

More information

Stacks. Chapter 5. Copyright 2012 by Pearson Education, Inc. All rights reserved

Stacks. Chapter 5. Copyright 2012 by Pearson Education, Inc. All rights reserved Stacks Chapter 5 Copyright 2012 by Pearson Education, Inc. All rights reserved Contents Specifications of the ADT Stack Using a Stack to Process Algebraic Expressions A Problem Solved: Checking for Balanced

More information

The SPL Programming Language Reference Manual

The SPL Programming Language Reference Manual The SPL Programming Language Reference Manual Leonidas Fegaras University of Texas at Arlington Arlington, TX 76019 fegaras@cse.uta.edu February 27, 2018 1 Introduction The SPL language is a Small Programming

More information

Chapter 9 STACK, QUEUE

Chapter 9 STACK, QUEUE Chapter 9 STACK, QUEUE 1 LIFO: Last In, First Out. Stacks Restricted form of list: Insert and remove only at front of list. Notation: Insert: PUSH Remove: POP The accessible element is called TOP. Stack

More information

Stacks. Manolis Koubarakis. Data Structures and Programming Techniques

Stacks. Manolis Koubarakis. Data Structures and Programming Techniques Stacks Manolis Koubarakis 1 Stacks and Queues Linear data structures are collections of components arranged in a straight line. If we restrict the growth of a linear data structure so that new components

More information

C++ Basics. Brian A. Malloy. References Data Expressions Control Structures Functions. Slide 1 of 24. Go Back. Full Screen. Quit.

C++ Basics. Brian A. Malloy. References Data Expressions Control Structures Functions. Slide 1 of 24. Go Back. Full Screen. Quit. C++ Basics January 19, 2012 Brian A. Malloy Slide 1 of 24 1. Many find Deitel quintessentially readable; most find Stroustrup inscrutable and overbearing: Slide 2 of 24 1.1. Meyers Texts Two excellent

More information

Introduction to C++ Professor Hugh C. Lauer CS-2303, System Programming Concepts

Introduction to C++ Professor Hugh C. Lauer CS-2303, System Programming Concepts Introduction to C++ Professor Hugh C. Lauer CS-2303, System Programming Concepts (Slides include materials from The C Programming Language, 2 nd edition, by Kernighan and Ritchie, Absolute C++, by Walter

More information

Heap, Variables, References, and Garbage. CS152. Chris Pollett. Oct. 13, 2008.

Heap, Variables, References, and Garbage. CS152. Chris Pollett. Oct. 13, 2008. Heap, Variables, References, and Garbage. CS152. Chris Pollett. Oct. 13, 2008. Outline. Dynamic Allocation. Variables and Constants. Aliases and Problems. Garbage. Introduction. On Wednesday, we were talking

More information

1. true / false By a compiler we mean a program that translates to code that will run natively on some machine.

1. true / false By a compiler we mean a program that translates to code that will run natively on some machine. 1. true / false By a compiler we mean a program that translates to code that will run natively on some machine. 2. true / false ML can be compiled. 3. true / false FORTRAN can reasonably be considered

More information

Cpt S 122 Data Structures. Course Review Midterm Exam # 2

Cpt S 122 Data Structures. Course Review Midterm Exam # 2 Cpt S 122 Data Structures Course Review Midterm Exam # 2 Nirmalya Roy School of Electrical Engineering and Computer Science Washington State University Midterm Exam 2 When: Monday (11/05) 12:10 pm -1pm

More information

COMP6771 Advanced C++ Programming

COMP6771 Advanced C++ Programming 1. COMP6771 Advanced C++ Programming Week 6 Part Three: 2016 www.cse.unsw.edu.au/ cs6771 2. Why? In C++, class names cannot be overloaded. Thus: 1 class IntStack { 2 public: 3 void push(int&); 4 void pop();

More information

UNIT- 3 Introduction to C++

UNIT- 3 Introduction to C++ UNIT- 3 Introduction to C++ C++ Character Sets: Letters A-Z, a-z Digits 0-9 Special Symbols Space + - * / ^ \ ( ) [ ] =!= . $, ; : %! &? _ # = @ White Spaces Blank spaces, horizontal tab, carriage

More information

CSCI-1200 Data Structures Fall 2017 Lecture 9 Iterators & STL Lists

CSCI-1200 Data Structures Fall 2017 Lecture 9 Iterators & STL Lists Review from Lecture 8 CSCI-1200 Data Structures Fall 2017 Lecture 9 Iterators & STL Lists Designing our own container classes Dynamically allocated memory in classes Copy constructors, assignment operators,

More information

... IntArray B (100); // IntArray with 100 elements, each initialized to 0

... IntArray B (100); // IntArray with 100 elements, each initialized to 0 Types with External Resources A class constructor is invoked when an object comes into scope. The constructor prepares the object by creating an environment in which the member functions operate. For many

More information

double d0, d1, d2, d3; double * dp = new double[4]; double da[4];

double d0, d1, d2, d3; double * dp = new double[4]; double da[4]; All multiple choice questions are equally weighted. You can generally assume that code shown in the questions is intended to be syntactically correct, unless something in the question or one of the answers

More information

Arrays and Linked Lists

Arrays and Linked Lists Arrays and Linked Lists Abstract Data Types Stacks Queues Priority Queues and Deques John Edgar 2 And Stacks Reverse Polish Notation (RPN) Also known as postfix notation A mathematical notation Where every

More information

Type Aliases. Examples: using newtype = existingtype; // C++11 typedef existingtype newtype; // equivalent, still works

Type Aliases. Examples: using newtype = existingtype; // C++11 typedef existingtype newtype; // equivalent, still works Type Aliases A name may be defined as a synonym for an existing type name. Traditionally, typedef is used for this purpose. In the new standard, an alias declaration can also be used C++11.Thetwoformsareequivalent.

More information

STUDY NOTES UNIT 1 - INTRODUCTION TO OBJECT ORIENTED PROGRAMMING

STUDY NOTES UNIT 1 - INTRODUCTION TO OBJECT ORIENTED PROGRAMMING OBJECT ORIENTED PROGRAMMING STUDY NOTES UNIT 1 - INTRODUCTION TO OBJECT ORIENTED PROGRAMMING 1. Object Oriented Programming Paradigms 2. Comparison of Programming Paradigms 3. Basic Object Oriented Programming

More information

7.1 Optional Parameters

7.1 Optional Parameters Chapter 7: C++ Bells and Whistles A number of C++ features are introduced in this chapter: default parameters, const class members, and operator extensions. 7.1 Optional Parameters Purpose and Rules. Default

More information

CS490: Problem Solving in Computer Science Lecture 6: Introductory Graph Theory

CS490: Problem Solving in Computer Science Lecture 6: Introductory Graph Theory CS490: Problem Solving in Computer Science Lecture 6: Introductory Graph Theory Dustin Tseng Mike Li Wednesday January 16, 2006 Dustin Tseng Mike Li: CS490: Problem Solving in Computer Science, Lecture

More information

Welcome Back. CSCI 262 Data Structures. Hello, Let s Review. Hello, Let s Review. How to Review 8/19/ Review. Here s a simple C++ program:

Welcome Back. CSCI 262 Data Structures. Hello, Let s Review. Hello, Let s Review. How to Review 8/19/ Review. Here s a simple C++ program: Welcome Back CSCI 262 Data Structures 2 - Review What you learned in CSCI 261 (or equivalent): Variables Types Arrays Expressions Conditionals Branches & Loops Functions Recursion Classes & Objects Streams

More information

UEE1302 (1102) F10: Introduction to Computers and Programming

UEE1302 (1102) F10: Introduction to Computers and Programming Computational Intelligence on Automation Lab @ NCTU Learning Objectives UEE1302 (1102) F10: Introduction to Computers and Programming Programming Lecture 00 Programming by Example Introduction to C++ Origins,

More information

This book is licensed under a Creative Commons Attribution 3.0 License

This book is licensed under a Creative Commons Attribution 3.0 License 6. Syntax Learning objectives: syntax and semantics syntax diagrams and EBNF describe context-free grammars terminal and nonterminal symbols productions definition of EBNF by itself parse tree grammars

More information

Lesson 13 - Vectors Dynamic Data Storage

Lesson 13 - Vectors Dynamic Data Storage Lesson 13 - Vectors Dynamic Data Storage Summary In this lesson we introduce the Standard Template Library by demonstrating the use of Vectors to provide dynamic storage of data elements. New Concepts

More information

Tokens, Expressions and Control Structures

Tokens, Expressions and Control Structures 3 Tokens, Expressions and Control Structures Tokens Keywords Identifiers Data types User-defined types Derived types Symbolic constants Declaration of variables Initialization Reference variables Type

More information

AN OVERVIEW OF C++ 1

AN OVERVIEW OF C++ 1 AN OVERVIEW OF C++ 1 OBJECTIVES Introduction What is object-oriented programming? Two versions of C++ C++ console I/O C++ comments Classes: A first look Some differences between C and C++ Introducing function

More information

Postfix (and prefix) notation

Postfix (and prefix) notation Postfix (and prefix) notation Also called reverse Polish reversed form of notation devised by mathematician named Jan Łukasiewicz (so really lü-kä-sha-vech notation) Infix notation is: operand operator

More information

SAURASHTRA UNIVERSITY

SAURASHTRA UNIVERSITY SAURASHTRA UNIVERSITY RAJKOT INDIA Accredited Grade A by NAAC (CGPA 3.05) CURRICULAM FOR B.Sc. (Computer Science) Bachelor of Science (Computer Science) (Semester - 1 Semester - 2) Effective From June

More information

ABSTRACT DATA TYPES (ADTS) COMP1927 Computing 2 16x1 Sedgewick Chapter 4

ABSTRACT DATA TYPES (ADTS) COMP1927 Computing 2 16x1 Sedgewick Chapter 4 ABSTRACT DATA TYPES (ADTS) COMP1927 Computing 2 16x1 Sedgewick Chapter 4 ABSTRACTION To understand a system, it should be enough to understand what its components do without knowing how Watching a television

More information

CS 211 Programming Practicum Fall 2018

CS 211 Programming Practicum Fall 2018 Due: Wednesday, 11/7/18 at 11:59 pm Infix Expression Evaluator Programming Project 5 For this lab, write a C++ program that will evaluate an infix expression. The algorithm REQUIRED for this program will

More information

Unit-II Programming and Problem Solving (BE1/4 CSE-2)

Unit-II Programming and Problem Solving (BE1/4 CSE-2) Unit-II Programming and Problem Solving (BE1/4 CSE-2) Problem Solving: Algorithm: It is a part of the plan for the computer program. An algorithm is an effective procedure for solving a problem in a finite

More information

The PCAT Programming Language Reference Manual

The PCAT Programming Language Reference Manual The PCAT Programming Language Reference Manual Andrew Tolmach and Jingke Li Dept. of Computer Science Portland State University September 27, 1995 (revised October 15, 2002) 1 Introduction The PCAT language

More information

Stacks. stacks of dishes or trays in a cafeteria. Last In First Out discipline (LIFO)

Stacks. stacks of dishes or trays in a cafeteria. Last In First Out discipline (LIFO) Outline stacks stack ADT method signatures array stack implementation linked stack implementation stack applications infix, prefix, and postfix expressions 1 Stacks stacks of dishes or trays in a cafeteria

More information

Chapter 12: Searching: Binary Trees and Hash Tables. Exercises 12.1

Chapter 12: Searching: Binary Trees and Hash Tables. Exercises 12.1 Chapter 12: Searching: Binary Trees and Hash Tables Exercises 12.1 1. 4, 6 2. 4, 1, 2, 3 3. 4, 6, 5 4. 4, 1, 0 5. 4, 6, 7, 8 6. template linearsearch(elementtype x[], ElementType

More information