0% found this document useful (0 votes)
13 views

CSC 302 Linear Data Structure Implementation Using C

The document discusses linear data structures in C including pointers, structures, stacks, and queues. It covers declaring and initializing structures, accessing structure members, manipulating structures, arrays of structures, and modeling abstract data types like stacks using arrays.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views

CSC 302 Linear Data Structure Implementation Using C

The document discusses linear data structures in C including pointers, structures, stacks, and queues. It covers declaring and initializing structures, accessing structure members, manipulating structures, arrays of structures, and modeling abstract data types like stacks using arrays.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 12

Linear Data Structure Implementation using C

Overview
1. Introduction to Pointers
2. Introduction to structures
3. Stack Implementation
4. Queue Implementation

Pointers: An Introduction
• Recall that the declaration int x=11; causes a C compiler to reserve,
statically, a cell of size two bytes and place the value 11 there.
• A detail we have not mentioned up to now is that apart from occupying
some space, each variable has also an address in memory.
• The address of a variable is important because it can be used to manipulate
the value(s) of the variable more efficiently.
• The address of a variable is usually implicitly referenced by the compiler
and can also be explicitly referenced by the programmer in C.
• A pointer variable is a variable that holds the address of another variable.
• Does a pointer variable have an address, too?

Pointers: An Introduction (cont.)


