0% found this document useful (0 votes)
4 views

Lecture 2 Basic Data Structures (Arrays and LinkedLists)

The document covers basic data structures, focusing on Abstract Data Types (ADTs) such as Lists and Stacks. It explains the definitions, operations, and implementations of these data structures, including their complexities. Additionally, it discusses practical applications like the Matching Parentheses Problem and provides examples of how to implement a stack using a linked list.

Uploaded by

bruha dev
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

Lecture 2 Basic Data Structures (Arrays and LinkedLists)

The document covers basic data structures, focusing on Abstract Data Types (ADTs) such as Lists and Stacks. It explains the definitions, operations, and implementations of these data structures, including their complexities. Additionally, it discusses practical applications like the Matching Parentheses Problem and provides examples of how to implement a stack using a linked list.

Uploaded by

bruha dev
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 71

#LifeKoKaroLift

Data Structures
Module Name- Basic Data
Structures
Class - Day 2
EditEdit
MasterMaster
Topic Name: Basic Data
texttext
Structures and Stacks
stylesstyles
Today’s Agenda

● Data Structures
● Studying basic ADT: List
● Implementations of Lists (Arrays and Linked List)
Data Structures

● So far we have dealt with many algorithms. An algorithm is a computational


process which deals with data.

● It can create, modify or delete data on execution.

● Data arrangement is very important to make the algorithms work well as


it does not only make the algorithm flexible and easy to modify, but can
lead to significant changes in the efficiency of the algorithm.

● This statement can be easily justified with the difference in speeds of the
operations like reading an element or adding an element when the data is
arranged as an Array List and when it is arranged as a Linked List.
Data Structures

● A data structure is a specialized format for storing and processing data which
provides us with an efficient way to use and modify our data.

● For any data structure, we study about its:

○ Abstract Data Type( ADT) used

○ Functionalities

○ Internal Design

○ Applications
Data Structures

● The terms data structures and Abstract Data Types are generally confused
with each other, but they are not the same.

● An abstract data type an be understood with an example of the list


interface, which is not a data structure in itself but helps in the
implementation of other data structures.

● In more technical terms, an ADT is an entity which defines the


capabilities of a data arrangement.

● A data structure on the other hand is just the concrete implementation


of these ADTs. Examples are Array Lists and Linked Lists.
Studying basic ADTs: List

● Taking this discussion to the Object Oriented environment, an Abstract Data


Type, such as a list is best understood as an interface.

● Data Structures like array lists and linked lists implement this interface.
Studying basic ADTs: List

● List ADT
○ A sequence of “n” elements of same type (n>=0) :

■ A1 A2 A3. . . .A4 A5 A6. . . .An


○ Each element has its POSITION
○ “n” denotes number of elements in the list or the LENGTH of the list
○ If n=0 we have an EMPTY LIST
○ Elements arranged in a linear fashion (Linearly Ordered)
■ Notion of PRECEDING and FOLLOWING elements
● A1 precedes A2
● A3 follows A2
■ Notion of FIRST and LAST elements
● A1 is FIRST element if n>=1
● An is LAST element if n>=1
Studying basic ADT: List

● List ADT
○ Define: END(L) (returns position following the last element or An)
○ Operations on List ADT
■ INSERT (x, p, L) :
● Inserts “x” at position “p” in List L (shifts elements to right)
■ LOCATE (x, L) :
● Returns position “p” in List L if element x is found at “p” or returns END(L)
■ RETREIVE (p, L) :
● Returns element at position “p” in List L and UNDEFINED if p = END(L) or p
is not a position in L
■ DELETE (p, L) :
● Removes an element at position “p” of List L
● Undefined if p = END(L) or p is not a valid position
Studying basic ADT: List

● List ADT
○ Operations on List ADT
■ NEXT (p, L) :
● Returns the POSITION following “p” in the list
● END(L) if p = n (last position of the list)
● Undefined if p = END(L)
● Undefined is “p” is not a position in L
■ PREVIOUS (p, L) :
● Returns the POSITION preceding “p” in the list
● Undefined if p = 1
● Undefined is “p” is not a position in L
■ MAKENULL (L) :
● Causes L to become empty list and returns position END(L)
■ FIRST (L) :
● Returns first position in List L
● END(L) if list is empty
Studying basic ADT: List

