Actually, C provides another type of variable which allows us to do just that. These are called dynamic variables.

Similar documents
Chapter 2 (Dynamic variable (i.e. pointer), Static variable)

At the end of this module, the student should be able to:

Data Structure Series

CS 31: Intro to Systems Pointers and Memory. Kevin Webb Swarthmore College October 2, 2018

Heap Arrays and Linked Lists. Steven R. Bagley

First of all, it is a variable, just like other variables you studied

CS113: Lecture 5. Topics: Pointers. Pointers and Activation Records

In Java we have the keyword null, which is the value of an uninitialized reference type

Elementary Data Structures: Part 1: Arrays, Lists. CSE 2320 Algorithms and Data Structures Vassilis Athitsos University of Texas at Arlington

Darshan Institute of Engineering & Technology for Diploma studies Unit 4

Linked Lists. .. and other linked structures. Pallab Dasgupta Professor, Dept. of Computer Sc & Engg INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR

C Programming Language: C ADTs, 2d Dynamic Allocation. Math 230 Assembly Language Programming (Computer Organization) Thursday Jan 31, 2008

Understanding Pointers

Chapter 7. Pointers. Copyright 2007 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.

MODULE 5: Pointers, Preprocessor Directives and Data Structures

Lecture 04 Introduction to pointers

CS24 Week 2 Lecture 1

Linked-List Basic Examples. A linked-list is Linear collection of self-referential class objects, called nodes Connected by pointer links

MARKS: Q1 /20 /15 /15 /15 / 5 /30 TOTAL: /100

C Structures & Dynamic Memory Management

MM1_ doc Page E-1 of 12 Rüdiger Siol :21

Pointers (part 1) What are pointers? EECS We have seen pointers before. scanf( %f, &inches );! 25 September 2017

FOR Loop. FOR Loop has three parts:initialization,condition,increment. Syntax. for(initialization;condition;increment){ body;

APS105. Structures 11/18/2013. Example A struct of stock items at a store: Structures. Lists. Arrays allow a collection of elements

Heap Arrays. Steven R. Bagley

Assist. Prof. Dr. Caner ÖZCAN

ECE 2400 Computer Systems Programming Fall 2017 Topic 4: C Pointers

Pointers. Part VI. 1) Introduction. 2) Declaring Pointer Variables. 3) Using Pointers. 4) Pointer Arithmetic. 5) Pointers and Arrays

EM108 Software Development for Engineers

Dynamic Memory Allocation and Linked Lists

At this time we have all the pieces necessary to allocate memory for an array dynamically. Following our example, we allocate N integers as follows:

Advanced Pointer Topics

Structures. Basics of Structures (6.1) EECS l Now struct point is a valid type. l Defining struct variables: struct point { int x; int y; };

Outline. Computer Memory Structure Addressing Concept Introduction to Pointer Pointer Manipulation Summary

Content. In this chapter, you will learn:

C Pointers. Indirection Indirection = referencing a value through a pointer. Creating Pointers. Pointer Declarations. Pointer Declarations

CS 31: Intro to Systems Pointers and Memory. Martin Gagne Swarthmore College February 16, 2016

CA341 - Comparative Programming Languages

Linked List. April 2, 2007 Programming and Data Structure 1

Goals of this Lecture

