Download 2. Non-Linear Data Structure: - In non linear data

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

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

Document related concepts

Lattice model (finance) wikipedia, lookup

Array data structure wikipedia, lookup

Quadtree wikipedia, lookup

Interval tree wikipedia, lookup

B-tree wikipedia, lookup

Binary search tree wikipedia, lookup

Linked list wikipedia, lookup

Transcript
UNIT-VIII
( Data Structures – Introduction to Data Structures, abstract data types, Linear list – single linked
list Implementation, insertion, deletion and searching operations on linear list, StacksOperations, array and linked representations of stacks, stack application-infix to postfix
conversion, postfix expression evaluation, recursion implementation, Queues-operations, array
and linked representations )
Learning objectives:
At the end of this unit students should be able to understand

Define data structures.

Define abstract data types

Explain about Linear List.

Describe Single Linked list and its implementation

Implement the Double Linked List program

Implement the Circular Linked List program

Define Stack and its basic operation

Explain the array representation of stacks

Explain stacks with Linked list representations

Stack application – infix to postfix conversion

Postfix expression evaluation

Recursion implementation

State various data structures.

Queues-Operations

Arrays and linked list representations.

Differentiate a Queue and a Circular Queue.

State the basic concepts of Queues and Circular Queues.
1
Data structure: In computer science, a data structure is a particular way of storing and
organizing data in a computer so that it can be used efficiently. Different kinds of data structures
are suited to different kinds of applications, and some are highly specialized to specific tasks.
Data structures are used in almost every program or software system. The implementation of a
data structure usually requires writing a set of procedures that create and manipulate instances of
that structure. Common data structures include: array, linked list, hash-table, heap, B-tree, stack,
and queue.
Data Structures can be classified as
1. Linear Data Structure: - Linear data structure is linear if element is adjacent to each
other. It has exactly two neighbor elements to which it is connected as its previous and
next member. Example of Linear Data Structure are Array, Linked List, Stack, Queue
2. Non-Linear Data Structure: - In non linear data elements are allowed to have more than
two adjacent elements. Example of Linear Data Structure are Tree and Graphs
There are two basic ways of representing such linear structures in memory such as
(i) Arrays and
(ii) Linked lists.
Note: Implementation of data structures using pointers is efficient than implementing using
arrays. It gives more flexibility for the operation.
Operations on Linear data structures:
The operations one normally performs on any linear structure, whether it be an array or a linked
list, include the following:
(a) Traversal: Processing each element to the list.
(b) Search: Finding the location of the element with a given value or the record with a given key.
(c) Insertion: Adding a new element to the list
(d) Deletion: Removing an element from the list
(e) Sorting: Arranging the elements in some type of order.
(f) Merging: Combining two lists into a single list.
Stacks:
 The stack is one of the most important linear data structure.
 A stock is defined as an ordered collection of data items in which insertions and deletions takes
place from one end called top.
 Stock maintains a pointer called top, which keeps track of the top most element in the stock.
 It works on the basis of LIFO (Last In First Out).
 In the stack, the elements are removed in the reverse order of that in which they were added to
the stack. That is Last element inserted is to be deleted first so it is called last in first out.
 The way the books are arranged on a table or the plates arranged on a table are the general
example for stacks.
2
Basic Operations on Stack:
 A stack can have any abstract data type as an element, for which we can perform two basic
operations: push, pop and display.
 The “push” operation adds a new item to the top of the stack, or initializing the stack if it is
empty, but if the stack is full and does not contain more space to accept the given item it is
considered as an Overflow state (It means that the stack is overloaded or no more space for
new item).

The “pop” operation removes an item from the top of the stack, a pop either reveals previously
concealed items, or results in an empty stack, but if the stack is empty then it goes under
underflow state (It means no items are present in stack to be removed).

Using display operation we can show the elements of a stack.
 A stack is a restricted data structure, because only a small number of operations are performed
