Download Data Structures through C 1.1 Algorithm Specification

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Red–black tree wikipedia , lookup

Array data structure wikipedia , lookup

Lattice model (finance) wikipedia , lookup

Quadtree wikipedia , lookup

Interval tree wikipedia , lookup

B-tree wikipedia , lookup

Binary search tree wikipedia , lookup

Linked list wikipedia , lookup

Transcript
Data Structures through C
Syllabus:
UNIT- I
Basic concepts- Algorithm Specification-Introduction, Recursive algorithms, Data Abstraction Performance
analysis- time complexity and space complexity, Asymptotic Notation-Big O, Omega and Theta notations,
Introduction to Linear and Non Linear data structures. Singly Linked Lists-Operations-Insertion, Deletion,
Concatenating singly linked lists, circularly linked lists- Operations for Circularly linked lists, Doubly Linked
Lists- Operations- Insertion, Deletion. Representation of single, two dimensional arrays, sparse matricesarray and linked representations.
1.1 Algorithm Specification
•
•
•
An algorithm is a finite set of instructions that accomplishes a particular task.
Criteria
• Input: Zero or more quantities that are externally supplied
• Output: At least one quantity is produced
• Definiteness: Clear and unambiguous
• Finiteness: Terminate after a finite number of steps
• Effectiveness: Instruction is basic enough to be carried out
A program does not have to satisfy the finiteness criteria.
•
Example 1.1 [Selection sort]:
• From those integers that are currently unsorted, find the smallest and place it next in the sorted list.
i
[0]
[1]
[2]
[3]
[4]
30
10
50
40
20
0
10
30
50
40
20
1
10
20
40
50
30
2
10
20
30
40
50
3
10
20
30
40
50
•
Example 1.2 [Binary search]:
[0]
[1]
[2]
[3]
8
14
26
30
left
0
4
4
0
0
right
6
6
4
6
2
middle
3
5
4
3
1
[4]
43
[5]
50
list[middle] : searchnum
30
<
43
50
>
43
43
==
43
30
>
18
14
<
18
[6]
52
2
2
2
26
>
18
2
1
• Searching a sorted list
while (there are more integers to check) {
middle = (left + right) / 2;
if (searchnum < list[middle])
right = middle - 1;
else if (searchnum == list[middle])
return middle;
else left = middle + 1;
}
int binsearch(int list[], int searchnum, int left, int right) {
/* search list[0] <= list[1] <= … <= list[n-1] for searchnum.
Return its position if found. Otherwise return -1 */
int middle;
while (left <= right) {
middle = (left + right)/2;
switch (COMPARE(list[middle], searchnum)) {
case -1: left = middle + 1;
break;
case 0 : return middle;
case 1 : right = middle – 1;
}
}
return -1;
}
1.2. Recursive algorithms
•
•
•
•
Beginning programmer view a function as something that is invoked (called) by another function
• It executes its code and then returns control to the calling function.
This perspective ignores the fact that functions can call themselves (direct recursion).
They may call other functions that invoke the calling function again (indirect recursion).
• extremely powerful
• frequently allow us to express an otherwise complex process in very clear term
We should express a recursive algorithm when the problem itself is defined recursively.
1.3 Data abstraction
•
•
•
•
Data
Type
A data type is a collection of objects and a set of operations that act on those objects.
• For example, the data type int consists of the objects {0, +1, -1, +2, -2, …, INT_MAX,
INT_MIN} and the operations +, -, *, /, and %.
The data types of C
• The basic data types: char, int, float and double
• The group data types: array and struct
• The pointer data type
• The user-defined types
Abstract Data Type

