Introduction To Data Structures
Introduction To Data Structures
Linear data fashion- Linked list is an example of linear data storage or structure. Linked list
stores data in an organized a linear fashion. They store data in the form of a list.
Non Linear data structure- Tree data structure is an example of a non linear data structure. A
tree has one node called as root node that is the starting point that holds data and links to other
nodes.
Linear data structure: A linear data structure traverses the data elements sequentially, in which
only one data element can directly be reached. Ex: Arrays, Linked Lists
Non-Linear data structure: Every data item is attached to several other data items in a way that
is specific for reflecting relationships. The data items are not arranged in a sequential
structure. Ex: Trees, Graphs
A stack is a data structure based on the principle Last In First Out. Stack is container to hold
nodes and has two operations - push and pop. Push operation is to add nodes into the stack and
pop operation is to delete nodes from the stack and returns the top most node.
A queue is a data structure based on the principle First in First Out. The nodes are kept in an
order. A node is inserted from the rear of the queue and a node is deleted from the front. The first
element inserted in the first element first to delete.
A priority queue is essentially a list of items in which each item has associated with it a priority
Items are inserted into a priority queue in any, arbitrary order. However, items are withdrawn
from a priority queue in order of their priorities starting with the highest priority item first.
In a circular singly linked list, the last node of the list is made to point to the first node. This
eases the traveling through the list
Stack applications:
Three applications of stacks are presented here. These examples are central to many activities
that a computer must do and deserve time spent with them.
1. Expression evaluation
2. Backtracking (game playing, finding paths, exhaustive searching)
3. Memory management, run-time environment for nested language features.
Expression evaluation
In particular we will consider arithmetic expressions. Understand that there are boolean and
logical expressions that can be evaluated in the same way. Control structures can also be treated
similarly in a compiler.
This study of arithmetic expression evaluation is an example of problem solving where you solve
a simpler problem and then transform the actual problem to the simpler one.
Aside: The NP-Complete problem. There are a set of apparently intractable problems: finding the
shortest route in a graph (Traveling Salesman Problem), bin packing, linear programming, etc.
that are similar enough that if a polynomial solution is ever found (exponential solutions abound)
for one of these problems, then the solution can be applied to all problems.
We are accustomed to write arithmetic expressions with the operation between the two
operands: a+b or c/d. If we write a+b*c, however, we have to apply precedence rules to avoid
the ambiguous evaluation (add first or multiply first?).
There's no real reason to put the operation between the variables or values. They can just as well
precede or follow the operands. You should note the advantage of prefix and postfix: the need
for precedence rules and parentheses are eliminated.
The time complexity is O(n) because each operand is scanned once, and each operation is
performed once.
Demonstration with 2 3 4 + * 5 -
This algorithm doesn't handle errors in the input, although careful analysis of parenthesis or lack
of parenthesis could point to such error determination.
Backtracking
Backtracking is used in algorithms in which there are steps along some path (state) from some
starting point to some goal.
In all of these cases, there are choices to be made among a number of options. We need some
way to remember these decision points in case we want/need to come back and try the alternative
Consider the maze. At a point where a choice is made, we may discover that the choice leads to
a dead-end. We want to retrace back to that decision point and then try the other (next)
alternative.
Again, stacks can be used as part of the solution. Recursion is another, typically more favored,
solution, which is actually implemented by a stack.
Memory Management
Any modern computer environment uses a stack as the primary memory management model for
a running program. Whether it's native code (x86, Sun, VAX) or JVM, a stack is at the center of
the run-time environment for Java, C++, Ada, FORTRAN, etc.
The discussion of JVM in the text is consistent with NT, Solaris, VMS, Unix runtime
environments.
Each program that is running in a computer system has its own memory allocation containing the
typical layout as shown below.
1. An activation record is created; its size depends on the number and size of the local
variables and parameters.
2. The Base Pointer value is saved in the special location reserved for it
3. The Program Counter value is saved in the Return Address location
4. The Base Pointer is now reset to the new base (top of the call stack prior to the creation
of the AR)
5. The Program Counter is set to the location of the first bytecode of the method being
called
6. Copies the calling parameters into the Parameter region
7. Initializes local variables in the local variable region
While the method executes, the local variables and parameters are simply found by adding a
constant associated with each variable/parameter to the Base Pointer.
1. Get the program counter from the activation record and replace what's in the PC
2. Get the base pointer value from the AR and replace what's in the BP
3. Pop the AR entirely from the stack.