on it. The nature of the pop and push operations also mean that stack elements have a natural
order. Elements are removed from the stack in the reverse order to the order of their addition:
therefore, the lower elements are those that have been on the stack the longest.
Working of a stack:
Consider a stack of maximum size 4. When top reaches MAX-1 (3) stack is over flow. When the
stack is empty TOP=-1
3
Implementation:
In most high level languages, a stack can be easily implemented either through an array or
a linked list.
Implementing stack using arrays:
The array implementation aims to create an array where the first element is the bottom. That
is, array[0] is the first element pushed onto the stack and the last element popped off.
Algorithm for inserting element into the stack:
Algorithm push()
1. If top=(max-size – 1) then write stack (‘stack over flow’) return.
2. read x
3. top <- top+1
4. stack[top] <- x
5. stop
C function for push operation:
void push()
{
if(top == max-1)
printf(“\n overflow”);
else
{
printf(“\n enter the elemnt”);
scanf(“%d”,&ele);
top++;
4
stack[top]=ele;
}
}
Algorithm to delete the element from the stack:
Algorithm pop()
1. if top = = -1 then write(‘ stack under flow’) return
2. x <- stack[top]
3. top <- top -1
4. return(x)
C function to delete the element from the stack
void pop()
{
if(top== -1)
printf(“\n under flow”);
else
{
ele=stack[top];
top - -;
printf(“\n the element deleted is %d”,ele);
}
}
Display of stack:
Algorithm print()
1. if top = =-1 then write(‘ stack empty’) Return
2. repeat for I <- top to 0 print ( stack[i])
3. stop.
C function to print the stack contents:
void print()
{
5
int i;
if(top = = -1)
printf(“ empty stock”);
else
{
for(i=top;i>=0;i--)
printf(“\n %d”,stack[i]);
}
}
/* Write C programs that implement stack (its operations) using Arrays */
#include<stdio.h>
#include<conio.h>
#include<process.h>
#include<stdlib.h>
int stack[20];
int top=-1,ele,temp;
void push();
void pop();
void display();
void main()
{
char choice;
do
{
printf(“======================================”);
printf(“\n\t\t MENU “);
printf(“\n======================================”);
printf(“\n[1] Push a element”);
printf(“\n[2] Pop element”);
printf(“\n[3] Elements present in Stack”);
printf(“\n[4] Stop\n”);
printf(“\n\tEnter your choice: “);
fflush(stdin);
scanf(“%c”,&choice);
switch(choice)
{
6
case 1:
push( );
break;
case 2:
pop( );
break;
case 3:
display( );
break;
case 4:
exit(1);
break;
default:
printf(“\nYour choice is invalid.\n”);
}
}while(choice!=4);
getch();
}
/*Implementing the push() function. */
void push( )
{
if(top==19)
{
printf(“stack is full.\n”);
getch();
exit(1);
}
else
{
printf(“\n enter the element”);
scnaf(“%d”,&ele);
top ++;
stack[top]=ele;
}
}
/*Implementing the pop() function. */
int pop_ele()
{
if(top = = -1)
{
printf(“\n\tstack is empty.\n”);
7
getch();
exit(1);
}
else
{
temp=stack[top];
top - -;
printf(“\n the deleted element is %d”,ele);
}
}
/*Implementing display() function. */
void display( )
{
int i;
if(top = = -1)
printf(“\n empty stack”);
else
{
printf(“\n\telements present in the stack are:\n\t”);
for(i=0;i<=t;i++)
printf(“%d\t”,stack[i]);
}
}
If we use a dynamic array, then we can implement a stack that can grow or shrink as much as
needed. The size of the stack is simply the size of the dynamic array. A dynamic array is a very
efficient implementation of a stack, since adding items to or removing items from the end of a
dynamic array is amortized O(1) time.
Linked list Implementation of Stack:
The linked-list implementation is equally simple and straightforward. In fact, a simple singly
linked list is sufficient to implement a stack -- it only requires that the head node or element can
be removed, or popped, and a node can only be inserted by becoming the new head node.
Unlike the array implementation, our structure typedef corresponds not to the entire stack
structure, but to a single node:
typedef struct stack {
int data;
struct stack *next;
} STACK;
Such a node is identical to a typical singly linked list node, at least to those that are implemented
in C.
8
The push() operation both initializes an empty stack, and adds a new node to a non-empty one. It
works by receiving a data value to push onto the stack, along with a target stack, creating a new
node by allocating memory for it, and then inserting it into a linked list as the new head:
A pop() operation removes the head from the linked list, and assigns the pointer to the head to
the previous second node. It checks whether the list is empty before popping from it:
C program to implement stack using pointers:
#include<stdio.h>
#include<conio.h>
#include<process.h>
#include<stdlib.h>
int size;
struct stack
{
int a[max];
int top;
};
void stk(struct stack *st)
{
st->top = –1;
}
void push(struct stack *st, int num)
{
if(st->top == size–1)
{
printf(“\n over flow\n”);
return;
}
st->top++;
st->a[st->top]=num;
}
int pop(stuct stack *st)
{
int num;
if(st->top==-1)
{
printf(“stack is under folw\n”);
return null;
}
num=st->a[st->top];
st->top—;
return num;
}
void display(struct stack *st)
{
int i;
9
for(i=st->top;i>=0;i—)
printf(“\n %d\t”,st->a[i]);
}
void main()
{
int d,i,n;
struct stack *ptr;
do
{
printf(“\n menu items\n1.push \t 2.pop\t3.display\t
4.exit\n”);
printf(“enter your choice:”);
scanf(“%d”,&i);
switch(i)
{
case 1: printf(“enter an element:”);
scanf(“%d”,&n);
push(&ptr,n);
break;
case 2: d=pop(&ptr);
printf(“\n deleted item %d”,d);
break;
case 3: printf(“elements of the stack are \n”);
display(&ptr);
break;
case 4: exit (0);
default: printf(“invalid choice”);
}
}
getch();
}
Stack applications:
Three applications of stacks are presented here. These examples are central to many activities
that a computer must do and deserve time spent with them.
1.
2.
3.
4.
5.
Expression evaluation
Parenthesis matching
Recursion
Backtracking (game playing, finding paths, exhaustive searching)
Memory management, run-time environment for nested language features.
Expression evaluation
In particular we will consider arithmetic expressions. Understand that there are Boolean and
logical expressions that can be evaluated in the same way. Control structures can also be treated
similarly in a compiler.
10
This study of arithmetic expression evaluation is an example of problem solving where you solve
a simpler problem and then transform the actual problem to the simpler one.
Infix, Prefix and Postfix Notation
We are accustomed to write arithmetic expressions with the operation between the two
operands: a+b or c/d. If we write a+b*c, however, we have to apply precedence rules to avoid
the ambiguous evaluation (add first or multiply first?).
There's no real reason to put the operation between the variables or values. They can just as well
precede or follow the operands. You should note the advantage of prefix and postfix: the need
for precedence rules and parentheses are eliminated.
Infix
a+b
Prefix
+ab
Postfix
ab+
a+b*c
+a*bc
abc*+
(a + b) * (c - d)
*+ab-cd
ab+cd-*
Postfix expressions are easily evaluated with the aid of a stack.
Postfix Evaluation Algorithm
Assume we have a string of operands and operators, an informal, by hand process is
1.
2.
3.
4.
Scan the expression left to right
Skip values or variables (operands)
When an operator is found, apply the operation to the preceding two operands
Replace the two operands and operator with the calculated value (three symbols are
replaced with one operand)
5. Continue scanning until only a value remains--the result of the expression
The time complexity is O(n) because each operand is scanned once, and each operation is
performed once.
A more formal algorithm:
create a new stack
while(input stream is not empty)
{
token = getNextToken();
if(token instanceof operand)
{
push(token);
}
else if (token instance of operator)
op2 = pop();
11
op1 = pop();
result = calc(token, op1, op2);
push(result);
}
}
return pop();
Infix transformation to Postfix
This process uses a stack as well. We have to hold information that's expressed inside
parentheses while scanning to find the closing ')'. We also have to hold information on operations
that are of lower precedence on the stack. The algorithm is:
1. Create an empty stack and an empty postfix output string/stream
2. Scan the infix input string/stream left to right
3. If the current input token is an operand, simply append it to the output string (note the
examples above that the operands remain in the same order)
4. If the current input token is an operator, pop off all operators that have equal or higher
precedence and append them to the output string; push the operator onto the stack. The
order of popping is the order in the output.
5. If the current input token is '(', push it onto the stack
6. If the current input token is ')', pop off all operators and append them to the output string
until a '(' is popped; discard the '('.
7. If the end of the input string is found, pop all operators and append them to the output
string.
This algorithm doesn't handle errors in the input, although careful analysis of parenthesis or lack
of parenthesis could point to such error determination.
Apply the algorithm to the above expressions.
Backtracking
Backtracking is used in algorithms in which there are steps along some path (state) from some
starting point to some goal.



