670 likes | 980 Views
Data Structures. Basics of structures Self-referential structures Dynamic memory allocation Linked lists Stacks Queues Trees. Data Hierarchy. Byte 8 bits (ASCII character ‘A’ = 01000001) Field Group of characters (character string “Fred”) Record Composed of related fields (struct)
E N D
Data Structures • Basics of structures • Self-referential structures • Dynamic memory allocation • Linked lists • Stacks • Queues • Trees
Data Hierarchy • Byte • 8 bits (ASCII character ‘A’ = 01000001) • Field • Group of characters (character string “Fred”) • Record • Composed of related fields (struct) • File • Group of related records (student record file) • Database • Group of related files (students, faculty, and staff files)
Structure Collection of related variables Structure tag “student” Structure’s members first, last, age, gpa struct student{char first[20];char *last;int age;double gpa; }; Structure Declaration
Define & initialize with list of variables Define & initialize using the dot operator (structure member operator) struct student s1 = {"Ted","Tanaka", 22, 2.22}; struct student s2; strcpy(s.first, "Sally"); s.last="Suzuki"; s.age = 33; s.gpa = 3.33; Structure Definition
Structure member operator, or dot operator For direct variables (.) Structure pointer operator For pointers (->) struct student s2; struct student*sPtr = s2; printf("%s %d\n", s1.last, s1.age); /*Tanaka 22*/ printf("%s %d\n", (*sPtr).last, sPtr->age); /*Suzuki 33*/ Accessing Members *See complete program at accessingMembers.c
sizeof Operator • Returns the size in bytes of a data type char a, b[10]; int c, d[10]; double e, f[10]; printf("sizeof(a) = %d\n",sizeof(a)); printf("sizeof(b) = %d\n",sizeof(b)); . . . /* sizeof(a) = 1 sizeof(b) = 10 */ /* sizeof(c) = 4 sizeof(d) = 40 */ /* sizeof(e) = 8 sizeof(f) = 80 */
sizeof Operator • Examples with pointers char b[10], *p1 = b; int d[10], *p2 = d; double f[10], *p3 = f; printf("sizeof(p1) = %d ",sizeof(p1)); printf("sizeof(*p1) = %d\n",sizeof(*p1)); . . . /* sizeof(p1) = 4 sizeof(*p1) = 1 */ /* sizeof(p2) = 4 sizeof(*p2) = 4 */ /* sizeof(p3) = 4 sizeof(*p3) = 8 */
sizeof Operator • Examples with structures struct student s1={"Ted","Tanaka", 22,2.22}; struct student s2; struct student *s3 = &s2; struct student s4[10]; printf("sizeof(s1) = %d\n", sizeof(s1)); . . . /* sizeof(s1) = 40 sizeof(s2) = 40 sizeof(s3) = 4 sizeof(s4) = 400 */
sizeof Operator struct student{ char first[20]; /* 20 bytes */ char *last; /* 4 bytes */ int age; /* 4 bytes */ double gpa; /* 8 bytes */ }; /* total = 36 bytes ?? */ • Structures may have “extra padding”, because computers may store specific data types on certain memory boundaries • See complete program at sizeof.c
Structures & Functions • You can pass a structure to a function by value struct student s1={"Ted","Tanaka", 22, 2.22}; incAge1(s1.age); printStudent(s1); /* Name = Ted Tanaka age = 22 gpa = 2.22 */ void incAge1(int a){ a++;} void printStudent(struct student s){ printf("Name = %s %s \n age = %d gpa = %.2f\n",s.first, s.last, s.age, s.gpa);}
Structures & Functions • Or pass by reference (pointer to a structure) struct student s1={"Ted","Tanaka", 22, 2.22}; struct student *p = &s1; incAge2(p); printStudent(s1); /* Name = Ted Tanaka age = 23gpa = 2.22 */ void incAge2(struct student *s){s->age++;} • See complete program at functions.c
Arrays of Structures • Can also have an array of a structure main(){ struct student s[100]={"","", 0, 0.0}; printStudent(s[0]); } /* Name = age = 0 gpa = 0.00 */
struct A{ /*See struct1.c*/ char b; int c; }; struct A fun(struct A); main(){ struct A d = {'e', 71}; /* sizeof(d)=8 */ struct A e[20]; printf("sizeof(e)=%d\n", sizeof(e)); e[0] = fun(d); printf("b=%c c=%d\n", d.b, d.c); printf("b=%c c=%d\n", e->b, (*e).c); } struct A fun(struct A a){ printf("b=%c c=%d\n", a.b++, ++a.c); return a;}
Dynamic Data Structures • Linked lists • Insert & delete anywhere in the list • Stacks • Insert & delete at the top • Used in compilers & operating systems • Queues • Insert at back & delete from front • Used in operating systems, print spooling, & networks • Binary trees • Quick searching & sorting
Self-Referential Structure • Contains a pointer that points to another structure of the same type struct node{ int data; struct node *next; }; • Self-referential structures linked together to form dynamic data structures
Dynamic Memory Allocation • Ability of a program to use more memory space at execution time • Hold new nodes • Use function malloc to allocate memory • Release space no longer needed • Use function free to deallocate memory • Use #include <stdlib.h> header file when using malloc & free functions
Functions malloc & free • ptr = malloc(sizeof(struct node)); • sizeof(struct node) returns the size in bytes of the structure • malloc() allocates the specified number of bytes in memory • Returns a pointer to the place in memory • Returns NULL, if no more memory is available • free(ptr); • Deallocates the memory referred to by the pointer so it can be reused
Program in Memory • Code segment • Contains instructions (program code) • Data segment • Contains static data (global variables) • Stack segment • Each function call creates a stack frame • Stack frame contains local variables, etc. • Function call: push stack frame • Function exit: pop stack frame • Grows from top of memory downwards
Stack & Heap • Stack • Implicit (automatic) allocation & deallocation • Heap • Memory explicitly allocated & deallocated by the programmer using functions malloc & free • At bottom of memory & grows upwards • When the stack & the heap meet, your program is out of memory • May occur if you don’t use free function to deallocate memory
Stack & Heap Example • See HeapStack.htm • Each function call creates a “stack frame” or “activation record” that stores information about the function on the stack • Parameters • Return address • Local variables • Each malloc() function call allocates data on the heap, while free() deallocates data from the heap
Linked List • Collection of nodes (self-referential structure) • Connected by links (pointer to next node) • Pointer points to the first node • Next pointer refers to next node • Last node has a NULL next pointer • Constrained versions of linked lists • Stacks (insert & delete at the top) • Queues (insert at back & delete from front)
Linked List Example • See fig12_03.c • A program that manipulates a list of characters • Insert a character in the list in alphabetical order • Delete a character from the list
Inserting a Character • Function prototype struct listNode { char data; struct listNode *nextPtr; }; typedef struct listNode ListNode; typedef ListNode *ListNodePtr; void insert(ListNodePtr *, char );
Inserting a Character • Equivalent code void insert(ListNodePtr *, char ); //void insert( struct listNode **, char); • sPtr is a pointer to a pointer, because • the address of the list is passed to the function • and the list itself is a pointer (a pointer to its 1st element)
Inserting a Character • Calling the function ListNodePtr startPtr = NULL; //struct listNode *startPtr = NULL; . . . insert( &startPtr, item ); • startPtr contains a pointer to the beginning node of the list
Inserting a Character void insert( ListNodePtr *sPtr, char value ){ ListNodePtr newPtr; /* pointer to new node */ ListNodePtr previousPtr; /* pointer to previous node in list */ ListNodePtr currentPtr; /* pointer to current node in list */ newPtr = malloc( sizeof( ListNode ) ); /* create node */
Inserting a Character if ( newPtr != NULL ) { /* is space available */ newPtr->data = value; /* place value in node */ newPtr->nextPtr = NULL; /* node does not link to another node */ previousPtr = NULL; currentPtr = *sPtr;
Inserting a Character while ( currentPtr != NULL && value > currentPtr->data ) { /* loop to find the correct location in the list */ previousPtr = currentPtr; /* walk to ... */ currentPtr = currentPtr->nextPtr; /* ... next node */ }
Inserting a Character if ( previousPtr == NULL ) { /* insert new node at beginning of list */ newPtr->nextPtr = *sPtr; *sPtr = newPtr; } else { /* insert new node between previousPtr and currentPtr */ previousPtr->nextPtr = newPtr; newPtr->nextPtr = currentPtr; }
Deleting a Character • Function prototype struct listNode { char data; struct listNode *nextPtr; }; typedef struct listNode ListNode; typedef ListNode *ListNodePtr; void delete(ListNodePtr *, char );
Deleting a Character • Equivalent code void delete(ListNodePtr *, char ); //void delete( struct listNode **, char); • sPtr is a pointer to a pointer, because • the address of the list is passed to the function • and the list itself is a pointer (a pointer to its 1st element)
Deleting a Character char delete( ListNodePtr *sPtr, char value ){ ListNodePtr previousPtr; /* pointer to previous node in list */ ListNodePtr currentPtr; /* pointer to current node in list */ ListNodePtr tempPtr; /* temporary node pointer */
Deleting a Character if ( value == ( *sPtr )->data ) { /* delete first node */ tempPtr = *sPtr; /* hold onto node being removed */ *sPtr = ( *sPtr )->nextPtr; /* de-thread the node */ free( tempPtr ); /* free the de-threaded node */ return value; }
Deleting a Character else { previousPtr = *sPtr; currentPtr = ( *sPtr )->nextPtr; while ( currentPtr != NULL && currentPtr->data != value ) { /* loop to find the correct location in the list */ previousPtr = currentPtr; /* walk to ... */ currentPtr = currentPtr->nextPtr; /* ... next node */ }
Deleting a Character if ( currentPtr != NULL ) { /* delete node at currentPtr */ tempPtr = currentPtr; previousPtr->nextPtr = currentPtr->nextPtr; free( tempPtr ); return value; }
Stacks • Referenced by a pointer to the top element • “Push” to the stack to insert data • Allocates memory to create a new node • Places new node on top of stack • “Pop” to the stack to delete data • Removes node from top of stack • Deallocates (frees) memory • Returns the data that was stored in the node
Dynamic Stack Example • See fig12_08.c • Program that implements a stack of integers • Push an integer onto the stack • Pop a value off the stack
Dynamic Stack Program • Self-referential structure struct stackNode { int data; struct stackNode *nextPtr; }; • Use typedef to create structure synonym & pointer to structure synonym typedef struct stackNodeStackNode; typedef StackNode *StackNodePtr;
Dynamic Stack Program • Push & pop must modify the stack (so must pass a pointer) • Since stack itself is a pointer (to the top of the stack), passing the address of the stack creates a pointer to a pointer (double indirection) void push( StackNodePtr*, int ); int pop( StackNodePtr* ); int isEmpty( StackNodePtr ); void printStack( StackNodePtr ); void instructions( void );
Dynamic Stack Program • Function main int main(){ /* points to stack top */ StackNodePtr stackPtr = NULL; int choice, value; instructions(); scanf( "%d", &choice ); while ( choice != 3 ) {
Dynamic Stack Program • Function call to push value on stack switch ( choice ) { case 1: printf( "Enter an integer: " ); scanf( "%d", &value ); push( &stackPtr, value ); printStack( stackPtr ); break;
Dynamic Stack Program • Inserting a node to the top of the stack void push(StackNodePtr *topPtr,int info){ StackNodePtr newPtr; /*allocate space for the node*/ newPtr = malloc(sizeof(StackNode)); if ( newPtr != NULL ) { newPtr->data = info; newPtr->nextPtr = *topPtr; *topPtr = newPtr; } else printf("No memory available.");}
Dynamic Stack Program • Function call to pop value off stack case 2: if ( !isEmpty( stackPtr ) ) printf( "The popped value is %d.\n", pop( &stackPtr ) ); printStack( stackPtr ); break;
Dynamic Stack Program • Remove a node from top of stack int pop( StackNodePtr *topPtr ){ StackNodePtr tempPtr; int popValue; tempPtr = *topPtr; popValue = (*topPtr)->data; *topPtr = (*topPtr)->nextPtr; /*deallocate memory used by node*/ free( tempPtr ); return popValue; }
Dynamic Stack Program • Print the stack void printStack(StackNodePtr currentPtr){ if ( currentPtr == NULL ) printf("The stack is empty.\n\n" ); else { printf( "The stack is:\n" ); while ( currentPtr != NULL ) { printf( "%d --> ", currentPtr->data ); currentPtr = currentPtr->nextPtr;} printf( "NULL\n\n" );}}
Dynamic Stack Program • Check to see if stack is empty int isEmpty( StackNodePtr topPtr ){ return topPtr == NULL; }
Queue Program • See fig12_13.c • Insert a character into a queue • Remove a character from a queue
Queue Program • Main function QueueNodePtr headPtr = NULL; /* initialize headPtr */ QueueNodePtr tailPtr = NULL; /* initialize tailPtr */ int choice; /* user's menu choice */ char item; /* char input by user */
Inserting a Node void enqueue( QueueNodePtr *headPtr, QueueNodePtr *tailPtr, char value ){ /* insert a node at queue tail */ QueueNodePtr newPtr; /* pointer to new node */ newPtr = malloc( sizeof( QueueNode ) ); if ( newPtr != NULL ) { /* is space available */ newPtr->data = value; newPtr->nextPtr = NULL;
Inserting a Node if ( isEmpty( *headPtr ) ) { /* if empty, insert node at head */ *headPtr = newPtr; } else { ( *tailPtr )->nextPtr = newPtr; } *tailPtr = newPtr; } else { printf( "%c not inserted. No memory available.\n", value );} }