● List ADT
○ Operations on List ADT
■ PRINTLIST (L) :
● Print elements in the order of occurrence
Implementation of List ADT: Arrays

0 1 2 3 4 5 n-1

A1 A2 A3 A4 A5 A6 ..... An

<Element_Type> arrList[] = new <Element_Type>[n]

int arrList[] = new int[n]


Implementation of List ADT: Linked List

IntegerListNode IntegerListNode
IntegerListNode
A1 A2 A3
An

.....

head

list1 (object)
Implementation of List ADT: Linked List

Best Case Complexities

Data structure Access Search Insertion Deletion

Array O(1) O(1) O(1) (at LAST) O(1) (at LAST)

Singly Linked list O(1) (FIRST) O(1) (at FIRST) O(1) (at FIRST) O(1) (at FIRST)
Implementation of List ADT: Linked List

Worst Case Complexities

Data structure Access Search Insertion Deletion

Array O(1) O(1)


O(N) O(1)
O(N) O(1)
O(N)

Singly Linked list O(N) O(N) O(N) O(N)


Introduction to Stack

● Generally, whenever we have to wait for something in a line, we are served


first come first serve basis. For example, in clinics, billing counters, ATMs
and government offices.
Introduction to Stack

● Can you imagine a real life example where


a line is resolved on last come first serve
basis?

● What if the professor decides to give a


penalty based on how late the students
arrive in the class?

● You definitely don’t want to come last in


that line.
Introduction to Stack

● Now, consider a stack of books.

● If you were to pick one random book from


the stack, from which portion of it would
you pick it?
○ From the top?
○ From the bottom?
○ Or from somewhere in between?

● Any sane person would always pick up


from the top.
Introduction to Stack

● Trying to pull out a book from


anywhere else in the stack
would be possible, but would
lead to difficulties, and
untoward results.

● In the same manner, if you


were to add a book to this
stack, where would you prefer
to add it? Again, at the top, of
course.
Introduction to Stack

● Let’s take another example of an office employee.

● He is peacefully doing his work when he gets assigned with an important


task. He leaves his work and start working in this task 1.

● Just as he is in the middle of task 1, he


gets assigned another important task 2.
He immediately switches to task 2 and he
has just started working on it when he gets
bombarded with another task 3 and he has
to switch to the latest task now.

● Clearly, the tasks are complete according


to the Last In First Out principle.
Introduction to Stack

● This structure of books where you add things at the


top and remove things again from the top is
analogous to a data structure called “Stacks”.

● In a stack, what goes in last is the first to come out.

● This property of the above structure is called last in


first out (or LIFO) order.
Introduction to Stack

● A stack is therefore anything:

○ Into which you insert (push) and


remove (pop) things from one end of it.

○ That follows LIFO rule.


Operations of Stack

Let’s now look at the various operations that can be performed on our newly
learnt data structure:

● PUSH: Inserts element at the top of the stack

● POP: Removes an element from the top of the stack

● PEEK: Returns an element from the top of the stack

● ISEMPTY: Returns true if the stack is empty otherwise returns false

Let’s understand it better with the help of a visual demonstration:


Operations of Stack

● pop(6);
● pop(5);
● pop(4);
● pop(3);
● pop(2);
Operations of Stack

Let’s see the visualization of the push and pop commands in these two slides:

● push(2);
● push(3);
● push(4);
● push(5);
● push(6);
Operations of Stack

