Pds
Pds
Abstract Data Types (ADTs) List ADT array-based implementation linked list
implementation singly linked lists- circularly linked lists- doubly-linked lists applications of
lists Polynomial Manipulation All operation (Insertion, Deletion, Merge, Traversal)
INTRODUCTION-DATA STRUCTURES
A data structure is a way of organizing data that considers not only the items stored, but
also their relationship to each other. Advance knowledge about the relationship between data
items allows designing of efficient algorithms for the manipulation of data.
A data structure is a way of organizing data in a computer's memory or even disk storage
such that they can be retrieved easily and efficiently. An example of several common data
structures are arrays, linked lists, queues, stacks, binary trees, and hash tables.
Two types:
Linear Data Structure: Linked list stores data in an organized a linear fashion. They
store data in the form of a list. Eg: arrays, linked lists, queues, stacks etc.
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. Eg: Trees, Graphs etc.
An abstract data type (ADT) is a set of operations. Abstract data types are mathematical
abstractions; nowhere in an ADT's definition is there any mention of how the set of operations is
implemented. This can be viewed as an extension of modular design.
Objects such as lists, sets, and graphs, along with their operations, can be viewed as
abstract data types, just as integers, reals, and booleans are data types. Integers, reals, and
booleans have operations associated with them, and so do abstract data types. For the set ADT,
we might have such operations as union, intersection, size, and complement. Alternately, we
Page 1
might only want the two operations union and find, which would define a different ADT on the
set.
3.2-LIST ADT
A list or sequence is an abstract data type that implements an ordered collection of values, where
the same value may occur more than once.
A list is a linear structure:
Each item except the first (front, head) has a unique predecessor
Each item except the last (end, tail) has a unique successor
First item has no predecessor, and last item has no successor
An item within a list is specified by its position in the list
List ADT is a sequential storage structure. General list of the form a1, a2, a3.., an and the size
of the list is 'n'.
Where,
a1->First element of the list
an -> last element of the list
Any element in the list at the position i is defined to be ai, ai+1 the successor of ai and ai-1 is the
predecessor of ai.
Page 2
3.2-ARRAY BASED IMPLEMENTATION OF LIST ADT
An array is a list of a finite number n of homogeneous data elements (i.e., data elements
of the same type) such that:
The elements of the array are referenced respectively by an index consisting of
n consecutive numbers.
The elements of the array are stored respectively in successive memory
locations.
Insertion and Deletion are expensive. For example, inserting at position 0 (which
amounts to making a new first element) requires first pushing the entire array down one spot to
make room, whereas deleting the first element requires shifting all the elements in the list up one,
so the worst case of these operations is O(n). On average, half the list needs to be moved for
either operation, so linear time is still required.
Insertion: Insertion refers to the operation of adding another element to the list at the specified
position. If an element is inserted at the end of the array, if there is a space to add the element then
insertion can be done easily. If we want to insert an element in the middle of the array then half of
the elements must be moved downwards to new location to accommodate the new element and retain
the order of the element. If an element is inserted at the beginning of the array then the entire array
elements can be moved downward one step to make space for new element.
Deletion Deletion refers to the operation of removing an element from the array. Deleting the
element from the end of the array can be done easily. Deleting the first element of the array requires
shifting all elements in the list up one. Deleting the other elements requires half of the list needs to be
moved.
Page 3
element of the array requires, shifting all elements up one position. So the worst case operation
requires the computation time O(n).
Because the running time for insertions and deletions is so slow and the list size must be
known in advance, simple arrays are generally not used to implement lists.
Drawbacks in Arrays:
Has a fixed size.
Data must be shifted during insertions and deletions.
Page 4
Figure: Linked List with values
Characteristics:
Each Node has its successor and predecessor.
First Node does not have predecessor while last node does not have any successor.
Last Node have successor reference as NULL.
Each node of the list contains
the data item (an object pointer in our ADT)
a pointer to the next node
Real-Time Example:
Think of it like a train. The programmer always stores the first node of the list. This
would be the engine of the train. The pointer is the connector between cars of the train. Every
time the train adds a car, it uses the connectors to add a new car. This is like a programmer using
the keyword new to create a pointer to a new struct or class.
Page 5
Operations Performed:
Procedure to placing a new node to the list:
Obtain space for new node.
Assign data to the data field of the new node.
Set the next field of the new node to the beginning of the list.
Change the reference pointer of the LL to point to the new node.
struct node
{
element_type element;
node_ptr next;
};
typedef node_ptr LIST;
typedef node_ptr position;
{
return( L->next == NULL );
}
Page 6
//Routine- Insertion routine for linked lists
Page 7
INSERT(O4,2,L): Insert an element 04 after the location 2 in the list L.
Page 8
The next routine we will write is find. Find, shown in Figure 3.10, returns the position
in the list of some element. Line 2 takes advantage of the fact that the and (&&) operation is
short-circuited: if the first half of the and is false, the result is automatically false and the second
half is not executed.
//Routine-Find routine
/* Return position of x in L; NULL if not found */
position find ( element_type x, LIST L )
{
position p;
p = L->next;
while( (p != NULL) && (p->element != x) )
p = p->next;
return p;
}
DELETE(03,P,NODE)
Advantages:
Page 9
Disadvantages:
2) Because of the above disadvantage, binary search algorithm cannot be implemented on the
singly linked list.
In DLL, each node has two link fields, one linking in the forward direction and another in
the backward direction and one data field.
Page 10
//Creation of a node in DLL//
struct node
int data;
};
Operations Performed:
Insertion:
if(temp!=NULL)
temp->data=num;
temp->next=p->next;
temp->next->prev=temp;
p->next=temp;
temp->prev=p; } }
Page 11
Before Insertion:
After Insertion:
Deletion Operation:
position p;
p=Find(X, L);
if(isLast(P.L)) {
Page 12
temp=p;
p->prev->next=NULL;
free(temp);
else
temp=p;
p->prev->next=p->next;
p->next->prev=p->prev;
free(temp);
Advantages:
1.We can traverse in both directions i.e. from starting to end and as well as from end to starting.
Page 13
Disadvantages:
1.It requires more space per space per node because one extra field is required for pointer to
previous node.
2. Insertion and deletion take more time than linear linked list because more pointer operations
are required than linear linked list.
In a circularly-linked list the first and last nodes are linked together. This works for both
singly and doubly-linked lists. In a singly-circularly-linked list the last node points to the first
node. In a doubly-circularly-linked list both the last and first nodes point to each other.
In this, the last node does not contain NULL pointer. Instead the last node contains a
pointer that has the address of first node and thus points back to the first node.
Advantages:
1. If we are at a node, then we can go to any node. But in linear linked list it is not possible to go
to previous node.
2. It saves time when we have to go to the first node from the last node. It can be done in single
step because there is no need to traverse the in between nodes. But in double linked list, we will
have to go through in between nodes.
Disadvantages:
Instead we have to complete the entire circle by going through the in between nodes and
then we will reach the required node
Page 14
Figure: Singly Circular Linked List
3.4-APPLICATION OF LISTS:
Polynomial ADT.
Radix sort.
Multi-list.
3.4.1-POLYNOMIAL ADT
We can define an abstract data type for single-variable polynomials (with nonnegative
exponents) by using a list. Let ( ) . If most of the coefficients ai are non-zero, we
can use a simple array to store the coefficients. An example of a single variable polynomial:
4x6 + 10x4 - 5x + 3
Page 15
p( x) a1 x e1 ... an x en
20 5
Polynomials A(X)=3X +2X +4,
4 3 2
B(X)=X +10X +3X +1
How to implement this?
Array Impementation:
Page 16
Ignoring the time to initialize the output polynomials to zero, the running time of the
multiplication routine is proportional to the product of the degree of the two input polynomials.
typedef struct
{
int coeff_array[ MAX_DEGREE+1 ];
unsigned int high_power;
} *POLYNOMIAL;
An alternative is to use a singly linked list. Each term in the polynomial is contained in
one cell, and the cells are sorted in decreasing order of exponents. For instance, the linked lists in
foll Figure:a represent p1(x) and p2(x). We could then use the declarations in Figure 3.23.
void
zero_polynomial( POLYNOMIAL poly )
{
unsigned int i;
for( i=0; i<=MAX_DEGREE; i++ )
poly->coeff_array[i] = 0;
poly->high_power = 0;
}
Page 17
Polynomial Add(poly1, poly2) ::= return the polynomial
poly1 +poly2
Polynomial Mult(poly1, poly2) ::= return the polynomial
poly1 poly2
void
add_polynomial( POLYNOMIAL poly1, POLYNOMIAL poly2, POLYNOMIAL poly_sum)
{
int i;
zero_polynomial( poly_sum );
poly_sum->high_power = max( poly1->high_power, poly2->high_power);
for( i=poly_sum->high_power; i>=0; i-- )
poly_sum->coeff_array[i] = poly1->coeff_array[i] + poly2->coeff_array[i];
}
void
mult_polynomial(POLYNOMIAL poly1, POLYNOMIAL poly2, POLYNOMIAL poly_prod )
{
unsigned int i, j;
zero_polynomial( poly_prod );
poly_prod->high_power = poly1->high_power + poly2->high_power;
if( poly_prod->high_power > MAX_DEGREE )
error("Exceeded array size");
else
for( i=0; i<=poly->high_power; i++ )
for( j=0; j<=poly2->high_power; j++ )
poly_prod->coeff_array[i+j] += poly1->coeff_array[i] * poly2->coeff_array[j];
}
Page 18
Advantages of using an Array:
Node Structure:
Page 19
Adding polynomials using a Linked list representation: (storing the result in p3)
Create a new node in p3 with the same exponent and with the sum of the
coefficients of p1 and p2.
Page 20
Page 21
typedef struct node *node_ptr;
struct node
{
int coefficient;
int exponent;
node_ptr next;
};
typedef node_ptr POLYNOMIAL; /* keep nodes sorted by exponent */
Figure e Type declaration for linked list implementation of the Polynomial ADT
Page 22
//Addition of two Polynomial//
void add()
{
POLYNOMIAL *p1, *p2, *new1;
p1=list 1;
p2=list2;
while(p1!=NULL && p2!=NULL)
{
new1=malloc(sizeof(struct POLYNOMIAL));
}
if(p1->exp==p2->exp)
{
new1->coef=p1->coef+p2->coef;
new1->exp=p1->exp;
new1->next=NULL;
list3=create(list3, new1);
}
else if(p1->exp>p2->exp)
{
new1->coef=p1->coef;
new1->exp=p1->exp;
new1->next=NULL;
list3=create(list3, new1);
p1=p1->next;
}
else
{
new1->coef=p2->coef;
new1->exp=p2->exp;
new1->next=NULL;
list3=create(list 3, new1);
Page 23
p2=p2->next;
}
}
The operations would then be straightforward to implement. The only potential difficulty
is that when two polynomials are multiplied, the resultant polynomial will have to have like
terms combined.
save space (dont have to worry about sparse polynomials) and easy to maintain.
dont need to allocate list size and can declare nodes (terms) only as needed
Polynomial Addition-
Easy implementation
3.4.2-RADIX SORT
A second example where linked lists are used is called radix sort. Radix sort is
sometimes known as card sort, because it was used, until the advent of modern computers, to
sort old-style punch cards.
Page 24
read, increment (by one) count[ai]. After all the input is read, scan the count array, printing out a
representation of the sorted list.
Pass-1
10 15
------------------------------------------------------------------------------------------------------------
0 1 2 3 4 5 6 7 8 9
Pass-II
15 187
08 10 25 256 174 80
0 1 2 3 4 5 6 7 8 9
Page 25
Pass-III
080
025
015
010 187
0 1 2 3 4 5 6 7 8 9
3.4.3-MULTILIST
In a general multi-linked list each node can have any number of pointers to other nodes,
and there may or may not be inverses for each pointer. The standard use of multi-linked lists is to
organize a collection of elements in two different ways. For example, suppose my elements
include the name of a person and his/her age. e.g.
I might want to order these elements alphabetically and also order them by age. I would
have two pointers - NEXT-alphabetically, NEXT-age - and the list header would have two
pointers, one based on name, the other on age.
Page 26
A list can have two pointers without having a backward pointer. For instance, we may
want to keep a set of data ordered on more than one "key". A key is a unique data item included
in a record which distinguishes one record from all other records included in the list. Suppose
we want to be able to access customer accounts in order by account number (integer) and by
customer name (string). We can in fact have one list that is ordered both ways. We need two
pointer fields. Each node of the list will have the form:
Page 27
Insertion and deletion require about twice the work since two sets of pointers must be
adjusted: one for the name and one for the account number. Essentially, you perform the same
adjustments as in a singly linked list but you do it twice.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
Page 28
print(head1);
printf("\nSecond Linked list:");
print(head2);
head3=merge(head1,head2);
printf("\nFinal List:");
print(head3);
getch();
}
node *merge(node *l1,node *l2)
{ node *l,*p;
l=NULL;
while(l1!=NULL && l2!=NULL)
{ if(l1->data < l2->data)
{ if(l==NULL)
{ l=p=l1;
l1=l1->next;
}
else
{ p->next=l1;
l1=l1->next;
p=p->next;
}
}
else
{ if(l==NULL)
{ l=p=l2;
l2=l2->next;
}
else
{ p->next=l2;
l2=l2->next;
p=p->next;
}
}
}
if(l1!=NULL)
{ if(l==NULL)
l=l1;
else
p->next=l1;
}
if(l2!=NULL)
{ if(l==NULL)
l=l2;
else
p->next=l2;
Page 29
}
return(l);
}
node *create_normal()
{ node *head=NULL,*p;
int n,x,i;
printf("\nNumber of nodes:");
scanf("%d",&n);
printf("\nEnter data:");
for(i=1;i<=n;i++)
{ scanf("%d",&x);
if(head==NULL)
{ p=head=(node*)malloc(sizeof(node));
p->next=NULL;
}
else
{p->next=(node*)malloc(sizeof(node));
p=p->next;
p->next=NULL;
}
p->data=x;
}
return(head);
}
node *create_sorted()
{ node *head=NULL,*p,*q;
int n,x,i;
printf("\nNumber of nodes:");
scanf("%d",&n);
printf("\nEnter data:");
for(i=1;i<=n;i++)
{ scanf("%d",&x);
p=(node*)malloc(sizeof(node));
p->data=x;
p->next=NULL;
if(head==NULL || x<head->data)
{ p->next=head;
head=p;
}
else
{ q=head;
while(q->next !=NULL && x>q->next->data)
q=q->next;
p->next=q->next;
q->next=p;
}
Page 30
}
return(head);
}
void print(node *head)
{ printf("\n");
while(head != NULL)
{ printf("%5d",head->data);
head=head->next;
}
}
void sort(node *head)
{ int i,j,n,temp;
node *p;
/*counting number of nodes*/
for(n=0,p=head;p!=NULL;p=p->next)
n++;
for(i=1;i<n;i++)
{p=head;
for(j=0;j<n-i;j++)
{if(p->data > p->next->data)
{ temp=p->data;
p->data=p->next->data;
p->next->data=temp;
}
p=p->next;
}
}
}
/*
OUTPUT:-
Number of nodes:2
Enter data:42 12
Number of nodes:3
Enter data:12 68 41
Page 31
12 42
Second Linked list:
12 41 68
Final List:
12 12 41 42 68
Page 32
print_list(f1);
printf("\n Second list is\n");
print_list(f2);
f3 = join_list(f1,f2);
printf("\nThe resultant list is \n");
print_list(f3);
} // main
Page 33
c->prev = p;
}
p = c;
printf("\n Enter data ( use 0 to exit ) : ");
scanf("%d",&tdata);
} //while
f->prev = c;
c->next= f;
return(f);
} // create list
if( f == NULL)
{
printf("List is empty");
return;
}
printf("%4d",f->data);
t = f->next;
while ( t != f)
{
printf("%4d",t->data);
t = t->next;
}
return;
}
Page 34
struct node *join_list(struct node *f1, struct node *f2)
{
int reply;
struct node *t1,*t2;
Page 35
Program Input
Program Output
REFERENCE:
Mark Allen Weiss, Data Structures and Algorithm Analysis in C, 2nd Edition, Pearson
Education, 1997.
Page 36
EXPECTED ANNA UNIVERSITY PART-B QUESTIONS
1.What is a linked list? Explain with suitable program segments any four
operations of a linked list. (12)
2.Explain polynomial manipulation using linked lists with an example
Page 37