An abstract data type(ADT) is a data type that is organized in such a way that the specification of
the objects and the operations on the objects is separated from the representation of the objects and the
implementation of the operations.
• We know what is does, but not necessarily how it will do it.
Specification vs. Implementation
• An ADT is implementation independent
• Operation specification
• function name
• the types of arguments
• the type of the results
• The functions of a data type can be classify into several categories:
• creator / constructor
• transformers
• observers / reporters
1.4 Performance analysis
•
•
•
Criteria
• Is it correct?
• Is it readable?
• …
Performance Analysis (machine independent)
• space complexity: storage requirement
• time complexity: computing time
Performance Measurement (machine dependent)
1.4.1 Space Complexity:
•
•
•
S(P)=C+SP(I)
Fixed Space Requirements (C) Independent of the characteristics of the inputs and outputs
• instruction space
• space for simple variables, fixed-size structured variable, constants
Variable Space Requirements (SP(I)) depend on the instance characteristic I
• number, size, values of inputs and outputs associated with I
• recursive stack space, formal parameters, local variables, return address
Example : In program 1.9, Sabc(I)=0.
Example : In program 1.10, Ssum(I)=Ssum(n)=0.
•
Program 1.11 is a recursive function for addition. Figure 1.1 shows the number of bytes required
for one recursive call.
1.4.2 Time Complexity:
•
•
•
•
•
•
•
T(P)=C+TP(I)
The time, T(P), taken by a program, P, is the sum of its compile time C and its run (or execution)
time, TP(I)
Fixed time requirements
• Compile time (C), independent of instance characteristics
Variable time requirements
• Run (execution) time TP
• TP(n)=caADD(n)+csSUB(n)+clLDA(n)+cstSTA(n)
A program step is a syntactically or semantically meaningful program segment whose execution time is
independent of the instance characteristics.
• Example
(Regard as the same unit machine independent)
• abc = a + b + b * c + (a + b - c) / (a + b) + 4.0
• abc = a + b + c
Methods to compute the step count
• Introduce variable count into programs
• Tabular method
• Determine the total number of steps contributed by each statement step per execution
frequency
• add up the contribution of all statements
Iterative summing of a list of numbers
Program 1.12: Program 1.10 with count statements (p.23)
float sum(float list[ ], int n)
{
float tempsum = 0; count++; /* for assignment */
int i;
for (i = 0; i < n; i++) {
count++;
/*for the for loop */
tempsum += list[i]; count++; /* for assignment */
}
count++;
/* last execution of for */
count++;
/* for return */
•
return
}
•
Tabular Method
Figure 1.2: Step count table for Program 1.10 (p.26)
Iterative function to sum a list of numbers steps/execution
•
•
Recursive summing of a list of numbers
Program 1.14: Program 1.11 with count statements added (p.24)
•
float rsum(float list[ ], int n)
{
count++;
/*for if conditional */
if (n) {
count++; /* for return and rsum invocation*/
return rsum(list, n-1) + list[n-1];
}
count++;
return list[0];
}
2n+2 steps
tempsum;
1.5 Asymptotic notation
•
•
•
•
•
•
•
•
Complexity of c1n2+c2n and c3n
• for sufficiently large of value, c3n is faster than c1n2+c2n
• for small values of n, either could be faster
• c1=1, c2=2, c3=100 --> c1n2+c2n c3n for n 98
• c1=1, c2=2, c3=1000 --> c1n2+c2n c3n for n 998
• break even point
• no matter what the values of c1, c2, and c3, the n beyond which c3n is always
faster than c1n2+c2n
Definition: [Big “oh’’]
• f(n) = O(g(n)) iff there exist positive constants c and n0 such that f(n) cg(n) for all n, n n0.
Definition: [Omega]
• f(n) = (g(n)) (read as “f of n is omega of g of n”) iff there exist positive constants c and n0 such that
f(n) cg(n) for all n, n n0.
Definition: [Theta]
• f(n) = (g(n)) (read as “f of n is theta of g of n”) iff there exist positive constants c1, c2, and n0 such
that c1g(n) f(n) c2g(n) for all n, n n0.
Theorem 1.2:
• If f(n) = amnm+…+a1n+a0, then f(n) = O(nm).
Theorem 1.3:
• If f(n) = amnm+…+a1n+a0 and am > 0, then f(n) = (nm).
Theorem 1.4:
• If f(n) = amnm+…+a1n+a0 and am > 0, then f(n) = (nm).
Examples
• f(n) = 3n+2
• 3n + 2 <= 4n, for all n >= 2, 3n + 2 = (n)
3n + 2 >= 3n, for all n >= 1, 3n + 2 = (n)
3n <= 3n + 2 <= 4n, for all n >= 2, 3n + 2 = (n)
• f(n) = 10n2+4n+2
• 10n2+4n+2 <= 11n2, for all n >= 5, 10n2+4n+2 = (n2)
10n2+4n+2 >= n2, for all n >= 1, 10n2+4n+2 = (n2)
n2 <= 10n2+4n+2 <= 11n2, for all n >= 5, 10n2+4n+2 = (n2)
• 100n+6=O(n)
/* 100n+6101n for n10 */
• 10n2+4n+2=O(n2) /* 10n2+4n+211n2 for n5 */
• 6*2n+n2=O(2n) /* 6*2n+n2 7*2n for n4 */
Example
•
Figure 1.9 gives the time needed by a 1 billion instructions per second computer to execute a program of
complexity f(n) instructions.
•
Although performance analysis gives us a powerful tool for assessing an algorithm’s space and time
complexity, at some point we also must consider how the algorithm executes on our machine.
• This consideration moves us from the realm of analysis to that of measurement.
•
Example
1.22
[Worst case performance of the selection function]:
• The tests were conducted on an IBM compatible PC with an 80386 cpu, an 80387 numeric
coprocessor, and a turbo accelerator. We use Broland’s Turbo C compiler.
1.6 Introduction to Linear and Non Linear data structures
Definition:
A data structure can be defined as a way of organizing and storing data in a computer so that it can used
efficiently.
Data can be organized in different ways. The logical and mathematical model of a particular organization
of data is called as a data structure.
The choice of a particular data model depends on two considerations.
•
•
It must be rich enough in structure to mirror the actual relationships of the data in the real world.
The structure should be simple enough that one can effectively process the data when necessary.
In programming, the term structure refers to scheme for organizing related pieces of information. The basic data
structures include arrays, structures, stacks, queues, linked lists, trees and graphs etc..
The data structures can be categorized into
•
linear and
•
non-linear data structures.
Linear data Structures:
•
•
•
Stacks
Queues
Linked Lists-Single Linked List, Double Linked List
Non Linear Data Structures:
•
•
Tree
Graphs
1.7 Singly Linked Lists-Operations-Insertion, Deletion
Linked Lists
The linked list is very different type of collection from an array. Using such lists, we can store collections
of information limited only by the total amount of memory that the OS will allow us to use. Further more, there is no
need to specify our needs in advance. The linked list is very flexible dynamic data structure : items may be added
to it or deleted from it at will. A programmer need not worry about how many items a program will have to
accommodate in advance. This allows us to write robust programs which require much less maintenance.
The linked allocation has the following draw backs:
•
•
No direct access to a particular element.
Additional memory required for pointers.
Linked list are of 3 types:
•
•
•
Singly Linked List
Doubly Linked List
Circularly Linked List
Singly Linked List
A singly linked list, or simply a linked list, is a linear collection of data items. The linear order is given by
means of POINTERS. These types of lists are often referred to as linear linked list.
* Each item in the list is called a node.
* Each node of the list has two fields:
• Information- contains the item being stored in the list.
• Next address- contains the address ti the next item in the list.
* The last node in the list contains NULL pointer to indicate that it is the end of
the list.
Conceptual view of Singly Linked List
Data
Data
Data
Ptr
Ptr
Ptr
Operations on Singly linked list:
•
•
•
•
Creation of a node
Insertions
Deletions
Traversing the list
Creation of a node:
Struct List
{
int data;
struct List *next;
};
Insertions: How do we place elements in the list: Usually, there are 4 cases we are inserted in:
• at the beginning
• end of the list
• before a given element
• after a given element
Deletions: Removing an element from the list, without destroying the integrity of the list itself.
Traversing the list: Assuming we are given the pointer to the head of the list, how do we get the end of the list.
Inserting a node in singly linked list
1.inserting a node at the beginning of the list
inserting a node at the end of the list
inserting a node at position 'p' in the list
Deletion of a node from a singly linked list
deleting first node in singly linked list
deleting last node in the singly linked list
deleting node from position 'p' in the list
Algorithm:
initialize the first and last nodes with null values
struct node *first=null,*last=null,*next,*prev,*cur;
1. Algorithm creating a new node:
Step 1: if the list is empty then first==NULL
Step 2: Create a new node
cur=(struct node*) malloc (sizeof (struct node));
Step 3: Read the content of node
Step 4: Assign new node link to NULL
cur->link=NULL
Step 5: Assign new node to first & last node
first=cur
last=cur
Step 6: If the list is not empty call insert function
insert ()
Step 7 : Stop
2. Algorithm for Inserting a new node:
Step 1 : Initialize count c to 1
Step 2 : Create inserting node
cur=(struct node*)malloc(sizeof (struct node));
Step 3: Read the content of node
Step 4: Read the position of insertion
Step 5: Inserting in first position
Check if the pos=1 and first!=NULL
cur->link=first;
first=cur;
Step 6: Inserting in a given position
next=first;
repeat the steps a to c until c < pos
• prev=next;
•
next=prev->link;
• c++;
cur->link=prev->link;
prev->link=cur;
Step 7 : Stop
In the algorithm, first, the memory for a new node is available or not is checked out. Here avail is a pointer
to the available memory.
If it is NULL then there is no memory. Otherwise a new node is created from available memory and it is
stored in new. The new contains the address of the new node and avail moves forward to point to next available
memory location. In the info field of new, x is stored and the link field of new points to the first element address of
the list. Now, new becomes the pointer to the whole list.
This can be shown as:
(a)
(b)
First is having value of 100, means it is Pointing the 100 th memory location. The node at 100th location is
having info as 10 and containing the address 200 of the next node. The second node at 200th location, contains 20
and address 300 of the next node. At,300th memory location, the node contains info as 30 and its link field is NULL.
That means it is no more having any nodes. That is, the list is having 3 nodes with a starting address of 100.
Now, we created another node new that is having the address of 50 and its info is 40 and its link field is
NULL.
After the call to insertbeg( ) function the list will look like.
The insertbeg( ) function, inserts a node by storing the address of the first node of list in the link field of
new and making the new address as the pointer to the list.
The algorithm for inserting an element at the end of the list:
Procedure insertend(x, first)
begin
if avail = null then /* Checking for memory availability */
write (‘ Availability Stack underflow’);
return(first);
else
/* Obtaining the next free node */
new ¬ avail;
/* Removing free node from available memory */
avail ¬ link(avail)
info(new) ¬ x
/* Initializing the fields of new node */
link(new) ¬ NULL
if first = NULL then
/* Is the list empty? */
return(new);
Save ¬ first /* Searching the last node */
Repeat while link (Save) ¹ NULL
Save ¬ link(Save) /* Setting the link field of last node to new */
Link (Save) ¬ new
return (first)
end;
The Pictorial Representation:
(a)
(b)
(c)
(d)
first (100) address is stored in Save to go through the end of the list, after reaching to the last node, set the address of
new node in the link field of last node.
Inserting in the middle:
In this process, the address of first is stored in Save to go to the particular node at which the insertion is to
be done. After reaching the particular node, set the link to point to new node, and set the link of new node to connect
the remaining nodes.
ALGORITHM: The algorithm for inserting an element in the middle of a list:
Procedure insertmid(x, first)
begin
if avail = NULL then
write (‘ Availability Stack Underflow’);
return (first)
else
/* Obtain the address of next free node */
new ¬ avail
avail ¬ link(avail) /* Removing free node */
info(new) ¬ x /* Copying Information into new node */
if first = NULL then /* Checking whether the list is empty */
link(new) ¬ NULL /* list is empty*/
return(new) /* if the new data precedes all other in the list */
if info(new) £ info(first) then
link(new) ¬ first
return(new) /* initialise temporary Pointer */
Save ¬ first
Repeat while link(Save) ¹ NULL and
Info(link(Save)) £ info(new)
Save ¬ link(Save) /* Search for predecessor of new data */
link(new) ¬ link(Save) /* Setting the links of new and its Predecessor*/
link(Save) ¬ new
return(first)
end
(a)
(b)
(c)
(d)
(e)
Deleting a node in a single linked list:
Deletion can be done in 3 ways:
1. Deleting an element in the beginning of the list.
2. Deleting in the middle and
3. Deleting at the end.
The algorithms for deleting an element in the list:
Procedure:
If the linked list is empty then write underflow and return
Repeat Step 3 while the end of the list has not been reached and the node has not been found.
Obtain the next node in the list and record its predecessor node.
If the end of the list has been reached then write node not found and return.
delete the node from the list.
Return the node to the availability area.
Algorithm for Deleting a node:
Step 1 : Initialize count c to 1
Step 2 : Read the position for deletion
Step 3 : Check if first=NULL
print list is empty
Step 4 : If the list contains single element
Check if pos=1 and first->link=NULL
print deleted element is first->data
Step 5 : Assign first to NULL
first=NULL;
Step 6 : If the list contains more than one element and to delete first element
if pos=1 and first->link!=NULL
cur=first;
first=first->link;
cur->link=NULL;
print deleted element is cur->data
free(cur)
Step 7 : If the list contains more than one element and to delete an element at given position
next=first;
repeat the steps a to c until c < pos
a. cur=next;
b. next=next->link;
c. c++;
cur->link=next->link;
next->link=NULL;
print deleted element is next->data
free(next);
Step 8 : Stop
In the algorithm, it first checks whether the list is empty, if it is empty it prints underflow message.
Otherwise, it initializes a temporary pointer to first. Until the Predecessor of x node found, the temporary pointer is
moved forward. If it reaches the end of the list, without finding the node of address x, it flashes an error message,
stating ‘node not found’. If x is the first address, then first node is deleted and now first points to second node.
Otherwise it sets the links so that it deletes the node of address x.
The original list is:
1. If x = 100 (First node)
(a)
(b)
The node which is 100th memory address will be added to free space
(ii)
if x = 200
(a)
(b)
(c)
(iii)
if x = 300 (Last node)
(a)
(b)
Traversing the List:
This includes, visiting the node and printing the data of that node one at a time and moving forward until it reaches
end of the list. (i.e., link becomes NULL)
Algorithm for Displaying a node:
Step1 : Check if first node is NULL
print list is empty
Step2: If first node is not NULL then
cur=first;
repeat the steps a to b until cur!=NULL
a . print cur->data
b . cur=cur->link;
Step3 : Stop
Applications Linked Lists:
The main Applications of Linked Lists are
It means in addition/subtraction /multipication.. of two polynimials.
Eg:p1=2x^2+3x+7 and p2=3x^3+5x+2
p1+p2=3x^3+2x^2+8x+9
* In Dynamic Memory Management
In allocation and releasing memory at runtime.
*In Symbol Tables
in Balancing paranthesis
* Representing Sparse Matrix
C program to implement singly linked list
#include<stdio.h>
#include<stdlib.h>
void create();
void insert();
void delete();
void display();
struct node
{
int data;
struct node*link;
};
struct node *first=NULL,*last=NULL,*next,*prev,*cur;
void create()
{
if(first==NULL)
{
cur=(struct node*)malloc(sizeof (struct node));
printf("\n enter the data:");
scanf("%d",&cur->data);
cur->link=NULL;
first=cur;
last=cur;
}
else
insert();
}
void insert()
{
int pos,c=1;
cur=(struct node*)malloc(sizeof (struct node));
printf("\n enter data");
scanf("%d",&cur->data);
printf("\n enter the position");
scanf("%d",&pos);
if( (pos==1) && (first!=NULL))
{
cur->link=first;
first=cur;
}
else
{
next=first;
while(c<pos)
{
prev=next;
next=prev->link;
c++;
}
if(prev==NULL)
printf("\n invalid position\n");
else
{
cur->link=prev->link;
prev->link=cur;
}
}
}
void delete()
{
int pos,c=1;
printf("\n enter position:");
scanf("%d",&pos);
if(first==NULL)
printf("\n list is empty \n");
else if(pos==1&&first->link==NULL)
{
printf("\n deleted element is%d \n ",first->data);
free(first);
first=NULL;
}
else if(pos==1&&first->link!=NULL)
{
cur=first;
first=first->link;
cur->link=NULL;
printf("\n deleted element is%d \n",cur->data);
free(cur);
}
else
{
next=first;
while(c<pos)
{
cur=next;
next=next->link;
c++;
}
cur->link=next->link;
next->link=NULL;
printf("\n deleted element is %d \n",next->data);
free(next);
}
}
void display()
{
if(first==NULL)
printf("\n list is empty");
else
{
cur=first;
while(cur!=NULL)
{
printf("%d-->",cur->data);
cur=cur->link;
}
}
}
void main()
{
int ch;
printf("\n\n singly linked list");
do
{
printf("\n1.create\n2.delete\n3.display\n4.exit");
printf("\n enter your choice");
scanf("%d",&ch);
switch(ch)
{
case 1: create();
display();
break;
case 2: delete();
display();
break;
case 3: display();
break;
case 4: exit(0);
default:printf("invalid choice");
exit(0);
}
} while(1);
}
1.8 Circularly linked lists- Operations for Circularly linked lists
Circularly Linked List
A circularly linked list, or simply circular list, is a linked list in which the last node is always points to the
first node. This type of list can be build just by replacing the NULL pointer at the end of the list with a pointer which
points to the first node. There is no first or last node in the circular list.
Advantages:
•
•
•
Any node can be traversed starting from any other node in the list.
There is no need of NULL pointer to signal the end of the list and hence, all pointers contain valid
addresses.
In contrast to singly linked list, deletion operation in circular list is simplified as the search for the previous
node of an element to be deleted can be started from that item itself.
The functions to insert and delete elements to/from the circular list can be written as follows:
int insert(CLinkedList *clist, int data)
{
struct Node *node, *tempnode;
node = (struct Node*) malloc(sizeof(struct Node));
node->dataw=data;
node->next=NULL;
if(!clist->Head)
{
clist->Head=node;
node->next=Head;
return 1;
}
tempnode=slist->Head;
while(tempnode->next!=Head)
tempnode=tempnode->next;
tempnode->next=Head;
return 1;
}
int delete(CLinkedList *clist, int nodeindx)
{
int i=1;
struct Node *tempnode, *prevnode, *nextnode;
if(!clist->Head)
return 0;
tempnode=slist->Head;
while(tempnode->next!=Head && i<nodeindx)
{
tempnode=tempnode->next;
i++;
}
if(i==nodeindx)
{
free((void *)tempnode);
return 1;
}
return 0;
}
1.9 Doubly Linked Lists- Operations- Insertion, Deletion.
DOUBLY LINKED LIST
A singly linked list has the disadvantage that we can only traverse it in one direction. Many applications require
searching backwards and forwards through sections of a list. A useful refinement that can be made to the singly
linked list is to create a doubly linked list. The distinction made between the two list types is that while singly linked
list have pointers going in one direction, doubly linked list have pointer both to the next and to the previous element
in the list.
Lptr
Lptr
Lptr
Info
Info
Info
Rptr
Rptr
Rptr
The main advantage of a doubly linked list is that, they permit traversing or searching of the list in both directions.
Operations on Doubly linked list:
•
•
•
•
Creation of a node
Insertions
Deletions
Traversing the list
A Doubly Linked List (DLL) contains an extra pointer, typically called previous pointer, together with next pointer
and data which are there in singly linked list.
Following is representation of a DLL node in C language.
/* Node of a doubly linked list */
struct node
{
int data;
struct node *next; // Pointer to next node in DLL
struct node *prev; // Pointer to previous node in DLL
};
Following are advantages/disadvantages of doubly linked list over singly linked list.
Advantages over singly linked list
1)
A
DLL
can
be
traversed
in
both
forward
and
backward
direction.
2) The delete operation in DLL is more efficient if pointer to the node to be deleted is given.
In singly linked list, to delete a node, pointer to the previous node is needed. To get this previous node, sometimes
the list is traversed. In DLL, we can get the previous node using previous pointer.
Disadvantages over singly linked list
1) Every node of DLL Require extra space for an previous pointer. It is possible to implement DLL with single
pointer though.
2) All operations require an extra pointer previous to be maintained. For example, in insertion, we need to modify
previous pointers together with next pointers. For example in following functions for insertions at different
positions, we need 1 or 2 extra steps to set previous pointer.
Insertion
A node can be added in four ways
1) At the front of the DLL
2) After a given node.
3) At the end of the DLL
4) Before a given node.
1.Insertion at the front of list
2.Insertion in the middle of the list
3.Insertion at the end of the list
Deletion
Write a function to delete a given node in a doubly linked list.
(a) Original Doubly Linked List
(a) After deletion of head node
(a) After deletion of middle node
(a) After deletion of last node
ALGORITHM :
Initialize the first and last nodes with NULL values
struct node *first=NULL,*last=NULL,*next,*prev,*cur;
1. Algorithm creating a new node:
Step 1: if the list is empty then first==NULL
Step 2: Create a new node
cur=(struct node*) malloc (sizeof (struct node));
Step 3: Read the content of node
Step 4: Assign new node left and right links to NULL
cur->left=NULL;
cur->right=NULL;
Step 5: Assign new node to first & last node
first=cur
last=cur
Step 6: If the list is not empty call insert function
insert ()
Step 7 : Stop
2. Algorithm for Inserting a new node:
Step 1 : Initialize count c to 1
Step 2 : Create inserting node
cur=(struct node*)malloc(sizeof (struct node));
Step 3: Read the content of node
Step 4: Read the position of insertion
Step 5: Inserting in first position
Check if the pos=1 and first!=NULL
cur->right=first;
cur->left=NULL;
first=cur;
Step 6: Inserting in a given position
next=first;
repeat the steps a to c until c < pos
• prev=next;
• next=prev->right;
• c++;
prev->right=cur;
cur->right=next;
Step 7 : Stop
3. Algorithm for Deleting a node:
Step 1 : Initialize count c to 1
Step 2 : Read the position for deletion
Step 3 : Check if first=NULL
print list is empty
Step 4 : If the list contains single element
Check if pos=1 and first->right=NULL
print deleted element is first->data
Step 5 : Assign first to NULL
first=NULL;
Step 6 : If the list contains more than one element and to delete first element
if pos=1 and first->right!=NULL
cur=first;
first=first->right;
cur->right=NULL;
print deleted element is cur->data
free(cur);
Step 7 : If the list contains more than one element and to delete an element at given position
next=first;
repeat the steps a to c until c < pos
• cur=next;
• next=next->right;
• c++;
cur->right=next->right;
next->right=NULL;
next->left=NULL;
print deleted element is next->data
free(next);
Step 8 : Stop
4. Algorithm for Displaying a node:
Step1 : Check if first node is NULL
print list is empty
Step2: If first node is not NULL then
cur=first;
repeat the steps a to b until cur!=NULL
a . print cur->data
b . cur=cur->right;
Step3 : Stop
Creation of a node:
Struct DList
{
int data;
struct DList *Lptr;
struct DList *Rptr;
};
Insertions: How do we place elements in the list ?
Deletions: Removing an element from the list, without destroying the integrity of the list itself.
Traversing the list: Assuming we are given the pointer to the head of the list, how do we get the end of the list.
C program to implement doubly linked list
#include<stdio.h>
#include<conio.h>
#include<malloc.h>
#include<process.h>
struct doubly
{
int number;
struct doubly *p,*next;
}*first;
int main()
{
int create(int);
int show(void);
void atbeg(int);
int option,nodes,n,j;
clrscr();
while(1)
{
clrscr();
printf("\n 1.Create List");
printf("\n 2.Display List");
printf("\n 3.Insert at begining");
printf("\n 4.Exit");
printf("\n Enter Your Choice\n");
scanf("%d",&option);
switch(option)
{
case 1:
printf("Enter Number Of Nodes\n");
scanf("%d",&nodes);
for(j=0;j<nodes;j++)
{
printf("Enter the element\n");
scanf("%d",&n);
create(n);
}
break;
case 2:
show();
break;
case 3:
printf("Enter the element\n");
scanf("%d",&n);
atbeg(n);
break;
case 4:
exit(0);
}
}
}
int create (int number)
{
struct doubly *q,*temp;
temp=(struct doubly*)malloc(sizeof(struct doubly));
temp->number=number;
temp->next=NULL;
if(first==NULL)
{
temp->p=NULL;
first->p=temp;
first=temp;
}
else
{
q=first;
while(q->next!=0)
q=q->next;
q->next=temp;
temp->p=q;
}
return 0;
}
int show()
{
struct doubly *q;
if(first==NULL)
{
printf("List is empty\n");
return 0;
}
q=first;
printf("\n List is..\n");
while(q!=NULL)
{
printf("%d",q->number);
q=q->next;
}
printf("\n");
getch();
return 0;
}
void atbeg(int j)
{
struct doubly *temp;
temp=(struct doubly*)malloc(sizeof(struct doubly));
temp->p=NULL;
temp->number=j;
temp->next=first;
first->p=temp;
first=temp;
}
1.10 Representation of single & two dimensional arrays
C programming language provides a data structure called the array, which can store a fixed-size sequential
collection of elements of the same type. An array is used to store a collection of data, but it is often more useful to
think of an array as a collection of variables of the same type.
Instead of declaring individual variables, such as number0, number1, ..., and number99, you declare one array
variable such as numbers and use numbers[0], numbers[1], and ..., numbers[99] to represent individual variables.
A specific element in an array is accessed by an index.
All arrays consist of contiguous memory locations.
The lowest address corresponds to the first element and the highest address to the last element.
The array may be categorized into –
· One dimensional array
· Two dimensional array
· Multidimensional array
1 Representation of One-Dimensional Array
In Pascal language we can define array as VAR X: array [ 1 … N] of integer {or any other type}.
That’s means the structure contains a set of data elements, numbered (N), for example called (X), its defined as type
of element, the second type is the index type, is the type of values used to access individual element of the array, the
value of index is 1<= I =< N
By this definition the compiler limits the storage region to storing set of element, and the first location is individual
element of array , and this called the Base Address, let’s be as 500. Base Address (501) and like for the all elements
and used the index I, by its value are range 1<= I => N according to Base Index (500), by using this relation:
Location ( X[I] ) = Base Address + (I-1)
When the requirement to bounding the forth element (I=4):
Location ( X[4] ) = 500 + (4-1)
= 500 +3
= 503
So the address of forth element is 503 because the first element in 500.
When the program indicate or dealing with element of array in any instruction like (write (X [I]), read (X [I] ) ), the
compiler depend on going relation to bounding the requirement address.
2 Two-Dimensional Arrays
 The simplest form of the multidimensional array is the two-dimensional array.
 A twodimensionalarray is, in essence, a list of one-dimensional arrays.
 To declare a two-dimensionalinteger array of size x,y you would write something as follows:
