self-referential structures and linked listisg/pds/slides/l10-1.pdf– inserting/deleting an element...
TRANSCRIPT
3/22/2016
1
Self-referential Structuresand
Linked List
1
Linked List :: Basic Concepts
• A list refers to a set of items organized sequentially.
– An array is an example of a list.
• The array index is used for accessing and manipulating array elements.
– Problems with array:
• The array size has to be specified at the
2
The array size has to be specified at the beginning.
• Deleting an element or inserting an element may require shifting of elements in the array.
3/22/2016
2
Contd.
• A completely different way to represent a list:
– Make each item in the list part of a structure.
– The structure also contains a pointer or link to the structure containing the next item.
– This type of list is called a linked list.
3
Structure 1 Structure 2 Structure 3
item item item
Contd.
• Each structure of the list is called a node, and consists of two fields:
O t i i th d t it ( )– One containing the data item(s).
– The other containing the address of the next item in the list (that is, a pointer).
• The data items comprising a linked list need not be contiguous in memory.
4
– They are ordered by logical links that are stored as part of the data in the structure itself.
– The link is a pointer to another structure of the same type.
3/22/2016
3
Contd.
• Such a structure can be represented as:struct node{
int item;struct node *next;
}
it
node
t
5
• Such structures which contain a member field pointing to the same structure type are called self-referential structures.
item next
Contd.
• In general, a node may be represented as follows:
struct node_name{
type member1;type member2;………
6
struct node_name *next;}
3/22/2016
4
Illustration
• Consider the structure:struct stud
{int roll;char name[30];int age;struct stud *next;
}
7
• Also assume that the list consists of three nodes n1, n2 and n3.
struct stud n1, n2, n3;
Contd.
• To create the links between nodes, we can write:
n1.next = &n2;
n2.next = &n3;
n3.next = NULL; /* No more nodes follow */
• Now the list looks like:
8
n1 n2 n3
rollname
agenext
3/22/2016
5
• Some important observations:
– The NULL pointer is used to indicate that no pmore nodes follow, that is, it is the end of the list.
– To use a linked list, we only need a pointer to the first element of the list.
– Following the chain of pointers, the successive l t f th li t b d belements of the list can be accessed by
traversing the list.
9
Example: without using function
#include <stdio.h>struct stud{
int roll;h [30]char name[30];int age;struct stud *next;
}
main(){
struct stud n1, n2, n3;
10
, ,struct stud *p;
scanf (”%d %s %d”, &n1.roll, n1.name, &n1.age);scanf (”%d %s %d”, &n2.roll, n2.name, &n2.age);scanf (”%d %s %d”, &n3.roll, n3.name, &n3.age);
3/22/2016
6
n1.next = &n2;n2.next = &n3;n3 next = NULL;n3.next = NULL;
/* Now traverse the list and print the elements */
p = &n1; /* point to 1st element */while (p != NULL){printf (”\n %d %s %d”, p->roll, p->name, p->age);
11
p = p->next;}
}
A function to carry out traversal
#include <stdio.h>struct stud
{int roll;char name[30];int age;struct stud *next;
}
void traverse (struct stud *head){
hil (h d ! NULL)
12
while (head != NULL){printf (”\n %d %s %d”, head->roll, head->name,
head->age);head = head->next;
}}
3/22/2016
7
The corresponding main() function
main(){{
struct stud n1, n2, n3, *p;
scanf (”%d %s %d”, &n1.roll, n1.name, &n1.age);scanf (”%d %s %d”, &n2.roll, n2.name, &n2.age);scanf (”%d %s %d”, &n3.roll, n3.name, &n3.age);
n1.next = &n2; n2.next = &n3;
13
;n3.next = NULL;
p = &n1;traverse (p);
}
Alternative and More General Way
• Dynamically allocate space for the nodes.
– Use malloc() or calloc() for allocating () () gspace for every individual nodes.
– No need for allocating additional space unnecessarily like in an array.
14
3/22/2016
8
Linked List in more detail
15
Introduction
• A linked list is a data structure which can change during execution.– Successive elements are connected by pointers.– Last element points to NULL.
– It can grow or shrink in size during execution of a program.
– It can be made just as long as required.
It d t thead
16
– It does not waste memory space.
A B C
3/22/2016
9
• Keeping track of a linked list:
– Must know the pointer to the first element ofMust know the pointer to the first element of
the list (called start, head, etc.).
• Linked lists provide flexibility in allowing the items to be rearranged efficiently.
Insert an element
17
– Insert an element.
– Delete an element.
Illustration: Insertion
A B C
head
Item to be inserted
A B C
Xhead
18
X
3/22/2016
10
Illustration: Deletion
A B C
Item to be deletedhead
CA B
head
19
In essence ...
• For insertion:– A record is created holding the new item.g
– 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:
20
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.
3/22/2016
11
Array versus Linked Lists
• Arrays are suitable for:– Inserting/deleting an element at the end.
– Randomly accessing any element.
– Searching the list for a particular value.
• Linked lists are suitable for:– Inserting an element.
– Deleting an element
21
Deleting an element.
– Applications where sequential access is required.
– In situations where the number of elements cannot be predicted beforehand.
Types of Lists
• Depending on the way in which the links are used to maintain adjacency, several different types of linked lists are possible.
– Linear singly-linked list (or simply linear list)
• One we have discussed so far.
head
22
A B C
3/22/2016
12
– Circular linked list
• The pointer from the last element in the list ppoints back to the first element.
A B C
head
23
– Doubly linked list
• Pointers exist between adjacent nodes in both directions.
• The list can be traversed either forward or backward.
• Usually two pointers are maintained to keep track of the list, head and tail.head tail
24
A B C
3/22/2016
13
Basic Operations on a List
• Creating a list
• Traversing the listTraversing the list
• Inserting an item in the list
• Deleting an item from the list
• Concatenating two lists into one
25
List is an Abstract Data Type
• What is an abstract data type?– It is a data type defined by the user.
– Typically more complex than simple data types like int, float, etc.
• Why abstract?– Because details of the implementation are
hidden.
Wh d ti th li t
26
– When you do some operation on the list, say insert an element, you just call a function.
– Details of how the list is implemented or how the insert function is written is no longer required.
3/22/2016
14
Conceptual Idea
List implementation
and therelated functions
Insert
Delete
27
related functionsTraverse
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;
};
28
/* A user-defined data type called “node” */
typedef struct stud node;node *head;
3/22/2016
15
Creating a List
29
How to begin?
• To start with, we have to create a node (the first node), and make head point to it.
head = (node *) malloc(sizeof(node));
head
nextname
roll
30
age
3/22/2016
16
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.
head
31
A B C
node *create_list() {
int k, n; node *p, *head;
printf ("\n How many elements to enter?"); scanf ("%d", &n);
for (k=0; k<n; k++) ( ; ; ){
if (k == 0) {head = (node *) malloc (sizeof(node)); p = head;
}else {
p->next = (node *) malloc (sizeof(node)); p = p->next;
}
f ("%d % %d" & > ll > & > )
32
scanf ("%d %s %d", &p->roll, p->name, &p->age); }
p->next = NULL; return (head);
}
3/22/2016
17
• To be called from main() function as:
node *head;
………
head = create_list();
33
Traversing the List
34
3/22/2016
18
What is to be done?
• 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.
35
p p p
void display (node *head){int count = 1;node *p;
p = head;while (p != NULL){printf ("\nNode %d: %d %s %d", count,
p->roll, p->name, p->age);count++;
36
count++;p = p->next;
}printf ("\n");
}
3/22/2016
19
• To be called from main() function as:
node *head;
………
display (head);
37
Inserting a Node in a List
38
3/22/2016
20
How to do?
• The problem is to insert a node before a specified node.
– Specified means some value is given for the node (called key).
– In this example, we consider it to be roll.
• Convention followed:
If th l f ll i i ti th
39
– If the value of roll is given as negative, the node will be inserted at the end of the list.
Contd.
• 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,
T i d b difi d
40
– Two next pointers need to be modified.
• Last node now points to the new node.
• New node points to NULL.
3/22/2016
21
• When a node is added in the middle,
– Two next pointers need to be modified.Two next pointers need to be modified.
• Previous node now points to the new node.
• New node points to the next node.
41
void insert (node **head) {
int k = 0, rno; node *p, *q, *new;
new = (node *) malloc (sizeof(node));
printf ("\nEnter data to be inserted: ");scanf ("%d %s %d", &new->roll, new->name, &new->age); printf ("\nInsert before roll (-ve for end):"); scanf ("%d", &rno);
p = *head;
42
if (p->roll == rno) /* At the beginning */ {
new->next = p; *head = new;
}
3/22/2016
22
else {while ((p != NULL) && (p->roll != rno)) {
q = p; p = p->next;
} }
if (p == NULL) /* At the end */ {
q->next = new; new->next = NULL;
}
else if (p->roll == rno) /* I th iddl */
43
/* In the middle */ {
q->next = new; new->next = p;
} }
}
The pointers q and p always point to consecutive nodes.
• To be called from main() function as:
node *head;
………
insert (&head);
44
3/22/2016
23
Deleting a node from the list
45
What is to be done?
• Here also we are required to delete a specified node.
– Say, the node whose roll field is given.
• Here also three conditions arise:
– Deleting the first node.
– Deleting the last node.
46
– Deleting an intermediate node.
3/22/2016
24
void delete (node **head) {
int rno; node *p, *q;
printf ("\nDelete for roll: "); scanf ("%d", &rno);
p = *head; if (p->roll == rno)
/* Delete the first element */ {
47
{*head = p->next; free (p);
}
else{
while ((p != NULL) && (p->roll != rno)) {
q = p; > tp = p->next;
}
if (p == NULL) /* Element not found */ printf ("\nNo match :: deletion failed");
else if (p->roll == rno) /* Delete any other element */
48
y{
q->next = p->next; free (p);
} }
}
3/22/2016
25
A sample main() function
int main(){
node *head;node head;
head = create_list();display(head);
insert(&head);display(head);
49
delete(&head);display(head);
}
Few Exercises to Try Out
• Write functions to:
1. Concatenate two given lists into one big list.node *concatenate (node *head1, node *head2);
2. Insert an element in a linked list in sorted order. The function will be called for every element to be inserted.
void insert_sorted (node **head, node *element);
3 Always insert elements at one end and delete
50
3. Always insert elements at one end, and delete elements from the other end (first-in first-out QUEUE).void insert_q (node **head, node*element)
node *delete_q (node **head) /* Return the deleted node */
3/22/2016
26
More Exercises
4. Implement a circular linked list, and write functions to insert, delete, and traverse nodes in the listin the list.
5. Represent a polynomial as a linked list, where every node will represent a term of the polynomial (anxn), and will contain the values of ‘n’ and ‘an’. Write a function to add two given polynomials.
51
Abstract Data Types
52
3/22/2016
27
Definition
• An abstract data type (ADT) is a specification of a set of data and the set of operations that pcan be performed on the data.
• Such data type is abstract in the sense that it is independent of various concrete implementations.
53
• Some examples follow.
Example 1 :: Complex numbers
struct cplx {float re;float im;
Structure d fi iti
;}
typedef struct cplx complex;
complex *add (complex a, complex b);complex *sub (complex a, complex b);complex *mul (complex a, complex b);complex *div (complex a, complex b);
definition
Function prototypes
54
p p pcomplex *read();void print (complex a);
prototypes
3/22/2016
28
add
sub
ComplexNumber
mul
div
55
read
Example 2 :: Set manipulation
struct node {int element;struct node *next;
Structure d fi iti
;}
typedef struct node set;
set *union (set a, set b);set *intersect (set a, set b);set *minus (set a, set b);void insert (set a, int x);
definition
Function prototypes
56
void delete (set a, int x);int size (set a);
p yp
3/22/2016
29
union
intersect
Setminus
insert
57
size
delete
Example 3 :: Last-In-First-Out STACK
Assume:: stack contains integer elements
void push (stack s, int element);void push (stack s, int element);/* Insert an element in the stack */
int pop (stack s);/* Remove and return the top element */
void create (stack s);/* Create a new stack */
int isempty (stack s);
58
int isempty (stack s);/* Check if stack is empty */
int isfull (stack s);/* Check if stack is full */
3/22/2016
30
push
pop
STACKcreate
isempty
59
isfull
Visualization of a Stack
In Out
ABC CB
60
3/22/2016
31
Contd.
• We shall later look into two different ways of implementing stack:
– Using arrays
– Using linked list
61
Example 4 :: First-In-First-Out QUEUE
Assume:: queue contains integer elements
void enqueue (queue q, int element);void enqueue (queue q, int element);/* Insert an element in the queue */
int dequeue (queue q);/* Remove an element from the queue */
queue *createq();/* Create a new queue */
int isempty (queue q);
62
int isempty (queue q);/* Check if queue is empty */
int size (queue q);/* Return the no. of elements in queue */
3/22/2016
32
enqueue
dequeue
QUEUEcreate
isempty
63
size
Visualization of a Queue
In Out
AC B AB
64
3/22/2016
33
Stack Implementation
a) Using arraysb) Using linked list
65
Basic Idea
• In the array implementation, we would:– Declare an array of fixed size (which determines the
i i f th t k)maximum size of the stack).
– Keep a variable top which always points to the “top” of the stack.
• Contains the array index of the “top” element.
• In the linked list implementation, we would:M i i h k li k d li
66
– Maintain the stack as a linked list.
– A pointer variable top points to the start of the list.
– The first element of the linked list is considered as the stack top.
3/22/2016
34
Declaration
#define MAXSIZE 100
struct lifo
struct lifo {
int value;{
int st[MAXSIZE];int top;
};
typedef struct lifo stack;
struct lifo *next;};
typedef struct lifo stack;
67
ARRAY LINKED LIST
Stack Creation
void create (stack *s){
(*s).top = -1;
void create (stack **top){
*top = NULL;
/* s.top points to last element pushed in; initially -1 */
}
/* top points to NULL,indicating emptystack */
}
ARRAYLINKED LIST
68
ARRAY
3/22/2016
35
Pushing an element into the stack
void push (stack *s, int element){
if ((*s).top == (MAXSIZE-1)){
printf (”\n Stack overflow”);exit(-1);
}else{
(*s).top++;(* ) t[(* ) t ] l t
69
(*s).st[(*s).top] = element;}
}
ARRAY
void push (stack **top, int element){
stack *new;
new = (stack *) malloc(sizeof(stack));if (new == NULL){
printf (”\n Stack is full”);exit(-1);
}
new->value = element; *
70
new->next = *top;*top = new;
}
LINKED LIST
3/22/2016
36
Popping an element from the stack
int pop (stack *s){
if ((*s).top == -1)(( ) p ){
printf (”\n Stack underflow”);exit(-1);
}else{
return ((*s).st[(*s).top--]);
71
p}
}
ARRAY
int pop (stack **top){
int t; stack *p;
if (*top == NULL){
printf (”\n Stack is empty”);exit(-1);
}else{
t = (*top)->value;p *top;
LINKED LIST
72
p = *top;*top = (*top)->next;free (p);return t;
}}
3/22/2016
37
Checking for stack empty
int isempty (stack s){
if (s.top == -1)
int isempty (stack *top){
if (top == NULL)return (1);
else return (0);
}
return (1);else
return (0);}
ARRAY LINKED LIST
73
Checking for stack full
int isfull (stack s){
if (s.top ==
• Not required for linked list implementation.
• In the push() function we( p(MAXSIZE–1))
return (1);else
return (0);}
• In the push() function, we can check the return value of malloc().
– If -1, then memory cannot be allocated.
ARRAY LINKED LIST
74
3/22/2016
38
Example main function :: array
#include <stdio.h>#define MAXSIZE 100
struct lifo
push(&A,30);push(&B,100); push(&B,5);
printf (”%d %d” pop(&A)struct lifo {
int st[MAXSIZE];int top;
};typedef struct lifo stack;
main(){
printf (”%d %d”, pop(&A),pop(&B));
push (&A, pop(&B));
if (isempty(B))printf (”\nB is empty”);
}
75
{stack A, B; create(&A); create(&B);push(&A,10);push(&A,20);
Example main function :: linked list
#include <stdio.h>struct lifo {
push(&A,30);push(&B,100); push(&B,5);
{int value;struct lifo *next;
};typedef struct lifo stack;
main(){
printf (”%d %d”, pop(&A), pop(&B));
push (&A, pop(&B));
if (isempty(B))printf (”\nB is empty”);
}
76
stack *A, *B;create(&A); create(&B);push(&A,10); push(&A,20);
}
3/22/2016
39
Queue Implementation using Linked List
77
Basic Idea
• 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). <Front>
• Another pointing to the end of the list (point where new elements will be inserted). <Rear>
Rear
78Front
Rear
3/22/2016
40
struct fifo {int value;
Declaration
struct fifo *next;};
typedef struct fifo queue;
queue *front, *rear;
79
Creating a queue
void createq (queue **front, queue **rear)
{{
*front = NULL;
*rear = NULL;
}
80
3/22/2016
41
Inserting an element in queue
void enqueue (queue **front, queue **rear, int x){
queue *ptr;ptr = (queue *) malloc(sizeof(queue));
if (*rear == NULL) /* Queue is empty */{
*front = ptr; *rear = ptr;ptr->value = x;ptr->next = NULL;
}else /* Queue is not empty */{
(* ) > t t
81
(*rear)->next = ptr;*rear = ptr;ptr->value = x;ptr->next = NULL;
}}
Deleting an element from queue
int dequeue (queue **front, queue **rear){
queue *old; int k;
if (*front == NULL) /* Queue is empty */printf (”\n Queue is empty”);
else if (*front == *rear) /* Single element */{
k = (*front)->value; free (*front); front = rear = NULL;return (k);
}else{
k (*front) > al e old *front
82
k = (*front)->value; old = *front; *front = (*front)->next;free (old);return (k);
}}
3/22/2016
42
Checking if empty
int isempty (queue *front){
if (front == NULL)return (1);
elsereturn (0);
}
83
Example main function
#include <stdio.h>
struct fifo
{
enqueue(&Af,&Ar,30);
printf (”%d %d”,{
int value;
struct fifo *next;
};
typedef struct fifo queue;
main()
{
dequeue (&Af,&Ar),
dequeue(&Af,&Ar));
if (isempty(Af))
printf (”\n Q is empty”);
}
84
queue *Af, *Ar;
createq (&Af, &Ar);
enqueue (&Af,&Ar,10);
enqueue (&Af,&Ar,20);
3/22/2016
43
Some Applications of Stack
85
Applications ….
• Handling function calls and return
• Handling recursionHandling recursion
• Parenthesis matching
• Evaluation of expressions
– Polish postfix and prefix notations
86