Ds Part B
Ds Part B
Ds Part B
The very common linear structure is array. Since arrays are usually easy to traverse,
search and sort, they are frequently used to store relatively permanent collections of
data.
An array is a list of a finite number n of homogeneous data elements (i.e., data
elements of the same type) such that:
Operations of Array
Two basic operations in an array are storing and retrieving (extraction)
Storing: A value is stored in an element of the array with the statement of the form,
Data[i] = X ; Where I is the valid index in the array and X is the element.
Extraction : Refers to getting the value of an element stored in an array. X = Data [ i ],
Where i is the valid index of the array and X is the element.
Array Representation
The number n of elements is called the length or size of the array. If not explicitly
stated we will assume that the index starts from 0 and end with n-1.
In general, the length (range) or the number of data elements of the array can be
obtained from the index by the formula,
Length = UB LB + 1
Where UB is the largest index, called the Upper Bound, and LB is the smallest index,
called Lower Bound, of the array.
If LB = 0 and UB = 4 then the length is,
Length = 4 0 + 1 = 5
The elements of an array A may be denoted by the subscript notation (or bracket
notation),
A[0], A[1], A[2], , A[N]
The number K in A[K] is called a subscript or an index and A[K] is called a
subscripted variable.
Subscripts allow any element of A to be referenced by its relative position in A.
If each element in the array is referenced by a single subscript, it is called single
dimensional array.
In other words, the number of subscripts gives the dimension of that array.
Two-dimensional Arrays:
A two-dimensional mXn array A is a collection of m*n data elements such that each
element is specified by a pair of integers (such as I, J), called subscripts, with the
property that,
0Im
and
0Jn
The element of A with first subscript i and second subscript j will be denoted by,
A[i,j] or A[i][j] (c language)
Two-dimensional arrays are called matrices in mathematics and tables in business
applications; hence two-dimensional arrays are sometimes are called matrix arrays.
There is a standard way of drawing a two-dimensional mXn array A where the
elements of A form a rectangular array with m rows and n columns and where the
element A[i][j] appears in row i and column j.
A row is a horizontal list of elements, and a column is a vertical list of elements.
Example:
Columns
Rows
A[0][0]
A[0][1]
A[0][2]
A[1][0]
A[1][1]
A[1][2]
A[2][0]
A[2][1]
A[2][2]
Note:
The array name will hold the address of the first element. It is called as BASE
ADDRESS of that array. The base address cant be modified during execution, because it is
static. It means that the increment /decrement operation would not work on the base
address. Consider the first element is stored in the address of 1020. It will look like this,
1020 1022 1024 1026 1028
9
14
5
1
0
1
2
3
4
.
a 12
Note :
Advantages:
Reduces memory access time, because all the elements are stored sequentially. By
incrementing the index, it is possible to access all the elements in an array.
Disadvantages:
data-type member m;
};
Here, struct is the required keyword; tag (optional) is a name that identifies structures of
this type; and member1, meber2, , member m are individual member declarations.
};
Here, regno, name, dept and year are the members of the student structure. And
this is the definition of the datatype.
So, no memory will be allocated at this stage. The memory will be allocated after the
declaration only. Structure variables can be declared as following methods:
a) Normal way of declaration
struct student s1, s2;
b) It is possible to combine the declaration of the structure composition with that of the
structure variables, as shown below:
struct student
{
int regno;
char name[20];
char dept[10];
int year;
} s1, s2;
c) If we are going to declare all the necessary structure variables at definition time then we
can create them without the tag, as shown below:
struct
{
int regno;
char name[20];
char dept[10];
int year;
} s1, s2;
Since there is no tag name, additional variables can not be generated other than this
location. i.e. cant create new variables with this structure in the local functions. If we want
we have to redefine the structure variable once again.
d) If we use the typedef in front of the struct keyword then the tag name alone can be used
in other places whenever you want to use the student data type.
typedef struct student
{
int regno;
char name[20];
char dept[10];
int year;
} ;student s1, s2; /* here the struct keyword is not needed because of typedef */
struct student
{int regno;
char name[20];
char dept[10];
int year;
};
s1
s2
sN
The size of each of these variables is 34 bytes because the size of the student datatype is
34 bytes. And the memory will be allocated for each variable as follows:
34 bytes
2 bytes
Address
6100
20 bytes
10 bytes
6102
2 bytes
6132
6122
s1
regno
name
dept
year
34 bytes
2 bytes
Address
1002
20 bytes
10 bytes
1004
2 bytes
1034
1024
s2
regno
name
dept
year
STORING VALUES
STRUCTURE VARIABLES:
s1.regno = 500;
strcpy(s1.name, Surya);
strcpy(s1.dept, CSE);
s1.year = 3;
b) also the scanf statement may be used to give values through the keyboard.
scanf(%d, &s1.regno);
scanf(%s, s1.name);
scanf(%s, s1.dept);
scanf(%d, &s1.year);
OR
scanf(%d%s%s%d, &s1.regno, s1.name, s1.dept, &s1.year);
ARRAYS IN THE STRUCTURE:
The derived data types like array can be included in the structure as a member.
Example:
struct student
{
int roll;
char name[20];
This is an int array. So each location can be accessed only with help of address only. So the subscripts are needed
int marks[5];
This is a char array but it is used as string. So no need to worry about the individual location and t
int total;
float avg;
char result[5];
}stu;
In memory it would be stored as given below:
stu (size is 43 bytes)
name array (size 20 bytes) mark array (size 10 bytes)
2190stu
2192
roll
name
2
mark
4 total
2228
avg
result
struct bill
To access this location
we need to use,
NESTED STRUCTURES:
{
stu.mark[3]
A structure variable may be defined as a memberintofcno;
another structure. In such
situations, the declaration of the embedded structure must appear
before the declaration of
char name[20];
the outer structure.
float amt;
struct date
{
int day;
int
Example:
struct date
{
month;
int year;
}billdate, paydate;
}b1, b2;
int day;
int month;
int year;
};
struct bill
OR
{
int cno;
char name[20];
float amt;
struct date billdate;
struct date paydate;
}b1, b2;
The second structure bill now contains another structure, date, as one of its members. The
structure may look like as follows:
b1 (size of the variable is 38 bytes)
billdate (size 6 bytes)
2190 2192
2212
2216
2218
2220
2224
2226
b1
cno
name
amt
day
month year
day
month
year
PROCESSING STRUCTURES:
Consider the following structure:
struct student
{
int regno;
char name[20];
char dept[10];
struct date
{
int day;
int month;
int year;
}bday;
int marks[5];
int year;
} s1;
The members of a structure are usually processed individually, as separate entities.
Therefore, we must be able to access the individual structure members. A structure member
can be accessed by writing
structure_variable.member
where variable refers to the name of a structure-type variable, and member refers to the
name of a member within the structure. The period (.) separates the variable name from
the member name. It is a member of the highest precedence group, and its associativity is
left to right.
Example:
s1.regno, s1.name, s1.dept, s1.year
A nested structure member can be accessed by writing
structure_variable.member.submember;
POINTERS TO STRUCTURES:
The address of a given structure variable can be obtained by using the & operator.
Pointers to structures, like all other pointer variables may be assigned addresses. The
following statements illustrate this concept.
Example:
struct student
{
int regno;
char name[20];
char dept[10];
int year;
};
20 bytes
6102
10 bytes
2 bytes
6132
6122
stu1
regno
name
dept
1008
sptr
6100
2 bytes
year
printf(Year of Study
: %d\n, sptr->year);
3. Discuss about Queue, its operation & types with example diagram?
A queue is an ordered list in which all insertions at one end called REAR and deletions
are made at another end called FRONT. queues are sometimes referred to as First In First
Out (FIFO) lists.
Rear Front
dequeue
(Deletion)
Example
1. The people waiting in line at a bank cash counter form a queue.
2. In computer, the jobs waiting in line to use the processor for execution. This queue is
called Job Queue.
Operations Of Queue
There are two basic queue operations. They are,
Enqueue Inserts an item / element at the rear end of the queue. An error occurs if the
queue is full.
Dequeue Removes an item / element from the front end of the queue, and returns it to
the user. An error occurs if the queue is empty.
Addition into a queue
addq (item : items);
{add item to the queue q}
begin
if rear=n then queuefull
else begin
rear :=rear+1;
q[rear]:=item;
end;
end;
Deletion in a queue
deleteq (var item : items);
{delete from the front of q and put into item}
begin
if front = rear then queueempty
else begin
front := front+1
item := q[front];
end;
end
Examples: supermarkets checkout, phone calls on hold
rear
Two elements with the same priority are processed according to the order in which
they were added to the queue. There are two types of queue are
Ascending Priority Queue: Collection of items into which item can be inserted arbitrarily &
from which only the smallest item can be removed.
Descending Priority Queue: Collection of items into which item can be inserted arbitrarily
& from which only the Largest item can be removed.
(iii) Double Ended Queue
A deque (short for double-ended queue) is an abstract data structure for which
elements can be added to or removed from the front or back(both end). This differs from a
normal queue, where elements can only be added to one end and removed from the other.
Both queues and stacks can be considered specializations of deques, and can be
implemented using deques.
1. Input Restricted Dqueue: Where the input (insertion) is restricted to the rear end and
the deletions has the options either end
2. Ouput Restricted Dqueue: Where the output (deletion) is restricted to the front end
and the insertion has the option either ends.
Example: Timesharing system using the prototype of priority queue programs of high
priority are processed first and programs with the same priority form a standard queue.
4. Explain the about Linked List and its types with operations.
A linked list, or one-way list, is a linear collection of data elements, called nodes,
where the linear order is given by means of pointers. That is, each node is divided
into two parts:
The first part contains the information of the element i.e. INFO or DATA.
The second part contains the link field, which contains the address of the next node
in the list.
NODE
INFO LINK
The linked list consists of series of nodes, which are not necessarily adjacent in
memory.
A list is a dynamic data structure i.e. the number of nodes on a list may vary
dramatically as elements are inserted and removed.
The pointer of the last node contains a special value, called the null pointer, which is
any invalid address. This null pointer signals the end of list.
The list with no nodes on it is called the empty list or null list.
Types
a.
b.
c.
d.
START
OR
HEAD
of Linked Lists:
Linear Singly Linked List
Circular Linked List
Two-way or doubly linked lists
Circular doubly linked lists
Is a collection of elements called Nodes. Each node consists of two fields, namely
data field to hold the values and link (next) field points to the next node in the list.
It consists of a sequence of nodes, each containing arbitrary data fields and one or
two references ("links") pointing to the next and/or previous nodes.
Linked lists permit insertion and removal of nodes at any point in the list in constant
time, but do not allow random access.
Several different types of linked list exist: singly-linked lists, doubly-linked lists, and
circularly-linked lists. One of the biggest advantages of linked lists is that nodes may
have multiple pointers to other nodes, allowing the same nodes to simultaneously
appear in different orders in several linked lists
b. Circularly-linked list
In a circularly-linked list, the first and final nodes are linked together. This can be
done for both singly and doubly linked lists. To traverse a circular linked list, you begin at
any node and follow the list in either direction until you return to the original node. Viewed
another way, circularly-linked lists can be seen as having no beginning or end. This type of
list is most useful for managing buffers for data ingest, and in cases where you have one
object in a list and wish to see all other objects in the list. The pointer pointing to the whole
list is usually called the end pointer.
c. Singly-circularly-linked list
In a singly-circularly-linked list, each node has one link, similar to an ordinary singlylinked list, except that the next link of the last node points back to the first node.
As in a singly-linked list, new nodes can only be efficiently inserted after a node we already
have a reference to. For this reason, it's usual to retain a reference to only the last element
in a singly-circularly-linked list, as this allows quick insertion at the beginning, and also
allows access to the first node through the last node's next pointer.
d. Doubly-circularly-linked list
In a doubly-circularly-linked list, each node has two links, similar to a doubly-linked
list, except that the previous link of the first node points to the last node and the next link
of the last node points to the first node. As in doubly-linked lists, insertions and removals
can be done at any point with access to any nearby node.
Sentinel nodes
Linked lists sometimes have a special dummy or sentinel node at the beginning and/or at
the end of the list, which is not used to store data.
Basic Operations on Linked Lists
1. Insertion
a. At first
b. At last
c. At a given location (At middle)
2. Deletion
a. First Node
b. Last Node
c. Node in given location or having given data item
Initial Condition
HEAD = NULL;
/* Address of the first node in the list is stored in HEAD. Initially there is no node in the list.
So, HEAD is initialized to NULL (No address) */
Doubly Linked Lists (or) Two Way Lists
There are some problems in using the Single linked list. They are
A singly linked list allows traversal of the list in only one direction. (Forward only)
Deleting a node from a list requires keeping track of the previous node, that is, the
node whose link points to the node to be deleted.
These major drawbacks can be avoided by using the double linked list. The doubly linked
list is a linear collection of data elements, called nodes, where each node is divided into
three parts. They are:
A pointer field LEFT which contains the address of the preceding node in the list
An information field INFO which contains the data of the Node
A pointer field RIGHT which contains the address of the next node in the list
LEFT
Example:
head
7060
7060
NULL
INFO RIGHT
2140
2140
7060
4020
4020
2140
end
NULL
4020
1
2
3
4
:
:
:
:
Allocate memory for a node and assign its address to the variable New
Assign the element in the data field of the new node.
Make the next field of the new node as the beginning of the existing list.
Make the new node as the Head of the list after insertion.
node is a structure with two values: a i and i. Thus, the length of the list will be k. The first
node will have (ak, k), the second node will have (ak-1, k-1) etc. The last node will be (a0, 0).
The polynomial 3x9 + 7x3 + 5 can be represented in a list as follows: (3,9) --> (7,3) -->
(5,0) where each pair of integers represent a node, and the arrow represents a link to its
neighbouring node.
Derivatives of polynomials can be easily computed by proceeding node by node. In our
previous example the list after computing the derivative would represented as follows:
(27,8) --> (21,2). The specific polynomial ADT will define various operations, such as
multiplication, addition, subtraction, derivative, integration etc. A polynomial ADT can be
useful for symbolic computation as well.
b. Large Integer ADT:
Large integers can also be implemented with primitive data structures. To conform to
our previous example, consider a large integer represented as a linked list. If we represent
the integer as successive powers of 10, where the power of 10 increments by 3 and the
coefficient is a three digit number, we can make computations on such numbers easier.
For
example,
we
can
represent
513(106) + 899(103) + 722(100).
Using
this
notation,
(513) --> (899) --> (722).
the
number
very
can
large
be
number
represented
as
follows:
as
follows:
The first number represents the coefficient of the 10 6 term, the next number
represents the coefficient of the 103 term and so on. The arrows represent links to adjacent
nodes.
The specific ADT will define operations on this representation, such as addition, subtraction,
multiplication, division, comparison, copy etc.
An array allocates memory for all its elements lumped together as one block of
memory. In contrast, a linked list allocates space for each element separately in its own
block of memory called a "linked list element" or "node". The list gets is overall structure by
using pointers to connect all its nodes together like the links in a chain.
Each node contains two fields: a "data" field to store whatever element type the list
holds for its client, and a "next" field which is a pointer used to link one node to the next
node.
Each node is allocated in the heap with a call to malloc(), so the node memory
continues to exist until it is explicitly deallocated with a call to free(). The front of the list is
a pointer to the first node. Here is what a list containing the numbers 1, 2, and 3 might look
like...
malloc() is a system function which allocates a block of memory in the "heap" and
returns a pointer to the new block. The prototype for malloc() and other heap functions are
in stdlib.h. The argument to malloc() is the integer size of the block in bytes. Unlike local
("stack") variables, heap memory is not automatically deallocated when the creating
function exits. malloc() returns NULL if it cannot fulfill the request. (extra for experts) You
may check for the NULL case with assert() if you wish just to be safe. Most modern
programming systems will throw an exception or do some other automatic error handling in
their memory allocator, so it is becoming less common that source code needs to explicitly
check for allocation failures.
free() is the opposite of malloc(). Call free() on a block of heap memory to indicate
to the system that you are done with it. The argument to free() is a pointer to a block of
memory in the heap a pointer which some time earlier was obtained via a call to malloc().
c. Sequential list
Contiguous cells, indexed by location Linked list: noncontiguous cells linked by pointers,
implicitly indexed by number of links away from head Both also contain location of first
element (head) length or end-of-list marker
Examples of end-of-list marker:
\0 for C strings (sequential list)
NULL for C linked list
d. Sequential List implementation
In C: typically an array with an int for the last used index.
A problem: must reserve memory for the list to grow into.
limits length of list to reserved length
reserved memory unusable for other purposes
Main advantage of sequential list: fast access to element by index.
e. Linked List implementation
Typically individual cells dynamically allocated containing a pointer to the next cell.
Advantages:
f. Time efficiency 1
In the following, let n be the length of the list.
Initialize to empty list:
Sequential and Linked O(1)
For sequential lists this really depends on the complexity of memory allocation, a complex
subject in itself. For linked lists, memory allocation time can affect the performance of the
other operations.
Select ith element
Sequential O(1) Linked O(i)
Time efficiency 2
Determine length:
Sequential and Linked
O(1) if recorded
O(n) for marker then linked takes longer following pointers and is more likely to leave the
cache
Traverse
Sequential and Linked O(n)
Linked takes longer for reasons above, but may be
insignificant compared to processing done on the elements.
Search
Sequential ordered O(log n)
Sequential unordered, Linked O(n)
Linked takes longer for reasons above.
Ordering can improve linked on average, since we can more
quickly detect that an element isnt in the list.
Time efficiency 3
These depend of course on how we locate where to make the change. The following describe
the additional cost.
Delete or insert element
Sequential O(n * size of an element) We must move elements over! Linked O(1)
Replace element (unordered)
Sequential and Linked O(1)
Replace data in an element
Sequential and Linked O(1)