type arrayName [ x ][ y ];
Where type can be any valid C data type and arrayName will be a valid C identifier.
 A twodimensional array can be think as a table which will have x number of rows and y number of
columns. A 2-dimensional array a, which contains three rows and four columns can be shown as below:
 Thus, every element in array a is identified by an element name of the form a[ i ][ j ], where a is
 the name of the array, and i and j are the subscripts that uniquely identify each element in a.
 1.10.2.1 Representation of two dimensional arrays in memory
 A two dimensional ‘m x n’ Array A is the collection of m X n elements.
Programming languages stores the two dimensional array in one dimensional memory in either of two ways-Row
Major Order:
First row of the array occupies the first set of memory locations reserved for the array;
Second row occupies the next set, and so forth.
To determine element address A[i,j]:
Location ( A[ i,j ] ) =Base Address + ( N x ( I - 1 ) ) + ( j - 1 )
For example:
Given an array [1…5,1…7] of integers. Calculate address of element T[4,6], where BA=900.
Sol) I = 4 , J = 6 M= 5 , N= 7
Location (T [4,6]) = BA + (7 x (4-1)) + (6-1)
= 900+ (7 x 3) +5
= 900+ 21+5
= 926
Column Major Order:
Order elements of first column stored linearly and then comes elements of next column.
To determine element address A[i,j]:
Location ( A[ i,j ] ) =Base Address + ( M x ( j - 1 ) ) + ( i - 1 )
For example:
Given an array [1…6,1…8] of integers. Calculate address element T[5,7], where BA=300
Sol) I = 5 , J = 7 M= 6 , N= 8
Location (T [4,6]) = BA + (6 x (7-1)) + (5-1)
= 300+ (6 x 6) +4
= 300+ 36+4
= 340
3 Operations on array
a) Traversing: means to visit all the elements of the array in an operation is called traversing.
b) Insertion: means to put values into an array
c) Deletion / Remove: to delete a value from an array.
d) Sorting: Re-arrangement of values in an array in a specific order (Ascending or Descending)
is called sorting.
e) Searching:
Arrays are used to implement mathematical vectors and matrices, as well as other kinds of rectangular tables.
Many databases, small and large, consist of (or include) one-dimensional arrays whose elements are records.
Arrays are used to implement other data structures, such as heaps, hash tables, deques, queues, stacks, strings, and
VLists.
One or more large arrays are sometimes used to emulate in-program dynamic memory allocation, particularly
memory pool allocation.
1.11 Sparse matrices-array and linked representations.
Sparse matrix
 Matrix with maximum zero entries is termed as sparse matrix.
 The natural method of representing matrices in memory as 2D arrays may not be suitable foe sparse