• A pointer variable is declared by preceding it with an asterisk, `*.' For
example, int *y;.
• Note that in the preceding pointer variable declaration, the keyword int and
the symbol * juxtaposed together, int *, form the type for y.
• A variable of type int * can only hold address of locations whose contents
are int values.
• Data variables and pointer variables can both be used to modify value(s)
stored in memory
• Data variables and pointer variables are used to achieve different effects:
e.g., passing parameters to function by value or by reference

Pointers: Example 1
#include <stdio.h>
void main()
{
int count = 10, x, *ip;

ip = &count;
x = *ip;

printf("count = %d, x = %d\n", count, x);


}

#include <stdio.h>
void main()
{
int i1, i2, *p1, *p2;

i1 = 5;
p1 = &i1;
i2 = *p1 / 2 + 10;
p2 = p1;

printf("i1 = %d, i2 = %d, *p1 = %d, \


*p2 = %d\n", i1, i2, *p1, *p2);
}

Accessing Arrays Elements: Using Indices


#include <stdio.h>
#define MAX_SIZE 50
void main()
{
int i, size, a[MAX_SIZE];

printf("How many array elements do you have?>");


scanf("%d", &size);

printf("OK. Enter the %d array elements>", size);


for(i=0; i<size; i++)
scanf("%d", &a[i]);

printf("The elements in reverse are:\n");


for(i=size-1; i>= 0; i--)
printf("%d ", a[i]);
}

1-D Arrays and Pointers: Another Example


#include<stdio.h>

void main()
{
int a[] = {2,3,5,7,11,13,17,19};
int *p = &a[5];

for (; p != a; p--)
printf("%d\n", *p);
}

Arrays and Pointers: Some Notes


• Given a 1-D array m, m[i] (or equivalently *(m + i)) refers to the element at
index i.

For example:
#include <stdio.h>
void main()
{
int m[4][3] = {{10,5,-3}, {9, 0, 0},
{32,20,1}, {7,0,8}};
int row, column, sum;

sum = 0;
for(row = 0; row < 4; row++ )
for(column = 0; column < 3; column++ )
sum = sum + *(*(m+row)+column);
printf("The total is %d\n", sum );
}

• Note that the arrangement of array elements (2-D and more) into rows and
columns is only conceptually true; there are no rows and columns in
memory.
• Hence 2-D array elements are arranged linearly in memory like (a base
address 3002 is assumed for m):

position: m[0][0] m[0][1] m[0][2] ... m[3][0] m[3][1] m[3][2]


content: 10 5 -3 ... 7 0 8
address: 3002 3004 3006 ... 3020 3022 3024

• All that the compiler remembers about a 1-D array is its base address. If we
consider a 2-D array m[4][3], the base addresses of the four 1-D
arrays1 would be stored in m[0],m[1],m[2],m[3].
• Naturally, the expression m[2]+1 would give the address of the second
element in the third 1-D array. The value at this address can be obtained by
the expression *(m[2]+1) or *(*(m+2)+1.
• In general, the 2-D array element m[i][j] can be accessed more efficiently
using pointers as *(*(m+i)+j).

Overview

1. Structures: A Motivation
2. Tools for Creating Structures
3. Declaring and Initialising Structures
4. Accessing and Modifying Structure Members
5. Preview: Structures (cont.)

Structures: Motivations

• Our programs so far used only the basic data types provided by C, i.e., char, int, float,
void and pointers.
• We are now at a more advanced stage where programmers can define their own data
types using structures
• Structures are types that represent structured collections of data pertaining to
particular objects
• Structures can be used to conveniently model things that would otherwise be difficult
to model using arrays
• Arrays versus structures:
o arrays elements and structure components are contiguously laid out in memory
o arrays are homogeneous, structures can be heterogeneous
o arrays are passed to functions by reference while structures have to be
explicitly passed by reference
• different structures (in the same program) can have the same component name. A
structure component name can also be the same as an ordinary variable name

Creating Structures: the Tools


1. the enum specifier
2. the struct specifier
3. the typedef specifier
4. the union specifier

Creating Structures: Examples


enum Days {SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY};
struct date {
int day;
int month;
int year;
};
typedef struct date {
int day;
int month;
int year;
} DATE;
union mixed {
char c;
float num;
int age;
};
Initialising Structures
1. At definiton time
2. struct date {
3. int day;
4. int month;
5. int year;
6. } today = {5, 7, 99};

7. After definiton time


8. struct date tomorrow = {5, 7, 99};
9. struct date someDay = {5};
10. Some invalid initialisations
11. struct date tomorrow;
12. tomorrow = {5, 7, 99};
13.
14. struct date {
15. int day = 5;
16. int month = 7;
17. int year = 99;
18. } today;
Accessing Structure Members
Structure members can be accessed using two operators:
1. The dot operator, `.' and
2. The arrow operator, `− > '.
struct date {
int day;
int month;
int year;
}

main()
{
struct date today;

today.day = 17;
today.month = 11;
today.year = 1998;

printf("Todays date is %d/%d/%d.\n",


today.month, today.day, today.year );
}

Manipulating Structures
#include <stdio.h>

void modify_date(struct date yaum)


{

yaum.month = 3;
yaum.year = 1999;
printf("The date is %d/%d/%d.\n",
yaum.day, yaum.month, yaum.year );
}

main()
{
struct date today;

today.day = 16;
today.month = 7;
today.year = 1998;
printf("The date is %d/%d/%d.\n",
today.day, today.month, today.year );

modify_date(today);

printf("The date is %d/%d/%d.\n",


today.day, today.month, today.year );
}

Manipulating Structures (cont.)


Write a program to enter in five dates, Store this information
in an array of structures.
#include <stdio.h>

struct date { /* Global definition of date */


int day, month, year;
};

main()
{
struct date dates[5];
int i;

for( i = 0; i < 5; ++i ) {


printf("Please enter the date (dd:mm:yy)" );
scanf("%d:%d:%d", &dates[i].day,
&dates[i].month, &dates[i].year );
}
}

Recap: Accessing Structure Members


#include<stdio.h>
typedef struct Point {
int x;
int y;
} POINT;

main()
{
POINT p;
printf("Please enter two integers:");
scanf("%d%d", &p.x, &p.y);

printf("\nThe point is (%d, %d).\n", p.x, p.y);


}

Structures: Important Notes


1. Do not initialise structures at the wrong place:
2.
3. struct date {
4. int day = 22;
5. int month = 12;
6. int year = 63;
7. } dob;
8. Do not attempt to compare two structures as unit entities. Rather, two
structures must be compared component-wise
9. Do not attempt to read or display a structure with a single I/O statement.
10. Do not define a structure that refers to itself. Like:
11. struct date {
12. int day, month, year;
13. struct date dob;
14. }

Overview
1. Arrays of Structures
2. Arrays of Structures using Pointers
3. Preview: Abstract Data Types (ADT) Concepts
Arrays of Structures: Example 1
Write a program to enter in five dates, Store this information
in an array of structures.
#include <stdio.h>

struct date {
int day, month, year;
};

main()
{
struct date dates[5];
int i;

for( i = 0; i < 5; ++i ) {


printf("Please enter the date (dd:mm:yy)" );
scanf("%d:%d:%d", &dates[i].day,
&dates[i].month, &dates[i].year );
}
}

Overview
1. The ADT Stack
2. The Stack Operations
3. Modeling the ADT Stack using an Array
4. A Simple Application: Reversing a Line of Text
5. Preview: Queue ADT
The ADT Stack
• An ADT, in general, is a non-implemented data structure
with a set of operations that can be used to access the
data structure
• The ADT specifies only the abstract or logical properties
of the data structure and access functions, leaving the
implementation to the programmer
• In the ADT stack, items are added/removed from the
same stack location called the stack top.
• The following operations define the applications
programmer's (i.e., user's) interface to the ADT stack:
1. createStack() 2. destroyStack() 3. isFullStack()
4. isEmptyStack() 5. pushStack() 6. popStack()

• Notice that the ADT stack operations are the same


independent of the particular implementation of the stack
data structure.
ADT Stack: Array Implementation
#define MAXSTACK 10
typedef char StackEntry;
typedef enum {FALSE, TRUE} BOOLEAN;

typedef struct ADTstack {


int top;
StackEntry entry[MAXSTACK];
} StackType;

/* CreateStack: initialize the stack to be empty.


Pre: None.
Post: The stack has been initialized to be empty.
*/
void CreateStack(StackType *s)
{
s->top = 0;
}

/* DestroyStack: make the stack elements inaccessible.


Pre: The stack exists.
Post: The stack has become logically inaccessible.
*/
void DestroyStack(StackType *s)
{
s->top = 0;
}

ADT Stack: Array Implementation (cont.)


/* Push: push an item onto the stack.
Pre: The stack exists and it is not full.
Post: The argument item has been stored at the top
of the stack.
*/
void Push(StackEntry item, StackType *s)
{
if (StackFull(s))
printf("Stack overflow: Canno push stack.");
else
s->entry[s->top++] = item;
}

/* Pop: pop an item from the stack.

Pre: The stack exists and it is not empty.


Post: The item at the top of stack has been removed
and returned in *item.
*/
void Pop(StackEntry *item, StackType *s)
{
if (StackEmpty(s))
prinf("Stack underflow: Cannot pop empty stack.");
else
*item = s->entry[--s->top];
}

ADT Stack: Array Implementation (cont.)


/* StackEmpty: returns non-zero if the stack is empty.

Pre: The stack exists and it has been initialized.


Post: Return non-zero if the stack is empty; return
zero, otherwise.
*/
Boolean StackEmpty(StackType *s)
{
return s->top == 0;
}
/* StackFull: returns non-zero if the stack is full.
Pre: The stack exists and it has been initialized.
Post: Return non-zero if the stack is full; return
zero, otherwise.
*/
Boolean StackFull(StackType *s)
{
return s->top == MAXSTACK;
}

ADT Stack: A Simple Application


/* ReverseRead: read one line of input and write
it backward.
Pre: The user supplies one line of input.
Post: The line has been printed backward, using a
stack.
*/
void ReverseRead(void)
{
StackEntry item;
Stack stack;

CreateStack(&stack);
while (!StackFull(&stack) &&
(item = getchar()) != '\n')
Push(item, &stack);

while (!StackEmpty(&stack)) {
Pop(&item, &stack);
putchar(item);
}
putchar('\n');
}

Overview
1. The ADT Queue
2. Possible Array-Based Representations
3. Queue ADT: Implementation Using Circular Array
The ADT Queue
• Like the array and the stack, the queue is also a
homogeneous collection of objects
• The difference between a stack and queue lies in the way
they are accessed
• While the stack is a LIFO structure, the queue is a FIFO
structure
• While a stack has one access point, the top, the queue has
two access points: the front where objects are removed
and the rear where objects are added
• The following operations define the applications
programmer's (i.e., user's) interface to the ADT queue:
1. createQueue() 2. destroyQueue() 3. isFullQueue()
4. isEmptyQueue() 5. enqueueItem() 6. dequeueItem()

• Note that both the stack and the queue are specialised
form of the linked list (to be discussed in the next few
lectures)
• Both the stack and the queue have many practical
applications in computer science. For example, the stack
in used in compilers and the queue is often used in
scheduling algorithms
Queue ADT: Circular Array Implementation
#include<stdio.h>
#define MAX_QUEUE 100
typedef char QueueEntry;
typedef enum {FALSE, TRUE} Boolean;

typedef struct ADTqueue {


int count;
int front;
int rear;
QueueEntry entry[MAX_QUEUE];
} QueueType;

void createQueue(QueueType *q)


{
q->count = 0;
q->front = 0;
q->rear = 0;
}

void destroyQueue(QueueType *q)


{
q->count = 0;
q->front = 0;
q->rear = 0;
}

Boolean QueueEmpty(QueueType *q)


{
return q->count == 0;
}

Boolean QueueFull(QueueType *q)


{
return q->count == MAX_QUEUE;
}

void enqueue(QueueEntry x, QueueType *q)


{
if (QueueFull(q))
printf("Cannot enqueue into a full queue.");
else { q->count++;
q->entry[q->rear] = x;
q->rear = (q->rear + 1) % MAX_QUEUE;
}
}

void dequeue(QueueEntry *x, QueueType *q)


{
if (QueueEmpty(q))
printf("Cannot dequeue an empty queue.");
else { q->count--;
*x = q->entry[q->front];
q->front = (q->front + 1) % MAX_QUEUE;
}
}

void inputQueue(QueueType *q)


{
QueueEntry c;
printf("Please enter your full name: ");

while (!QueueFull(q) && (c = getchar()) != '\n')


enqueue(c, q);
}

void outputQueue(QueueType *q)


{
QueueEntry c;
while (!QueueEmpty(q)) {
dequeue(&c, q);
putchar(c);
}
}

main()
{
QueueType queue;

createQueue(&queue);
inputQueue(&queue);
outputQueue(&queue);
destroyQueue(&queue);
return;
}

You might also like