The C Programming Language Part 4. (with material from Dr. Bin Ren, William & Mary Computer Science, and

(13-2) Dynamic Data Structures I H&K Chapter 13. Instructor - Andrew S. O Fallon CptS 121 (November 17, 2017) Washington State University

CS 261 Fall C Introduction. Variables, Memory Model, Pointers, and Debugging. Mike Lam, Professor

Data Structures and Algorithms (DSA) Course 5 Lists. Iulian Năstac

Subject: Fundamental of Computer Programming 2068

High Performance Programming Programming in C part 1

Dynamically Allocated Memory in C

C Review. MaxMSP Developers Workshop Summer 2009 CNMAT

CS61, Fall 2012 Section 2 Notes

Chapter 14. Dynamic Data Structures. Instructor: Öğr. Gör. Okan Vardarlı. Copyright 2004 Pearson Addison-Wesley. All rights reserved.

DECLARAING AND INITIALIZING POINTERS

Intermediate Programming, Spring 2017*

C Introduction. Comparison w/ Java, Memory Model, and Pointers

by Pearson Education, Inc. All Rights Reserved.

JTSK Programming in C II C-Lab II. Lecture 3 & 4

Self-referential Structures and Linked List. Programming and Data Structure 1

Lecture 8 Dynamic Memory Allocation

COMP26120: Pointers in C (2018/19) Lucas Cordeiro

Linked List in Data Structure. By Prof. B J Gorad, BECSE, M.Tech CST, PHD(CSE)* Assistant Professor, CSE, SITCOE, Ichalkaranji,Kolhapur, Maharashtra

Cpt S 122 Data Structures. Data Structures

Announcements. assign0 due tonight. Labs start this week. No late submissions. Very helpful for assign1

Name :. Roll No. :... Invigilator s Signature : INTRODUCTION TO PROGRAMMING. Time Allotted : 3 Hours Full Marks : 70

CSC 270 Survey of Programming Languages. What is a Pointer?

2/28/2018. Overview. The C Programming Language Part 4. Pointers. Pointers. Pointers. Pointers

ESc101: (Linear, Circular, Doubly) Linked Lists, Stacks, Queues, Trees. Introduction to Linked Lists

CS 11 C track: lecture 5

Unit 7. Functions. Need of User Defined Functions

The time and space are the two measure for efficiency of an algorithm.

CS61C : Machine Structures

Linked Data Representations

Binary Trees. Height 1

ECE551 Midterm Version 1

CS132 Algorithm. Instructor: Jialiang Lu Office: Information Center 703

Fundamental of Programming (C)

C: Pointers. C: Pointers. Department of Computer Science College of Engineering Boise State University. September 11, /21

CS 137 Part 8. Merge Sort, Quick Sort, Binary Search. November 20th, 2017

Pointers. Introduction

C++ Programming Chapter 7 Pointers

Introduction to C: Pointers

MYcsvtu Notes LECTURE 34. POINTERS

CS61C Machine Structures. Lecture 4 C Structs & Memory Management. 9/5/2007 John Wawrzynek. www-inst.eecs.berkeley.edu/~cs61c/

CS61C : Machine Structures

Outline. Briefly review the last class Pointers and Structs Memory allocation Linked lists

Dynamic Memory Management. Bin Li Assistant Professor Dept. of Electrical, Computer and Biomedical Engineering University of Rhode Island

Variation of Pointers

Review: C Strings. A string in C is just an array of characters. Lecture #4 C Strings, Arrays, & Malloc

Subject: PROBLEM SOLVING THROUGH C Time: 3 Hours Max. Marks: 100

Memory Allocation in C C Programming and Software Tools. N.C. State Department of Computer Science

advanced data types (2) typedef. today advanced data types (3) enum. mon 23 sep 2002 defining your own types using typedef

A. Year / Module Semester Subject Topic 2016 / V 2 PCD Pointers, Preprocessors, DS

Chapter 6 - Pointers

Dynamic memory allocation (malloc)

The combination of pointers, structs, and dynamic memory allocation allow for creation of data structures

Lab 3. Pointers Programming Lab (Using C) XU Silei

CS61C : Machine Structures

Arrays and Pointers. CSE 2031 Fall November 11, 2013

SYSC 2006 C Winter 2012

Dynamic memory allocation

Arrays and Pointers (part 1)

C Pointers. Abdelghani Bellaachia, CSCI 1121 Page: 1

Transcription:

When a program is run, memory space is immediately reserved for the variables defined in the program. This memory space is kept by the variables until the program terminates. These variables are called static variables they exist throughout the program. In some cases, however, certain variables are used only at some point, say at the beginning of the program. But since they exist until the program terminates, we can say that memory is not used efficiently because the variables still occupy memory space even when they are no longer needed. Wouldn t it be a great idea to be able to dispose the variables (and thus recover memory space) at some point in the program when they are no longer necessary? Actually, C provides another type of variable which allows us to do just that. These are called dynamic variables.

This module discusses dynamic variables variables that are created and disposed during program execution. It s possible to create dynamic variables at some point in the program, and destroy it later when they are no longer needed. The main purpose of using dynamic variables is to conserve main memory space and use it efficiently.

Before we start discussing how to create dynamic variables, it could be helpful to have a short discussion on how the operating system (if you forgot what an operating system is, review module 1) manages the main memory. The main memory is finite, and the operating system keeps track of the memory locations that are currently being used by programs running, and those that are not being used (called free memory). When a new program is started, its variables are assigned to some free memory locations, and these memory locations are then classified as used. When the program terminates, these memory locations become free again.

free free used A used A used B used B free used num1 free used num2 free used temp free used temp free free (a) Before program execution (b) While program is being executed Figure 9.1 Variables in main memory

#include <stdio.h> int num1, num2; main() { program statements here } Figure 9.2 Sample program

Figure 9.1 shows a conceptual view of a portion of the main memory before and while the program in Figure 9.2 is running. The memory addresses are left out. Each memory location is marked either free or used. Initially, the figure shows three variables, A, B and temp, using up memory space. These locations are marked used, and the rest are free. When the program is started, the operating system looks for two free memory locations and assigns variables num1 and num2 in those locations. Subsequently, these locations are marked used.

When the program terminates, the memory locations assigned to num1 and num2 are marked free again. Managing used and free memory is only one of the functions of the operating system. It also does other things like coordinating computer devices such as printers and hard disks.

The only way to refer to a dynamic variable is through a pointer, so if we are to create a dynamic variable in the program, we have to define a pointer. The pointer and the dynamic variable to be created must have matching types, so if we intend to create a dynamic integer variable, a pointer to an integer must be defined.

A dynamic variable can be created by making a function call to malloc, a standard function. It s prototype is void *malloc(size_t n); The parameter n is of type size_t. size_t is a special data type you can think of it as a data type that can store a very large integer value. So parameter n is actually an integer. When the function is called, it searches for n bytes of free memory space and reserves it (i.e., mark it used ) for a dynamic variable. It returns a pointer to the memory space reserved. If there is not enough free memory for n bytes, it returns NULL, a constant pointer value. The dynamic variable created by malloc does not have any name, so the pointer returned must be assigned to a pointer variable so that it can be accessed later.

For example, let s create a dynamic integer variable. We ll need a pointer to an integer, say p, declared as int *p; Assuming that the size of an integer variable is four bytes, the statement p = (int *) malloc(4); creates a dynamic variable. As you can see, a type cast is used since malloc returns a pointer type void *. And to store and retrieve values to/from the dynamic variable, we use the indirection operator * on p, so *p = 17; stores 17 in the variable p.

You might be wondering how many bytes do the other data types consist of. Actually, the size of data types vary in different computer systems. On some systems, the int type is 4 bytes; while on others, it s 8 bytes. To make your program work on different systems, C provides a unary operator called sizeof which gives the size (in bytes) of a specified type. Its usage is sizeof(type-name)

So, the statement above that calls malloc can be equally written as p = (int *) malloc(sizeof(int)); Note that the value 4 was replaced here with sizeof(int). As another example, the statements below create a dynamic float variable, stores 0.5 in it, and outputs it. float t; t = (float *) malloc(sizeof(float)); *t = 0.5; printf( %f, *t);

A dynamic variable can also be a structure type. Below is an example. typedef struct account { int number; float balance; } acct; acct p; p = (acct *) malloc(sizeof(acct)); p->number = 1012; p->balance = 9812.50; In the program, p is a pointer to an acct type. The structure has two fields: number and balance. A dynamic structure variable is created, where the values 1012 and 9812.50 are stored. Conceptually, we can view the dynamic struct variable as p 1012 9812.50

The left box is the number field, while the right box is balance. The dynamic variable is pointed to by p, and so we may access its fields as p->number and p->balance. When a dynamic variable is no longer needed, it can be disposed (or destroyed) using the standard function free. The statement free(p); disposes the dynamic variable pointed to by p. The memory space pointed to becomes free again, and p no longer points to any variable.

Thus, it would be an error to assign values to *p. And by the way, whenever we use malloc and free in a program, we have to place #include <stdlib.h> at the beginning of the program. The file stdlib.h contains the function prototypes of malloc, free, and other built-in functions, and for the functions to work properly in your program, you have to include stdio.h.

The sample programs presented in the previous section were designed to illustrate how dynamic variables are created; such programs are hardly found in real-life applications. Actually, the main purpose of using dynamic variables is to make programs flexible in storing any size of data. To achieve this, dynamic variables are used to form complex data structures. These so-called complex structures are made up of self-referential structures interconnected with each other.

What is a self-referential structure? It is a structure that contains as field a pointer to a structure similar to itself. Below is a definition of a self-referential structure. struct node { int x; struct node *ptr; }; struct node has two fields: an integer, and a pointer to a struct node. Isn t the definition circular? Well, it is, and C allows that. Now, let s continue with the program and examine some statements.

struct node A, B; A.x = 10; B.x = 20; A.ptr = &B; Two variables, A and B, are defined as type struct node. The statement A.x= 10; stores 10 in the integer field of variable A, while the statement B.x =20; stores 20 in B. The last statement makes the pointer field of A point to B.

Conceptually, the variables can be pictured as 10 20 A B Having made the pointer field of variable A point to B, B can now be referred to as *(A.ptr). So the expressions B.x and *(A.ptr).x now refer to the same variable. Alternatively, we can also use A.ptr->x. The statement A.ptr->x = 25; replaces the value 20 with 25.

Variable B also has a pointer field for which we have not stored any address yet. We can make it point to A with the statement B.ptr = &A; Here s a diagram showing how the variables look like after the two previous statements. 10 20 A B

Did you note that we can actually make a variable point to itself? The statement A.ptr = &A; makes the pointer field of A point to A: 10 A In this case, the expressions A.x, A.ptr->x and A.ptr->ptr->x all refer to the same variable.

The primary use of dynamic variables is to form flexible structures whose size can expand or shrink to accommodate varying data sizes. Consider for example the task of writing a program that maintains a list of hotel reservations. A reservation consists of the customer s name, room size, and perhaps the expected date of arrival. The program should allow reservations to be added and deleted from the list. Now, what type of data structure would you use to store the list of reservations? An array? Probably not, because the list has no fixed size and so we wouldn t know how large an array to define.

A data structure appropriate for the problem just mentioned is a linked list. A linked list consists of several dynamic variables linked together to form a chain-like structure (Figure 9.1). head data data data NULL Fig. 9.1 A linked list

As shown in Figure 9.1, the dynamic variables that make up the linked list are structures, each consisting of one (or more) field that stores data and another field variable head is a pointer variable that points to the first node. This pointer is needed because dynamic variables don t have names. The only way to refer to them is through a pointer. The pointer field of the last node is NULL, denoting the end of the linked list. A pointer field having a NULL value does not point to any memory location.

To illustrate, let s build a linked list to store the integers 3, 20, 8, 5. We ll need the following type and variable definitions: struct node { }; int x; struct node *next; typedef struct node nd; nd *head, *p;

Note that the data field here is of type integer. Here, struct node is self-referential, and head and p are pointers to struct node. To build the linked list, the first task is to create the first node. This is done by making a function call to malloc: head = (nd *) malloc(sizeof(nd)); head now points to a newly-created dynamic variable, where we store 3 using the statement head->x = 3;

At this point, we can picture our linked list as head 3 The following statements create the second node and stores 20 in it. The linked list is drawn after each statement. head->next = (nd *) malloc(sizeof(nd)); head 3 head->next->x = 20; head 3 20

Alternatively, we can use the other pointer variable, p, to effectively create the second node. The two statements above can be equally written as p = head; p->next = (nd *) malloc(sizeof(nd)); p->next->x = 20; The first statement, p = head; makes p point to where head points (which is, to the first node). The expression p->next then refer to the pointer field of the node (the first node) pointed to by p.

The idea of using p as an auxillary pointer might seem senseless at this point, but as you ll see below, this leads to a more compact code. Assuming p now points to the first node, the following statements create the third and fourth nodes: p = p->next; p->next = (nd *) malloc(sizeof(nd)); p->next->x = 8; p = p->next; p->next = (nd *) malloc(sizeof(nd)); p->next->x = 5; p = p->next; p->next = NULL;

The statement p = p->next; makes p point to the node following the node it currently points to. The last statement, p->next = NULL; assigns a NULL value to the pointer field of the last node. This is necessary so that later, when we try to output the values stored in the linked list, we ll know when to stop.

If you still find the discussion confusing, then, maybe a little illustration will help. The statements to create the linked list are written again below, together with a pictorial view of the linked list after each statement. head = (nd *) malloc(sizeof(nd)); head head->x = 3; head 3

p = head; head 3 p p->next = (nd *) malloc(sizeof(nd)); head 3 p p->next->x = 20; head p 3 20

p = p->next; head 3 20 p->next = (nd *) malloc(sizeof(nd)); head 3 20 p->next->x = 8; p p head 3 20 8 p

p = p->next; head 3 20 8 p->next = (nd *) malloc(sizeof(nd)); p head 3 20 p->next->x = 5; p = p->next; p->next = NULL; head 3 20 8 p 8 5 NULL p

Let s discuss some common operations that are usually done on linked lists. These are: (1) building a linked list, (2) outputting contents of the list, (3) inserting a data item into the list, (4) deleting a data item from the list, and (5) disposing the linked list.

The previous section showed how to store a list of four integers (3, 20, 8 and 5) in a linked list. The entire code is again given below. head = (nd *) malloc(sizeof(nd)); head->x = 3; p = head; p->next = (nd *) malloc(sizeof(nd)); p->next->x = 20; p = p->next; p->next = (nd *) malloc(sizeof(nd)); p->next->x = 8; p = p->next; p->next = (nd *) malloc(sizeof(nd)); p->next->x = 5; p = p->next; p->next = NULL;

Do you notice that the 4th, 5th and 6th statements are successively repeated? What do the statements actually do? It creates a dynamic variable, stores a value in it, and moves the pointer p. The three statements are repeated three times to create the second, third and fourth node. The repeated occurrence of these statements suggests that they can be placed in the loop.

In general, the program would then look like head = (nd *) malloc(sizeof(nd)); head->x = data; p = head; while there is data { p->next = (nd *) malloc(sizeof(nd)); p->next->x = data; p = p->next; } p->next = NULL; The statements before the while loop creates the first node. data can either be inputted, in which case we use an input function like scanf, or it can be obtained from other variables such as an array.

Let s do the task of storing integers 1-10 in a linked list. This is accomplished by the statements below. head = (nd *) malloc(sizeof(nd)); head->x = 1; p = head; for (i=2; i<=10; i++) { p->next = (nd *) malloc(sizeof(nd)); p->next->x = i; p = p->next; } p->next = NULL; The second statement stores the value 1 in the first node. The for loop takes care of the rest of the values (2-10). Note that the control variable, i, is initialized to 2 and is incremented until it reaches 10.

One way to output data stored in the linked list is to list down the data fields of the nodes, as in printf( %d\n, head->x); printf( %d\n, head->next->x); printf( %d\n, head->next->next->x); This method, however, is impractical because if the list is long, we ll be listing down a lot of statements. A better way is to use a loop, just like what we did when building the linked list.

The program code to output the integers stored in the linked list is shown below: p = head; while (p!= NULL) { printf( %d\n, p->x); p = p->next; } The idea is to let a pointer, p in this case, move starting from the first node up to the last node of the linked list. And as it moves, the data field of the node pointed to by p is outputted. The first statement makes p point to the first node. Then, the while statement tests if p is NULL, because if so, the end of the list has been reached.

To insert a new data item into the linked list, four things have to be done: 1. Create a new node (a dynamic variable). 2. Store the data value in the newly created node. 3. Locate the position in the linked list where the new node is to be inserted. 4. Manipulating the pointers to cause the insertion.

Let s have an example. Suppose that we would like to insert the data value 0 at the beginning of our linked list containing integers 1 to 10. To do this, we ll need an additional pointer, nd *temp; The first two steps are accomplished by the statements below. A pictorial view of the dynamic variable is also shown. temp = (nd *) malloc(sizeof(nd)); temp->x = 0; temp 0

In the next step (step 3), we need to locate the position where we are to insert the new node. But since we are inserting at the beginning of the linked list, we need not locate this position since head always points to the first node. To accomplish step 4, we simply make head point to the new node, and let the new node s pointer field point to the node previously pointed to by head. The sequence of statements needed to do these is given below, together with the pictorial view of the linked list after each statement.

p = head; temp 0 head p 1 2 head = temp; temp head p 0 1 2

temp->next = p; temp head p 0 1 2 Note that head now points to the new node. Also note that the statement p = head; is necessary. If we don t do this, there s no way we can refer to the node containing 1 once we have changed head to point to the new node.

To summarize, the complete set of statements to insert 0 at the beginning of the linked list is given below. temp = (nd *) malloc(sizeof(nd)); temp->x = 0; p = head; head = temp; temp->next = p;

The program statements that insert an item at the middle of the list are quite different from those that insert at the beginning of the list. This is because when we insert at the middle, we don t need to change where head points. Also, we need to locate the proper place to insert the item. For example, suppose we would like to insert 0 after 5 instead of at the beginning. To do this, we first create a new node in the same way we did before (that was done by the first two statements).

temp = (nd *) malloc(sizeof(nd)); temp->x = 0; temp 0 Then, we locate the node after which the new node will be inserted. This node is the one that contains 5, and we make p point to it: temp 0 4 5 6 p

This locate and point process can be accomplished by the program code below: p = head; while (p->x!= 5) p = p->next; Then, we execute the following statements: temp->next = p->next; temp 0 4 5 6 p

p->next = temp; temp 0 4 5 6 p As shown, the first statement makes the pointer field of the node to be inserted point to the node it is supposed to follow, and the second statement points the pointer field of the node containing 5 to the new node. For these two statements to work, the prerequisite is to have p pointing to the node that would precede the new data item to be inserted.

Let s write a function called insert_list that inserts an integer into the linked list whose data items are in ascending order. When the function inserts a new integer, the integer should be inserted in the proper place so that the ascending order is maintained. The function is given below. It has two parameters: the head of the linked list and the integer to be inserted.

void insert_list(nd *head, int num) { nd *p, temp; temp = (nd *) malloc(sizeof(nd)); temp->x = num; p = head; if (num < head->x) /* insert at beginning */ { head = temp; temp->next = p; } else { /* locate proper place */ while (num > p->next->x && p->next!= NULL) p = p->next; /* insert node */ temp->next = p->next; p->next = temp; }

The first two statements create a new node to be inserted. Then, the if statement tests if the first data item in the linked list is greater than num. If so, the new node is inserted at the start of the list, so as to maintain the ascending order of the data items. Otherwise, the proper place to insert is searched by going through the data items until either an item not less than num is found or the end of the linked list is reached. The node is then inserted in the manner discussed previously.

Deleting a node from a linked list involves two steps: (1) changing the pointers so that the node is effectively removed from the list, and (2) disposing the node removed using the free function. Like insertion, we differentiate the case of deleting a node at the beginning of the linked list from that of deleting at the middle.

The following statements delete the first node of the linked list. temp = head; head temp 1 2 head = temp->next; head temp 1 2 free(temp); head temp 2

The last statement destroys the dynamic variable, and temp now points to nowhere. As discussed previously, it s important to destroy dynamic variables that are no longer used since they occupy memory space. To delete a node at the middle or end of the list, we ll need a pointer, say p, that points to the node preceding the node to be deleted. For example, if we d like to delete the node containing 5 from the linked list, we have to make p point to the node containing 4, as shown below.

p 4 5 6 To achieve this, we can use the locate and point program code presented when we discussed insertion in the previous subsection. After making p point to the proper place, we then manipulate the pointers to remove the node from the list. This is accomplished by the following statements.

temp = p->next; p p->next = p->next->next; p free(temp); p 4 5 6 temp 4 5 6 temp 4 6 temp Let s write another function, delete_list, that deletes a data item from the list. This is shown below.

void delete_list(nd *head, int num) { nd *p, *temp; /* check if list is empty */ if (head == NULL) return; if (num == head->x) /* delete first node */ { temp = head; head = head->next; free(temp); } else { /* search node to delete */ p = head; while (num!= p->next->x && p->next!= NULL) p = p->next; if (p->next!= NULL)

} } /* node is found, so delete it */ { temp = p->next; p->next = p->next->next; free(temp); } Note that at the beginning of the function, we first check if the linked list is empty. If so, we immediately exit from the function by executing a return; statement.

Variables that are defined in the program are referred to as static variables they exist throughout the program. C provides another type of variable called dynamic variables these variables can be created at some point in the program and destroyed when they are no longer needed. By using dynamic variables, memory space is efficiently utilized because they can be destroyed when no longer needed. In most applications, dynamic variables are used to store data that vary in size. Complex data structures are built by interconnecting dynamic variables. One such structure is the linked list. A linked list is a collection of self-referential dynamic variables interconnected to form a chain-like structure. It s used to store a list of data items, and items can be inserted and deleted from the linked list. And since linked lists are made up of dynamic variables, it can expand or shrink to accommodate any data size.