matrices. One may save space by storing for only non zero entries.
 Each non-zero element is represented by
[ row , column, non-zero value]
first row represent the dimension of matrix and
last column tells the number of non zero values;
second row onwards it is giving the position and value of non zero number.

It can be represented as:
1. Lower triangular matrix: It has non-zero entries on or below diagonal.
2. Upper Triangular matrix: It has non-zero entries on or above diagonal.
3.
Tri-diagonal matrix: It has non-zero entries on diagonal and at the places immediately above or
below diagonal.
Two types of Sparse Matrix Representation
1. Array Representation of Sparse Matrix
2. Linked List Representation of Sparse Matrix
1. Array Representation of Sparse Matrix
If most of the elements in a matrix have the value 0, then the matrix is called spare matrix.
Example For 3 X 3 Sparse Matrix:
| 1 0 0|
| 0 0 0|
| 0 4 0|
3-Tuple Representation Of Sparse Matrix:
| 3 3 2|
| 0 0 1|
| 2 1 4|
Elements in the first row represents the number of rows, columns and non-zero values in sparse matrix.
First Row - | 3 3 2 |
3 - rows
3 - columns
2 - non- zero values
Elements in the other rows gives information about the location and value of non-zero elements.
| 0 0 1 | ( Second Row) - represents value 1 at 0th Row, 0th column
| 2 1 4 | (Third Row) - represents value 4 at 2nd Row, 1st column
Eample:2
0 0 0 15
0000
0900
0040
Here the memory required is 16 elements X 2 bytes = 32 bytes
sparse matrix form
Code:
443
0 3 15
219
324
Here the memory required is 12elements X 2 bytes = 24 bytes
Program
#iinclude <stdio.h>
#include <stdlib.h>
int count;
int main() {
int *data, *tuple, row, col, tot, i, j, k =0, x = 0, y = 0;
printf("Enter the no of rows & columns:");
scanf("%d%d", &row, &col);
tot = row * col;
data = (int *) malloc(sizeof (int) * tot);
for (i = 0; i < tot; i++) {
if (y % col == 0 && y != 0) {
y = 0;
x++;
}
printf("data[%d][%d]:", x, y);
scanf("%d", &data[i]);
if (data[i])
count++;
y++;
}
tuple = (int *) malloc(sizeof (int) * (count + 1) * 3);
/* store row, column & count in 3-tuple array - in 1st row */
tuple[k++] = row;
tuple[k++] = col;
tuple[k++] = count;
x = y = 0;
for (i = 0; i < tot; i++) {
if (y % col == 0 && y != 0) {
y = 0;
x++;
}
/* store row, column and non-zero val in 3 tuple */
if (data[i] != 0) {
tuple[k++] = x;
tuple[k++] = y;
tuple[k++] = data[i];
}
y++;
}
printf("Given Sparse Matrix has %d non-zero elements\n", count);
x = y = 0;
/* printing given sparse matrix */
for (i = 0; i < tot; i++) {
if (y % col == 0 && y != 0) {
y = 0;
x++;
printf("\n");
}
printf("%d ", data[i]);
y++;
}
printf("\n\n");
/* 3-tuple represenation of sparse matrix */
printf("3-Tuple representation of Sparse Matrix:\n");
for (i = 0; i < (count + 1) * 3; i++) {
if (i % 3 == 0)
printf("\n");
printf("%d ", tuple[i]);
}
printf("\n\n");
return 0;
}
Output
Enter the no of rows & columns:3 3
data[0][0]:1
data[0][1]:0
data[0][2]:0
data[1][0]:0
data[1][1]:0
data[1][2]:0
data[2][0]:0
data[2][1]:4
data[2][2]:0
Given Sparse Matrix has 2 non-zero elements
100
000
040
3-Tuple representation of Sparse Matrix:
332
001
214
2.
Linked List Representation Of Sparse Matrix
If most of the elements in a matrix have the value 0, then the matrix is called spare matrix.
Example For 3 X 3 Sparse Matrix:
| 1 0 0|
| 0 0 0|
| 0 4 0|
3-Tuple Representation Of Sparse Matrix Using Arrays:
| 3 3 2|
| 0 0 1|
| 2 1 4|
Elements in the first row represents the number of rows, columns and non-zero values in sparse matrix.
First Row - | 3 3 2 |
3 - rows
3 - columns
2 - non- zero values
Elements in the other rows gives information about the location and value of non-zero elements.
| 0 0 1 | ( Second Row) - represents value 1 at 0th Row, 0th column
| 2 1 4 | (Third Row) - represents value 4 at 2nd Row, 1st column
3-Tuple Representation Of Sparse Matrix Using Linked List:
AH - Additional Header (sparseHead)
AH
chead-col 0
chead - col 1
chead - col 2
+---------------+
+----------------+
+----------------+ +----------------+
| | 3 | 3 | -|-> |
| 0 | -|-> |
| 1 | -|-> |
| 2 |N |
+---------------+
+----------------+
+----------------+ +----------------+
|
|
|
v rhead -row 0
v (node)
+
+----------------+ +------------------+
|
|
| 0 | -|-> |0row| 0col | 1 |
+
+----------------+ +------------------+
|
|
| NULL | NULL|
+
v rhead - row1 +------------------+
|
+----------------+
+
|
| 1 |N|
|
+----------------+
+
|
|
v rhead-row2
v (node)
+----------------+
+--------------------+
| N | 2 | -|-------------------------->| 2row | 1col | 4 |
+----------------+
+--------------------+
| NULL | NULL|
+---------------------+
Example2:
Linked List Representation of Sparse Matrix
Program:
#iinclude <stdio.h>
#include <stdlib.h>
/* structure to store data */
struct node {
int row, col, val;
struct node *right, *down;
};
/* structure of column head */
struct chead {
int col;
struct chead *next;
struct node *down;
};
/* structure of row head */
struct rhead {
int row;
struct rhead *next;
struct node *right;
};
/* structure of additional head */
struct sparsehead {
int rowCount, colCount;
struct rhead *frow;
struct chead *fcol;
};
/* main node */
struct sparse {
int row, *data;
struct node *nodePtr;
struct sparsehead *smatrix;
struct rhead **rowPtr;
struct chead **colPtr;
};
int count = 0;
/* Establish row and column links */
void initialize(struct sparse *sPtr, int row, int col) {
int i;
sPtr->rowPtr = (struct rhead **) calloc(1, (sizeof (struct rhead) * row));
sPtr->colPtr = (struct chead **) calloc(1, (sizeof (struct chead) * col));
for (i = 0; i < row; i++)
sPtr->rowPtr[i] = (struct rhead *) calloc(1, sizeof (struct rhead));
for (i = 0; i < row - 1; i++) {
sPtr->rowPtr[i]->row = i;
sPtr->rowPtr[i]->next = sPtr->rowPtr[i + 1];
}
for (i = 0; i < col; i++)
sPtr->colPtr[i] = (struct chead *) calloc(1, sizeof (struct chead));
for (i = 0; i < col - 1; i++) {
sPtr->colPtr[i]->col = i;
sPtr->colPtr[i]->next = sPtr->colPtr[i + 1];
}
/* update additional head information */
sPtr->smatrix = (struct sparsehead *) calloc(1, sizeof (struct sparsehead));
sPtr->smatrix->rowCount = row;
sPtr->smatrix->colCount = col;
sPtr->smatrix->frow = sPtr->rowPtr[0];
sPtr->smatrix->fcol = sPtr->colPtr[0];
return;
}
/* input sparse matrix */
void inputMatrix(struct sparse *sPtr, int row, int col) {
int i, n, x = 0, y = 0;
n = row * col;
sPtr->data = (int *) malloc(sizeof (int) * n);
for (i = 0; i < n; i++) {
if (y != 0 && y % col == 0) {
x++;
y = 0;
}
printf("data[%d][%d] : ", x, y);
scanf("%d", &(sPtr->data[i]));
if (sPtr->data[i])
count++;
y++;
}
return;
}
/* display sparse matrix */
void displayInputMatrix(struct sparse s, int row, int col) {
int i;
for (i = 0; i < row * col; i++) {
if (i % col == 0)
printf("\n");
printf("%d ", s.data[i]);
}
printf("\n");
return;
}
/* create 3-tuple array from input sparse matrix */
void createThreeTuple(struct sparse *sPtr, struct sparse s, int row, int col) {
int i, j = 0, x = 0, y = 0, l = 0;
sPtr->row = count;
sPtr->data = (int *) malloc(sizeof (int) * (sPtr->row * 3));
for (i = 0; i < row * col; i++) {
if (y % col == 0 && y != 0) {
x++;
y = 0;
}
if (s.data[i] != 0) {
sPtr->data[l++] = x;
sPtr->data[l++] = y;
sPtr->data[l++] = s.data[i];
}
y++;
}
return;
}
/* insert element to the list */
void insert(struct sparse *sPtr, int row, int col, int val) {
struct rhead *rPtr;
struct chead *cPtr;
struct node *n1, *n2;
struct sparsehead *smat = sPtr->smatrix;
int i, j;
/* update node values */
sPtr->nodePtr = (struct node *) malloc(sizeof (struct node));
sPtr->nodePtr->row = row;
sPtr->nodePtr->col = col;
sPtr->nodePtr->val = val;
/* get the row headnode */
rPtr = smat->frow;
/* move to corresponding row */
for (i = 0; i < row; i++)
rPtr = rPtr->next;
/* traverse the nodes in current and locate new node */
n1 = rPtr->right;
if (!n1) {
rPtr->right = sPtr->nodePtr;
sPtr->nodePtr->right = NULL;
} else {
while (n1 && n1->col < col) {
n2 = n1;
n1 = n1->right;
}
n2->right = sPtr->nodePtr;
sPtr->nodePtr->right = NULL;
}
/* get the column head node */
cPtr = sPtr->smatrix->fcol;
/* move to corresponding column (1/2/3..) */
for (i = 0; i < col; i++)
cPtr = cPtr->next;
/*
* traverse the node in current column and locate
* new node in appropriate position
*/
n1 = cPtr->down;
if (!n1) {
cPtr->down = sPtr->nodePtr;
sPtr->nodePtr->down = NULL;
} else {
while (n1 && n1->row < row) {
n2 = n1;
n1 = n1->down;
}
n2->down = sPtr->nodePtr;
sPtr->nodePtr->down = NULL;
}
return;
}
/* create list for 3-Tuple representation */
void createList(struct sparse *sPtr) {
int i, j = 0;
for (i = 0; i < sPtr->row; i++) {
insert(sPtr, sPtr->data[j], sPtr->data[j + 1], sPtr->data[j + 2]);
j = j + 3;
}
return;
}
/* Display data from linked list of 3-Tuple*/
void displayList(struct sparse s) {
struct node *n;
int row = s.smatrix->rowCount, i;
for (i = 0; i < row; i++) {
n = s.rowPtr[i]->right;
if (n) {
while (n->right) {
printf("%d %d %d\n", n->row, n->col, n->val);
n = n->right;
}
if (n->row == i) {
printf("%d %d %d\n", n->row, n->col, n->val);
}
}
}
printf("\n");
}
int main() {
struct sparse input, output;
int row, col;
printf("Enter the rows and columns:");
scanf("%d%d", &row, &col);
initialize(&input, row, col);
initialize(&output, row, col);
inputMatrix(&input, row, col);
printf("Given Sparse Matrix has %d non-zero elements\n", count);
printf("Input Sparse Matrix:\n");
displayInputMatrix(input, row, col);
printf("\n\n");
createThreeTuple(&output, input, row, col);
createList(&output);
printf("3-Tuple representation of the given sparse matrix:\n");
printf("%d %d %d\n", output.smatrix[0].rowCount,
output.smatrix[0].colCount, count);
displayList(output);
return 0;
}
Output: ( Linked List Representation of Sparse Matrix)
/$ ./a.out
Enter the rows and columns:3 3
data[0][0] : 1
data[0][1] : 0
data[0][2] : 0
data[1][0] : 0
data[1][1] : 0
data[1][2] : 0
data[2][0] : 0
data[2][1] : 4
data[2][2] : 0
Given Sparse Matrix has 2 non-zero elements
Input Sparse Matrix:
100
000
040
3-Tuple representation of the given sparse matrix:
3 3 2
0 0 1
2 1 4