Find your way through a maze.
Find a path from one point in a graph (roadmap) to another point.
Play a game in which there are moves to be made (checkers, chess).
In all of these cases, there are choices to be made among a number of options. We need some
way to remember these decision points in case we want/need to come back and try the alternative
Consider the maze. At a point where a choice is made, we may discover that the choice leads to
a dead-end. We want to retrace back to that decision point and then try the other (next)
alternative.
12
Again, stacks can be used as part of the solution. Recursion is another, typically more favored,
solution, which is actually implemented by a stack.
Call and return process
When a method/function is called
1. An activation record is created; its size depends on the number and size of the local
variables and parameters.
2. The Base Pointer value is saved in the special location reserved for it
3. The Program Counter value is saved in the Return Address location
4. The Base Pointer is now reset to the new base (top of the call stack prior to the creation
of the AR)
5. The Program Counter is set to the location of the first bytecode of the method being
called
6. Copies the calling parameters into the Parameter region
7. Initializes local variables in the local variable region
While the method executes, the local variables and parameters are simply found by adding a
constant associated with each variable/parameter to the Base Pointer.
When a method returns
1. Get the program counter from the activation record and replace what's in the PC
2. Get the base pointer value from the AR and replace what's in the BP
3. Pop the AR entirely from the stack.
Recursion in stack
There are different ways in which data can be organized. For example, if you are to store five
numbers then we can store them in five different variables, an array, a linked list, a binary tree,
etc. All these different ways of organizing the data are known as data structures. The compiler
uses one such data structure called stack for implementing normal as well as recursive function
calls.
A stack is a Last In First Out (LIFO) data structure. This means that the last item to get stored on
the stack (often called Push operation) is the first one to get out of it (often called as Pop
operation).
for examplemain( )
{
int a = 5, b = 2, c ;
c = add ( a, b ) ;
printf ( "sum = %d", c ) ;
}
add ( int i, int j )
{
int sum ;
13
sum = i + j ;
return sum ;
}
In this program before transferring the execution control to the function fun( ) the values of
parameters a and b are pushed onto the stack. Following this the address of the statement printf( )
is pushed on the stack and the control is transferred to fun( ). It is necessary to push this address
on the stack. In fun( ) the values of a and b that were pushed on the stack are referred as i and j.
In fun( ) the local variable sum gets pushed on the stack. When value of sum is returned sum is
popped up from the stack. Next the address of the statement where the control should be returned
is popped up from the stack. Using this address the control returns to the printf( ) statement in
main( ). Before execution of printf( ) begins the two integers that were earlier pushed on the
stack arenow popped off.
Queue:

A queue is a special kind of data structure in which insertions takes place from one end called
“rear” end and deletions takes place from other end called “front” end. That is insertions and
deletions take place from different ends.

Queue works on the basis of First In First Out(FIFO) , since the first element entered in a queue
will be the first element to be deleted.

This type of data structures used in time sharing systems where many user jobs will be waiting
in the system queue for processing.

A queue can be represented using sequential allocation or using pointers.
For example:
People waiting in the line at a bank form a queue., where the first person in the line is the first
person to be served and so on.
Classification of Queues:

Ordinary Queue or Linear Queue

Circular Queue

Double ended Queue( D Queue)

Priority Queue
Basic Operations on Queue: The operations that can be performed on queue are

Insertion

Deletion

Display
14
Queue maintains two pointers called rear and front. From rear end elements are inserted and from
front end elements are deleted.
Working of a Linear Queue:
0
1
3
4
2
3
4
0
1
Front=Rear= -1
0
1
2
10
F
10
R
2
4
20
F
i) Add 10
3
R
ii) add 20
0
10
1
2
20
30
3
40
4
50
F
R
iii) add 30,40,50
Now if we try to add element 60 results queue overflow. Now delete element 10 results front
pointer increment i.e that points next element in the queue.
0
1
2
20
30
F
3
40
4
50
R
Now delete 20,30,40 then queue state will as follow
15
0
1
2
3
4
50
F R
Here if we delete the element 50 from the queue then Front=Rear= -1;
/* Write C programs that implement Queue (its operations) using Pointers */
#define true 1
#define false 0
#include<stdio.h>
#include<conio.h>
#include<process.h>
struct q_point
{
int ele;
struct q_point* n;
};
struct q_point *f_ptr = NULL;
int e_que(void);
void add_ele(int);
int rem_ele(void);
void show_ele();
/*main function*/
void main()
{
int ele,choice,j;
while(1)
{
clrscr();
printf("\n\n****IMPLEMENTATION OF QUEUE USING POINTERS****\n");
printf("==============================================");
printf("\n\t\t MENU\n");
printf("==============================================");
printf("\n\t[1] To insert an element");
printf("\n\t[2] To remove an element");
printf("\n\t[3] To display all the elements");
printf("\n\t[4] Exit");
printf("\n\n\tEnter your choice:");
scanf("%d", &choice);
16
switch(choice)
{
case 1:
{
printf("\n\tElement to be inserted:");
scanf("%d",&ele);
add_ele(ele);
getch();
break;
}
case 2:
{
if(!e_que())
{
j=rem_ele();
printf("\n\t%d is removed from the queue",j);
getch();
}
else
{
printf("\n\tQueue is Empty.");
getch();
}
break;
}
case 3:
show_ele();
getch();
break;
case 4:
exit(1);
break;
default:
printf("\n\tInvalid choice.");
getch();
break;
}
}
}
/* Function to check if the queue is empty*/
int e_que(void)
{
if(f_ptr==NULL)
17
return true;
return false;
}
/* Function to add an element to the queue*/
void add_ele(int ele)
{
struct q_point *queue = (struct q_point*)malloc(sizeof(struct q_point));
queue->ele = ele;
queue->n = NULL;
if(f_ptr==NULL)
f_ptr = queue;
else
{
struct q_point* ptr;
ptr = f_ptr;
for(ptr=f_ptr ;ptr->n!=NULL; ptr=ptr->n);
ptr->n = queue;
}
}
/* Function to remove an element from the queue*/
int rem_ele()
{
struct q_point* queue=NULL;
if(e_que()==false)
{
int j = f_ptr->ele;
queue=f_ptr;
f_ptr = f_ptr->n;
free (queue);
return j;
}
else
{
printf("\n\tQueue is empty.");
return -9999;
}
}
/* Function to display the queue*/
void show_ele()
{
struct q_point *ptr=NULL;
ptr=f_ptr;
if(e_que())
{
printf("\n\tQUEUE is Empty.");
return;
}
18
else
{
printf("\n\tElements present in Queue are:\n\t");
while(ptr!=NULL)
{
printf("%d\t",ptr->ele);
ptr=ptr->n;
}
}
}
______________________________________________________________________________
/* C program to implement Queue using arrays*/
# include<stdio.h>
# define MAX 5
int cqueue_arr[MAX];
int front = -1;
int rear = -1;
main()
{
int choice;
while(1)
{
printf("1.Insert\n");
printf("2.Delete\n");
printf("3.Display\n");
printf("4.Quit\n");
printf("Enter your choice : ");
scanf("%d",&choice);
switch(choice)
{
case 1 :
insert();
break;
case 2 :
del();
break;
case 3:
display();
break;
case 4:
exit(1);
default:
printf("Wrong choice\n");
}/*End of switch*/
}/*End of while */
19
}/*End of main()*/
insert()
{
int added_item;
if(rear == MAX-1)
{
printf("Queue Overflow \n");
return;
}
else
{
printf("Input the element for insertion in queue : ");
scanf("%d", &added_item);
if (front == -1) /*If queue is empty */
{
front = 0;
rear = 0;
}
rear = rear+1;
cqueue_arr[rear] = added_item ;
}/*End of insert()*/
del()
{
if (front == -1)
{
printf("Queue Underflow\n");
return ;
}
printf("Element deleted from queue is : %d\n",cqueue_arr[front]);
if(front == rear) /* queue has only one element */
{
front = -1;
rear=-1;
}
else
front = front+1;
}/*End of del() */
display()
{
int i;
if(front == -1)
{
printf("Queue is empty\n");
return;
}
else
20
{
printf("Queue elements :\n");
For(i=front;i<=rear;i++)
printf(“%d\n “,queue_arr[i]);
}/*End of else */
printf("\n");
}/*End of display() */
Circular Queue
A circular queue is a Queue but a particular implementation of a queue. It is very efficient. It is
also quite useful in low level code, because insertion and deletion are totally independent.
Algorithm for Insertion:Step-1: If "rear" of the queue is pointing to the last position then go to step-2 or else step-3
Step-2: make the "rear" value as 0
Step-3: increment the "rear" value by one
Step-4:
1. if the "front" points where "rear" is pointing and the queue holds a not NULL value for it,
then its a "queue overflow" state, so quit; else go to step-4.2
2. insert the new value for the queue position pointed by the "rear"
Algorithm for deletion:Step-1: If the queue is empty then say "empty queue" and quit; else continue
Step-2: Delete the "front" element
Step-3: If the "front" is pointing to the last position of the queue then step-4 else step-5
Step-4: Make the "front" point to the first position in the queue and quit
Step-5: Increment the "front" position by one
Program:
/* Program of circular queue using array*/
# include<stdio.h>
# define MAX 5
int cqueue_arr[MAX];
int front = -1;
int rear = -1;
main()
{
int choice;
while(1)
{
printf("1.Insert\n");
printf("2.Delete\n");
printf("3.Display\n");
printf("4.Quit\n");
21
printf("Enter your choice : ");
scanf("%d",&choice);
switch(choice)
{
case 1 :
insert();
break;
case 2 :
del();
break;
case 3:
display();
break;
case 4:
exit(1);
default:
printf("Wrong choice\n");
}/*End of switch*/
}/*End of while */
}/*End of main()*/
insert()
{
int added_item;
if((front == 0 && rear == MAX-1) || (front == rear+1))
{
printf("Queue Overflow \n");
return;
}
if (front == -1) /*If queue is empty */
{
front = 0;
rear = 0;
}
else
if(rear == MAX-1)/*rear is at last position of queue */
rear = 0;
else
rear = rear+1;
printf("Input the element for insertion in queue : ");
scanf("%d", &added_item);
cqueue_arr[rear] = added_item ;
}/*End of insert()*/
del()
{
if (front == -1)
{
printf("Queue Underflow\n");
22
return ;
}
printf("Element deleted from queue is : %d\n",cqueue_arr[front]);
if(front == rear) /* queue has only one element */
{
front = -1;
rear=-1;
}
else
if(front == MAX-1)
front = 0;
else
front = front+1;
}/*End of del() */
display()
{
int front_pos = front,rear_pos = rear;
if(front == -1)
{
printf("Queue is empty\n");
return;
}
printf("Queue elements :\n");
if( front_pos <= rear_pos )
while(front_pos <= rear_pos)
{
printf("%d ",cqueue_arr[front_pos]);
front_pos++;
}
else
{
while(front_pos <= MAX-1)
{
printf("%d ",cqueue_arr[front_pos]);
front_pos++;
}
front_pos = 0;
while(front_pos <= rear_pos)
{
printf("%d ",cqueue_arr[front_pos]);
front_pos++;
}
}/*End of else */
printf("\n");
}/*End of display() */
23
A priority queue:
It is
an abstract
data
type in computer
programming.
It
is
exactly
like
a
regular queue or stack data structure, but additionally, each element is associated with a
"priority". priority queue: elements are pulled highest-priority-first (e.g. cutting in line,
or VIP service). A priority queue is an abstract concept like "a list" or "a map"; just like a list can
be implemented with a linked list or an array, a priority queue can be implemented with a heap
or a variety of other methods.
A priority queue must at least support the following operations:

insertWithPriority: add an element to the queue with an associated priority

pullHighestPriorityElement: remove the element from the queue that has the highest priority,
and return it

More advanced implementations may support more complicated operations, such as
pullLowestPriorityElement, inspecting the first few highest- or lowest-priority elements
clearing the queue, clearing subsets of the queue, performing a batch insert, etc.
One can imagine a priority queue as a modified queue, but when one would get the next element
off the queue, the highest-priority one is retrieved first. Stacks and queues may be modeled as
particular kinds of priority queues.
D queus:
In computer science, a double-ended queue (dequeue) is an abstract data structure that
implements a queue for which elements can only be added to or removed from the front (head)
or back (tail). It is also often called a head-tail linked list. This differs from the queue abstract
data type or First-In-First-Out List (FIFO), where elements can only be added to one end and
removed from the other. This general data class has some possible sub-types:

An input-restricted deque is one where deletion can be made from both ends, but insertion can
only be made at one end.

An output-restricted deque is one where insertion can be made at both ends, but deletion can be
made from one end only.
Both the basic and most common list types in computing, queues and stacks can be considered
specializations of deques, and can be implemented using deques.
24
LINKED LIST:
Introduce to Singly-linked List
Singly-linked list is a list of elements in which the elements of the list can be placed anywhere in
heap memory. All of list elements are linked together with each other using an explicit link field,
that is, by storing the address of the next element in the link field of the previous element.
Singly-linked list has a dynamic size and its size can be determined at run-time not compile time.
Here the picture which demonstrate a singly-linked list. Their are four elements in the list.
The head pointer is the pointer pointing to the first element of the list.
Add a New Element to a Singly-linked List
This picture demonstrates how to add a new elemen to the list. The process is simple as follows:
- If the existing list is empty we need to insert a new element (or node) as the starting node
- Otherwise we traverses the existing list to get the pointer to the last node of it;
1.
Create a new node.
2.
Change the next pointer of the last node to the new node.
3.
The next pointer of new node is pointed to NULL and it becomes the last node of the list.
New node
Implement Singly-linked List in C
A Linked list is a chain of structs or records called Nodes. Each node has at least two members,
one of which points to the next Node in the list and the other holds the data. These are defined as
Single Linked Lists because they can only point to the next Node in the list but not to the
previous.
1. struct Node
2. {
3. int Data;
4. struct Node *Next;
5. }*Head;
25
We use above structure for a Node in our example. Variable Data holds the data in the Node
while pointer of type struct Node Next holds the address to the next Node in the list. Head is a
pointer of type struct Node which acts as the Head to the list.
Initially we set 'Head' as NULL which means list is empty.
1. //Set HEAD as NULL
2. Head=NULL;
Let us see Insertion Functions .. addBeg, addEnd, addAt.
1. // Adding a Node at the Beginning of the List
2.
3. void addBeg(int num)
4. {
5. struct Node *temp;
6.
7. temp=(struct Node *)malloc(sizeof(struct Node));
8. temp->Data = num;
9.
10. if (Head == NULL)
11. {
12.
//List is Empty
13.
Head=temp;
14.
Head->Next=NULL;
15. }
16. else
17. {
18.
temp->Next=Head;
19.
Head=temp;
20. }
21. }
We create 'temp' node and save the Data part.
26
If Head is NULL it means list is empty. So we set temp node as the Head of the list and set
theNext as NULL. Else we set the Next in temp node as Head and reassign Head with temp.
1. //Adding a Node at the end of the list
2.
3. void addEnd(int num)
4. {
5.
struct Node *temp1, *temp2;
6.
7.
temp1=(struct Node *)malloc(sizeof(struct Node));
8.
temp1->Data=num;
9.
10. // Copying the Head location into another node.
11. temp2=Head;
12.
13. if(Head == NULL)
14. {
15.
// If List is empty we create First Node.
16.
Head=temp1;
17.
Head->Next=NULL;
18. }
19. else
20. {
21.
// Traverse down to end of the list.
22.
while(temp2->Next != NULL)
23.
temp2=temp2->Next;
24.
25.
// Append at the end of the list.
26.
temp1->Next=NULL;
27.
temp2->Next=temp1;
28. }
29. }
27
1. // Adding a new Node at specified position
2.
3. void addAt(int num, int loc)
4. {
5. int i;
6. struct Node *temp, *prev_ptr, *cur_ptr;
7.
8. cur_ptr=Head;
9.
10. if(loc > (length()+1) || loc <= 0)
11. {
12.
printf("\nInsertion at given location is not possible\n ");
13. }
14. else
15. {
16.
// If the location is starting of the list
17.
if (loc == 1)
18.
{
19.
addBeg(num);
20.
}
21.
else
22.
{
23.
for(i=1;i<loc;i++)
24.
{
25.
prev_ptr=cur_ptr;
26.
cur_ptr=cur_ptr->Next;
27.
}
28.
29.
temp=(struct Node *)malloc(sizeof(struct Node));
30.
temp->Data=num;
31.
32.
prev_ptr->Next=temp;
33.
temp->Next=cur_ptr;
34.
}
35. }
36. }
37.
38. // Counting number of elements in the List
39.
40. int length()
41. {
42. struct Node *cur_ptr;
43. int count=0;
44.
45. cur_ptr=Head;
46.
47. while(cur_ptr != NULL)
48. {
49.
cur_ptr=cur_ptr->Next;
50.
count++;
28
51. }
52. return(count);
53. }
Now we will see how to delete a node from the list depending upon the data in the Node.
1. // Deleting a node from List depending upon the data in the node.
2.
3. int delNodeData(int num)
4. {
5. struct Node *prev_ptr, *cur_ptr;
6.
7. cur_ptr=Head;
8.
9. while(cur_ptr != NULL)
10. {
11.
if(cur_ptr->Data == num)
12.
{
13.
if(cur_ptr==Head)
14.
{
15.
Head=cur_ptr->Next;
16.
free(cur_ptr);
17.
return 0;
18.
}
19.
else
20.
{
21.
prev_ptr->Next=cur_ptr->Next;
22.
free(cur_ptr);
23.
return 0;
24.
}
25.
}
26.
else
27.
{
28.
prev_ptr=cur_ptr;
29.
cur_ptr=cur_ptr->Next;
30.
}
29
31. }
32.
33. printf("\nElement %d is not found in the List", num);
34. return 1;
35. }
If the value to be deleted is the head of the list.
If the value to be deleted is not the head of the list.
Similarly if we want to delete a node based on its location in the list.
1. // Deleting a node from List depending upon the location in the list.
2.
3. int delNodeLoc(int loc)
4. {
5. struct Node *prev_ptr, *cur_ptr;
6. int i;
7.
8. cur_ptr=Head;
9.
10. if(loc > (length()) || loc <= 0)
30
11. {
12.
printf("\nDeletion of Node at given location is not possible\n ");
13. }
14. else
15. {
16.
// If the location is starting of the list
17.
if (loc == 1)
18.
{
19.
Head=cur_ptr->Next;
20.
free(cur_ptr);
21.
return 0;
22.
}
23.
else
24.
{
25.
for(i=1;i<loc;i++)
26.
{
27.
prev_ptr=cur_ptr;
28.
cur_ptr=cur_ptr->Next;
29.
}
30.
31.
prev_ptr->Next=cur_ptr->Next;
32.
free(cur_ptr);
33.
}
34. }
35. return 1;
36. }
Displaying a list.
1. // Displaying list contents
2.
3. void display()
4. {
5. struct Node *cur_ptr;
6.
7. cur_ptr=Head;
8.
9. if(cur_ptr==NULL)
10. {
11.
printf("\nList is Empty");
12. }
13. else
14. {
15.
printf("Elements in the List: ");
16.
//traverse the entire linked list
17.
while(cur_ptr!=NULL)
18.
{
19.
printf(" -> %d ",cur_ptr->Data);
20.
cur_ptr=cur_ptr->Next;
21.
}
31
22.
printf("\n");
23. }
24. }
Reversing a list.
1. //Reversesing a Linked List
2.
3. void reverse()
4. {
5. struct Node *prev_ptr, *cur_ptr, *temp;
6.
7. cur_ptr=Head;
8. prev_ptr=NULL;
9.
10. while(cur_ptr != NULL)
11. {
12.
temp=prev_ptr;
13.
prev_ptr=cur_ptr;
14.
15.
cur_ptr=cur_ptr->Next;
16.
prev_ptr->Next=temp;
17. }
18.
19. Head=prev_ptr;
20. }
Alternate program for linked list:
01
02
#include stdio.h>
#include <stdlib.h>
03
04
struct node{
05
06
int data;
struct node *next;
07
08
};
09
10
struct node* add(struct node *head, int data){
struct node *tmp;
11
12
if(head == NULL){
13
14
head=(struct node *)malloc(sizeof(struct node));
if(head == NULL){
32
15
16
printf("Error! memory is not available\n");
exit(0);
17
18
}
head-> data = data;
19
20
head-> next = head;
}else{
21
22
tmp = head;
23
24
while (tmp-> next != head)
tmp = tmp-> next;
25
26
tmp-> next = (struct node *)malloc(sizeof(struct node));
if(tmp -> next == NULL)
27
28
{
printf("Error! memory is not available\n");
29
30
exit(0);
}
32
tmp = tmp->
next;
tmp-> data = data;
33
34
tmp-> next = head;
}
35
36
return head;
}
37
38
void printlist(struct node *head)
39
40
{
struct node *current;
41
42
current = head;
if(current!= NULL)
43
44
{
do
45
46
{
printf("%d\t",current->data);
47
current = current->next;
} while (current!=
head);
31
48
49
50
printf("\n");
}
51
else
33
52
printf("The list is empty\n");
53
54
}
55
56
void destroy(struct node *head)
57
58
{
struct node *current, *tmp;
59
60
current = head->next;
61
62
head->next = NULL;
while(current != NULL) {
63
64
tmp = current->next;
free(current);
65
66
current = tmp;
}
67
68
}
void main()
69
70
{
struct node *head = NULL;
71
72
head = add(head,1); /* 1 */
printlist(head);
73
74
head = add(head,20);/* 20 */
75
76
printlist(head);
77
78
head = add(head,10);/* 1 20 10 */
printlist(head);
79
80
head = add(head,5); /* 1 20 10 5*/
81
82
printlist(head);
83
84
destroy(head);
getchar();
85
}
34
Questions from Previous papers:
1. What are the operations on linear lists? Differentiate between using arrays and linked lists for
implementing of linear lists.[7M]
2. Write a structure of implementing linked list of integers . Write C function for insertion
operation in linked list.[8M]
3. Write an algorithm for evaluating postfix expression . Demonstrate your algorithm with stack
contents for each operation using the postfix expression 235+*
[8M]
4. Write structure for linked list implementation of stack and function for pop operation. [7M]
5. Write an algorithm that convert the given infix expression in to postfix. Demonstrate your
algorithm using stack for the expression a+b*c [7M]
6. Write a C structure for implementing queues using linked list. Using this structure , write cfunction for D queue operation. [8M]
7. Write a C structure for implementing stack using an array. Using this structure write c
functions for push and pop operations. [8M]
8. Using recursive function for factorial, explain the execution of the function call fact(5) using
stack. [7M].
**************************all the best***************************
35