There is a Stack class in Java which implements stack data structure. The class
provides the following functions:
`
● push(object element)- inserts the element onto the top of the stack

● pop()- removes an element on top of the stack

● isEmpty()- returns true if the stack is empty otherwise returns false

● peek()- returns the element on the top of the stack

● search(object element)- searches for the element in the stack and returns
its location in the stack, If the element is not present then it returns ‘-1’
java.util package has Stack class
equals() method and toString() method belong to Object class

equals() method compares two OBJECT REFERENCES for EQUALITY using the “==“ operator
equals() method and toString() method belong to Object class

equals() method compares two OBJECT REFERENCES for EQUALITY using the “==“ operator
Operations of Stack

There are two kinds of exceptions you could encounter in stacks:

● Underflow: Trying to pop/peek an element from an empty stack

● Overflow: Trying to push an element into a stack that is already at its max
capacity
Operations of Stack

● You try to avoid these exceptions by writing


checks in your code or by handling
exceptions.

● For the underflow, you saw that a condition


was framed, where a pop is not allowed from
an empty stack
Operations of Stack

● On the other hand, you learnt


that a stack overflow is caused
when you've used up more
memory for a stack than your
program was supposed to use.

● An instance of this is when there


are infinite recursive calls and
the compiler shows a stack
overflow due to the overflow in
the program stack.
Matching Parentheses Problem

● Congratulations, you have completed the basics of stack data structure. Let’s
put this knowledge to use now in an attempt to solve a very common and
important question, Parentheses Matching.

● One of the things that must happen for a program to be well-formed is that all
its parentheses should match, i.e. if there’s an open parenthesis anywhere in
the program, there must also be a corresponding closing parenthesis.
Matching Parentheses Problem

● Obviously, the closing parenthesis must


follow, and not precede, its corresponding
open parenthesis.

● For example, "({})" and "(){}()" are well-


formed strings, but “(()”, “())” and even ")
(" are not.

● So, having an equal number of open


and close parentheses is necessary
but not sufficient for a string to be
well-formed
Matching Parentheses Problem

We can use a very basic filter to separate a few of the non-matching parenthesis:

● Declare a variable count and initialize it to 0.

● Start scanning from the left and one by one, scan each character of the string.

● Whenever an opening parenthesis is encountered, increase the count value by


one and when a closing parenthesis is detected, decrease it by 1.

● If the value is 0, the string is well formed and does not have matching
parenthesis. If non zero(either positive or negative), we conclude that the
parenthesis are matching.
Matching Parentheses Problem

The code for our algorithm is given below:


int count = 0;
char[] chars = parens.toCharArray();
for (char c : chars) { //loop updating the
counter
if (count < 0) {
return false; }
if (c == '(') {
count++; }
else if (c == ')'){
if (count > 0) {
count--; }
else {
return false; }}}
if (count == 0) { //returning final
boolean T/F
return true; }
else {
return false; }
Matching Parentheses Problem

● The approach we just saw is very efficient when we have to deal with a
single type of bracket (either ‘(’ or ‘{’).

● But as we saw in examples earlier, there may be string with both types of
brackets, for eg. “({}){}”.

● Will a single counter accommodate all the types of brackets?

● If not, what changes should be done to make out algorithm work?


Matching Parentheses Problem

● The answer is NO. We will have to use multiple counters each of which
keeps the track of count of a particular type of bracket.

● The output will be true only if all the counters have 0 value after string
traversal.

● The image on right explains one such


example. Since both the counters
C1( for ‘()’) and C2( for ‘{}’) have zero as
the count values after all the characters
are traversed, the parentheses are said
to be matching.
Matching Parentheses Problem

Let’s check the code for our new algorithm:


int count1 = 0, count2 = 0;
char[] chars = parens.toCharArray();
for (char c : chars) { //loop updating the
counters
if (c == '(') {
count1++;
} else if (c == ')') {
if (count1 > 0) {
count1--;
} else if (c == '{') {
count2++;
} else if (c == '}') {
if (count2 > 0) {
count2--;
} else {
return false; }
} else {
throw new Exception("Invalid character " + c);}}}
Matching Parentheses Problem

if (count1 == 0 && count2 == 0) { //returning final boolean T/F


return true;
} else {
return false; }}

● As we saw, the code with two counters became a little entangled with the
conditional statements.

● Moreover, this algorithm doesn’t work all the times. What about a string like
“({)}”? It is clear that brackets aren’t matching. But what does our logic say?

● we can use stacks to solve this problem for both single and multiple bracket
types.
Implementation of Stack

● Here’s an interesting challenge for


you. Can you implement a stack using
a linked list?

● You have to implement our basic


methods:
○ Push
○ Pop
○ isEmpty

● Can you code a stack now?


(You can use the library LinkedList in
java.)
Implementation of Stack

Let’s see the java code of the same:

public void push(T e){


this.list.add(e);
}

public T pop(){
this has if (this.list.size() > 0) {
the reference T e = list.get(list.size() - 1);
to currently list.remove(list.size() - 1);
calling object return e;
}
throw new EmptyStackException(); }

public Boolean isEmpty(){


return this.list.size() == 0; }
Example to explain this keyword

Ignore the
errors
Matching Parentheses Problem

The use of stacks really simplifies the algorithm for us as we don’t have to
maintain any counter. So, let’s see how the approach actually works:
Opening Parenthesis : PUSH “(“ into stack
1. Initialise stack S to be empty.
Closing Parenthesis : POP “(“ from the stock
2. Scan the string from left to right. As you go symbol by symbol, whenever you
meet an open parenthesis, push ’(’ into S.

3. If you meet a closing parenthesis, pop a ’(’ from S. However, if S is already


empty, it means error; so return false.

4. If you reach the end of string, and S is empty now, it means that the string is
well-formed; so return true. Otherwise, return false.
Matching Parentheses Problem

The code of this algorithm is fairly simple as well:

for (char c : parens.toCharArray()) {


if (c == '(') {
stack.push('(');
} else if (c == ')') {
if (!stack.isEmpty()) {
stack.pop();
} else {
return false; }
} else {
throw new Exception("Unexpected character " + c);
}}
if (stack.isEmpty()) {
return true;
} else {
return false; }}
Top
Top
Matching Parentheses Problem

Let’s see the approach to solve the multiple bracket problems using stacks now:

1. Initialise stack S to be empty.

2. Scan the string from left to right.

3. As you go symbol by symbol, whenever you meet an open parenthesis, push


’(’ into S. If see an open brace push ’{ ’ into S.

4. If you meet a close parenthesis, pop a symbol from S. If it’s not an open
parenthesis (e.g. if it’s an open brace), return false. Also, if S is already empty,
it means error; so return false.
Matching Parentheses Problem

5. If you meet a close brace, pop a symbol from S. If it’s not an open brace
(e.g.
if it’s an open parenthesis), return false. Also, if S is already empty, it means
error; so return false.

6. If you reach the end of string, and S is empty, it means that the string is
well-formed; so return true. Otherwise, return false.

Let’s see a few sample inputs and outputs to understand the algorithm better.
Matching Parentheses Problem

Consider the two cases show on the right:


Case -1
● In case 1, the algorithm loops through
the entire string without any violation
and also, the stack is empty at the
end. So we say, the parentheses are
matching.
Case -2
● In case 2 however, the bracket
popped from the stack after the first
closed bracket is of different type.
The algorithm end here and the result
is shown as non matching.
Matching Parentheses Problem

Let’s quickly, revise our algorithm for our better understanding:

● Declare a character stack 'S'.


● Traverse the expression string.
● If the current character is an opening bracket- ( or {, push it into the stack.
● If the current character is a closing bracket- ) or } , pop the character off the
stack.
● If the popped bracket is of same type as that of current closing bracket, then
continue; otherwise, the parentheses are not balanced.
● If the stack is empty at the end. the string is correctly formed.
● If pop() is called on an empty stack, the string is ill formed.
Matching Parentheses Problem

Now, let’s see the java code for our algorithm:

Stack<Character> stack = new Stack<Character>();


//STEP-1

for(char c : parens.toCharArray()) {
//STEP-2
if(c == '(' || c == '{') {
stack.push(c); }
//STEP-3

else if(c == ')') {


try {
char t = stack.pop();
if(t != '(') {
return false; }}
Matching Parentheses Problem
else if(c == '}') {
try {
char t = stack.pop();
if(t != '{') {
return false; }}

catch(EmptyStackException e) {
return false; }}
//STEP-5

else{ throw new Exception("Unexpected character" + c);


}}

if(stack.isEmpty()) {
return true;}

else{ return false; }}}


Matching Parentheses Problem

As an assignment, can you modify this code to take care of both square( “[ ]” ) and
angular( “< >” ) as well?

Let’s now look at some applications of Stack data structure:


Applications of Stack

Let’s look at a very common example of stacks in our daily life, the back button on
our internet browsers:

● Every time you visit a website or the hyperlinks within a website, the contents
are pushed onto a stack and the stack keeps on increasing as you visit more
and more webpages from your current webpage.

● So, when the back button is pressed, we just pop the last webpage pushed
into the stack.

● The undo feature in text editors and some other softwares uses the same
core logic using stacks.
Applications of Stack

● Let’s understand it better with another very


important application of stacks, Program
Stack.

● The program stack is also referred to as a


call stack, run-time stack, or execution
stack.

● If you are given a function which makes


call to different functions, it is done with
the help of a stack data structure.
Applications of Stack

● Let’s say you have a function – f()


which calls a function g() which in
turn calls a function h().

● Let’s see the working of program


stack in this case with the help of a
visual demonstration:
Applications of Stack

● So, the program stack first finds a reference to the function f(), pushes it into
the stack.
Applications of Stack

● Then, it finds the reference to function g(), then pushes it into the stack.
Eventually, it finds a reference to function h(), and pushes it into the stack.
Applications of Stack

● When, h() is solved, it is popped from stack. Then g() is solved and popped
and finally f() is popped.
Applications of Stack

● Now, there is a very common error called ‘stack


overflow’, which is caused when you use up more
memory for a stack than your program is supposed
to use.

● For example, when you frame a recursive logic


errantly and you give an infinite recursive call, your
compiler will give a stack overflow error when the
size of the stack grows to be greater than its
maximum allowed size.

● You all must be familiar with this logo already. Now


you know what it literally means as well.
Applications of Stack

● This next application of stacks is in


the compilers. Compiler is a
program which takes your program
and turns it into a program in some
other language, like machine
language or byte code.

● A very crucial and complicated


function performed by the
compilers is parsing which uses
stacks during implementation.
Applications of Stack

Parsing, in simple language,


means reading.

A compiler really uses parsing


to figure out if a program it’s
compiling is really well-formed
or not.

All the keywords, punctuation


marks etc. are checked.
Applications of Stack

● For a program to successfully compile, it’s


necessary but not sufficient that it should be
well-formed.

● If a program is not well-formed, i.e. if it’s ill-


formed, the compiler will typically detect
that, and will flag a syntax error.

● An example of syntax error can be taken


when the parentheses in a java code aren’t
matching. We know that every java function
is enclosed in a pair of {,}. Therefore, an
unmatched } or { causes a syntax error.
Applications of Stacks

Now, let’s see some examples where we use stacks in real life:

● We already saw a very essential application of stack, the program stack.

● Now, let’s the example of how an internet browser implements this stack
functionality.
○ Whenever you visit a website, it is added on top of a stack.
○ When you push the back button, the website at the top of the stack is
popped off, and you come at the site which was the previous visited
website.

● Another important application of stacks is the file versioning system,


which is explained in the coming slides.
Applications of Stacks

● File versioning is very essential in today’s life because all the important
files(including this presentation) have many people working on the same
file.

● All the major collaborative softwares like google docs, dropbox use stacks
as their core data structure and each version of the file is a node in the
stack.
Applications of Stacks

● Whenever you make changes to a


file let’s say – Version 1, and you
save the file, the new file gets stored
as Version 2 and is pushed on top of
the stack.

● Now when you have to undo your


changes, you call, pop() which
reverts to the previous version.

● You could go back multiple versions


to restore an older version, or could
see the no. of versions etc..
Key Takeaways

It’s time to answer the key takeaways from this lesson.

Follow the path to answer:


Module:- Stack & Queues
Session:- Stacks
Segment:- Summary

OR

Follow the link:


<https://learn.upgrad.com/v/course/439/session/39890/segment/214106>
#LifeKoKaroLift

Thank You!

P.S. - Don’t forget the home assignment for today.


<https://learn.upgrad.com/v/course/439/session/39890/segment/214108>

Happy learning!

You might also like