Data Structures
Data Structures
• A sequence of elements
• There is first and last element
• Each element has previous and next
– Nothing before first
– Nothing after last
Why linked lists ?
• A linked list is a dynamic data structure.
– It can grow or shrink in size during the execution
of a program.
– It can be made just as long as required.
– It does not waste memory space.
• Linked lists provide flexibility in allowing the
items to be rearranged efficiently.
– Insert an element.
– Delete an element.
• What we can do with a linear list?
– Delete element
– Insert element
– Find element
– Traverse list
Illustration: Insertion
A B C
Item to be
X inserted
A B C
X
Illustration: Deletion
A B C
A B C
In essence ...
• For insertion:
– A record is created holding the new item.
– The next pointer of the new record is set to link it
to the item which is to follow it in the list.
– The next pointer of the item which is to precede it
must be modified to point to the new item.
• For deletion:
– The next pointer of the item immediately preceding
the one to be deleted is altered, and made to point
to the item following the deleted item.
Traverse: list elements in
order
• get_first(list) -
– returns first element if it exists
• get_next(list) -
– returns next element if it exists
• Both functions return NULL otherwise
• Calling get_next in a loop we will get one by one all
elements of the list
How we can implement a list?
• Array?
• Search is easy (sequential or binary)
• Traversal is easy:
for(i = first; i <= last; ++i)
process(a[i]);
• Insert and delete is not easy
– a good part of the array has to be moved!
• Hard to guess the size of an array
A linked list implementation
Insert
List
implementation
Delete
and the
related functions
Traverse
Example: Working with linked list
• Consider the structure of a node as follows:
struct stud {
int roll;
char name[25];
int age;
struct stud *next;
};
name next
age
Contd.
• If there are n number of nodes in the initial
linked list:
– Allocate n records, one by one.
– Read in the fields of the records.
– Modify the links of the records so that the
chain is formed.
void create_list (node *list)
{
int k, n;
node *p;
printf (“\n How many elements?”);
scanf (“%d”, &n);
To be called from the main()
list = (node *) malloc (sizeof (node)); function as:
p = list;
for (k=0; k<n; k++) node *head;
{ …….
create_list (head);
scanf (“%d %s %d”, &p->roll,
p->name, &p->age);
p->next = (node *) malloc
(sizeof (node));
p = p->next;
}
free (p->next);
p->next = NULL;
}
Traversing the List
• Once the linked list has been constructed
and head points to the first node of the list,
– Follow the pointers.
– Display the contents of the nodes as they are
traversed.
– Stop when the next pointer points to NULL.
void display_list (node *list)
{
int k = 0;
node *p;
p = list;
while (p != NULL)
{
printf (“Node %d: %d %s %d”, k, p->roll,
p->name, p->age);
k++;
p = p->next;
}
}
Inserting a Node in the List
• The problem is to insert a node before a
specified node.
– Specified means some value is given for the
node (called key).
– Here it may be roll.
• Convention followed:
– If the value of roll is given as negative, the
node will be inserted at the end of the list.
• When a node is added at the beginning,
– Only one next pointer needs to be modified.
• head is made to point to the new node.
• New node points to the previously first element.
• When a node is added at the end,
– Two next pointers need to be modified.
• Last node now points to the new node.
• New node points to NULL.
• When a node is added in the middle,
– Two next pointers need to be modified.
• Previous node now points to the new node.
• New node points to the next node.
void insert_node (node *list)
{
int k = 0, rno;
node *p, *q, *new;
p = list;
if (p->roll == rno) /* At the beginning */
{
new->next = p;
list = new;
}
while ((p != NULL) && (p->roll != rno))
{
q = p;
p = p->next;
}
The pointers q and p
if (p == NULL) /* At the end */ always point to
{
consecutive nodes.
q->next = new;
new->next = NULL;
}
p = list;
if (p->roll == rno) /* Delete the first element */
{
list = p->next;
free (p);
}
while ((p != NULL) && (p->roll != rno))
{
q = p;
p = p->next;
}
A B C
Assignment :
Insertion, deletion in a doubly
linked list
A First-in First-out (FIFO) List
In Out
C B A B A
C B A B C
Also called a
STACK
Stack
Stacks in Our Life
More Stacks
pop
create
STACK
isempty
isfull
Assume:: stack contains integer elements
struct lifo {
int st[MAXSIZE];
int top;
};
typedef struct lifo stack;
Stack Creation
struct lifo {
int element;
struct lifo *next;
};
typedef struct lifo stack;
stack *top;
Contd.
• Basic concept:
– Insertion (push) and deletion (pop) operations
take place at one end of the list only.
– For stack creation / push operation
• Required to call malloc function
– How to check stack underflow?
• Easy. Simply check if top points to NULL.
– How to check overflow?
• Check is malloc returns –1.
Sample Usage
stack A, B;
7 4 1 5
front rear
11 37 22 15 3 -7 1
Structure for a queue array
struct intqueue {
int *queueArray;
int maxSize;
int count;
int front;
int rear;
};
Queue Implementation Using Linked List
• Basic idea:
– Create a linked list to which items would be added to one end
and deleted from the other end.
– Two pointers will be maintained:
• One pointing to the beginning of the list (point from where
elements will be deleted).
• Another pointing to the end of the list (point where new
elements will be inserted). Rear
Front
Assume:: queue contains integer elements
front = NULL;
rear = NULL;
Inserting an element in queue
void enqueue (queue q, int x)
{
queue *ptr;
ptr = (queue *) malloc (sizeof (queue));