POINTERS
Every variable in C has a name and a value associated with it.
When a variable is declared, a specific block of memory within the computer is allocated to hold the value of that variable.
The size of the allocated block depends on the data type.
Consider the following statement.�int x = 10;
Lvalue=rvalur
Printf(“%d”,sizeof(x))
The compiler reserves memory for the integer variable x and stores the rvalue 10 in it.
x refers to the value stored at the memory location set aside for x, in this case 10
A pointer is a variable that contains the memory location of another variable. ����
A pointer is a variable that represents the location of a data item, such as a variable or an array element.
These applications include:�Pointers are used to pass information back and forth between functions.� Pointers enable the programmers to return multiple data items from a function via function arguments.� Pointers provide an alternate way to access the individual elements of an array.� Pointers are used to pass arrays and strings as function arguments. � Pointers are used to create complex data structures, such as trees, linked lists, linked stacks, linked queues, and graphs.�Pointers are used for the dynamic memory allocation of a variable.
General Syntax
data_type *ptr_name;
int *pnum;�char *pch;�float *pfnum; ��
�
int x= 10;�int *ptr;�ptr = &x;
The * informs the compiler that ptr is a pointer variable and the int specifies that it will store the address of an integer variable.
Memory Address | Value stored |
1000 | 0000 |
| 0010 |
1002 | 0000 |
| 1006 |
1004 | |
| |
1006 | 0000 |
| 1010 |
1008 | |
| | | | |
1000 | 1001 | 1002 | 1003 | 1004 |
0000 | 0010 | | | |
X Name of the variable
ptr Name of the pointer variable
1006 (x) |
10 |
1002 (ptr) |
1006 |
ptr = &x; ptr is assigned address of variable x
y = *ptr; y is assigned a value of content of the address pointed by ptr
#include <stdio.h>�int main()�{�int num, *pnum;�pnum = # �printf("\n Enter the number : ");�scanf("%d", &num);�printf("\n The number that was entered is : %d\n", *pnum);
printf("\n The number that was entered is : %d\n", num);
printf("\n The address is : %u", ptr);
return 0;�} �
What is the expected output?
The number that was entered is :
The number that was entered is :
The address is :
* pnum Pointer de-referencing
Pointer referencing
int num1 = 2, num2 = 3, sum = 0, mul = 0, div = 1;�int *ptr1, *ptr2;�ptr1 = &num1;�ptr2 = &num2;�sum = *ptr1 + *ptr2;�mul = sum * (*ptr1);�*ptr2 += 1;�div = 9 + (*ptr1)/(*ptr2) – 30;
Valid pointer operations
Addition
Subtraction
Comparing pointer (relational Operations)
Multiplication ( not widely used)
No division operation are possible
++,--- are valid operations
void *ptr = NULL; Represents null pointer �
Relation between array and pointers
# include <stdio.h>�int main( )�{�int i = 3 ;�printf ( "Address of i = %u\n", &i ) ;�printf ( "Value of i = %d\n", i ) ;�printf ( "Value of i = %d\n", *( &i ) ) ;�return 0 ;�} �
‘*’, called ‘value at address
(pointer de-referencing)
Assume address
What is the program output
representation
Example
Consider the declaration: int x[5] = {1, 2, 3, 4, 5};
Suppose that each integer requires 4 bytes
Compiler allocates a contiguous storage of size 5x4 = 20 bytes
Suppose the starting address of that storage is 2500 Element Value Address
Compiler allocates sufficient amount of storage to contain all the elements of the array in contiguous memory location
Array_Nmae[Index] | value | Address |
X[0] | 1 | 2500 |
X[1] | 2 | 2504 |
X[2] | 3 | 2508 |
X[3] | 4 | 2512 |
X[4] | 5 | 2516 |
base address is the location of the first element (index 0, x[0] in above table) of the array
such as in above table 2500
The array name as a constant pointer to the first element
Both x and &x[0] have the value 2500
int *p is declared and if we define
p = x;
Or
p = &x[0]; they are equivalent
If we increment with p++ then p=&x[1]
Array_Name[Index] | value | Address | P | P pointer | *(p+i) |
X[0] | 1 | 2500 | P | P=x | *(p+0) x[0] value 1 |
X[1] | 2 | 2504 | P+1 | P++ | *(p+1) |
X[2] | 3 | 2508 | P+2 | P++ | *(p+2) |
X[3] | 4 | 2512 | P+3 | P++ | *(p+3) |
X[4] | 5 | 2516 | P+4 | P++ | *(p+4) |
Int x[5]={5,6,7,8};
Int i ;
For(i=0;i<5;i++)
printf(“%d”,x[i]);
Int x[5]={5,6,7,8};
Int *p,i;
p=x;
For(i=0;i<5;i++)
printf(“%d”,*(p+i));
Dynamic Memory Management
malloc() | Allocates memory and returns a pointer to the first byte of allocated space |
calloc() | Allocates space for an array of elements, initializes them to zero and returns a pointer to the memory |
free() | Frees previously allocated memory |
realloc() | Alters the size of previously allocated memory |
�
free memory region is called heap
#include <stdio.h>�#include <stdlib.h>�int main ()�{�int i,n;�int *arr;�printf ("\n Enter the number of elements: ");�scanf("%d",&n);�arr = (int*) calloc(n,sizeof(int));�if (arr==NULL) exit (1);�printf("\n Enter the %d values to be stored in the array", n);�for (i = 0; i < n; i++)�scanf ("%d",&arr[i]);�printf ("\n You have entered: ");�for(i = 0; i < n; i++)�printf ("%d",arr[i]);�free(arr);�return 0;�} �
#include<stdio.h>
// Dynamic array using pointer
Void main()
{
int i,n,*p;
printf(“enter number of elements in an array”);
scanf(“%d”,&n);
for(i=0;i<n;i++)
scanf(“%d”,(p+i));
for(i=0;i<n;i++)
printf(“%u=%d”,(p+i),*(p+i));
}
Output
Enter number of elements in an array 5
1 2 3 4 5
1212=1
1214=2
1216=3
1218=4
1220=5
int main()�{�int **arr, i, j, ROWS, COLS; // **a is pointer to pointer�printf("\n Enter the number of rows and columns in the array: ");�scanf("%d %d", ROWS, COLS);�arr = (int **)malloc(ROWS * sizeof(int *));
// allocate memory as per row size�if(arr == NULL)�{�printf("\n Memory could not be allocated");�exit(-1);�}�for(i=0; i<ROWS; i++)�{�arr[i] = (int *)malloc(COLS * sizeof(int));// to Each column�if(arr[i] == NULL)�{�printf("\n Memory Allocation Failed");�exit(-1);�}�} �
void main()
{
int i,j,a[3][3];
int **p;
p=(int**) calloc(3,sizeof(int));
for(i=0;i<3;i++)
p[i]=(int*)malloc(3*sizeof(int));
for(i=0;i<3;i++)
for(j=0;j<3;j++)
scanf("%d",(p[i]+j));
for(i=0;i<3;i++)
for(j=0;j<3;j++)
printf("%d",*(p[i]+j));
}
Structures
A structure is in many ways similar to a record.
It stores related information about an entity.�Structure is basically a user-defined data type that can store related information
A structure is therefore a collection of variables under a single name. �The variables within a structure are of different data types
Ex
struct student�{�int r_no;�char name[20];�char course[20];�float fees;�};
Here structure is similar to user defined data type.
As it’s a data type we have to define a new variable to use it
struct student stud1;
�� �
struct student�{�int r_no;�char name[20];�char course[20];�float fees;�} stud1 = {01, "Rahul", "BCA", 45000};
Or
struct student stud1 = {01, "Rahul", "BCA", 45000};
Or
stud1.r_no = 01;�stud1.name = "Rahul";�stud1.course = "BCA";�stud1.fees = 45000; �Or
scanf("%d", &stud1.r_no);�scanf("%s", stud1.name); � scanf("%s", stud1.course);
scanf(“%f", &stud1.fees); � �
#include <stdio.h>�#include <conio.h>�int main()�{�typedef struct complex�{�int real;�int imag;�} COMPLEX;�COMPLEX c1, c2, sum_c, sub_c;
printf("\n Enter the real and imaginary parts of the irst complex number : ");�scanf("%d %d", &c1.real, &c1.imag);�printf("\n Enter the real and imaginary parts of the �second complex number : ");�scanf("%d %d", &c2.real, &c2.imag);
sum_c.real = c1.real + c2.real;�sum_c.imag = c1.imag + c2.imag; � printf("\n The sum of two complex numbers is : %d+%di",sum_c.real, sum_c.imag); � }�
THE POLYNOMIAL
#define�typedef�MAX—DEGREE 101 / * Max degree of polynomial + 1 * /�struct {�int degree;
float coef[MAX-DEGREE];�} polynomial;
Degree 4 | --- | 4 | 3 | 2 | 1 | 0 | |
| --- | x | x | x | x | x | |
Coef | --- | 1 | 0 | 1 | 0 | 4 | |
MAX—TERMS 100 / * size of terms array * typedef struct { float coef;� int expon; } polynomial;�polynomial terms[MAX—TERMS];�int avail =0; |
A Expon | --- | 4 | 2 | 0 |
Coef | --- | 1 | 1 | 4 |
B Expon | --- | 4 | 2 | 0 |
Coef | --- | 3 | 2 | 4 |
C Expon | --- | 4 | 2 | 0 |
Coef | --- | 4 | 3 | 8 |
MAX—TERMS 100 / * size of terms array * typedef struct { float coef;� int expon; } polynomial;�polynomial terms[MAX—TERMS];�int avail 0; |
THE SPARSE MATRIX
A matrix which has few non-zero entries is called as sparse matrix
A sparse matrix wastes memory space as many entries are zero
To reduce memory space wastage we must consider alternate forms of representation.
�
#define MAX-TERMS 101 �typedef struct {� int col;� int row;� int value;�} term;�term a[MAX-TERMS];
The matrix is represented as a triplet
( Row, Col, Value)
The first row a[0] contains
No.of Rows in original Matrix
No of Column in original Matrix
No of Non Zero Values
A[0][0]=6
A[0][1]=6
A[0][2]=8
Transposing a Matrix
for all elements in column j�place element <i, j, value > element in <j, i, value>
REPRESENTATION OF MULTIDIMENSIONAL ARRAYS
char str[] = {'H', 'E', 'L', 'L', 'O', '\0'};
Input | Output |
Scanf(“%s”,Str); | Printf(“%s”,Str) |
gets(str) | Puts(Str); |
Getche(),getch(),getc() | Putchar(),putc() |
char name[5][10] = {"Ram", "Mohan", "Shyam", "Hari","Gopal"};
STACKS
Plate5 | Top |
Plate4 | |
Plate3 | |
Plate2 | |
Plate1 | Bottom |
A stack is a linear data structure, where elements can be added and deleted from the same end called top of the stack.
Stack exhibits Last In First Out (LIFO) behavior
Operation of adding / Inserting elements to the stack is called as PUSH operation
Operation of removing / deleting elements to the stack is called as POP operation
Stack has a capacity defined STACK_SIZE
Stack full condition:- If total number of elements on the stack are equal to STACK_SIZE , push operation gives STACK FULL error ( Stack Overflow error)
Stack Empty: If stack is empty, calling operation POP on stack results in stack empty error ( Stack Underflow Error)
Static using array
#define stack_size 100
typedef stack
{
int Key;
} ;
stack st[stack_size];
int top = -1;
Dynamic representation
typedef stack
{
int key;
} ;
Stack *st;
Malloc(stack, sizeof(*stack));
Capacity=0;
Top=-1;
/* when stack full condition error occurs following code is executed */
Realloc(stack,2*capacity*sizeof(stack));
/*this allocates additional space*/
int stack[MAX];
void push(int st[], int val)�{
if(top == MAX-1)
{
printf("\n STACK OVERFLOW");
}� else�{� top++;� st[top] = val;�}�}
int pop(int st[])�{�int val;�if(top == -1)�{� printf("\n STACK UNDERFLOW");� return -1;�}�else�{� val = st[top];� top--;� return val;�}�}
void display(int st[])�{int i;�if(top == -1)� printf("\n STACK IS EMPTY");
else�{�for(i=top; i>=0; i--)� printf("\n %d",st[i]);� }
int stacktop(int st[])�{
if(top == -1)
{
printf("\n STACK IS EMPTY");�return -1; }�else�return (st[top]);�}
Struct stack { int a[SIZE]; int top; }; Struct stack st; St.top=-1; /* defined as a global value*/ int push(int val) { if ( st.top==SIZE) { printf(“Stack Overflow”); return 1 ; } st.top=st.top+1; St.a[st.top]=val; } Void display() { int I; if(st.top=-1) { printf(“ stack empty / Underflow”); return -1; } For( i=st.top; i>-1 ; i--) printf(“%d “, st.a[i]); }
| Int pop() { if(s.top=-1) { printf(“ stack empty / Underflow”); return -1; } val=s.a[s.top]; st.top--; return val; } Int stacktop() { if(st.top=-1) { printf(“ stack empty / Underflow”); return -1; } Return st.a[s.top]; }
|
Reversing a list�Parentheses checker Conversion of an infix expression into a postfix expression�Evaluation of a postfix expression�Conversion of an infix expression into a prefix expression�Evaluation of a prefix expression�Recursion
QUEUE
A queue is a FIFO (First-In, First-Out) data structure in which the element that is inserted first is the first one to be taken out. The elements in a queue are added at one end called the REAR and removed from the other end called the FRONT.
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Front = 0 | | | | | | | | |
Rear = 0 | | | | | | | | |
#define MAX 10 // Changing this value will change length of array�int queue[MAX];�int front = -1, rear = -1;
void insert()�{�int num;�printf(“\n Enter the number to be inserted in the queue : “);�scanf(“%d”, &num);�if(rear == MAX-1)
{
printf(“\n OVERFLOW”);
Return ;
}�else
if(front == -1 && rear == -1)�front = rear = 0;�else�rear++;�queue[rear] = num;�} �
int delete_element()�{� int val ;
if(front == -1 || front>rear)�{
printf(“\n UNDERFLOW”);�return -1;
}�else�{�val = queue[front];�front++;�if(front > rear)�front = rear = -1;�return val;�}�}
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Front = -1 | | | | | | | | |
Rear = -1 | | | | | | | | |
| 3,4,5,9,11,45,99,8 | |||||||
| 3 | 4 | 5 | 9 | 11 | 45 | 99 | 8 |
Rear = 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Front=0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | Queue Full |
| 3,4,5,9,11,45,99,8 | |||||||
| | 4 | 5 | 9 | 11 | 45 | 99 | 8 |
Rear = 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Front=0 | | 0 | 0 | 0 | 0 | 0 | 0 | Queue Full |
| | | 5 | 9 | 11 | 45 | 99 | 8 |
Rear = 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Front=0 | | 1 | 2 | | | 0 | 0 | Queue Full |
void display()
{
int i;
printf(“\n”);
if(front == -1 || front > rear)
printf(“\n QUEUE IS EMPTY”);
else
{
for(i = front;i <= rear;i++)
printf(“\t %d”, queue[i]);
}
}
TYPES OF QUEUES�A queue data structure can be classified into the following types:�1. Circular Queue
2. De-queue ( Double Ended Queue)
3. Priority Queue
4. Multiple Queue �
Double Ended Queue (DeQueue)
Input restricted
Output Restricted
Priority Queue
Multiple Queues
Linked List
struct node {
int data;
struct node *next; } �
#define NUMNODES 500�struct nodetype {�int info, next;
}�struct nodetype node[NUMNOOES];
avail = 0;�for (i = 0 i < NUMNODES-1; i++)�node(i] .next= i + 1;�node[ NUMNODES-1].next = -1; �
int getnode(void)
{�int p;�if (avail == -1)
{�printf("overflow\n");�exit(1);
}�p = avail;�avail =node[avail].next;�return(p);�}
void freenode(int p)
{�node[ p. next] = avail;�avail = p;�return;
}
void insafter(int p, int x )
{
int q;� If(p=-1) {�printf("vod insertion\n');�return; }�q = getnode();�node[q].info=x;�node[q] next = node[p] .next;�node[p].next=q; return;�}
NOOEPTR getnodé(void)
{
NODEPTR p;
p= (NODEPTR) malloc (sizeof(struct node));
return(p);
}
void freenode(NODEPTR p)
{
free(p);
}�
struct node
{
int info;
struct node *next;
}
typedef struct node *NODEPTR; �
p= (NODEPTR) malloc(sizeof (struct node));
NODEPTR list;
list=NULL;
p->info=10;
p=list;
list=p;
/*free(p)*/
Linked list as stack implementation
struct node
{�int info;�struct node next;
};�typedef struct node *NODEPTR; �NODEPTR p ;�
P=getnode();�
NODEPTR push(int x)
{
NODEPTR p;
P=getnode();
P->info=x;
P=list;
List=p;
Return list;
}
int pop()
{
NODEPTR P=list;
If(p==NULL)
{ printf(“List empty”);
return 0;
}
X=p->info;
List=p->next;
Free(p);
Return x;
}
Void display()
{
NODEPTR p;
P=list;
If(p==NULL)
{ printf(“List empty”);
return ;
}
For(p=list;p!=NULL;p=p->next)
printf(“%d”,p->info);
return; }
struct node {�int info;�struct node next; };�typedef struct node *NODEPTR; �NODEPTR p ;� P=getnode(); | struct node {�int info;�struct node next; };�typedef struct node *NODEPTR; �NODEPTR p ;� P=getnode(); � |
struct queue { �int front, rear; }; �struct queue q; Int empty ( struct queue *pq) { Return (pq.front==-1):TRUE?FALSE; } | struct queue { �INODEPTR front, rear; }�struct queue q; Int empty ( struct queue *pq) { Return (pq->front==NULL):TRUE?FALSE; } |
void insafter(NODEPTR p, int x)
{�NODEPTR q;�if (p ==NULL)
{�printf("void insertion\n”);�exit(1);
}�q= getnode();�q -> info =x;�q -> next = p -> next;�P -> next =q;�} �
void deafter(NODEPTR p, int *px)�{
NODEPTR q;�if((p == NULL) || (p -> next == NULL))�{
printf(ojd deletion\n);�exit(1);
}�q=p -> next;�px = q -> info.;�P -> next = q -> next;�freenode(q);�} �
LINKED LIST PRIORITY QUEUES
void place(NOOEPTR *plist, int x)
{�NOOEPTR p, q;�q = NULL;�for (p =*plist; p != NULL && x > p->info; p =p->next)
q =p;
�if (q ==NULL)
push(*plist, x);�else�insafter(q, x);
}
int pop()
{
NODEPTR P=list;
If(p==NULL)
{
printf(“List empty”);
return 0;
}
X=p->info;
List=p->next;
Freenode(p);
Return x;
}
//Insert at end of list
void insend(NODEPTR *piist, int x)
{�NODEPTR p, q;�p= getnode();�p->info= x;�p->next = NULL; �if (*pljst == NULL) �*plist = p:�else�for (q = *plist; q->next != NULL; q =q->next);
q->next = p;�} ��
NODEPTR search(NODEPTR list, int x)
{�NODEPTR p;�for (p = list; p != NULL; p = p->next)�if (p->info== x)�return (p);�else�return (NULL);�} �
typedef struct poly_node *poly_pointer;�typedef struct poly_node
{�int coef;�int expon;�poly_pointer link;�};
poly_pointer a,b,d; �
NODEPTR insert(NODEPTR *clist,int x)
{
NODEPTR p;
p=getnode();
P->info=x;
If(CLIST==NULL)
{
CLIST=p;
CLIST->next=CLIST; }
Else
{ p->next=clist->next;
clist->next=p;
}
Return clist; }
Int delete(NODEPTR *clist)
{
NODEPTR p;
If(clist==NULL)
{ printf(“List empty”);
exit(0); }
p=clist->next;
X=P->info;
If( p->next==clist->next)
clist=NULL;
else
c->next=p->next;
}
int empty(NODEPTR *pstack)
{�return ((pstack == NULL) ? TRUE : FALSE);
} �
Void push(NODEPTR pstack, int x)�{�NODEEPTR p;�P – getnode();�p->info=x;�if (empty(pstack) ==TRUE)�pstack =p;�else�p->next =(*pstack) -> next;�(*psrack) -> next =p;
}�
int POP(NODEPTR pstack)�{�int x;�NOOEPTR p;�if (empty(pstack) ==TRUE)
{�printf('stack underflow\n");�exit(1);� }
P = (*pstack) -> next;�x = p->info;�if (p== *pstack)�*pstack = NULL;�else�(pstack) -> next =p->next;�freenode(p);�return(x);�}�
void insert(NODEPTR *pq, int x)�{
NODEPTR p;�p =getnode();�p->info =x;�if (empty(pq) == TRUE)�*pq =p;�else�p->next=(*pq) -> next;�(*pq) -> next =p;�*pq =p;�return;�}�// CLIST as a queue
int Delete(NODEPTR pq)�{�int x;�NOOEPTR p;�if (empty(pq) ==TRUE)
{�printf(‘Queue Empty\n");�exit(1);� }
P = (*pq) -> next;�x = p->info;�if (p== *pq)�*pq = NULL;�else�(pq) -> next =p->next;�freenode(p);�return(x);�}�
SPARCE MATRIX REPRESENTAION AS LINKED LIST
Rows | Cols | Value |
4 | 4 | 4 |
0 | 2 | 11 |
1 | 0 | 12 |
0 | 1 | -4 |
3 | 3 | -15 |
Representation of sparse Matrix as
Circular Linked List
Doubly linked list
Doubly Linked list contains two pointes , 1 pointing to previous node, called left pointer
Right pointer points to Successor node or next node
Hence each node has Left pointer and right pointer
They are symmetric in nature
The list can be traversed in any direction
A Doubly Linked List ( DLL) may contain a header node
Left(right(p))=p=right(left(p))
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | | | | | | | |
N | O | B | O | D | Y | N | O | T | I | C | E | H | I | M | T |
N | O | T |
|
|
|
|
|
|
|
|
|
|
|
| P |
| N | O | T |
|
|
|
|
|
|
|
|
|
|
|
|
|
| N | O | T |
|
|
|
|
|
|
|
|
|
|
|
|
|
| N | O | T |
|
|
|
|
|
|
|
|
|
|
|
|
|
| N | O | T |
|
|
|
|
|
|
|
|
|
|
|
|
|
| N | O | T |
|
|
|
|
|
|
|
|
|
|
|
|
|
| N | O | T |
|
|
|
|
|
|
|
ALGORITHM BruteForceStringMatch(T [0..n - 1], P[0..m - 1])�//Implements brute-force string matching�//Input: An array T [0..n - 1] of n characters representing a text and�for i ← 0 to n - m do�j ← 0� while j < m and P[j] = T[i + j] do� j ← j + 1� if j = m
return i�return -1
Knuth-Morris-Pratt Algorithm�
KMP algorithm is used to find a "Pattern" in a "Text".
This algorithm compares character by character from left to right.
Whenever a mismatch occurs, it uses a preprocessed table called "Prefix Table" to skip characters comparison while matching.
The prefix table is also known as "Longest proper Prefix which is also Suffix" LPS Table.
Steps for Creating LPS Table (Prefix Table)
a pattern...
void computeLPSArray(const char* pat, int M, int* lps)
{
int len = 0;
lps[0] = 0;
int i = 1;
while (i < M) {
if (pat[i] == pat[len]) {
len++;
lps[i] = len;
i++;
}
else {
if (len != 0) {
len = lps[len - 1];
}
else {
lps[i] = 0;
i++;
}
}
}
}
KMPSearch
(const char* pat, const char* txt, int* count)
{
computeLPSArray(pat, M, lps);
while ((N - i) >= (M - j)) {
if (pat[j] == txt[i]) {
j++; i++;
}
if (j == M) {
result[*count] = i - j + 1; (*count)++;
j = lps[j - 1];
}
else if (i < N && pat[j] != txt[i]) {
if (j != 0) {
j = lps[j - 1];
}
else {
i = i + 1;
}
}
}
free(lps);
return result;
}