maskedbard.altervista.orgmaskedbard.altervista.org/resume/notesdsc.docx  · web viewlanguage...

162
90.360: Introduction to Data Structures using C Instructor: Dan Leach Course materials copyright © 2001 by Dan Leach All rights reserved. [email protected] Revision 1.04 June, 2001

Upload: trantuyen

Post on 08-Feb-2018

219 views

Category:

Documents


0 download

TRANSCRIPT

90.360: Introduction to Data Structures using C

Instructor: Dan Leach

Course materials copyright © 2001 by Dan LeachAll rights [email protected] 1.04June, 2001

1. Notes.................................................................................................................................... 1-11.1 Language overview.......................................................................................................1-1

1.1.1 Storage allocation and name scope.......................................................................1-11.1.2 Control structures...................................................................................................1-11.1.3 Data types..............................................................................................................1-11.1.4 Data attributes........................................................................................................1-21.1.5 Built in function.......................................................................................................1-21.1.6 Other...................................................................................................................... 1-2

1.2 Hungarian Notation........................................................................................................1-31.3 Other Coding Conventions............................................................................................1-41.4 General Data Structure Features...................................................................................1-51.5 Stacks............................................................................................................................ 1-61.6 A Stack Implementation.................................................................................................1-7

1.6.1 stddef.h................................................................................................................... 1-71.6.2 error.h..................................................................................................................... 1-71.6.3 error.c..................................................................................................................... 1-71.6.4 stack.h.................................................................................................................... 1-81.6.5 stacka.h.................................................................................................................. 1-91.6.6 stacka.c.................................................................................................................. 1-91.6.7 stackl.h................................................................................................................. 1-121.6.8 stackl.c.................................................................................................................1-121.6.9 stktst.c.................................................................................................................. 1-171.6.10 bldsta.bat..............................................................................................................1-201.6.11 bldstl.bat...............................................................................................................1-201.6.12 stktsta.out.............................................................................................................1-201.6.13 stktstl.out..............................................................................................................1-20

1.7 Recursion.................................................................................................................... 1-221.7.1 fac.c...................................................................................................................... 1-221.7.2 fib.c.......................................................................................................................1-231.7.3 twrs.c.................................................................................................................... 1-241.7.4 twrs.out................................................................................................................. 1-271.7.5 bldta.bat................................................................................................................1-281.7.6 bldtl.bat................................................................................................................. 1-281.7.7 eightq.c................................................................................................................. 1-281.7.8 eightqx.out............................................................................................................1-31

1.8 Queues........................................................................................................................ 1-321.9 A Queue Implementation.............................................................................................1-33

1.9.1 queue.h................................................................................................................1-331.9.2 queuea.c...............................................................................................................1-331.9.3 queuea.h..............................................................................................................1-341.9.4 queuel.c................................................................................................................1-351.9.5 queuel.h................................................................................................................1-37

1.10 Lists............................................................................................................................. 1-381.10.1 Singly linked versus Doubly linked.......................................................................1-381.10.2 With versus without a header node......................................................................1-381.10.3 Circularly linked versus linearly linked..................................................................1-381.10.4 Positional versus non-positional...........................................................................1-38

1.11 A List Implementation..................................................................................................1-391.11.1 list.h......................................................................................................................1-391.11.2 pslist.h.................................................................................................................. 1-391.11.3 pslist.c..................................................................................................................1-401.11.4 pdlist.h.................................................................................................................. 1-451.11.5 pdlist.c.................................................................................................................. 1-461.11.6 listsort.c................................................................................................................1-521.11.7 listsort.in...............................................................................................................1-561.11.8 listsort.out.............................................................................................................1-56

Copyright © 2001 Dan Leach i

1.11.9 bldlsd.bat..............................................................................................................1-571.11.10 bldlss.bat...........................................................................................................1-57

1.12 Searching.................................................................................................................... 1-581.12.1 Linear Search.......................................................................................................1-581.12.2 Binary Search.......................................................................................................1-58

1.13 A Linear Search Implementation.................................................................................1-591.13.1 listsqs.c.................................................................................................................1-591.13.2 bldlsqss.bat..........................................................................................................1-631.13.3 bldlsqsd.bat..........................................................................................................1-63

1.14 A Binary Search Implementation.................................................................................1-641.14.1 listbs.c..................................................................................................................1-641.14.2 bldlbss.bat............................................................................................................1-691.14.3 bldlbsd.bat............................................................................................................1-69

1.15 Sorting......................................................................................................................... 1-701.15.1 sorts.h................................................................................................................... 1-701.15.2 sorts.c...................................................................................................................1-701.15.3 tstsorts.c...............................................................................................................1-791.15.4 tstsorts.out............................................................................................................1-821.15.5 bldtsts.bat.............................................................................................................1-831.15.6 bldtstd.bat.............................................................................................................1-83

1.16 Hash Tables................................................................................................................1-841.16.1 list.h......................................................................................................................1-841.16.2 hasht.h.................................................................................................................. 1-851.16.3 hasht.c..................................................................................................................1-851.16.4 testhash.c.............................................................................................................1-911.16.5 testhash.out..........................................................................................................1-961.16.6 names.txt..............................................................................................................1-971.16.7 delete.txt...............................................................................................................1-981.16.8 replace.txt.............................................................................................................1-981.16.9 bldthd.bat..............................................................................................................1-981.16.10 bldths.bat..........................................................................................................1-98

1.17 Binary Trees................................................................................................................1-991.17.1 tree.h....................................................................................................................1-991.17.2 tree.c.................................................................................................................... 1-991.17.3 treesort.c............................................................................................................1-102

1.18 Graphs....................................................................................................................... 1-1061.18.1 graph.h...............................................................................................................1-1061.18.2 graph.c...............................................................................................................1-1071.18.3 graphtst.c............................................................................................................1-1171.18.4 build.bat..............................................................................................................1-1201.18.5 shortest.h............................................................................................................1-1201.18.6 shortest.c............................................................................................................1-1201.18.7 shorttst.c.............................................................................................................1-1251.18.8 build.bat..............................................................................................................1-126

2. Homeworks for Advanced C++.............................................................................................2-12.1 Homework 1.................................................................................................................. 2-12.2 Homework 2.................................................................................................................. 2-2

2.2.1 bldhw2a.bat............................................................................................................2-22.2.2 bldhw2l.bat.............................................................................................................2-22.2.3 hw2.in..................................................................................................................... 2-22.2.4 hw2.out................................................................................................................... 2-2

2.3 Homework 3.................................................................................................................. 2-42.4 Homework 4.................................................................................................................. 2-52.5 Homework 5.................................................................................................................. 2-7

Copyright © 2001 Dan Leach ii

1. Notes

1.1Language overview

1.1.1 Storage allocation and name scopeauto default; allocate variable on stack on entry to defining block and deallocate it on

exit from the blockstatic allocate space for variable at the beginning of the program run and don't

deallocate it until the end of the program run; at the module level, this has the effect of hiding the name from the global name scope

register keep the indicated variable in a register if at all possible for its life; this request is not honored by newer compilers including Microsoft’s 32-bit compilers

extern don't allocate storage if data member (this can be applied to function names as well); the name tagged with this attribute is merely described here and is defined elsewhere either in this module or another module

const the indicated variable is unchanged by the function or any functions it is passed to by this function

volatile the indicated variable may be changed by the OS or another thread; reload the variable each time its value is requested rather than trying to optimize usage

1.1.2 Control structuresif conditional executionelse what to do if the associated if was not trueswitch multiway conditional execution; a selection statementcase a case within a selection statement (switch)default describes the else condition in a selection statement; switch will do nothing if a

default is not present and none of the conditions are truecontinue start the next iteration of the enclosing loopbreak exit the enclosing loop or case statementfor iterative loop which describes both an initial step and an iterative step in addition

to a termination condition and a body; termination condition is tested before execution of body

do may be used with the while statement to describe a do-until situation; that is, the body is executed before testing the termination condition; sometimes called a test last loop structure

while used to indicated a test in a loopgoto we won't use this four letter word in this coursereturn return from function; pass argument to caller if present

1.1.3 Data typeschar holds an ASCII characterdouble holds a floating point number (usually twice the size of a normal float)enum an enumerated variablefloat holds a floating point numberint holds an integerlong holds an integer (usually twice the size of a normal int) short holds an integer (usually half the size of a normal int) void untyped if applied to data; can also be used to indicate that there will be no value

returned from a function

1.1.4 Data attributessigned default; store a signed number in the indicated variable

Copyright © 2001 Dan Leach 1

unsigned store an unsigned number in the indicated variablestruct aggregate data typetypedef define the indicated name as a data typeunion allocate storage associated with the largest of the specified members but allow

that storage to be used in all specified ways

1.1.5 Built in functionsizeof return the size of the indicated variable or data type (either basic or user defined)

in bytes

1.1.6 Otherasm used to indicate that assembler has been inserted inline

Copyright © 2001 Dan Leach 2

1.2Hungarian NotationIn general, Hungarian notation names a variable with a lower-case prefix to identify the type of the variable. There is no such thing as standard HN, so the point here is to create a consistent notation system. In this class, we'll use the following standards.

c: signed character uc: unsigned character i: integer ui: unsigned integer s: short integer l: long integer f: float d: double sz: string of characters, terminated by a null character b: an integer or character being used as a boolean value pfs: file stream pointer pfn: pointer to a function px: pointer to a variable of type x, e.g. pi, pf, pli

These prefixes are combined with an identifying name where each significant part begins with a capital letter: iUserChoice - holds the selection from a numeric menu cUserChoice - holds the selection from an alphabetic menu szFileName - a zero-terminated string with a file name in it pfsUnsortedNumbers - file pointer to a data file ctBytesProcessed - counter of work done

Function names (other than main) also follow this pattern of upper/lower case: ProcessRecord() GetUserChoice() HandleError()

As the semester goes along, we may add more standard notations. If you find you need a variable that does not fit in these classes, create a new prefix and use it consistently.

Copyright © 2001 Dan Leach 3

1.3Other Coding ConventionsFunction interfaces and definitions should be in a separate header file (usually one per data structure).

Similarly, implementation of these function classes should be in separate c files (usually one per data structure).

Your test program should always be in a separate file from the data structure implementations.

Comment liberally. Each function should start with a one line comment or short block comment explaining the function’s purpose. Major blocks of code (or even short blocks if you’re doing something that is less than obvious) within functions should contain similar comments.

Names of both functions and variables should be descriptive. Non-descriptive variable names (especially one character variable names and variable names containing only one character and a number) should be used sparingly and only where it is obvious what their purpose is (such as counters, temporary storage, and certain input parameters to functions).

Copyright © 2001 Dan Leach 4

1.4General Data Structure FeaturesThe data structures that we study in this course are primarily containers. They hold data encapsulated with functions to access that data. They are similar in many ways to C++ classes.

All data structures contain the following features in some sense or other (though they may have other names):Create Initialize an empty data structure (analogous to a C++ constructor).Destroy Return all storage in a data structure to the system (analogous to a C++ destructor).

Add Add an element to the data structure.Remove Remove an element from the data structure; usually returns the element removed.

Many may also contain the following functions (though, again, they may have other names):Clear Remove all entries from the stack (return it to an empty state)Empty Tell if the data structure is empty (contains no elements).Full Tell if the data structure is full (no more elements may be added).Size Return the number of entries currently in the data structure.Get Return the element without removing it.Set Change the value of an element.Traverse Call a passed function for each element in a defined order.Print A special case of the Traverse function which would print the contents of the data

structure without changing its contents.

Copyright © 2001 Dan Leach 5

1.5StacksA stack is a data structure to which elements are added to and then removed from the top in a LIFO (last in, first out) manner.

Required functions for a stack are:Create Return an empty stackEmpty Tell whether the stack is emptyFull Tell whether the stack is fullPush Add an entry to the top of the stackPop Remove an entry from the top of the stack

Other functions that may be provided:Top Return the top of the stack without removing itSize Return the number of entries currently in the stackClear Remove all entries from the stack (return it to an empty state)Traverse Visit each entry in the stack with a function passed as an argument; beginning at the

top and proceeding to the bottom; stack is unchanged as a result of traversing itPrint A special case of the Traverse function which would print the contents of the stack

without changing the stack

Copyright © 2001 Dan Leach 6

1.6A Stack Implementation

1.6.1 stddef.h 1: // stddef.h 2: // standard defines 3: 4: #pragma once 5: 6: #if !defined(Boolean) 7: typedef int Boolean; 8:#endif 9: 10: #if !defined(true) 11: #define true 1 12: #endif 13: 14: #if !defined(false) 15: #define false 0 16: #endif

1.6.2 error.h 1: // error.h 2: // interface to error handling routines 3: 4: #pragma once 5:#include "stddef.h" 6: 7: void SetError(); 8: void ClearError(); 9:Boolean GetError(); 10: void Error(char * szError);

1.6.3 error.c 1: // error.c 2: // implementation of error handling routines 3: 4: #include <stdio.h> 5:#include "error.h" 6: 7: // error flag 8: static Boolean bError = false; 9: 10: // set the error flag 11: void SetError() 12: { 13: bError = true; 14: } 15: 16: // clear the error flag 17: void ClearError() 18: { 19: bError = false; 20: }

Copyright © 2001 Dan Leach 7

21: 22: // get the error flag 23: Boolean GetError() 24: { 25: return bError; 26: } 27: 28: // print an error and set the error flag 29: void Error(char * szError) 30: { 31: fprintf(stderr,"ERROR: %s\n", szError); 32: SetError(); 33: }

1.6.4 stack.h 1: // stack.h 2: // interface to stack 3: 4: #pragma once 5: 6: #include "stddef.h" 7: 8: // common defines and dcls 9:#define MAX_NAME 10 10: #define MAX_MESSAGE_LENGTH 160 11: 12: typedef int StackEntry; 13: #define atose atoi 14: 15: extern unsigned int g_uiLevel; 16: extern unsigned int g_uiMaxLevel; 17: 18: // picks which stack implementation based on define 19: 20: #if defined (LINKED_STACK) 21: #include "stackl.h" 22: 23: #elif defined (FIXED_STACK) 24: #include "stacka.h" 25: 26: #else 27: #error You must pick a stack type: FIXED_STACK or LINKED_STACK 28: 29: #endif 30: 31: // interface to functions 32: void Indent(); 33: void IncrementLevel(); 34: void DecrementLevel(); 35: void PrintStack(Stack * pstk, char * szMessage); 36: Boolean StackFull(Stack * pstk); 37: Boolean StackEmpty(Stack * pstk); 38: void Push(Stack * pstk, StackEntry se); 39: void Pop(Stack * pstk, StackEntry * pse); 40: void CreateStack(Stack * pstk, char * szName);

Copyright © 2001 Dan Leach 8

41: void ClearStack(Stack * pstk); 42: char * StackName(Stack * pstk); 43: void StackTop(Stack * pstk, StackEntry * pse); 44: int StackSize(Stack * pstk); 45: void TraverseStack(Stack * pstk, void(*Visit)(StackEntry));

1.6.5 stacka.h 1: // stacka.h 2: // stack implementation definitions for fixed stack 3: 4: #pragma once 5: 6: #define MAX_STACK 10 7: 8: typedef struct 9: { 10: int iTop; 11: StackEntry seEntries[MAX_STACK]; 12: char szName [MAX_NAME]; 13: } Stack;

1.6.6 stacka.c 1: // stacka.c 2: // implementation of fixed stack 3: 4: #include <stdio.h> 5:#include <string.h> 6:#include "error.h" 7: #include "stack.h" 8: 9: // format for output 10: char * g_szEntryFormat = "%d "; 11: 12: // global level count 13: unsigned int g_uiLevel = 0; 14: 15: // global max level 16: unsigned int g_uiMaxLevel = 0; 17: 18: // add indents to output 19: void Indent() 20: { 21: unsigned int ui; 22: for (ui=0;ui<g_uiLevel;ui++) 23: printf("\t"); 24: } 25: 26: // increment global level count 27: void IncrementLevel() 28: { 29: if (g_uiLevel<20) 30: g_uiLevel++; 31: if (g_uiLevel>g_uiMaxLevel) 32: g_uiMaxLevel = g_uiLevel; 33: }

Copyright © 2001 Dan Leach 9

34: 35: // increment global level count 36: void DecrementLevel() 37: { 38: if (g_uiLevel>0) 39: g_uiLevel--; 40: } 41: 42: // return the top item from the stack if there is one 43: // otherwise, error 44: void StackTop(Stack * pstk, StackEntry * pse) 45: { 46: char szMessage [MAX_MESSAGE_LENGTH]; 47: 48: if(StackEmpty(pstk)) 49: { 50: sprintf(szMessage,"%s: Stack is empty", pstk->szName); 51: Error(szMessage); 52: } 53: else 54: *pse=pstk->seEntries[pstk->iTop-1]; 55: } 56: 57: // return the stack size 58: int StackSize(Stack * pstk) 59: { 60: int i=0; 61: 62: if(!StackEmpty(pstk)) 63: i=pstk->iTop; 64: 65: return i; 66: } 67: 68: // traverse the stack 69: void TraverseStack(Stack * pstk, void(*Visit)(StackEntry)) 70: { 71: int i; 72: for (i=pstk->iTop;i>0;i--) 73: Visit(pstk->seEntries[i-1]); 74: } 75: 76: // print an entry 77: void PrintEntry(StackEntry se) 78: { 79: printf(g_szEntryFormat, se); 80: } 81: 82: // print the stack 83: void PrintStack(Stack * pstk, char * szMessage) 84: { 85: char szOutput[MAX_MESSAGE_LENGTH]; 86: 87: strcpy(szOutput,""); 88: 89: if (strlen(pstk->szName))

Copyright © 2001 Dan Leach 10

90: { 91: strcat(szOutput,pstk->szName); 92: strcat(szOutput,": "); 93: } 94: 95: if (strlen(szMessage)) 96: { 97: strcat(szOutput, szMessage); 98: strcat(szOutput,": "); 99: } 100: 101: strcat(szOutput,"(TOP) "); 102: printf(szOutput); 103: 104: TraverseStack(pstk,PrintEntry); 105: 106: printf("(BOTTOM)\n"); 107: } 108: 109: // return stack name 110: char * StackName(Stack * pstk) 111: { 112: return pstk->szName; 113: } 114: 115: // return whether the stack is full 116: Boolean StackFull(Stack * pstk) 117: { 118: return pstk->iTop>=MAX_STACK; 119: } 120: 121: // return whether the stack is empty 122: Boolean StackEmpty(Stack * pstk) 123: { 124: return pstk->iTop<=0; 125: } 126: 127: // add an item to the stack if there is room 128: // otherwise, error 129: void Push(Stack * pstk, StackEntry seItem) 130: { 131: char szMessage [MAX_MESSAGE_LENGTH]; 132: if(StackFull(pstk)) 133: { 134: sprintf(szMessage,"%s: Stack is full", pstk->szName); 135: Error(szMessage); 136: } 137: else 138: pstk->seEntries[pstk->iTop++] = seItem; 139: } 140: 141: // remove an item from the stack if there is one 142: // otherwise, error 143: void Pop(Stack * pstk, StackEntry * pseItem) 144: { 145: char szMessage [MAX_MESSAGE_LENGTH];

Copyright © 2001 Dan Leach 11

146: 147: if(StackEmpty(pstk)) 148: { 149: sprintf(szMessage,"%s: Stack is empty", pstk->szName); 150: Error(szMessage); 151: } 152: else 153: *pseItem=pstk->seEntries[--pstk->iTop]; 154: } 155: 156: // initialize the stack to be empty 157: void CreateStack(Stack * pstk, char * szName) 158: { 159: char szMessage [MAX_MESSAGE_LENGTH]; 160: 161: pstk->iTop=0; 162: if (strlen(szName)<MAX_NAME) 163: strcpy(pstk->szName,szName); 164: else 165: { 166: strcpy(pstk->szName,"BAD NAME"); 167: sprintf(szMessage,"Name too long: %s", szName); 168: Error(szMessage); 169: } 170: } 171: 172: // reset the stack to be empty 173: void ClearStack(Stack * pstk) 174: { 175: pstk->iTop=0; 176: }

1.6.7 stackl.h 1: // stackl.h 2: // stack implementation definitions for linked stack 3: 4: #pragma once 5: 6: typedef struct _StackNode 7: { 8: StackEntry se; 9: struct _StackNode * psnNext; 10: } StackNode; 11: 12: typedef struct 13: { 14: StackNode * psnTop; 15: char szName [MAX_NAME]; 16: } Stack;

1.6.8 stackl.c 1: // stackl.c 2: // implementation of linked stack 3: 4: #include <stdio.h>

Copyright © 2001 Dan Leach 12

5: #include <string.h> 6:#include <stdlib.h> 7:#include "error.h" 8: #include "stack.h" 9: 10: // format for output 11: char * g_szEntryFormat = "%d "; 12: 13: // global level count 14: unsigned int g_uiLevel = 0; 15: 16: // global max level 17: unsigned int g_uiMaxLevel = 0; 18: 19: // add indents to output 20: void Indent() 21: { 22: unsigned int ui; 23: for (ui=0;ui<g_uiLevel;ui++) 24: printf("\t"); 25: } 26: 27: // increment global level count 28: void IncrementLevel() 29: { 30: if (g_uiLevel<20) 31: g_uiLevel++; 32: if (g_uiLevel>g_uiMaxLevel) 33: g_uiMaxLevel = g_uiLevel; 34: } 35: 36: // increment global level count 37: void DecrementLevel() 38: { 39: if (g_uiLevel>0) 40: g_uiLevel--; 41: } 42: 43: // make a stack node 44: StackNode * MakeNode(StackEntry se) 45: { 46: StackNode * psn; 47: 48: psn=(StackNode *)calloc(1,sizeof(StackNode)); 49: 50: if (psn!=NULL) 51: { 52: psn->psnNext=NULL; 53: psn->se=se; 54: } 55: 56: return psn; 57: } 58: 59: // delete a stack node 60: void DeleteNode(StackNode * psn)

Copyright © 2001 Dan Leach 13

61: { 62: if (psn!=NULL) 63: free(psn); 64: } 65: 66: // set next in a stack node 67: void SetNext(StackNode * psn,StackNode * psnNext) 68: { 69: if (psn!=NULL) 70: psn->psnNext=psnNext; 71: } 72: 73: // return stack entry part of stack node 74: StackEntry GetStackEntry(StackNode * psn) 75: { 76: StackEntry se=0; 77: if (psn!=NULL) 78: se=psn->se; 79: return se; 80: } 81: 82: // return next node part of stack node 83: StackNode * GetNext(StackNode * psn) 84: { 85: StackNode * psnNext=NULL; 86: if (psn!=NULL) 87: psnNext=psn->psnNext; 88: return psnNext; 89: } 90: 91: // return the top item from the stack if there is one 92: // otherwise, error 93: void StackTop(Stack * pstk, StackEntry * pse) 94: { 95: char szMessage [MAX_MESSAGE_LENGTH]; 96: 97: if(StackEmpty(pstk)) 98: { 99: sprintf(szMessage,"%s: Stack is empty", pstk->szName); 100: Error(szMessage); 101: } 102: else 103: *pse=GetStackEntry(pstk->psnTop); 104: } 105: 106: // return the stack size 107: int StackSize(Stack * pstk) 108: { 109: int i=0; 110: StackNode * psn; 111: 112: for (psn=pstk->psnTop;psn!=NULL;psn=GetNext(psn)) 113: i++; 114: 115: return i; 116: }

Copyright © 2001 Dan Leach 14

117: 118: // traverse the stack 119: void TraverseStack(Stack * pstk, void(*Visit)(StackEntry)) 120: { 121: StackNode * psn; 122: for (psn=pstk->psnTop;psn!=NULL;psn=GetNext(psn)) 123: Visit(GetStackEntry(psn)); 124: } 125: 126: // print an entry 127: void PrintEntry(StackEntry se) 128: { 129: printf(g_szEntryFormat, se); 130: } 131: 132: // print the stack 133: void PrintStack(Stack * pstk, char * szMessage) 134: { 135: char szOutput[MAX_MESSAGE_LENGTH]; 136: 137: strcpy(szOutput,""); 138: 139: if (strlen(pstk->szName)) 140: { 141: strcat(szOutput,pstk->szName); 142: strcat(szOutput,": "); 143: } 144: 145: if (strlen(szMessage)) 146: { 147: strcat(szOutput, szMessage); 148: strcat(szOutput,": "); 149: } 150: 151: strcat(szOutput,"(TOP) "); 152: printf(szOutput); 153: 154: TraverseStack(pstk,PrintEntry); 155: 156: printf("(BOTTOM)\n"); 157: } 158: 159: // return stack name 160: char * StackName(Stack * pstk) 161: { 162: return pstk->szName; 163: } 164: 165: // return whether the stack is full 166: Boolean StackFull(Stack * pstk) 167: { 168: Boolean bResult=false; 169: StackNode * psn; 170: 171: pstk; // ref to formal param to clear warning 172: psn=MakeNode(0);

Copyright © 2001 Dan Leach 15

173: bResult=(psn==NULL); 174: if (psn!=NULL) 175: DeleteNode(psn); 176: return bResult; 177: } 178: 179: // return whether the stack is empty 180: Boolean StackEmpty(Stack * pstk) 181: { 182: return pstk->psnTop==NULL; 183: } 184: 185: // add an item to the stack if there is room 186: // otherwise, error 187: void Push(Stack * pstk, StackEntry se) 188: { 189: char szMessage [MAX_MESSAGE_LENGTH]; 190: StackNode * psn; 191: 192: if(StackFull(pstk)) 193: { 194: sprintf(szMessage,"%s: Stack is full", pstk->szName); 195: Error(szMessage); 196: } 197: else 198: { 199: psn=MakeNode(se); 200: if (psn==NULL) 201: { 202: sprintf(szMessage,"%s: Stack is full", pstk->szName); 203: Error(szMessage); 204: } 205: else 206: { 207: SetNext(psn,pstk->psnTop); 208: pstk->psnTop=psn; 209: } 210: } 211: } 212: 213: // remove an item from the stack if there is one 214: // otherwise, error 215: void Pop(Stack * pstk, StackEntry * pse) 216: { 217: char szMessage [MAX_MESSAGE_LENGTH]; 218: StackNode * psn; 219: 220: if(StackEmpty(pstk)) 221: { 222: sprintf(szMessage,"%s: Stack is empty", pstk->szName); 223: Error(szMessage); 224: } 225: else 226: { 227: *pse=GetStackEntry(pstk->psnTop); 228: psn=pstk->psnTop;

Copyright © 2001 Dan Leach 16

229: pstk->psnTop=GetNext(pstk->psnTop); 230: DeleteNode(psn); 231: } 232: } 233: 234: // initialize the stack to be empty 235: void CreateStack(Stack * pstk, char * szName) 236: { 237: char szMessage [MAX_MESSAGE_LENGTH]; 238: 239: pstk->psnTop=NULL; 240: if (strlen(szName)<MAX_NAME) 241: strcpy(pstk->szName,szName); 242: else 243: { 244: strcpy(pstk->szName,"BAD NAME"); 245: sprintf(szMessage,"Name too long: %s", szName); 246: Error(szMessage); 247: } 248: } 249: 250: // reset the stack to be empty 251: void ClearStack(Stack * pstk) 252: { 253: StackNode * psn; 254: StackNode * psnNext; 255: 256: for (psn=pstk->psnTop;psn!=NULL;psn=psnNext) 257: { 258: psnNext=GetNext(psn); 259: DeleteNode(psn); 260: } 261: 262: pstk->psnTop=NULL; 263: }

1.6.9 stktst.c 1: // stktst.c 2: // test stack 3: 4: #include <stdio.h> 5:#include "stack.h" 6:#include "error.h" 7: 8: // pop the top two values on the stack and push the result 9: void Plus(Stack* pstk) 10: { 11: StackEntry seArg1=0; 12: StackEntry seArg2=0; 13: 14: if (!GetError()) 15: Pop(pstk, &seArg1); 16: if (!GetError()) 17: Pop(pstk, &seArg2); 18: if (!GetError())

Copyright © 2001 Dan Leach 17

19: Push(pstk, seArg1+seArg2); 20: } 21: 22: void main() 23: { 24: StackEntry seAnswer=0; 25: StackEntry se; 26: Stack stk; 27: 28: // init stack 29: CreateStack(&stk,"A"); 30: 31: // push two numbers, call plus, pop result 32: if (!GetError()) 33: { 34: PrintStack(&stk,"empty stack"); 35: Push(&stk,1); 36: } 37: 38: if (!GetError()) 39: { 40: PrintStack(&stk,"pushed 1"); 41: Push(&stk,2); 42: } 43: 44: if (!GetError()) 45: { 46: PrintStack(&stk,"pushed 2"); 47: Plus(&stk); 48: } 49: 50: if (!GetError()) 51: { 52: PrintStack(&stk,"called plus"); 53: Pop(&stk,&seAnswer); 54: } 55: 56: if (!GetError()) 57: { 58: PrintStack(&stk,"popped answer"); 59: printf("seAnswer = %d\n",seAnswer); 60: } 61: 62: ClearError(); 63: 64: if (!GetError()) 65: { 66: for(se=1;(!GetError()) && (!StackFull(&stk) && se<12);se++) 67: { 68: Push(&stk,se); 69: if (!GetError()) 70: PrintStack(&stk,"after push"); 71: } 72: 73: ClearError(); 74:

Copyright © 2001 Dan Leach 18

75: printf("stack size = %d\n", StackSize(&stk)); 76: StackTop(&stk,&se); 77: printf("stack top = %d\n", se); 78: PrintStack(&stk,"stack should be unchanged"); 79: 80: // stack should overflow this time if using fixed stack 81: Push(&stk,se); 82: if (!GetError()) 83: PrintStack(&stk,"shouldn't see this if fixed stack"); 84: else 85: ClearError(); 86: 87: // add numbers till error 88: // stack should underflow last time through 89: while((!GetError()) && (!StackEmpty(&stk))) 90: { 91: Plus(&stk); 92: if (!GetError()) 93: PrintStack(&stk,"called plus"); 94: } 95: 96: ClearError(); 97: } 98: 99: ClearStack(&stk); 100: } 101: 102: /* 103: output: 104: A: empty stack: (TOP) (BOTTOM) 105: A: pushed 1: (TOP) 1 (BOTTOM) 106: A: pushed 2: (TOP) 2 1 (BOTTOM) 107: A: called plus: (TOP) 3 (BOTTOM) 108: A: popped answer: (TOP) (BOTTOM) 109: seAnswer = 3 110: A: after push: (TOP) 1 (BOTTOM) 111: A: after push: (TOP) 2 1 (BOTTOM) 112: A: after push: (TOP) 3 2 1 (BOTTOM) 113: A: after push: (TOP) 4 3 2 1 (BOTTOM) 114: A: after push: (TOP) 5 4 3 2 1 (BOTTOM) 115: A: after push: (TOP) 6 5 4 3 2 1 (BOTTOM) 116: A: after push: (TOP) 7 6 5 4 3 2 1 (BOTTOM) 117: A: after push: (TOP) 8 7 6 5 4 3 2 1 (BOTTOM) 118: A: after push: (TOP) 9 8 7 6 5 4 3 2 1 (BOTTOM) 119: A: after push: (TOP) 10 9 8 7 6 5 4 3 2 1 (BOTTOM) 120: stack size = 10 121: stack top = 10 122: A: stack should be unchanged: (TOP) 10 9 8 7 6 5 4 3 2 1 (BOTTOM) 123: ERROR: A: Stack is full 124: A: called plus: (TOP) 19 8 7 6 5 4 3 2 1 (BOTTOM) 125: A: called plus: (TOP) 27 7 6 5 4 3 2 1 (BOTTOM) 126: A: called plus: (TOP) 34 6 5 4 3 2 1 (BOTTOM) 127: A: called plus: (TOP) 40 5 4 3 2 1 (BOTTOM) 128: A: called plus: (TOP) 45 4 3 2 1 (BOTTOM) 129: A: called plus: (TOP) 49 3 2 1 (BOTTOM) 130: A: called plus: (TOP) 52 2 1 (BOTTOM)

Copyright © 2001 Dan Leach 19

131: A: called plus: (TOP) 54 1 (BOTTOM) 132: A: called plus: (TOP) 55 (BOTTOM) 133: ERROR: A: Stack is empty 134: */

1.6.10 bldsta.bat

1: cl /Festktsta.exe /DFIXED_STACK stktst.c stacka.c error.c

1.6.11 bldstl.bat

1: cl /Festktstl.exe /DLINKED_STACK stktst.c stackl.c error.c

1.6.12 stktsta.out 1:A: empty stack: (TOP) (BOTTOM) 2:A: pushed 1: (TOP) 1 (BOTTOM) 3:A: pushed 2: (TOP) 2 1 (BOTTOM) 4:A: called plus: (TOP) 3 (BOTTOM) 5:A: popped answer: (TOP) (BOTTOM) 6: seAnswer = 3 7:A: after push: (TOP) 1 (BOTTOM) 8:A: after push: (TOP) 2 1 (BOTTOM) 9:A: after push: (TOP) 3 2 1 (BOTTOM) 10: A: after push: (TOP) 4 3 2 1 (BOTTOM) 11: A: after push: (TOP) 5 4 3 2 1 (BOTTOM) 12: A: after push: (TOP) 6 5 4 3 2 1 (BOTTOM) 13: A: after push: (TOP) 7 6 5 4 3 2 1 (BOTTOM) 14: A: after push: (TOP) 8 7 6 5 4 3 2 1 (BOTTOM) 15: A: after push: (TOP) 9 8 7 6 5 4 3 2 1 (BOTTOM) 16: A: after push: (TOP) 10 9 8 7 6 5 4 3 2 1 (BOTTOM) 17: stack size = 10 18: stack top = 10 19: A: stack should be unchanged: (TOP) 10 9 8 7 6 5 4 3 2 1 (BOTTOM) 20: ERROR: A: Stack is full 21: A: called plus: (TOP) 19 8 7 6 5 4 3 2 1 (BOTTOM) 22: A: called plus: (TOP) 27 7 6 5 4 3 2 1 (BOTTOM) 23: A: called plus: (TOP) 34 6 5 4 3 2 1 (BOTTOM) 24: A: called plus: (TOP) 40 5 4 3 2 1 (BOTTOM) 25: A: called plus: (TOP) 45 4 3 2 1 (BOTTOM) 26: A: called plus: (TOP) 49 3 2 1 (BOTTOM) 27: A: called plus: (TOP) 52 2 1 (BOTTOM) 28: A: called plus: (TOP) 54 1 (BOTTOM) 29: A: called plus: (TOP) 55 (BOTTOM) 30: ERROR: A: Stack is empty

1.6.13 stktstl.out 1:A: empty stack: (TOP) (BOTTOM) 2:A: pushed 1: (TOP) 1 (BOTTOM) 3:A: pushed 2: (TOP) 2 1 (BOTTOM) 4:A: called plus: (TOP) 3 (BOTTOM) 5:A: popped answer: (TOP) (BOTTOM) 6: seAnswer = 3 7:A: after push: (TOP) 1 (BOTTOM) 8:A: after push: (TOP) 2 1 (BOTTOM)

Copyright © 2001 Dan Leach 20

9:A: after push: (TOP) 3 2 1 (BOTTOM) 10: A: after push: (TOP) 4 3 2 1 (BOTTOM) 11: A: after push: (TOP) 5 4 3 2 1 (BOTTOM) 12: A: after push: (TOP) 6 5 4 3 2 1 (BOTTOM) 13: A: after push: (TOP) 7 6 5 4 3 2 1 (BOTTOM) 14: A: after push: (TOP) 8 7 6 5 4 3 2 1 (BOTTOM) 15: A: after push: (TOP) 9 8 7 6 5 4 3 2 1 (BOTTOM) 16: A: after push: (TOP) 10 9 8 7 6 5 4 3 2 1 (BOTTOM) 17: A: after push: (TOP) 11 10 9 8 7 6 5 4 3 2 1 (BOTTOM) 18: stack size = 11 19: stack top = 11 20: A: stack should be unchanged: (TOP) 11 10 9 8 7 6 5 4 3 2 1 (BOTTOM) 21: A: shouldn't see this if fixed stack: (TOP) 11 11 10 9 8 7 6 5 4 3 2 1 (BOTTOM) 22: A: called plus: (TOP) 22 10 9 8 7 6 5 4 3 2 1 (BOTTOM) 23: A: called plus: (TOP) 32 9 8 7 6 5 4 3 2 1 (BOTTOM) 24: A: called plus: (TOP) 41 8 7 6 5 4 3 2 1 (BOTTOM) 25: A: called plus: (TOP) 49 7 6 5 4 3 2 1 (BOTTOM) 26: A: called plus: (TOP) 56 6 5 4 3 2 1 (BOTTOM) 27: A: called plus: (TOP) 62 5 4 3 2 1 (BOTTOM) 28: A: called plus: (TOP) 67 4 3 2 1 (BOTTOM) 29: A: called plus: (TOP) 71 3 2 1 (BOTTOM) 30: A: called plus: (TOP) 74 2 1 (BOTTOM) 31: A: called plus: (TOP) 76 1 (BOTTOM) 32: A: called plus: (TOP) 77 (BOTTOM) 33: ERROR: A: Stack is empty

Copyright © 2001 Dan Leach 21

1.7RecursionRecursive functions call themselves. Recursive processes are usually defined in terms of a basis (what to do for a particular value) and a recursive step (what to do for a value in terms of other results of the same function). There are also co-recursive processes (A calls B which calls A again). Some examples of recursive programs follow.

1.7.1 fac.c 1: // fac.c 2: // computes factorial recursively 3: 4: #include <stdio.h> 5:#include <stdlib.h> 6: 7: unsigned int g_uiCalls = 0; 8: 9: // factorial 10: unsigned int Factorial(unsigned int ui) 11: { 12: unsigned int uiFac; 13: 14: g_uiCalls++; 15: 16: if(ui<2) 17: uiFac=1; 18: else 19: uiFac=ui*Factorial(ui-1); 20: 21: return uiFac; 22: } 23: 24: typedef enum 25: { 26: RC_SUCCESS=0, 27: RC_SURPRISE, 28: RC_ERROR 29: } ReturnCode; 30: 31: // test program for fac 32: ReturnCode main(int uiArgumentCount,char * szArguments[]) 33: { 34: unsigned int uiFac; 35: ReturnCode rc=RC_SUCCESS; 36: 37: if (uiArgumentCount!=2) { 38: fprintf(stderr,"USAGE: %s number\n",szArguments[0]); 39: rc=RC_ERROR; 40: } 41: 42: else 43: { 44: uiFac=atoi(szArguments[1]); 45: printf("%d!=%d\n",uiFac,Factorial(uiFac)); 46: } 47:

Copyright © 2001 Dan Leach 22

48: printf("number of calls to Factorial=%d\n",g_uiCalls); 49: return rc; 50: } 51: 52: /* 53: output from fac 10: 54: 55: 10!=3628800 56: number of calls to Factorial=10 57: 58: */

1.7.2 fib.c 1: // fib.c 2: // computes Fibonacci numbers recursively 3: 4: #include <stdio.h> 5:#include <stdlib.h> 6: 7: unsigned int g_uiCalls = 0; 8: 9: // Fibonacci 10: unsigned int Fibonacci(unsigned int ui) 11: { 12: unsigned int uiFib; 13: 14: g_uiCalls++; 15: if (ui==0) 16: uiFib=0; 17: 18: else if (ui==1) 19: uiFib=1; 20: 21: else 22: uiFib=Fibonacci(ui-1)+Fibonacci(ui-2); 23: 24: return uiFib; 25: } 26: 27: typedef enum 28: { 29: RC_SUCCESS=0, 30: RC_SURPRISE, 31: RC_ERROR 32: } ReturnCode; 33: 34: // test program for fib 35: ReturnCode main(int uiArgumentCount,char * szArguments[]) 36: { 37: unsigned int uiFib; 38: ReturnCode rc=RC_SUCCESS; 39: 40: if (uiArgumentCount!=2) { 41: fprintf(stderr,"USAGE: %s number\n",szArguments[0]); 42: rc=RC_ERROR;

Copyright © 2001 Dan Leach 23

43: } 44: 45: else 46: { 47: uiFib=atoi(szArguments[1]); 48: printf("Fibonacci(%d)=%d\n",uiFib,Fibonacci(uiFib)); 49: } 50: 51: printf("number of calls to Fibonacci=%d\n",g_uiCalls); 52: return rc; 53: } 54: /* 55: output from fib 10: 56: 57: Fibonacci(10)=55 58: number of calls to Fibonacci=177 59: 60: */

1.7.3 twrs.c 1: // twrs.c 2: // Towers of Hanoi 3: 4: #include <stdlib.h> 5:#include <stdio.h> 6:#include <string.h> 7:#include "stack.h" 8: 9:Stack g_stkA; 10: Stack g_stkB; 11: Stack g_stkC; 12: 13: // print the stacks 14: void PrintState() 15: { 16: Indent(); 17: PrintStack(&g_stkA,""); 18: Indent(); 19: PrintStack(&g_stkB,""); 20: Indent(); 21: PrintStack(&g_stkC,""); 22: } 23: 24: // set up state for Towers 25: void InitState(unsigned int uiSize) 26: { 27: unsigned int ui; 28: 29: CreateStack(&g_stkA,"A"); 30: CreateStack(&g_stkB,"B"); 31: CreateStack(&g_stkC,"C"); 32: 33: for (ui=1;ui<=uiSize;ui++) 34: Push(&g_stkA, uiSize-ui+1); 35:

Copyright © 2001 Dan Leach 24

36: PrintState(); 37: } 38: 39: // clear stacks 40: void ClearState() 41: { 42: PrintState(); 43: 44: ClearStack(&g_stkA); 45: ClearStack(&g_stkB); 46: ClearStack(&g_stkC); 47: } 48: 49: // move a disk 50: unsigned int g_uiMoveCount = 0; 51: void Move(Stack * pstkSource, Stack * pstkDestination) 52: { 53: unsigned int ui; 54: g_uiMoveCount++; 55: Pop(pstkSource,&ui); 56: Indent(); 57: printf( 58: "*** Moving disk %d from %s to %s ***\n", 59: ui, 60: StackName(pstkSource), 61: StackName(pstkDestination) 62: ); 63: Push(pstkDestination, ui); 64: 65: PrintState(); 66: } 67: 68: // towers of hanoi 69: void Towers( 70: unsigned int uiSize, 71: Stack * pstkSource, 72: Stack * pstkDestination, 73: Stack * pstkAuxilary, 74: char * szMessage 75: ) 76: { 77: IncrementLevel(); 78: Indent(); 79: printf( 80: "%s: level=%d disks=%d src=%s dest=%s aux=%s\n", 81: szMessage, 82: g_uiLevel, 83: uiSize, 84: StackName(pstkSource), 85: StackName(pstkDestination), 86: StackName(pstkAuxilary) 87: ); 88: 89: if (uiSize == 1) 90: Move(pstkSource, pstkDestination); 91: else {

Copyright © 2001 Dan Leach 25

92: Towers( 93: uiSize-1, 94: pstkSource, 95: pstkAuxilary, 96: pstkDestination, 97: "1st rec call" 98: ); 99: Move(pstkSource, pstkDestination); 100: Towers( 101: uiSize-1, 102: pstkAuxilary, 103: pstkDestination, 104: pstkSource, 105: "2nd rec call" 106: ); 107: } 108: 109: Indent(); 110: printf("returning from level %d\n",g_uiLevel); 111: 112: DecrementLevel(); 113: } 114: 115: typedef enum 116: { 117: RC_SUCCESS=0, 118: RC_SURPRISE, 119: RC_ERROR 120: } ReturnCode; 121: 122: // definition of command line arguments 123: typedef enum 124: { 125: CLA_PROGRAM_NAME=0, 126: CLA_NUMBER_OF_DISKS 127: } CommandLineArguments; 128: 129: // test program for Towers 130: ReturnCode main(int uiArgumentCount,char * szArguments[]) 131: { 132: unsigned int uiSize; 133: ReturnCode rc = RC_SUCCESS; 134: 135: if (uiArgumentCount!=2) 136: { 137: fprintf( 138: stderr, 139: "USAGE: %s number\n", 140: szArguments[CLA_PROGRAM_NAME] 141: ); 142: rc=RC_ERROR; 143: } 144: else 145: uiSize = atoi(szArguments[CLA_NUMBER_OF_DISKS]); 146: 147: #if defined(FIXED_STACK)

Copyright © 2001 Dan Leach 26

148: if (uiSize>MAX_STACK) 149: { 150: fprintf( 151: stderr, 152: "Maximum size is %d\n", 153: MAX_STACK 154: ); 155: rc=RC_ERROR; 156: } 157: #endif 158: 159: if (rc==RC_SUCCESS) 160: { 161: InitState(uiSize); 162: 163: Towers( 164: uiSize, 165: &g_stkA, 166: &g_stkC, 167: &g_stkB, 168: "called from main" 169: ); 170: 171: ClearState(); 172: 173: printf( 174: "Total number of moves: %d\n", 175: g_uiMoveCount 176: ); 177: printf( 178: "Maximum number of " 179: "active calls to Towers: %d\n", 180: g_uiMaxLevel 181: ); 182: } 183: 184: return rc; 185: }

1.7.4 twrs.out 1:A: (TOP) 1 2 3 (BOTTOM) 2:B: (TOP) (BOTTOM) 3:C: (TOP) (BOTTOM) 4: called from main: level=1 disks=3 src=A dest=C aux=B 5: 1st rec call: level=2 disks=2 src=A dest=B aux=C 6: 1st rec call: level=3 disks=1 src=A dest=C aux=B 7: *** Moving disk 1 from A to C *** 8: A: (TOP) 2 3 (BOTTOM) 9: B: (TOP) (BOTTOM) 10: C: (TOP) 1 (BOTTOM) 11: returning from level 3 12: *** Moving disk 2 from A to B *** 13: A: (TOP) 3 (BOTTOM) 14: B: (TOP) 2 (BOTTOM) 15: C: (TOP) 1 (BOTTOM)

Copyright © 2001 Dan Leach 27

16: 2nd rec call: level=3 disks=1 src=C dest=B aux=A 17: *** Moving disk 1 from C to B *** 18: A: (TOP) 3 (BOTTOM) 19: B: (TOP) 1 2 (BOTTOM) 20: C: (TOP) (BOTTOM) 21: returning from level 3 22: returning from level 2 23: *** Moving disk 3 from A to C *** 24: A: (TOP) (BOTTOM) 25: B: (TOP) 1 2 (BOTTOM) 26: C: (TOP) 3 (BOTTOM) 27: 2nd rec call: level=2 disks=2 src=B dest=C aux=A 28: 1st rec call: level=3 disks=1 src=B dest=A aux=C 29: *** Moving disk 1 from B to A *** 30: A: (TOP) 1 (BOTTOM) 31: B: (TOP) 2 (BOTTOM) 32: C: (TOP) 3 (BOTTOM) 33: returning from level 3 34: *** Moving disk 2 from B to C *** 35: A: (TOP) 1 (BOTTOM) 36: B: (TOP) (BOTTOM) 37: C: (TOP) 2 3 (BOTTOM) 38: 2nd rec call: level=3 disks=1 src=A dest=C aux=B 39: *** Moving disk 1 from A to C *** 40: A: (TOP) (BOTTOM) 41: B: (TOP) (BOTTOM) 42: C: (TOP) 1 2 3 (BOTTOM) 43: returning from level 3 44: returning from level 2 45: returning from level 1 46: A: (TOP) (BOTTOM) 47: B: (TOP) (BOTTOM) 48: C: (TOP) 1 2 3 (BOTTOM) 49: Total number of moves: 7 50: Maximum number of active calls to Towers: 3

1.7.5 bldta.bat 1: cl /Fetwrsa.exe /DFIXED_STACK twrs.c stacka.c error.c

1.7.6 bldtl.bat 1: cl /Fetwrsl.exe /DLINKED_STACK twrs.c stackl.c error.c

1.7.7 eightq.c 1: // eightq.c 2: 3: // 8 Queens program adpated from section 3.3 in 4: // "Data Structures & Program Design in C", 5: // Second Edition 6: // by Robert Kruse, C. L. Tondo, and Bruce Leung 7: 8: // Adapted by Dan Leach 9: 10: #include "stddef.h" 11:

Copyright © 2001 Dan Leach 28

12: #define BOARDSIZE 8 13: #define DIAGONAL (2*BOARDSIZE-1) 14: const unsigned int g_uiConstDownOffset = 7; 15: 16: unsigned int g_uiQueenColumn[BOARDSIZE]; 17: Boolean g_bColumnFree[BOARDSIZE]; 18: Boolean g_bUpFree[DIAGONAL]; 19: Boolean g_bDownFree[DIAGONAL]; 20: int g_iQueenCount=-1; 21: unsigned int g_uiNumberOfSolutions=0; 22: unsigned int g_uiNumberOfBoards=0; 23: 24: // print one row of the board 25: void WriteRow(unsigned int uiCol) 26: { 27: unsigned int ui; 28: 29: for (ui=0;ui<BOARDSIZE;ui++) 30: { 31: if (ui==uiCol) 32: printf(" Q "); 33: else 34: printf(" . "); 35: } 36: 37: printf("\n"); 38: } 39: 40: // print the board 41: void WriteBoard() 42: { 43: unsigned int ui; 44: 45: g_uiNumberOfSolutions++; 46: for (ui=0;ui<BOARDSIZE;ui++) 47: WriteRow(g_uiQueenColumn[ui]); 48: 49: for (ui=0;ui<BOARDSIZE;ui++) 50: printf("---"); 51: 52: printf("\n"); 53: } 54: 55: // add a queen recursively with backtracking 56: void AddQueen() 57: { 58: int uiColumn; 59: g_iQueenCount++; 60: 61: for (uiColumn=0;uiColumn<BOARDSIZE;uiColumn++) 62: { 63: g_uiNumberOfBoards++; 64: if ( 65: g_bColumnFree[uiColumn] && 66: g_bUpFree[g_iQueenCount+uiColumn] && 67: g_bDownFree[

Copyright © 2001 Dan Leach 29

68: g_iQueenCount- 69: uiColumn+ 70: g_uiConstDownOffset 71: ] 72: ) 73: { 74: g_uiQueenColumn[g_iQueenCount]=uiColumn; 75: 76: g_bColumnFree[uiColumn]=false; 77: g_bUpFree[g_iQueenCount+uiColumn]=false; 78: g_bDownFree[ 79: g_iQueenCount- 80: uiColumn+ 81: g_uiConstDownOffset 82: ] 83: =false; 84: 85: if(g_iQueenCount==BOARDSIZE-1) 86: WriteBoard(); 87: else 88: AddQueen(); 89: 90: g_bColumnFree[uiColumn]=true; 91: g_bUpFree[g_iQueenCount+uiColumn]=true; 92: g_bDownFree[ 93: g_iQueenCount- 94: uiColumn+ 95: g_uiConstDownOffset 96: ] 97: =true; 98: } 99: } 100: 101: g_iQueenCount--; 102: } 103: 104: // main program for solving the eight queens problem 105: void main() 106: { 107: int i; 108: for (i=0;i<BOARDSIZE;i++) 109: g_bColumnFree[i]=true; 110: 111: for (i=0;i<DIAGONAL;i++) 112: { 113: g_bUpFree[i]=true; 114: g_bDownFree[i]=true; 115: } 116: 117: AddQueen(); 118: 119: printf( 120: "Number of solutions: %d\n", 121: g_uiNumberOfSolutions 122: ); 123: printf(

Copyright © 2001 Dan Leach 30

124: "Number of boards considered: %d\n", 125: g_uiNumberOfBoards 126: ); 127: }

1.7.8 eightqx.out 1: this output was exerted from eightq.out 2: 3: Q . . . . . . . 4: . . . . Q . . . 5: . . . . . . . Q 6: . . . . . Q . . 7: . . Q . . . . . 8: . . . . . . Q . 9: . Q . . . . . . 10: . . . Q . . . . 11: ------------------------ 12: Q . . . . . . . 13: . . . . . Q . . 14: . . . . . . . Q 15: . . Q . . . . . 16: . . . . . . Q . 17: . . . Q . . . . 18: . Q . . . . . . 19: . . . . Q . . . 20: ------------------------ 21: . 22: . 23: . 24: ------------------------ 25: . . . . . . . Q 26: . . . Q . . . . 27: Q . . . . . . . 28: . . Q . . . . . 29: . . . . . Q . . 30: . Q . . . . . . 31: . . . . . . Q . 32: . . . . Q . . . 33: ------------------------ 34: Number of solutions: 92 35: Number of boards considered: 15720

Copyright © 2001 Dan Leach 31

1.8QueuesA queue is a data structure to which elements are added to the rear and then removed from the front in a FIFO (first in, first out) manner. A queue may be viewed as a line (such as a line at the check out register in a grocery store), in fact, in England, instead of saying "standing in line" they say "standing on queue".

Required functions for a queue are:Create Return an empty queueEmpty Tell whether the queue is emptyFull Tell whether the queue is fullAppend Add an entry to the back of the queueServe Remove an entry from the front of the queue

Other functions that may be provided:Top Return the top of the queue without removing itSize Return the number of entries currently in the queueClear Remove all entries from the queue (return it to an empty state)Traverse Visit each entry in the queue with a function passed as an argument; beginning at the

top and proceeding to the bottom; queue is unchanged as a result of traversing itPrint A special case of the Traverse function which would print the contents of the queue

without changing the queue

Copyright © 2001 Dan Leach 32

1.9A Queue Implementation

1.9.1 queue.h 1: // queue.h 2: // interface to queues for airport simulation 3: 4: #pragma once 5:#include "stddef.h" 6: 7: typedef enum 8: { 9: ARRIVE, 10: DEPART 11: } Action; 12: 13: typedef struct 14: { 15: int iId; // identification number of airplane 16: int iTm; // time of arrival in queue 17: } Plane; 18: 19: typedef Plane QueueEntry; 20: 21: #if defined(FIXED_QUEUE) 22: #include "queuea.h" 23: 24: #elif defined(LINKED_QUEUE) 25: #include "queuel.h" 26: 27: #else 28: #error You must pick a list type: FIXED_QUEUE or LINKED_QUEUE 29: 30: #endif 31: 32: void CreateQueue(Queue * pq); 33: int QueueSize(Queue * pq); 34: Boolean QueueEmpty(Queue * pq); 35: Boolean QueueFull(Queue * pq); 36: void Append(QueueEntry qe, Queue * pq); 37: void Serve(QueueEntry * pqe, Queue * pq);

1.9.2 queuea.c 1: // queue.c 2: // implementation of queues for airport simulation 3: 4: #include "stddef.h" 5: #include "error.h" 6: #include "queue.h" 7: 8: // initialize a queue 9: void CreateQueue(Queue * pq) 10: { 11: pq->iCount = 0; 12: pq->iFront = 0;

Copyright © 2001 Dan Leach 33

13: pq->iRear = -1; 14: } 15: 16: // return the queue's size 17: int QueueSize(Queue * pq) 18: { 19: return pq->iCount; 20: } 21: 22: // return true if queue is empty, false otherwise 23: Boolean QueueEmpty(Queue * pq) 24: { 25: return pq->iCount <= 0; 26: } 27: 28: // return true if queue is full, false otherwise 29: Boolean QueueFull(Queue * pq) 30: { 31: return pq->iCount >= MAXQUEUE; 32: } 33: 34: // add an entry to the queue 35: void Append(QueueEntry qe, Queue * pq) 36: { 37: if (QueueFull(pq)) 38: Error("Cannot append an entry to a full queue."); 39: else { 40: pq->iCount++; 41: pq->iRear = (pq->iRear + 1) % MAXQUEUE; 42: pq->qeEntry[pq->iRear] = qe; 43: } 44: } 45: 46: // remove an entry from the queue 47: void Serve(QueueEntry * pqe, Queue * pq) 48: { 49: if (QueueEmpty(pq)) 50: Error("Cannot serve from an empty queue."); 51: else { 52: pq->iCount--; 53: *pqe = pq->qeEntry[pq->iFront]; 54: pq->iFront = (pq->iFront + 1) % MAXQUEUE; 55: } 56: }

1.9.3 queuea.h 1: // queuea.h 2: // interface to fixed queue 3: 4: #pragma once 5:#include "stddef.h" 6: 7: #define MAXQUEUE 5 // use a small value for testing 8: 9: typedef struct

Copyright © 2001 Dan Leach 34

10: { 11: int iCount; // number of airplanes in the queue 12: int iFront; // front of the queue 13: int iRear; // rear of the queue 14: QueueEntry qeEntry[MAXQUEUE]; 15: } Queue;

1.9.4 queuel.c 1: // queuel.c 2: // implementation of linked queue 3: 4: #include "stddef.h" 5: #include "error.h" 6: #include "queue.h" 7:#include "stdio.h" 8: 9: // make an empty queue node 10: QueueNode * MakeEmptyQueueNode () 11: { 12: QueueNode * pqn = (QueueNode *)calloc(1,sizeof(QueueNode)); 13: 14: return pqn; 15: } 16: 17: // make a queue node 18: QueueNode * MakeQueueNode (QueueEntry qe) 19: { 20: QueueNode * pqn = MakeEmptyQueueNode(); 21: 22: if (pqn!=NULL) 23: { 24: pqn->m_qe=qe; 25: pqn->m_pqnNext=NULL; 26: } 27: else 28: Error("No space for additional queue node can be obtained"); 29: 30: return pqn; 31: } 32: 33: // get queue entry from queue node 34: QueueEntry GetEntryQueueNode (QueueNode * pqn) 35: { 36: return pqn->m_qe; 37: } 38: 39: // set next queue node 40: void SetEntryQueueNode (QueueNode * pqn, QueueEntry qe) 41: { 42: pqn->m_qe=qe; 43: } 44: 45: // get next queue node 46: QueueNode * GetNextQueueNode (QueueNode * pqn) 47: {

Copyright © 2001 Dan Leach 35

48: return pqn->m_pqnNext; 49: } 50: 51: // set next queue node 52: void SetNextQueueNode (QueueNode * pqn, QueueNode * pqnNext) 53: { 54: pqn->m_pqnNext=pqnNext; 55: } 56: 57: // delete a queue node 58: DeleteQueueNode (QueueNode * pqn) 59: { 60: if (pqn!=NULL) 61: free(pqn); 62: } 63: 64: // initialize a queue 65: void CreateQueue(Queue * pq) 66: { 67: pq->iCount = 0; 68: pq->pqnFront = NULL; 69: pq->pqnRear = NULL; 70: } 71: 72: // return the queue's size 73: int QueueSize(Queue * pq) 74: { 75: return pq->iCount; 76: } 77: 78: // return true if queue is empty, false otherwise 79: Boolean QueueEmpty(Queue * pq) 80: { 81: return pq->iCount <= 0; 82: } 83: 84: // return true if queue is full, false otherwise 85: Boolean QueueFull(Queue * pq) 86: { 87: return pq->iCount >= MAXQUEUE; 88: } 89: 90: // add an entry to the queue 91: void Append(QueueEntry qe, Queue * pq) 92: { 93: QueueNode * pqn; 94: 95: if (QueueFull(pq)) 96: Error("Cannot append an entry to a full queue."); 97: else 98: { 99: pq->iCount++; 100: pqn = MakeQueueNode(qe); 101: if (!GetError()) 102: { 103: // append to current rear if necessary

Copyright © 2001 Dan Leach 36

104: if (pq->pqnRear!=NULL) 105: SetNextQueueNode(pq->pqnRear,pqn); 106: 107: pq->pqnRear=pqn; 108: 109: // reset front if necessary 110: if (pq->pqnFront==NULL) 111: pq->pqnFront=pqn; 112: } 113: } 114: } 115: 116: // remove an entry from the queue 117: void Serve(QueueEntry * pqe, Queue * pq) 118: { 119: if (QueueEmpty(pq)) 120: Error("Cannot serve from an empty queue."); 121: else { 122: pq->iCount--; 123: *pqe = GetEntryQueueNode(pq->pqnFront); 124: pq->pqnFront = GetNextQueueNode(pq->pqnFront); 125: 126: // reset rear in necessary 127: if (pq->iCount==0) 128: pq->pqnRear=NULL; 129: } 130: }

1.9.5 queuel.h 1: // queuel.h 2: // interface to linked queue 3: 4: #pragma once 5:#include "stddef.h" 6: 7: #define MAXQUEUE 5 // use a small value for testing 8: 9: typedef struct _QueueNode 10: { 11: QueueEntry m_qe; 12: struct _QueueNode * m_pqnNext; 13: } QueueNode; 14: 15: typedef struct 16: { 17: int iCount; // number of entries in the queue 18: QueueNode * pqnFront; // front of the queue 19: QueueNode * pqnRear; // rear of the queue 20: } Queue;

Copyright © 2001 Dan Leach 37

1.10 ListsLists are sequential data structures. You may insert data into and remove data from any part of a list.

Lists take on a number of different, independent attributes. Some are discussed below.

1.10.1 Singly linked versus Doubly linkedSingly linked lists have one set of pointers. You move to another element in the list via a Next function.

Doubly linked lists have two sets of pointer. You move to another element in the list via either a Next function or a Previous Function.

1.10.2 With versus without a header nodeA header node contains information about a list and at least a pointer to the beginning of it. If a list has a header node, the list is manipulated through the header node.

1.10.3 Circularly linked versus linearly linkedA linear list is null terminated (the last node’s next pointer is null; in the case of a doubly linked list, the previous pointer from the first node is also null). A circularly linked list ties the end back to the beginning (a doubly linked list also ties the beginning to the end).

1.10.4 Positional versus non-positionalA positional list allow insertion based on a numeric position. A non-positional list only allows insertion based on a pointer to a node.

Copyright © 2001 Dan Leach 38

1.11 A List Implementation

1.11.1 list.h

1: // list.h 2: // interface to lists 3: 4: #pragma once 5: 6: #include "stddef.h" 7: 8: typedef char * ListEntry; 9: 10: typedef int Position; 11: 12: #if defined(PDLIST) 13: #include "pdlist.h" 14: 15: #elif defined(PSLIST) 16: #include "pslist.h" 17: 18: #else 19: #error You must pick a list type: PDLIST or PSLIST 20: 21: #endif 22: 23: List * CreateList(Boolean bFreeOnClear); 24: int ListSize(List * plst); 25: Boolean ListEmpty(List * plst); 26: Boolean ListFull (List * plst); 27: Position CurrentListPosition(List * plst); 28: ListNode * ListNext(List * plst); 29: void SetListPosition(List * plst, Position pos); 30: void InsertList(List * plst, Position pos, ListEntry le); 31: void DeleteList(List * plst, Position pos, ListEntry * ple); 32: void RetrieveList(List * plst, Position pos, ListEntry * ple); 33: void ReplaceList(List * plst, Position pos, ListEntry le); 34: void ClearList(List * plst); 35: void DestroyList(List * plst); 36: void PrintList(List * plst); 37: void TraverseList(List * plst, void(*Visit)(ListEntry));

1.11.2 pslist.h 1: // pslist.h 2: // interface to positional singly linked list 3: 4: #pragma once 5: 6: #include "stddef.h" 7: 8: typedef struct _ListNode 9: { 10: ListEntry m_le; 11: struct _ListNode * m_plnNext;

Copyright © 2001 Dan Leach 39

12: } ListNode; 13: 14: typedef struct 15: { 16: int m_iCount; 17: ListNode * m_plnCurrent; 18: ListNode * m_plnHead; 19: Position m_posCurrent; 20: Boolean m_bFreeOnClear; 21: } List;

1.11.3 pslist.c 1: // pslist.c 2: // implementation of positional singly linked list 3: 4: #include <stdio.h> 5:#include <stdlib.h> 6:#include "error.h" 7: #include "list.h" 8: 9: char * g_szEntryFormat = "%s\n"; 10: 11: // create an empty list 12: List * CreateList(Boolean bFreeOnClear) 13: { 14: List * plst; 15: plst = (List *)calloc(1,sizeof(List)); 16: if (plst!=NULL) 17: { 18: plst->m_iCount=0; 19: plst->m_plnHead=NULL; 20: plst->m_plnCurrent=NULL; 21: plst->m_posCurrent=0; 22: plst->m_bFreeOnClear=bFreeOnClear; 23: } 24: else 25: Error("No space for list can be obtained"); 26: 27: return plst; 28: } 29: 30: // get the size of the list 31: int ListSize(List * plst) 32: { 33: return plst->m_iCount; 34: } 35: 36: // return whether the list is empty 37: Boolean ListEmpty(List * plst) 38: { 39: return(ListSize(plst)==0); 40: } 41: 42: // make an empty list node 43: ListNode * MakeEmptyListNode ()

Copyright © 2001 Dan Leach 40

44: { 45: ListNode * pln = (ListNode *)calloc(1,sizeof(ListNode)); 46: 47: return pln; 48: } 49: 50: // make a list node 51: ListNode * MakeListNode (ListEntry le) 52: { 53: ListNode * pln = MakeEmptyListNode(); 54: 55: if (pln!=NULL) 56: { 57: pln->m_le=le; 58: pln->m_plnNext=NULL; 59: } 60: else 61: Error("No space for additional list node can be obtained"); 62: 63: return pln; 64: } 65: 66: // get list entry from list node 67: ListEntry GetEntryListNode (ListNode * pln) 68: { 69: return pln->m_le; 70: } 71: 72: // set next list node 73: void SetEntryListNode (ListNode * pln, ListEntry le) 74: { 75: pln->m_le=le; 76: } 77: 78: // get next list node 79: ListNode * GetNextListNode (ListNode * pln) 80: { 81: return pln->m_plnNext; 82: } 83: 84: // set next list node 85: void SetNextListNode (ListNode * pln, ListNode * plnNext) 86: { 87: pln->m_plnNext=plnNext; 88: } 89: 90: // delete a list node 91: DeleteListNode (ListNode * pln) 92: { 93: if (pln!=NULL) 94: free(pln); 95: } 96: 97: // return whether the list is full 98: Boolean ListFull (List * plst) 99: {

Copyright © 2001 Dan Leach 41

100: Boolean bReturn = false; 101: 102: if (plst->m_iCount!=0) 103: { 104: ListNode * pln = MakeEmptyListNode(); 105: 106: if (pln==NULL) 107: bReturn=true; 108: else 109: DeleteListNode(pln); 110: } 111: 112: return bReturn; 113: } 114: 115: // get the current list position 116: Position CurrentListPosition(List * plst) 117: { 118: return plst->m_posCurrent; 119: } 120: 121: // move to the next position in the list 122: ListNode * ListNext(List * plst) 123: { 124: if (plst->m_plnCurrent==NULL) 125: Error ("Attempt to go beyond the list"); 126: else 127: { 128: plst->m_plnCurrent= 129: GetNextListNode(plst->m_plnCurrent); 130: plst->m_posCurrent++; 131: } 132: 133: return plst->m_plnCurrent; 134: } 135: 136: // set the current list position as indicated 137: void SetListPosition(List * plst, Position pos) 138: { 139: if (pos<0 || pos>=plst->m_iCount) 140: Error("Attempt to set a position not in the list"); 141: else 142: { 143: if (pos<CurrentListPosition(plst)) 144: { 145: // need to start over 146: // reset to beginning of list 147: plst->m_plnCurrent=plst->m_plnHead; 148: plst->m_posCurrent=0; 149: } 150: 151: while (pos>CurrentListPosition(plst)) 152: ListNext(plst); 153: } 154: } 155:

Copyright © 2001 Dan Leach 42

156: 157: // insert into list at indicated position 158: void InsertList(List * plst, Position pos, ListEntry le) 159: { 160: ListNode * plnNewNode; 161: 162: if (pos<0 || pos>ListSize(plst)) 163: Error("Attempt to insert in a position not in the list"); 164: else 165: { 166: plnNewNode=MakeListNode(le); 167: if (plnNewNode!=NULL) 168: { 169: if (pos==0) 170: { 171: // insert at the beginning of the list 172: SetNextListNode(plnNewNode,plst->m_plnHead); 173: plst->m_plnHead=plnNewNode; 174: } 175: else 176: { 177: SetListPosition(plst,pos-1); 178: SetNextListNode( 179: plnNewNode, 180: GetNextListNode(plst->m_plnCurrent) 181: ); 182: SetNextListNode( 183: plst->m_plnCurrent, 184: plnNewNode 185: ); 186: } 187: 188: plst->m_plnCurrent=plnNewNode; 189: plst->m_posCurrent=pos; 190: plst->m_iCount++; 191: } 192: } 193: } 194: 195: // delete the list entry at the indicated position 196: void DeleteList(List * plst, Position pos, ListEntry * ple) 197: { 198: ListNode * plnTemp; 199: 200: if (pos>0) 201: { 202: SetListPosition(plst, pos-1); 203: if (!GetError()) 204: { 205: plnTemp=GetNextListNode(plst->m_plnCurrent); 206: SetNextListNode( 207: plst->m_plnCurrent, 208: GetNextListNode(plnTemp) 209: ); 210: } 211: }

Copyright © 2001 Dan Leach 43

212: else 213: { 214: SetListPosition(plst, 0); 215: if (!GetError()) 216: { 217: plnTemp=plst->m_plnCurrent; 218: plst->m_plnHead=GetNextListNode(plnTemp); 219: } 220: } 221: 222: if (!GetError()) 223: { 224: *ple=GetEntryListNode(plnTemp); 225: plst->m_plnCurrent=plst->m_plnHead; 226: plst->m_posCurrent=0; 227: plst->m_iCount--; 228: DeleteListNode(plnTemp); 229: } 230: } 231: 232: // retrieve the list entry at the indicated position 233: void RetrieveList(List * plst, Position pos, ListEntry * ple) 234: { 235: SetListPosition(plst, pos); 236: if (!GetError()) 237: *ple=GetEntryListNode(plst->m_plnCurrent); 238: } 239: 240: // replace the list entry at the indicated position 241: void ReplaceList(List * plst, Position pos, ListEntry le) 242: { 243: SetListPosition(plst, pos); 244: if (!GetError()) 245: SetEntryListNode(plst->m_plnCurrent, le); 246: } 247: 248: // clear the list 249: void ClearList(List * plst) 250: { 251: ListEntry le; 252: 253: while(!ListEmpty(plst)) 254: { 255: DeleteList(plst,0,&le); 256: if (plst->m_bFreeOnClear && (le!=NULL)) 257: free (le); 258: } 259: } 260: 261: // destroy the list 262: void DestroyList(List * plst) 263: { 264: ClearList (plst); 265: free (plst); 266: } 267:

Copyright © 2001 Dan Leach 44

268: // traverse the list 269: void TraverseList(List * plst, void(*Visit)(ListEntry)) 270: { 271: ListEntry le; 272: int i; 273: 274: for (i=0;!GetError() && i<ListSize(plst);i++) 275: { 276: RetrieveList(plst,i,&le); 277: if (!GetError()) 278: Visit(le); 279: } 280: } 281: 282: // print an entry 283: void PrintEntry(ListEntry le) 284: { 285: printf(g_szEntryFormat, le); 286: } 287: 288: // print the list 289: void PrintList (List * plst) 290: { 291: puts("(LIST START)"); 292: TraverseList(plst,PrintEntry); 293: puts("(LIST END)"); 294: }

1.11.4 pdlist.h 1: // pdlist.h 2: // interface to positional doubly linked list 3: 4: #pragma once 5: 6: #include "stddef.h" 7: 8: typedef struct _ListNode 9: { 10: ListEntry m_le; 11: struct _ListNode * m_plnNext; 12: struct _ListNode * m_plnPrevious; 13: } ListNode; 14: 15: typedef struct 16: { 17: int m_iCount; 18: ListNode * m_plnCurrent; 19: ListNode * m_plnHead; 20: Position m_posCurrent; 21: Boolean m_bFreeOnClear; 22: } List; 23: 24: ListNode * ListPrevious(List * plst);

Copyright © 2001 Dan Leach 45

1.11.5 pdlist.c 1: // pdlist.c 2: // implementation of positional doubly linked list 3: 4: #include <stdio.h> 5:#include <stdlib.h> 6:#include "error.h" 7: #include "list.h" 8: 9: char * g_szEntryFormat = "%s\n"; 10: 11: // create an empty list 12: List * CreateList(Boolean bFreeOnClear) 13: { 14: List * plst; 15: plst = (List *)calloc(1,sizeof(List)); 16: if (plst!=NULL) 17: { 18: plst->m_iCount=0; 19: plst->m_plnHead=NULL; 20: plst->m_plnCurrent=NULL; 21: plst->m_posCurrent=0; 22: plst->m_bFreeOnClear=bFreeOnClear; 23: } 24: else 25: Error("No space for list can be obtained"); 26: 27: return plst; 28: } 29: 30: // get the size of the list 31: int ListSize(List * plst) 32: { 33: return plst->m_iCount; 34: } 35: 36: // return whether the list is empty 37: Boolean ListEmpty(List * plst) 38: { 39: return(ListSize(plst)==0); 40: } 41: 42: // make an empty list node 43: ListNode * MakeEmptyListNode () 44: { 45: ListNode * pln = (ListNode *)calloc(1,sizeof(ListNode)); 46: 47: return pln; 48: } 49: 50: // make a list node 51: ListNode * MakeListNode (ListEntry le) 52: { 53: ListNode * pln = MakeEmptyListNode(); 54:

Copyright © 2001 Dan Leach 46

55: if (pln!=NULL) 56: { 57: pln->m_le=le; 58: pln->m_plnNext=NULL; 59: pln->m_plnPrevious=NULL; 60: } 61: else 62: Error("No space for additional list node can be obtained"); 63: 64: return pln; 65: } 66: 67: // get list entry from list node 68: ListEntry GetEntryListNode (ListNode * pln) 69: { 70: return pln->m_le; 71: } 72: 73: // set next list node 74: void SetEntryListNode (ListNode * pln, ListEntry le) 75: { 76: pln->m_le=le; 77: } 78: 79: // get next list node 80: ListNode * GetNextListNode (ListNode * pln) 81: { 82: return pln->m_plnNext; 83: } 84: 85: // set next list node 86: void SetNextListNode (ListNode * pln, ListNode * plnNext) 87: { 88: pln->m_plnNext=plnNext; 89: } 90: 91: // get previous list node 92: ListNode * GetPreviousListNode (ListNode * pln) 93: { 94: return pln->m_plnPrevious; 95: } 96: 97: // set previous list node 98: void SetPreviousListNode (ListNode * pln, ListNode * plnPrevious) 99: { 100: pln->m_plnPrevious=plnPrevious; 101: } 102: 103: // delete a list node 104: DeleteListNode (ListNode * pln) 105: { 106: if (pln!=NULL) 107: free(pln); 108: } 109: 110: // return whether the list is full

Copyright © 2001 Dan Leach 47

111: Boolean ListFull (List * plst) 112: { 113: Boolean bReturn = false; 114: 115: if (plst->m_iCount!=0) 116: { 117: ListNode * pln = MakeEmptyListNode(); 118: 119: if (pln==NULL) 120: bReturn=true; 121: else 122: DeleteListNode(pln); 123: } 124: 125: return bReturn; 126: } 127: 128: // get the current list position 129: Position CurrentListPosition(List * plst) 130: { 131: return plst->m_posCurrent; 132: } 133: 134: // move to the next position in the list 135: ListNode * ListNext(List * plst) 136: { 137: if (plst->m_plnCurrent==NULL) 138: Error ("Attempt to go beyond the list"); 139: else 140: { 141: plst->m_plnCurrent= 142: GetNextListNode(plst->m_plnCurrent); 143: plst->m_posCurrent++; 144: } 145: 146: return plst->m_plnCurrent; 147: } 148: 149: // move to the previous position in the list 150: ListNode * ListPrevious(List * plst) 151: { 152: if (plst->m_plnCurrent==NULL) 153: Error ("Attempt to go beyond the list"); 154: else 155: { 156: plst->m_plnCurrent= 157: GetPreviousListNode(plst->m_plnCurrent); 158: plst->m_posCurrent--; 159: } 160: 161: return plst->m_plnCurrent; 162: } 163: 164: // set the current list position as indicated 165: void SetListPosition(List * plst, Position pos) 166: {

Copyright © 2001 Dan Leach 48

167: if (pos<0 || pos>=plst->m_iCount) 168: Error("Attempt to set a position not in the list"); 169: else 170: { 171: if (plst->m_plnCurrent==NULL) 172: { 173: // list has been run out on previous traversal 174: // reset to beginning of list 175: plst->m_plnCurrent=plst->m_plnHead; 176: plst->m_posCurrent=0; 177: } 178: 179: while (pos>CurrentListPosition(plst)) 180: ListNext(plst); 181: 182: while (pos<CurrentListPosition(plst)) 183: ListPrevious(plst); 184: } 185: } 186: 187: 188: // insert into list at indicated position 189: void InsertList(List * plst, Position pos, ListEntry le) 190: { 191: ListNode * plnNewNode; 192: 193: if (pos<0 || pos>ListSize(plst)) 194: Error("Attempt to insert in a position not in the list"); 195: else 196: { 197: plnNewNode=MakeListNode(le); 198: if (plnNewNode!=NULL) 199: { 200: if (pos==0) 201: { 202: // insert at the beginning of the list 203: SetNextListNode(plnNewNode,plst->m_plnHead); 204: plst->m_plnHead=plnNewNode; 205: } 206: else 207: { 208: SetListPosition(plst,pos-1); 209: SetNextListNode( 210: plnNewNode, 211: GetNextListNode(plst->m_plnCurrent) 212: ); 213: SetPreviousListNode( 214: plnNewNode, 215: plst->m_plnCurrent 216: ); 217: SetNextListNode( 218: plst->m_plnCurrent, 219: plnNewNode 220: ); 221: } 222:

Copyright © 2001 Dan Leach 49

223: if (GetNextListNode(plnNewNode)!=NULL) 224: SetPreviousListNode( 225: GetNextListNode(plnNewNode), 226: plnNewNode 227: ); 228: 229: if (GetPreviousListNode(plnNewNode)!=NULL) 230: SetNextListNode( 231: GetPreviousListNode(plnNewNode), 232: plnNewNode 233: ); 234: plst->m_plnCurrent=plnNewNode; 235: plst->m_posCurrent=pos; 236: plst->m_iCount++; 237: 238: } 239: } 240: } 241: 242: // delete the list entry at the indicated position 243: void DeleteList(List * plst, Position pos, ListEntry * ple) 244: { 245: ListNode * plnTemp; 246: SetListPosition(plst, pos); 247: if (!GetError()) 248: { 249: plnTemp=plst->m_plnCurrent; 250: if (GetPreviousListNode(plnTemp)!=NULL) 251: SetNextListNode( 252: GetPreviousListNode(plnTemp), 253: GetNextListNode(plnTemp) 254: ); 255: if (GetNextListNode(plnTemp)!=NULL) 256: SetPreviousListNode( 257: GetNextListNode(plnTemp), 258: GetPreviousListNode(plnTemp) 259: ); 260: *ple=GetEntryListNode(plnTemp); 261: if (plnTemp==plst->m_plnHead) 262: plst->m_plnHead=GetNextListNode(plnTemp); 263: plst->m_plnCurrent=plst->m_plnHead; 264: plst->m_posCurrent=0; 265: plst->m_iCount--; 266: DeleteListNode(plnTemp); 267: } 268: } 269: 270: // retrieve the list entry at the indicated position 271: void RetrieveList(List * plst, Position pos, ListEntry * ple) 272: { 273: SetListPosition(plst, pos); 274: if (!GetError()) 275: *ple=GetEntryListNode(plst->m_plnCurrent); 276: } 277: 278: // replace the list entry at the indicated position

Copyright © 2001 Dan Leach 50

279: void ReplaceList(List * plst, Position pos, ListEntry le) 280: { 281: SetListPosition(plst, pos); 282: if (!GetError()) 283: SetEntryListNode(plst->m_plnCurrent, le); 284: } 285: 286: // clear the list 287: void ClearList(List * plst) 288: { 289: ListEntry le; 290: 291: while(!ListEmpty(plst)) 292: { 293: DeleteList(plst,0,&le); 294: if (plst->m_bFreeOnClear && (le!=NULL)) 295: free (le); 296: } 297: } 298: 299: // destroy the list 300: void DestroyList(List * plst) 301: { 302: ClearList (plst); 303: free (plst); 304: } 305: 306: // traverse the list 307: void TraverseList(List * plst, void(*Visit)(ListEntry)) 308: { 309: ListEntry le; 310: int i; 311: 312: for (i=0;!GetError() && i<ListSize(plst);i++) 313: { 314: RetrieveList(plst,i,&le); 315: if (!GetError()) 316: Visit(le); 317: } 318: } 319: 320: // print an entry 321: void PrintEntry(ListEntry le) 322: { 323: printf(g_szEntryFormat, le); 324: } 325: 326: // print the list 327: void PrintList (List * plst) 328: { 329: puts("(LIST START)"); 330: TraverseList(plst,PrintEntry); 331: puts("(LIST END)"); 332: }

Copyright © 2001 Dan Leach 51

1.11.6 listsort.c 1: // listsort.c 2: // reads strings from a file 3: // puts them in a list 4: // sorts the list 5: // then prints it 6: 7: #include <stdio.h> 8:#include <string.h> 9:#include "error.h" 10: #include <ctype.h> 11: #include "list.h" 12: 13: // copy a list 14: List * CopyList(List * plst) 15: { 16: List * plstNew; 17: Position pos; 18: Position posSave; 19: ListEntry leCurrent; 20: 21: posSave=CurrentListPosition(plst); 22: plstNew = CreateList(false); 23: for (pos=0;!GetError() && pos<ListSize(plst);pos++) 24: { 25: RetrieveList(plst,pos,&leCurrent); 26: InsertList(plstNew,pos,leCurrent); 27: } 28: 29: if (!GetError()) 30: { 31: SetListPosition(plst,posSave); 32: SetListPosition(plstNew,posSave); 33: } 34: 35: return plstNew; 36: } 37: 38: // reverse a list 39: void ReverseList(List * plst) 40: { 41: Position pos; 42: Position posSave; 43: ListEntry le1; 44: ListEntry le2; 45: 46: posSave=CurrentListPosition(plst); 47: for (pos=0;!GetError() && pos<ListSize(plst)/2;pos++) 48: { 49: RetrieveList(plst,pos,&le1); 50: RetrieveList(plst,ListSize(plst)-1-pos,&le2); 51: ReplaceList(plst,pos,le2); 52: ReplaceList(plst,ListSize(plst)-1-pos,le1); 53: } 54:

Copyright © 2001 Dan Leach 52

55: if (!GetError()) 56: SetListPosition(plst,posSave); 57: } 58: 59: // swaps the node at position pos1 with the node at position pos2 60: void Swap(Position pos1, Position pos2, List * plst) 61: { 62: ListEntry le1; 63: ListEntry le2; 64: 65: if (pos1>pos2) 66: { 67: DeleteList(plst,pos1,&le1); 68: DeleteList(plst,pos2,&le2); 69: InsertList(plst,pos2,le1); 70: InsertList(plst,pos1,le2); 71: } 72: 73: if (pos2>pos1) 74: { 75: DeleteList(plst,pos2,&le2); 76: DeleteList(plst,pos1,&le1); 77: InsertList(plst,pos1,le2); 78: InsertList(plst,pos2,le1); 79: } 80: 81: } 82: 83: #define LT(sz1,sz2) (strcmp(sz1,sz2)<0) 84: 85: // sorts an interaval using the insertion sort method 86: void SortInterval(Position posStart, int iIncrement, List * plst) 87: { 88: Position posFirstUnsorted; 89: Position posPlace; 90: ListEntry leCurrent; 91: ListEntry le; 92: 93: for ( 94: posFirstUnsorted=posStart+iIncrement; 95: posFirstUnsorted<ListSize(plst); 96: posFirstUnsorted+=iIncrement 97: ) 98: { 99: RetrieveList(plst, posFirstUnsorted, &leCurrent); 100: RetrieveList(plst, posFirstUnsorted-iIncrement, &le); 101: if (LT(leCurrent,le)) 102: { 103: for ( 104: posPlace=posFirstUnsorted-iIncrement; 105: posPlace>=0; 106: posPlace-=iIncrement 107: ) 108: { 109: Swap(posPlace,posPlace+iIncrement,plst); 110: if (posPlace<iIncrement)

Copyright © 2001 Dan Leach 53

111: break; 112: RetrieveList( 113: plst, 114: posPlace-iIncrement, 115: &le 116: ); 117: if (LT(le,leCurrent)) 118: break; 119: } 120: } 121: } 122: } 123: 124: // insertion sort; calls SortInterval for the full list 125: // using an increment of 1 126: void InsertionSort(List * plst) 127: { 128: SortInterval(0,1,plst); 129: } 130: 131: // definition of return codes 132: typedef enum 133: { 134: RC_SUCCESS=0, 135: RC_SURPRISE, 136: RC_ERROR 137: } ReturnCode; 138: 139: // definition of command line arguments 140: typedef enum 141: { 142: CLA_PROGRAM_NAME=0, 143: CLA_INPUT_FILE_NAME 144: } CommandLineArguments; 145: 146: #define MAX_LINE 200 147: 148: // main program 149: ReturnCode main( 150: unsigned int uiArgumentCount, 151: char * szArguments[] 152: ) 153: { 154: ReturnCode rc=RC_SUCCESS; 155: FILE * pfsIn=NULL; 156: char szLine [MAX_LINE]; 157: List * plst; 158: List * plstSort; 159: ListEntry le; 160: 161: // too many args 162: if (uiArgumentCount>2) 163: { 164: fprintf( 165: stderr, 166: "usage: %s [filename]\n",

Copyright © 2001 Dan Leach 54

167: szArguments[CLA_PROGRAM_NAME] 168: ); 169: rc=RC_ERROR; 170: } 171: 172: // use input file 173: else if (uiArgumentCount==2) 174: { 175: pfsIn=fopen(szArguments[CLA_INPUT_FILE_NAME],"r"); 176: if(pfsIn==NULL) 177: { 178: fprintf( 179: stderr, 180: "can't open %s for read\n", 181: szArguments[CLA_INPUT_FILE_NAME] 182: ); 183: rc=RC_ERROR; 184: } 185: } 186: 187: // use stdin 188: else 189: pfsIn=stdin; 190: 191: if (rc==RC_SUCCESS) 192: { 193: // read the list into l 194: plst = CreateList(true); 195: 196: while ( 197: !GetError() && 198: fgets(szLine, sizeof(szLine), pfsIn) 199: ) 200: { 201: // trim white space from end of line 202: szLine[strlen(szLine)-1]='\0'; 203: while (isspace(szLine[strlen(szLine)-1])) 204: szLine[strlen(szLine)-1]='\0'; 205: 206: // insert line into list 207: if(strlen(szLine)!=0) 208: { 209: le = (ListEntry) calloc( 210: 1, 211: strlen(szLine)+1 212: ); 213: strcpy(le,szLine); 214: InsertList(plst,ListSize(plst),le); 215: } 216: 217: if (GetError()) 218: rc=RC_ERROR; 219: } 220: } 221: 222: if (rc==RC_SUCCESS)

Copyright © 2001 Dan Leach 55

223: // copy the list for use by the sort methods 224: plstSort = CopyList(plst); 225: 226: if (GetError()) 227: rc=RC_ERROR; 228: 229: if (rc==RC_SUCCESS) 230: { 231: // insertion sort the list and print stats 232: InsertionSort(plstSort); 233: printf("List after Insertion Sort:\n"); 234: PrintList(plstSort); 235: printf("\nReverse sorted list:\n"); 236: ReverseList(plstSort); 237: PrintList(plstSort); 238: printf("\nOriginal list:\n"); 239: PrintList(plst); 240: DestroyList(plstSort); 241: DestroyList(plst); 242: } 243: 244: if (GetError()) 245: rc=RC_ERROR; 246: 247: if (pfsIn!=NULL) 248: fclose(pfsIn); 249: 250: return rc; 251: }

1.11.7 listsort.in 1: aaa 2:a 3:aa 4:abbb 5:ab 6:abb 7:This is a test 8:So Is This 9:And This Too

1.11.8 listsort.out 1: List after Insertion Sort: 2: (LIST START) 3: And This Too 4: So Is This 5: This is a test 6: a 7: aa 8: aaa 9: ab 10: abb 11: abbb 12: (LIST END) 13:

Copyright © 2001 Dan Leach 56

14: Reverse sorted list: 15: (LIST START) 16: abbb 17: abb 18: ab 19: aaa 20: aa 21: a 22: This is a test 23: So Is This 24: And This Too 25: (LIST END) 26: 27: Original list: 28: (LIST START) 29: aaa 30: a 31: aa 32: abbb 33: ab 34: abb 35: This is a test 36: So Is This 37: And This Too 38: (LIST END)

1.11.9 bldlsd.bat 1: cl /Felsd.exe /DPDLIST listsort.c pdlist.c error.c

1.11.10 bldlss.bat 1: cl /Felss.exe /DPSLIST listsort.c pslist.c error.c

Copyright © 2001 Dan Leach 57

1.12 SearchingThere are two types of searches that will be discussed in this class

1.12.1 Linear SearchThis looks at each element in turn until the structure is exhausted or a match was found. This is an order n search. It is optimal for unordered sequences.

1.12.2 Binary SearchThis looks at the middle element in a range and determines if a match was found – if not, it recourses with either the right or left sub-range depending on the relative value. This is an order log n search, but the sequence must be ordered. It is optimal for ordered sequences for which no other access method exists.

Copyright © 2001 Dan Leach 58

1.13 A Linear Search Implementation

1.13.1 listsqs.c 1: // listsqs.c 2: // reads strings from a file 3: // puts them in a list 4: // searchs the list 5: // then prints the result 6: 7: #include <stdio.h> 8: #include <string.h> 9: #include "error.h" 10: #include <ctype.h> 11: #include "list.h" 12: 13: int g_iNumberOfCompares=0; 14: 15: Boolean EQ(ListEntry le1, ListEntry le2) 16: { 17: g_iNumberOfCompares++; 18: return !strcmp(le1, le2); 19: } 20: 21: Boolean LT(ListEntry le1, ListEntry le2) 22: { 23: g_iNumberOfCompares++; 24: return strcmp(le1, le2) < 0; 25: } 26: 27: /* SequentialSearch: contiguous version. 28: 29: 30: Pre: The contiguous list list has been created. 31: Post: If an entry in list has key equal to target, then the function 32: returns the location of the first such entry (success). 33: Otherwise the function returns -1 (failure). 34: */ 35: 36: Position SequentialSearch(List* plst, ListEntry leTarget) 37: { 38: Position pos; 39: ListEntry le; 40: 41: for (pos = 0; pos < ListSize(plst); pos++) 42: { 43: RetrieveList(plst, pos, &le); 44: 45: if (EQ(le, leTarget)) 46: return pos; 47: } 48: return -1; 49: } 50: 51: // definition of return codes

Copyright © 2001 Dan Leach 59

52: typedef enum 53: { 54: RC_SUCCESS=0, 55: RC_SURPRISE, 56: RC_ERROR 57: } ReturnCode; 58: 59: // definition of command line arguments 60: typedef enum 61: { 62: CLA_PROGRAM_NAME=0, 63: CLA_INPUT_FILE_NAME 64: } CommandLineArguments; 65: 66: #define MAX_LINE 200 67: 68: // main program 69: ReturnCode main( 70: unsigned int uiArgumentCount, 71: char * szArguments[] 72: ) 73: { 74: ReturnCode rc=RC_SUCCESS; 75: FILE * pfsIn=NULL; 76: char szLine [MAX_LINE]; 77: List * plst; 78: ListEntry le; 79: 80: // too many args 81: if (uiArgumentCount>2) 82: { 83: fprintf( 84: stderr, 85: "usage: %s [filename]\n", 86: szArguments[CLA_PROGRAM_NAME] 87: ); 88: rc=RC_ERROR; 89: } 90: 91: // use input file 92: else if (uiArgumentCount==2) 93: { 94: pfsIn=fopen(szArguments[CLA_INPUT_FILE_NAME],"r"); 95: if(pfsIn==NULL) 96: { 97: fprintf( 98: stderr, 99: "can't open %s for read\n", 100: szArguments[CLA_INPUT_FILE_NAME] 101: ); 102: rc=RC_ERROR; 103: } 104: } 105: 106: // use stdin 107: else

Copyright © 2001 Dan Leach 60

108: pfsIn=stdin; 109: 110: if (rc==RC_SUCCESS) 111: { 112: // read the list into lst 113: plst = CreateList(true); 114: 115: while ( 116: !GetError() && 117: fgets(szLine, sizeof(szLine), pfsIn) 118: ) 119: { 120: // trim white space from end of line 121: szLine[strlen(szLine)-1]='\0'; 122: while (isspace(szLine[strlen(szLine)-1])) 123: szLine[strlen(szLine)-1]='\0'; 124: 125: // insert line into list 126: if(strlen(szLine)!=0) 127: { 128: le = (ListEntry) calloc( 129: 1, 130: strlen(szLine)+1 131: ); 132: strcpy(le,szLine); 133: InsertList(plst,ListSize(plst),le); 134: } 135: 136: if (GetError()) 137: rc=RC_ERROR; 138: } 139: } 140: 141: if (rc==RC_SUCCESS) 142: PrintList(plst); 143: 144: if (rc==RC_SUCCESS) 145: { 146: // search the list for "xyzzy" 147: // should not be found 148: Position pos = 149: SequentialSearch(plst, "xyzzy"); 150: if (pos<0) 151: printf("\"xyzzy\" not found\n"); 152: else 153: printf("\"xyzzy\" found at position %d\n",pos); 154: 155: printf 156: ( 157: "number of compares was:%d\n", 158: g_iNumberOfCompares 159: ); 160: 161: g_iNumberOfCompares=0; 162: 163: // search the list for "dan"

Copyright © 2001 Dan Leach 61

164: // should be found 165: pos = 166: SequentialSearch(plst, "dan"); 167: if (pos<0) 168: printf("\"dan\" not found\n"); 169: else 170: printf("\"dan\" found at position %d\n",pos); 171: 172: printf 173: ( 174: "number of compares was:%d\n", 175: g_iNumberOfCompares 176: ); 177: 178: DestroyList(plst); 179: } 180: 181: if (GetError()) 182: rc=RC_ERROR; 183: 184: if (pfsIn!=NULL) 185: fclose(pfsIn); 186: 187: return rc; 188: } 189: 190: /* output of a sample run: 191: (LIST START) 192: sam 193: jan 194: jen 195: over 196: under 197: through 198: anyone 199: lived 200: in 201: a 202: pretty 203: how 204: town 205: with 206: up 207: so 208: floating 209: many 210: bells 211: down 212: dan 213: (LIST END) 214: "xyzzy" not found 215: number of compares was:21 216: "dan" found at position 20 217: number of compares was:21 218: */

Copyright © 2001 Dan Leach 62

1.13.2 bldlsqss.batcl /Felsqsd.exe /DPSLIST listsqs.c pdlist.c error.c

1.13.3 bldlsqsd.batcl /Felsqsd.exe /DPDLIST listsqs.c pdlist.c error.c

Copyright © 2001 Dan Leach 63

1.14 A Binary Search Implementation

1.14.1 listbs.c 1: // listbs.c 2: // reads strings from a file 3: // puts them in a list 4: // searchs the list 5: // then prints the result 6: 7: #include <stdio.h> 8: #include <string.h> 9: #include "error.h" 10: #include <ctype.h> 11: #include "list.h" 12: 13: int g_iNumberOfCompares=0; 14: 15: Boolean EQ(ListEntry le1, ListEntry le2) 16: { 17: g_iNumberOfCompares++; 18: return !strcmp(le1, le2); 19: } 20: 21: Boolean LT(ListEntry le1, ListEntry le2) 22: { 23: g_iNumberOfCompares++; 24: return strcmp(le1, le2) < 0; 25: } 26: 27: Boolean GT(ListEntry le1, ListEntry le2) 28: { 29: g_iNumberOfCompares++; 30: return strcmp(le1, le2) > 0; 31: } 32: 33: /* BinarySearchWithCheck: recognizing equality version of binary search. 34: 35: Pre: 36: The contiguous list plst has been created. 37: Post: 38: If an entry in plst has key equal to leTarget, then the function 39: returns the location of one such entry (success). 40: Otherwise the function returns -1 (failure). 41: */ 42: Position BinarySearchWithCheck(List * plst, ListEntry leTarget) 43: { 44: Position posBottom, posMiddle, posTop; 45: ListEntry le; 46: 47: posTop = ListSize(plst) - 1; /* Initialize bounds to encompass entire list. */ 48: posBottom = 0; 49: while (posTop >= posBottom) /* Check terminating condition. */ 50: { 51: posMiddle = (posTop + posBottom) / 2;

Copyright © 2001 Dan Leach 64

52: RetrieveList(plst, posMiddle, &le); 53: if (EQ(leTarget, le)) 54: return posMiddle; 55: else if (LT(leTarget, le)) 56: posTop = posMiddle - 1; /* Reduce to the bottom half of the list. */ 57: else 58: posBottom = posMiddle + 1; /* Reduce to the top half of the list. */ 59: } 60: return -1; 61: } 62: 63: /* BinarySearchForgetful: forgetful version of binary search. 64: 65: Pre: 66: The contiguous list plst has been created. 67: Post: 68: If an entry in plst has key equal to leTarget, then the function 69: returns the location of the first such entry (success). 70: Otherwise the function returns -1 (failure). 71: */ 72: Position BinarySearchForgetful(List * plst, ListEntry leTarget) 73: { 74: Position posBottom, posMiddle, posTop; 75: ListEntry le; 76: 77: posTop = ListSize(plst) - 1; /* Initialize bounds to encompass entire list. */ 78: posBottom = 0; 79: while (posTop > posBottom) /* Check terminating condition. */ 80: { 81: posMiddle = (posTop + posBottom) / 2; 82: RetrieveList(plst, posMiddle, &le); 83: if (GT(leTarget, le)) 84: posBottom = posMiddle + 1; /* Reduce to the top half of the list. */ 85: else 86: posTop = posMiddle; /* Reduce to the bottom half of the list. */ 87: } 88: if (posTop == -1) 89: return -1; /* Search for an empty list always fails. */ 90: RetrieveList(plst, posTop, &le); 91: if (EQ(le, leTarget)) 92: return posTop; 93: else 94: return -1; 95: } 96: 97: // definition of return codes 98: typedef enum 99: { 100: RC_SUCCESS=0, 101: RC_SURPRISE, 102: RC_ERROR 103: } ReturnCode; 104: 105: // definition of command line arguments 106: typedef enum 107: {

Copyright © 2001 Dan Leach 65

108: CLA_PROGRAM_NAME=0, 109: CLA_INPUT_FILE_NAME 110: } CommandLineArguments; 111: 112: #define MAX_LINE 200 113: 114: // main program 115: ReturnCode main( 116: unsigned int uiArgumentCount, 117: char * szArguments[] 118: ) 119: { 120: ReturnCode rc=RC_SUCCESS; 121: FILE * pfsIn=NULL; 122: char szLine [MAX_LINE]; 123: List * plst; 124: ListEntry le; 125: 126: // too many args 127: if (uiArgumentCount>2) 128: { 129: fprintf( 130: stderr, 131: "usage: %s [filename]\n", 132: szArguments[CLA_PROGRAM_NAME] 133: ); 134: rc=RC_ERROR; 135: } 136: 137: // use input file 138: else if (uiArgumentCount==2) 139: { 140: pfsIn=fopen(szArguments[CLA_INPUT_FILE_NAME],"r"); 141: if(pfsIn==NULL) 142: { 143: fprintf( 144: stderr, 145: "can't open %s for read\n", 146: szArguments[CLA_INPUT_FILE_NAME] 147: ); 148: rc=RC_ERROR; 149: } 150: } 151: 152: // use stdin 153: else 154: pfsIn=stdin; 155: 156: if (rc==RC_SUCCESS) 157: { 158: // read the list into lst 159: plst = CreateList(true); 160: 161: while ( 162: !GetError() && 163: fgets(szLine, sizeof(szLine), pfsIn)

Copyright © 2001 Dan Leach 66

164: ) 165: { 166: // trim white space from end of line 167: szLine[strlen(szLine)-1]='\0'; 168: while (isspace(szLine[strlen(szLine)-1])) 169: szLine[strlen(szLine)-1]='\0'; 170: 171: // insert line into list 172: if(strlen(szLine)!=0) 173: { 174: le = (ListEntry) calloc( 175: 1, 176: strlen(szLine)+1 177: ); 178: strcpy(le,szLine); 179: InsertList(plst,ListSize(plst),le); 180: } 181: 182: if (GetError()) 183: rc=RC_ERROR; 184: } 185: } 186: 187: if (rc==RC_SUCCESS) 188: PrintList(plst); 189: 190: if (rc==RC_SUCCESS) 191: { 192: // search the list for "xyzzy" 193: // should not be found 194: Position pos = 195: BinarySearchWithCheck(plst, "xyzzy"); 196: if (pos<0) 197: printf("\"xyzzy\" not found\n"); 198: else 199: printf("\"xyzzy\" found at position %d\n",pos); 200: 201: printf 202: ( 203: "number of compares was:%d\n", 204: g_iNumberOfCompares 205: ); 206: 207: g_iNumberOfCompares=0; 208: 209: // search the list for "dan" 210: // should be found 211: pos = 212: BinarySearchWithCheck(plst, "dan"); 213: printf("BinarySearchWithCheck:\n"); 214: if (pos<0) 215: printf("\"dan\" not found\n"); 216: else 217: printf("\"dan\" found at position %d\n",pos); 218: 219: printf

Copyright © 2001 Dan Leach 67

220: ( 221: "number of compares was:%d\n", 222: g_iNumberOfCompares 223: ); 224: 225: g_iNumberOfCompares=0; 226: 227: // search the list for "xyzzy" 228: // should not be found 229: printf("BinarySearchForgetful:\n"); 230: pos = 231: BinarySearchForgetful(plst, "xyzzy"); 232: if (pos<0) 233: printf("\"xyzzy\" not found\n"); 234: else 235: printf("\"xyzzy\" found at position %d\n",pos); 236: 237: printf 238: ( 239: "number of compares was:%d\n", 240: g_iNumberOfCompares 241: ); 242: 243: g_iNumberOfCompares=0; 244: 245: // search the list for "dan" 246: // should be found 247: pos = 248: BinarySearchForgetful(plst, "dan"); 249: if (pos<0) 250: printf("\"dan\" not found\n"); 251: else 252: printf("\"dan\" found at position %d\n",pos); 253: 254: printf 255: ( 256: "number of compares was:%d\n", 257: g_iNumberOfCompares 258: ); 259: 260: DestroyList(plst); 261: } 262: 263: if (GetError()) 264: rc=RC_ERROR; 265: 266: if (pfsIn!=NULL) 267: fclose(pfsIn); 268: 269: return rc; 270: } 271: 272: /* 273: output from sample run: 274: (LIST START) 275: a

Copyright © 2001 Dan Leach 68

276: anyone 277: bells 278: dan 279: down 280: floating 281: how 282: in 283: jan 284: jen 285: lived 286: many 287: over 288: pretty 289: sam 290: so 291: through 292: town 293: under 294: up 295: with 296: (LIST END) 297: "xyzzy" not found 298: number of compares was:10 299: BinarySearchWithCheck: 300: "dan" found at position 3 301: number of compares was:9 302: BinarySearchForgetful: 303: "xyzzy" not found 304: number of compares was:5 305: "dan" found at position 3 306: number of compares was:6 307: */

1.14.2 bldlbss.batcl /Felbss.exe /DPSLIST listbs.c pslist.c error.c

1.14.3 bldlbsd.batcl /Felbsd.exe /DPDLIST listbs.c pdlist.c error.c

Copyright © 2001 Dan Leach 69

1.15 SortingA number of comparison sorts will be discussed.

1.15.1 sorts.h 1: // sorts.h 2: // interface to sort routines and counters 3: 4: #pragma once 5: 6: #include "list.h" 7: 8: void AppendList(List * plst, List * plstNew); 9: List * CopyList(List * plst); 10: int GetSwapCount(); 11: void ClearSwapCount(); 12: int GetCompareCount(); 13: void ClearCompareCount(); 14: void InsertionSort(List * plst); 15: void SelectionSort(List * plst); 16: void ShellSort1(List * plst, int iIncrement[], int iNumberOfIncrements); 17: void ShellSort2(List * plst); 18: void QuickSort(List * plst); 19: void HeapSort(List * plst); 20: void RadixSort(List * plst);

1.15.2 sorts.c 1: // sorts.c 2: // sort routines and counters 3: 4: #include <stdio.h> 5:#include <stdlib.h> 6:#include "sorts.h" 7:#include "error.h" 8: 9: // append the contents of one list to another list 10: void AppendList(List * plst, List * plstNew) 11: { 12: Position pos; 13: ListEntry leNew; 14: 15: for (pos=0;!GetError() && pos<ListSize(plstNew);pos++) 16: { 17: RetrieveList(plstNew,pos,&leNew); 18: InsertList(plst,ListSize(plst),leNew); 19: } 20: } 21: 22: // copy one list to another 23: void CopyToExistingList(List * plstOutput, List * plstInput) 24: { 25: Position pos; 26: Position posSave; 27: ListEntry leCurrent;

Copyright © 2001 Dan Leach 70

28: 29: ClearList(plstOutput); 30: posSave=CurrentListPosition(plstInput); 31: for (pos=0;!GetError() && pos<ListSize(plstInput);pos++) 32: { 33: RetrieveList(plstInput,pos,&leCurrent); 34: InsertList(plstOutput,pos,leCurrent); 35: } 36: 37: if (!GetError()) 38: { 39: SetListPosition(plstInput,posSave); 40: SetListPosition(plstOutput,posSave); 41: } 42: } 43: 44: // copy a list 45: List * CopyList(List * plst) 46: { 47: List * plstNew; 48: 49: plstNew=CreateList(); 50: CopyToExistingList(plstNew,plst); 51: 52: return plstNew; 53: } 54: 55: static int gs_iSwapCount = 0; 56: 57: // return the number of swaps so far 58: int GetSwapCount() 59: { 60: return gs_iSwapCount; 61: } 62: 63: // set the number of swaps to 0 64: void ClearSwapCount() 65: { 66: gs_iSwapCount=0; 67: } 68: 69: // add 1 to the number of swaps 70: void IncrementSwapCount() 71: { 72: gs_iSwapCount++; 73: } 74: 75: static int gs_iCompareCount = 0; 76: 77: // return the number of compares so far 78: int GetCompareCount() 79: { 80: return gs_iCompareCount; 81: } 82: 83: // set the number of compares to 0

Copyright © 2001 Dan Leach 71

84: void ClearCompareCount() 85: { 86: gs_iCompareCount=0; 87: } 88: 89: // add 1 to the number of compares 90: void IncrementCompareCount() 91: { 92: gs_iCompareCount++; 93: } 94: 95: // generic compare operation: 96: // returns 1 if le1>le2, 97: // returns -1 if le2>le1, 98: // returns 0 if le1==le2 99: int Compare(ListEntry le1,ListEntry le2) 100: { 101: int iReturn = -1; 102: IncrementCompareCount(); 103: if (le1>le2) 104: iReturn = 1; 105: else if (le1==le2) 106: iReturn = 0; 107: return iReturn; 108: } 109: 110: // returns true if le1<=le2; False,otherwise 111: Boolean LE (ListEntry le1,ListEntry le2) 112: { 113: return (Compare(le1,le2)<=0); 114: } 115: 116: // returns true if le1<le2; False,otherwise 117: Boolean LT (ListEntry le1,ListEntry le2) 118: { 119: return (Compare(le1,le2)<0); 120: } 121: 122: // returns true if le1>=le2; False,otherwise 123: Boolean GE (ListEntry le1,ListEntry le2) 124: { 125: return (Compare(le1,le2)>=0); 126: } 127: 128: // returns true if le1>le2; False,otherwise 129: Boolean GT (ListEntry le1,ListEntry le2) 130: { 131: return (Compare(le1,le2)>0); 132: } 133: 134: // swaps the node at position pos1 with the node at position pos2 135: void Swap(Position pos1,Position pos2,List * plst) 136: { 137: ListEntry le1; 138: ListEntry le2; 139:

Copyright © 2001 Dan Leach 72

140: IncrementSwapCount(); 141: 142: if (pos1>pos2) { 143: DeleteList(plst,pos1,&le1); 144: DeleteList(plst,pos2,&le2); 145: InsertList(plst,pos2,le1); 146: InsertList(plst,pos1,le2); 147: } 148: 149: if (pos2>pos1) { 150: DeleteList(plst,pos2,&le2); 151: DeleteList(plst,pos1,&le1); 152: InsertList(plst,pos1,le2); 153: InsertList(plst,pos2,le1); 154: } 155: } 156: 157: // moves a node from one list to another 158: void Move( 159: List * plstSrc, 160: Position posSrc, 161: List * plstDest, 162: Position posDest 163: ) 164: { 165: ListEntry le; 166: 167: IncrementSwapCount(); 168: 169: DeleteList(plstSrc,posSrc,&le); 170: InsertList(plstDest,posDest,le); 171: } 172: 173: // sorts an interaval using the insertion sort method 174: void SortInterval(Position posStart,int iIncrement,List * plst) 175: { 176: Position posFirstUnsorted; 177: Position posPlace; 178: ListEntry leCurrent; 179: ListEntry le; 180: 181: for ( 182: posFirstUnsorted=posStart+iIncrement; 183: posFirstUnsorted<ListSize(plst); 184: posFirstUnsorted+=iIncrement 185: ) 186: { 187: RetrieveList(plst,posFirstUnsorted,&leCurrent); 188: RetrieveList( 189: plst, 190: posFirstUnsorted-iIncrement, 191: &le 192: ); 193: if (LT(leCurrent,le)) 194: { 195: for (

Copyright © 2001 Dan Leach 73

196: posPlace=posFirstUnsorted-iIncrement; 197: posPlace>=0; 198: posPlace-=iIncrement 199: ) 200: { 201: Swap(posPlace,posPlace+iIncrement,plst); 202: if (posPlace<iIncrement) 203: break; 204: RetrieveList( 205: plst, 206: posPlace-iIncrement, 207: &le 208: ); 209: if (LE(le,leCurrent)) 210: break; 211: } 212: } 213: } 214: } 215: 216: // insertion sort; calls SortInterval for the full list 217: // using an increment of 1 218: void InsertionSort(List * plst) 219: { 220: SortInterval(0,1,plst); 221: } 222: 223: // determines the maximum key in a list; used by SelectionSort 224: Position MaxKey(Position pLow,Position pHigh,List * plst) 225: { 226: Position pLargest; 227: Position pCurrent; 228: ListEntry leLargest; 229: ListEntry leCurrent; 230: 231: pLargest=pLow; 232: for (pCurrent=pLow+1; pCurrent<=pHigh; pCurrent++) 233: { 234: RetrieveList(plst,pLargest,&leLargest); 235: RetrieveList(plst,pCurrent,&leCurrent); 236: 237: if (LT(leLargest,leCurrent)) 238: pLargest=pCurrent; 239: } 240: 241: return pLargest; 242: } 243: 244: // selection sort algorithm 245: void SelectionSort(List * plst) 246: { 247: Position pMaximum; 248: Position pCurrent; 249: 250: for (pCurrent=ListSize(plst)-1; pCurrent>0; pCurrent--) 251: {

Copyright © 2001 Dan Leach 74

252: pMaximum=MaxKey(0,pCurrent,plst); 253: Swap(pMaximum,pCurrent,plst); 254: } 255: } 256: 257: // shell sort algorithm; uses an array of increments, 258: // the size of which is passed in iNumberOfIncrements 259: void ShellSort1(List * plst, int iIncrement[], int iNumberOfIncrements) 260: { 261: Position posStart; 262: int i; 263: for (i=0; i<iNumberOfIncrements; i++) 264: for (posStart=0;posStart<iIncrement[i];posStart++) 265: SortInterval(posStart,iIncrement[i],plst); 266: } 267: 268: // shell sort algorithm from text 269: void ShellSort2(List * plst) 270: { 271: Position pStart; 272: int iIncrement=ListSize(plst); 273: do 274: { 275: iIncrement=iIncrement/3+1; 276: 277: for (pStart=0;pStart<iIncrement;pStart++) 278: SortInterval(pStart,iIncrement,plst); 279: 280: } while (iIncrement>1); 281: 282: } 283: 284: // return the ListEntry at pos in plst 285: ListEntry Entry(Position pos,List * plst) 286: { 287: ListEntry le; 288: 289: RetrieveList(plst,pos,&le); 290: 291: return le; 292: } 293: 294: // rearrange 295: Position Rearrange (List * plst, Position posLower, Position posUpper) 296: { 297: Position posPivot = posLower; 298: ListEntry lePivot = Entry(posLower, plst); 299: Position posUp = posUpper; 300: Position posDown = posLower; 301: 302: do 303: { 304: while( 305: posUp>posDown && 306: (GE(Entry(posUp,plst),lePivot)) 307: )

Copyright © 2001 Dan Leach 75

308: posUp--; 309: 310: posPivot=posUp; 311: if (posUp!=posDown) 312: { 313: Swap(posDown, posUp, plst); 314: while( 315: posUp>posDown && 316: (LE(Entry(posUp,plst),lePivot)) 317: ) 318: posDown++; 319: 320: posPivot=posDown; 321: if (posUp!=posDown) 322: Swap(posDown, posUp, plst); 323: } 324: 325: } while (posUp!=posDown); 326: 327: return posPivot; 328: } 329: 330: // QuickRec 331: void QuickRec (List * plst, Position posLower, Position posUpper) 332: { 333: Position posPivot; 334: 335: if (posLower<posUpper) 336: { 337: posPivot=Rearrange(plst, posLower, posUpper); 338: QuickRec(plst, posLower, posPivot-1); 339: QuickRec(plst, posPivot+1, posUpper); 340: } 341: } 342: 343: // main entry for quick sort 344: void QuickSort(List * plst) 345: { 346: QuickRec(plst, 0, ListSize(plst)-1); 347: } 348: 349: // returns the index of the left child of current in l 350: Position LeftChild(Position pCurrent) 351: { 352: return 2*pCurrent+1; 353: } 354: 355: // returns the index of the right child of current in l 356: Position RightChild(Position pCurrent) 357: { 358: return 2*(pCurrent+1); 359: } 360: 361: // returns whether current is a leaf 362: Boolean Leaf(Position pCurrent,Position pLast) 363: {

Copyright © 2001 Dan Leach 76

364: return (pLast<LeftChild(pCurrent)); 365: } 366: 367: // returns the index of the larger child of current in l 368: Position LargerChild( 369: Position pCurrent, 370: List * plst, 371: Position pLast 372: ) 373: { 374: Position pLarger=LeftChild(pCurrent); 375: 376: if ((RightChild(pCurrent)<=pLast) && 377: (GT(Entry(RightChild(pCurrent),plst), 378: Entry(LeftChild(pCurrent),plst)))) 379: pLarger=RightChild(pCurrent); 380: 381: return pLarger; 382: } 383: 384: // assumes that the root may be out of place in the heap 385: // and moves it to the current position as necessary 386: void FixHeap(List * plst,Position pFirst,Position pLast) 387: { 388: Position pCurrent=pFirst; 389: Position pLarger; 390: Boolean bDone=false; 391: 392: while (!Leaf(pCurrent,pLast) && !bDone) { 393: pLarger=LargerChild(pCurrent,plst,pLast); 394: if (GT(Entry(pLarger,plst),Entry(pCurrent,plst))) { 395: Swap(pCurrent,pLarger,plst); 396: pCurrent=pLarger; 397: } 398: else 399: bDone=true; 400: } 401: } 402: 403: // build a heap 404: void BuildHeap(List * plst) 405: { 406: Position i; 407: for (i=(ListSize(plst)/2-1);i>=0;i--) { 408: FixHeap(plst,i,ListSize(plst)-1); 409: } 410: } 411: 412: // heap sort 413: void HeapSort(List * plst) 414: { 415: Position i; 416: BuildHeap(plst); 417: for (i=ListSize(plst)-1;i>0;i--) { 418: Swap(0,i,plst); 419: FixHeap(plst,0,i-1);

Copyright © 2001 Dan Leach 77

420: } 421: } 422: 423: // test bit 424: Boolean TestBit(ListEntry le, int iDigit) 425: { 426: ListEntry leMask = 1; 427: Boolean bReturn; 428: leMask<<=iDigit; 429: bReturn = (le & leMask)!=0; 430: return bReturn; 431: } 432: 433: // radix sort 434: void RadixSort(List * plst) 435: { 436: List * plst0sBucket = NULL; 437: List * plst1sBucket = NULL; 438: int iDigit=0; 439: int iNumberOfDigits=sizeof(ListEntry)*8; 440: 441: plst0sBucket = CreateList(); 442: if (!GetError()) 443: plst1sBucket = CreateList(); 444: 445: while (!GetError() && iDigit<iNumberOfDigits) 446: { 447: // divide list into buckets 448: while (!GetError() && !ListEmpty(plst)) 449: { 450: if (TestBit(Entry(0,plst),iDigit)) 451: Move( 452: plst, 453: 0, 454: plst1sBucket, 455: ListSize(plst1sBucket) 456: ); 457: else 458: Move( 459: plst, 460: 0, 461: plst0sBucket, 462: ListSize(plst0sBucket) 463: ); 464: } 465: 466: // merge buckets back to plst 467: CopyToExistingList(plst,plst0sBucket); 468: AppendList(plst,plst1sBucket); 469: ClearList(plst0sBucket); 470: ClearList(plst1sBucket); 471: iDigit++; 472: } 473: 474: if (plst0sBucket!=NULL) 475: DestroyList(plst0sBucket);

Copyright © 2001 Dan Leach 78

476: if (plst1sBucket!=NULL) 477: DestroyList(plst1sBucket); 478: }

1.15.3 tstsorts.c 1: // tstsorts.c 2: 3: #include <stdio.h> 4:#include <stdlib.h> 5:#include <string.h> 6:#include "error.h" 7: #include "list.h" 8: #include "sorts.h" 9: 10: // definition of return codes 11: typedef enum 12: { 13: RC_SUCCESS=0, 14: RC_SURPRISE, 15: RC_ERROR 16: } ReturnCode; 17: 18: void Output( 19: char * szComment, 20: char * szSortName, 21: int iSize, 22: long lSwapCount, 23: long lCompareCount) 24: { 25: int i; 26: char szLineBuffer [60]; 27: char szTemp[12]; 28: 29: for (i=0;i<sizeof(szLineBuffer);i++) 30: szLineBuffer[i]=' '; 31: szLineBuffer[sizeof(szLineBuffer)-1]='\0'; 32: strncpy(&szLineBuffer[0],szComment,strlen(szComment)); 33: strncpy( 34: &szLineBuffer[10], 35: szSortName, 36: strlen(szSortName) 37: ); 38: sprintf(szTemp,"%4d",iSize); 39: strncpy(&szLineBuffer[25],szTemp,strlen(szTemp)); 40: sprintf(szTemp,"%7d",lSwapCount); 41: strncpy(&szLineBuffer[31],szTemp,strlen(szTemp)); 42: sprintf(szTemp,"%7d",lCompareCount); 43: strncpy(&szLineBuffer[40],szTemp,strlen(szTemp)); 44: puts(szLineBuffer); 45: } 46: 47: void TestSort( 48: List * plst, 49: void(*Sort)(List*), 50: char * szName,

Copyright © 2001 Dan Leach 79

51: char * szComment 52: ) 53: { 54: ReturnCode rc=RC_SUCCESS; 55: List * plstSort=NULL; 56: 57: // copy the list for use by the sort 58: plstSort = CopyList(plst); 59: 60: if (GetError()) 61: rc=RC_ERROR; 62: 63: if (rc==RC_SUCCESS) 64: { 65: // sort the list and print stats 66: ClearCompareCount(); 67: ClearSwapCount(); 68: 69: Sort(plstSort); 70: Output( 71: szComment, 72: szName, 73: ListSize(plst), 74: GetSwapCount(), 75: GetCompareCount() 76: ); 77: 78: } 79: 80: if (plstSort!=NULL) 81: DestroyList(plstSort); 82: } 83: 84: // makes the interface to ShellSort1 the 85: // same as the other sorts 86: void ShellSort1Wrapper(List * plst) 87: { 88: int iIncrement[3]={5,3,1}; 89: ShellSort1( 90: plst, 91: iIncrement, 92: sizeof(iIncrement)/sizeof(int) 93: ); 94: } 95: 96: void RunSorts(List * plst, char * szComment) 97: { 98: TestSort(plst, InsertionSort, "Insertion Sort", szComment); 99: TestSort(plst, SelectionSort, "Selection Sort", szComment); 100: TestSort(plst, ShellSort1Wrapper, "Shell Sort1", szComment); 101: TestSort(plst, ShellSort2, "Shell Sort2", szComment); 102: TestSort(plst, QuickSort, "Quick Sort", szComment); 103: TestSort(plst, HeapSort, "Heap Sort", szComment); 104: TestSort(plst, RadixSort, "Radix Sort", szComment); 105: } 106:

Copyright © 2001 Dan Leach 80

107: void RunTest(int iSize) 108: { 109: List * plst; 110: ListEntry le; 111: int i; 112: 113: // sorted 114: plst = CreateList(); 115: for (i=0;i<iSize;i++) 116: InsertList(plst,ListSize(plst),i+1); 117: 118: RunSorts(plst,"sorted"); 119: DestroyList(plst); 120: 121: // reversed 122: plst = CreateList(); 123: for (i=0;i<iSize;i++) 124: InsertList(plst,ListSize(plst),iSize-i); 125: 126: RunSorts(plst,"reversed"); 127: DestroyList(plst); 128: 129: // random 130: plst = CreateList(); 131: srand(0); 132: for (i=0;i<iSize;i++) 133: InsertList(plst,ListSize(plst),rand()); 134: 135: RunSorts(plst,"random"); 136: DestroyList(plst); 137: } 138: 139: // main program 140: void main() 141: { 142: RunTest(100); 143: RunTest(500); 144: } 145: 146: /* output: 147: sorted Insertion Sort 100 0 99 148: sorted Selection Sort 100 99 4950 149: sorted Shell Sort1 100 0 291 150: sorted Shell Sort2 100 0 446 151: sorted Quick Sort 100 0 4950 152: sorted Heap Sort 100 640 1081 153: sorted Radix Sort 100 3200 0 154: reversed Insertion Sort 100 4950 4950 155: reversed Selection Sort 100 99 4950 156: reversed Shell Sort1 100 1030 1223 157: reversed Shell Sort2 100 262 618 158: reversed Quick Sort 100 50 5000 159: reversed Heap Sort 100 516 944 160: reversed Radix Sort 100 3200 0 161: random Insertion Sort 100 2451 2550 162: random Selection Sort 100 99 4950

Copyright © 2001 Dan Leach 81

163: random Shell Sort1 100 695 979 164: random Shell Sort2 100 341 750 165: random Quick Sort 100 51 1392 166: random Heap Sort 100 567 1020 167: random Radix Sort 100 3200 0 168: sorted Insertion Sort 500 0 499 169: sorted Selection Sort 500 499 124750 170: sorted Shell Sort1 500 0 1491 171: sorted Shell Sort2 500 0 3245 172: sorted Quick Sort 500 0 124750 173: sorted Heap Sort 500 4354 7756 174: sorted Radix Sort 500 16000 0 175: reversed Insertion Sort 500 124750 124750 176: reversed Selection Sort 500 499 124750 177: reversed Shell Sort1 500 25150 26143 178: reversed Shell Sort2 500 2068 4824 179: reversed Quick Sort 500 250 125000 180: reversed Heap Sort 500 3676 7010 181: reversed Radix Sort 500 16000 0 182: random Insertion Sort 500 58822 59320 183: random Selection Sort 500 499 124750 184: random Shell Sort1 500 13531 15012 185: random Shell Sort2 500 3049 6084 186: random Quick Sort 500 248 8870 187: random Heap Sort 500 4052 7430 188: random Radix Sort 500 16000 0 189: */

1.15.4 tstsorts.out 1: sorted Insertion Sort 100 0 99 2: sorted Selection Sort 100 99 4950 3: sorted Shell Sort1 100 0 291 4: sorted Shell Sort2 100 0 446 5: sorted Quick Sort 100 0 4950 6: sorted Heap Sort 100 640 1081 7: sorted Radix Sort 100 3200 0 8: reversed Insertion Sort 100 4950 4950 9: reversed Selection Sort 100 99 4950 10: reversed Shell Sort1 100 1030 1223 11: reversed Shell Sort2 100 262 618 12: reversed Quick Sort 100 50 5000 13: reversed Heap Sort 100 516 944 14: reversed Radix Sort 100 3200 0 15: random Insertion Sort 100 2451 2550 16: random Selection Sort 100 99 4950 17: random Shell Sort1 100 695 979 18: random Shell Sort2 100 341 750 19: random Quick Sort 100 51 1392 20: random Heap Sort 100 567 1020 21: random Radix Sort 100 3200 0 22: sorted Insertion Sort 500 0 499 23: sorted Selection Sort 500 499 124750 24: sorted Shell Sort1 500 0 1491 25: sorted Shell Sort2 500 0 3245 26: sorted Quick Sort 500 0 124750

Copyright © 2001 Dan Leach 82

27: sorted Heap Sort 500 4354 7756 28: sorted Radix Sort 500 16000 0 29: reversed Insertion Sort 500 124750 124750 30: reversed Selection Sort 500 499 124750 31: reversed Shell Sort1 500 25150 26143 32: reversed Shell Sort2 500 2068 4824 33: reversed Quick Sort 500 250 125000 34: reversed Heap Sort 500 3676 7010 35: reversed Radix Sort 500 16000 0 36: random Insertion Sort 500 58822 59320 37: random Selection Sort 500 499 124750 38: random Shell Sort1 500 13531 15012 39: random Shell Sort2 500 3049 6084 40: random Quick Sort 500 248 8870 41: random Heap Sort 500 4052 7430 42: random Radix Sort 500 16000 0

1.15.5 bldtsts.bat 1: cl /Fetsts.exe /DPSLIST tstsorts.c error.c sorts.c pslist.c >bldtsts.out 2: emacs bldtsts.out

1.15.6 bldtstd.bat 1: cl /Fetstd.exe /DPDLIST tstsorts.c error.c sorts.c pdlist.c >bldtstd.out 2: emacs bldtstd.out

Copyright © 2001 Dan Leach 83

1.16 Hash Tables

1.16.1 list.h

This is a variation on lists to be used in the hash table implementation.

1: // list.h 2: // interface to lists 3: 4: #pragma once 5: 6: #include "stddef.h" 7: 8: typedef char * Key; 9: typedef char * Data; 10: 11: typedef struct 12: { 13: Key m_key; 14: Data m_data; 15: } TableEntry; 16: 17: typedef TableEntry * ListEntry; 18: 19: typedef int Position; 20: 21: #if defined(PDLIST) 22: #include "pdlist.h" 23: 24: #elif defined(PSLIST) 25: #include "pslist.h" 26: 27: #else 28: #error You must pick a list type: PDLIST or PSLIST 29: 30: #endif 31: 32: List * CreateList(); 33: int ListSize(List * plst); 34: Boolean ListEmpty(List * plst); 35: Boolean ListFull (List * plst); 36: Position CurrentListPosition(List * plst); 37: ListNode * ListNext(List * plst); 38: void SetListPosition(List * plst, Position pos); 39: void InsertList(List * plst, Position pos, ListEntry le); 40: void DeleteList(List * plst, Position pos, ListEntry * ple); 41: void RetrieveList(List * plst, Position pos, ListEntry * ple); 42: void ReplaceList(List * plst, Position pos, ListEntry le); 43: void ClearList(List * plst); 44: void DestroyList(List * plst); 45: void PrintList(List * plst); 46: void TraverseList(List * plst, void(*Visit)(ListEntry));

Copyright © 2001 Dan Leach 84

1.16.2 hasht.h 1: // hasht.h 2: // interface to hash table 3: 4: #pragma once 5: 6: #include "list.h" 7: 8: typedef struct 9: { 10: int(*m_pfHash)(Key); 11: Boolean(*m_pfCompare)(Key,Key); 12: int m_iTableSize; 13: int m_iNumberOfEntries; 14: List ** m_pplstHashTable; 15: } HashTable; 16: 17: HashTable * CreateHashTable( 18: int iTableSize, 19: int(*Hash)(Key), 20: Boolean(*Compare)(Key,Key) 21: ); 22: 23: int HashTableSize(HashTable * pht); 24: int HashTableNumberOfEntries(HashTable * pht); 25: Boolean HashTableEmpty(HashTable * pht); 26: Boolean HashTableFull (HashTable * pht); 27: void InsertHashTable(HashTable * pht, Key key, Data data); 28: void DeleteHashTable(HashTable * pht, Key key, Data * pdata); 29: void RetrieveHashTable(HashTable * pht, Key key, Data * pdata); 30: void ReplaceHashTable(HashTable * pht, Key key, Data data, Data * pdata); 31: void ClearHashTable(HashTable * pht); 32: void DestroyHashTable(HashTable * pht); 33: void PrintHashTable(HashTable * pht); 34: void TraverseHashTable(HashTable * pht, void(*Visit)(TableEntry*));

1.16.3 hasht.c 1: // hasht.c 2: // implementation of hash table with chaining 3: 4: #include "hasht.h" 5: #include "string.h" 6:#include "stdlib.h" 7:#include "stdio.h" 8:#include "error.h" 9: 10: // allocate and init hash table 11: // return NULL if failure 12: HashTable * CreateHashTable( 13: int iTableSize, 14: int(*Hash)(Key), 15: Boolean(*Compare)(Key,Key) 16: ) 17: { 18: HashTable * pht;

Copyright © 2001 Dan Leach 85

19: 20: pht = (HashTable *) calloc(1, sizeof(HashTable)); 21: if (pht!=NULL) 22: { 23: pht->m_pplstHashTable= 24: (List **)calloc(iTableSize,sizeof(List *)); 25: if (pht->m_pplstHashTable==NULL) 26: { 27: free(pht); 28: pht=NULL; 29: } 30: } 31: 32: if (pht==NULL) 33: Error("no room for hash table"); 34: 35: if (pht!=NULL) 36: { 37: int i; 38: for (i=0; i<iTableSize && !GetError(); i++) 39: pht->m_pplstHashTable[i]= 40: CreateList(); 41: 42: if (GetError()) 43: { 44: for (i=0; i<iTableSize; i++) 45: if (pht->m_pplstHashTable[i]!=NULL) 46: DestroyList(pht->m_pplstHashTable[i]); 47: free(pht->m_pplstHashTable); 48: free(pht); 49: pht=NULL; 50: } 51: else 52: { 53: pht->m_pfHash=Hash; 54: pht->m_pfCompare=Compare; 55: pht->m_iTableSize=iTableSize; 56: pht->m_iNumberOfEntries=0; 57: } 58: } 59: 60: return pht; 61: } 62: 63: // return table size 64: int HashTableSize(HashTable * pht) 65: { 66: return pht->m_iTableSize; 67: } 68: 69: // return number of entries in table 70: int HashTableNumberOfEntries(HashTable * pht) 71: { 72: return pht->m_iNumberOfEntries; 73: } 74:

Copyright © 2001 Dan Leach 86

75: // return true if table is empty 76: Boolean HashTableEmpty(HashTable * pht) 77: { 78: return pht->m_iNumberOfEntries==0; 79: } 80: 81: // return true if table is full 82: Boolean HashTableFull (HashTable * pht) 83: { 84: return ListFull(pht->m_pplstHashTable[0]); 85: } 86: 87: // clear hash table 88: void ClearHashTable(HashTable * pht) 89: { 90: int i; 91: List * plst; 92: TableEntry * te; 93: for (i=0; i<pht->m_iTableSize; i++) 94: { 95: plst=pht->m_pplstHashTable[i]; 96: while(!ListEmpty(plst)) 97: { 98: DeleteList(plst,0,&te); 99: if (te!=NULL) 100: { 101: if (te->m_key!=NULL) 102: free(te->m_key); 103: if (te->m_data!=NULL) 104: free(te->m_data); 105: free (te); 106: } 107: } 108: } 109: } 110: 111: // destroy hash table 112: void DestroyHashTable(HashTable * pht) 113: { 114: int i; 115: 116: ClearHashTable(pht); 117: for (i=0; i<pht->m_iTableSize; i++) 118: DestroyList(pht->m_pplstHashTable[i]); 119: 120: free(pht->m_pplstHashTable); 121: free(pht); 122: } 123: 124: #define NOT_FOUND -1 125: 126: // find a key in the list; return NOT_FOUND if not present 127: Position LocateKey(Key key, List * plst, int(*Compare)(Key,Key)) 128: { 129: Position pos; 130: Position posReturn=NOT_FOUND;

Copyright © 2001 Dan Leach 87

131: ListEntry leTry; 132: 133: for ( 134: pos=0; 135: !GetError() && pos<ListSize(plst) && posReturn==NOT_FOUND; 136: pos++ 137: ) 138: { 139: RetrieveList(plst,pos,&leTry); 140: if (!GetError() && Compare(key,leTry->m_key)) 141: posReturn=pos; 142: } 143: 144: return posReturn; 145: } 146: 147: // add entry to hash table 148: void InsertHashTable(HashTable * pht, Key key, Data data) 149: { 150: int i; 151: TableEntry * pte; 152: 153: i=pht->m_pfHash(key); 154: i=i%pht->m_iTableSize; 155: 156: if ( 157: LocateKey( 158: key, 159: pht->m_pplstHashTable[i], 160: pht->m_pfCompare 161: ) 162: == 163: NOT_FOUND 164: ) 165: { 166: pte=(TableEntry*)calloc(1,sizeof(TableEntry)); 167: if (pte!=NULL) 168: { 169: pte->m_key=key; 170: pte->m_data=data; 171: 172: InsertList( 173: pht->m_pplstHashTable[i], 174: 0, 175: pte 176: ); 177: 178: pht->m_iNumberOfEntries++; 179: } 180: else 181: Error("table full"); 182: } 183: } 184: 185: // print an entry 186: void PrintTableEntry(TableEntry * te)

Copyright © 2001 Dan Leach 88

187: { 188: printf("key=%s data=%s ", te->m_key, te->m_data); 189: } 190: 191: // print the row 192: void PrintRow (List * plst) 193: { 194: TraverseList(plst,PrintTableEntry); 195: puts(""); 196: } 197: 198: // print the hash table 199: void PrintHashTable(HashTable * pht) 200: { 201: int i; 202: printf( 203: "number of entries=%d\n", 204: HashTableNumberOfEntries(pht) 205: ); 206: printf("(START HASH TABLE)\n"); 207: for (i=0; i<pht->m_iTableSize; i++) 208: { 209: if (!ListEmpty(pht->m_pplstHashTable[i])) 210: { 211: printf( 212: "%d(%d): ", 213: i, 214: ListSize(pht->m_pplstHashTable[i]) 215: ); 216: PrintRow(pht->m_pplstHashTable[i]); 217: } 218: } 219: printf("(END HASH TABLE)\n"); 220: } 221: 222: // remove an entry 223: void DeleteHashTable(HashTable * pht, Key key, Data * pdata) 224: { 225: int i; 226: TableEntry * pte; 227: Position pos; 228: 229: *pdata=NULL; 230: 231: i=pht->m_pfHash(key); 232: i=i%pht->m_iTableSize; 233: 234: pos = LocateKey( 235: key, 236: pht->m_pplstHashTable[i], 237: pht->m_pfCompare 238: ); 239: 240: if (pos != NOT_FOUND) 241: { 242: DeleteList(

Copyright © 2001 Dan Leach 89

243: pht->m_pplstHashTable[i], 244: pos, 245: &pte 246: ); 247: *pdata=pte->m_data; 248: free(pte->m_key); 249: free(pte); 250: pht->m_iNumberOfEntries--; 251: } 252: } 253: 254: // retrieve an entry 255: void RetrieveHashTable(HashTable * pht, Key key, Data * pdata) 256: { 257: int i; 258: TableEntry * pte; 259: Position pos; 260: 261: *pdata=NULL; 262: 263: i=pht->m_pfHash(key); 264: i=i%pht->m_iTableSize; 265: 266: pos = LocateKey( 267: key, 268: pht->m_pplstHashTable[i], 269: pht->m_pfCompare 270: ); 271: 272: if (pos != NOT_FOUND) 273: { 274: RetrieveList( 275: pht->m_pplstHashTable[i], 276: pos, 277: &pte 278: ); 279: *pdata=pte->m_data; 280: } 281: } 282: 283: // replace an entry 284: void ReplaceHashTable(HashTable * pht, Key key, Data data, Data * pdata) 285: { 286: int i; 287: TableEntry * pte; 288: Position pos; 289: 290: *pdata=NULL; 291: 292: i=pht->m_pfHash(key); 293: i=i%pht->m_iTableSize; 294: 295: pos = LocateKey( 296: key, 297: pht->m_pplstHashTable[i], 298: pht->m_pfCompare

Copyright © 2001 Dan Leach 90

299: ); 300: 301: if (pos != NOT_FOUND) 302: { 303: RetrieveList( 304: pht->m_pplstHashTable[i], 305: pos, 306: &pte 307: ); 308: *pdata=pte->m_data; 309: pte->m_data=data; 310: } 311: } 312: 313: // traverse the hash table 314: void TraverseHashTable(HashTable * pht, void(*Visit)(TableEntry*)) 315: { 316: int i; 317: for (i=0; i<pht->m_iTableSize; i++) 318: TraverseList(pht->m_pplstHashTable[i],Visit); 319: }

1.16.4 testhash.c 1: // testhash.c 2: // test program for hash table 3: 4: #include <stdio.h> 5:#include <stdlib.h> 6:#include <string.h> 7:#include <ctype.h> 8:#include "hasht.h" 9: #include "error.h" 10: 11: // definition of return codes 12: typedef enum 13: { 14: RC_SUCCESS=0, 15: RC_SURPRISE, 16: RC_ERROR 17: } ReturnCode; 18: 19: // definition of command line arguments 20: typedef enum 21: { 22: CLA_PROGRAM_NAME=0, 23: CLA_ADD, 24: CLA_DELETE, 25: CLA_REPLACE 26: } CommandLineArguments; 27: 28: #define MAX_LINE 200 29: #define TABLE_SIZE 100 30: 31: int MyHash(Key key) 32: {

Copyright © 2001 Dan Leach 91

33: int i; 34: int iHash=key[0]; 35: for (i=0;i<strlen(key);i++) 36: iHash+=key[i]; 37: iHash*=iHash; 38: iHash/=100; 39: iHash%=1000; 40: return iHash; 41: } 42: 43: Boolean MyCompare(Key key1, Key key2) 44: { 45: return stricmp(key1, key2)==0; 46: } 47: 48: void Extract(char szLine[], Key * pkey, Data * pdata) 49: { 50: char szKey [MAX_LINE]; 51: char szData [MAX_LINE]; 52: int i; 53: 54: *pkey=NULL; 55: *pdata=NULL; 56: 57: // trim white space from end of line 58: szLine[strlen(szLine)-1]='\0'; 59: while (isspace(szLine[strlen(szLine)-1])) 60: szLine[strlen(szLine)-1]='\0'; 61: 62: if (strchr(szLine,',')!=NULL) 63: { 64: // extract key (name up to ',') 65: for (i=0; szLine[i]!=','; i++) 66: szKey[i]=szLine[i]; 67: szKey[i]='\0'; 68: 69: // extract data 70: strcpy(szData,strchr(szLine,',')+1); 71: 72: *pkey = (Key) calloc( 73: 1, 74: strlen(szKey)+1 75: ); 76: 77: *pdata = (Data) calloc( 78: 1, 79: strlen(szData)+1 80: ); 81: 82: if ((pkey!=NULL) && (pdata!=NULL)) 83: { 84: strcpy(*pkey,szKey); 85: strcpy(*pdata,szData); 86: } 87: else 88: Error("No space for new data.");

Copyright © 2001 Dan Leach 92

89: } 90: } 91: 92: // main program 93: ReturnCode main( 94: unsigned int uiArgumentCount, 95: char * szArguments[] 96: ) 97: { 98: ReturnCode rc=RC_SUCCESS; 99: FILE * pfsIn=NULL; 100: char szLine [MAX_LINE]; 101: Key key; 102: Data data; 103: HashTable * pht=NULL; 104: 105: // too many args 106: if (uiArgumentCount!=4) 107: { 108: fprintf( 109: stderr, 110: "usage: %s names-to-add names-to-delete " 111: "names-to-replace\n", 112: szArguments[CLA_PROGRAM_NAME] 113: ); 114: rc=RC_ERROR; 115: } 116: 117: // setup table 118: if (rc==RC_SUCCESS) 119: { 120: pfsIn=fopen(szArguments[CLA_ADD],"r"); 121: if(pfsIn==NULL) 122: { 123: fprintf( 124: stderr, 125: "can't open %s for read\n", 126: szArguments[CLA_ADD] 127: ); 128: rc=RC_ERROR; 129: } 130: } 131: 132: if (rc==RC_SUCCESS) 133: { 134: pht = CreateHashTable(TABLE_SIZE,MyHash,MyCompare); 135: while ( 136: !GetError() && 137: fgets(szLine, sizeof(szLine), pfsIn) 138: ) 139: { 140: if (strchr(szLine,',')!=NULL) 141: { 142: Extract(szLine,&key,&data); 143: 144: if ((key!=NULL) && (data!=NULL))

Copyright © 2001 Dan Leach 93

145: InsertHashTable(pht, key, data); 146: } 147: 148: if (GetError()) 149: rc=RC_ERROR; 150: } 151: fclose(pfsIn); 152: 153: if (!GetError()) 154: { 155: puts("initial table:"); 156: PrintHashTable(pht); 157: puts(""); 158: } 159: } 160: 161: // remove some entries from table 162: if (rc==RC_SUCCESS) 163: { 164: pfsIn=fopen(szArguments[CLA_DELETE],"r"); 165: if(pfsIn==NULL) 166: { 167: fprintf( 168: stderr, 169: "can't open %s for read\n", 170: szArguments[CLA_DELETE] 171: ); 172: rc=RC_ERROR; 173: } 174: } 175: 176: if (rc==RC_SUCCESS) 177: { 178: while ( 179: !GetError() && 180: fgets(szLine, sizeof(szLine), pfsIn) 181: ) 182: { 183: if (strchr(szLine,',')!=NULL) 184: { 185: Extract(szLine,&key,&data); 186: 187: if ((key!=NULL) && (data!=NULL)) 188: { 189: free(data); 190: DeleteHashTable(pht, key, &data); 191: free(data); 192: } 193: } 194: 195: if (GetError()) 196: rc=RC_ERROR; 197: } 198: fclose(pfsIn); 199: 200: if (!GetError())

Copyright © 2001 Dan Leach 94

201: { 202: puts("table with some entries removed:"); 203: PrintHashTable(pht); 204: puts(""); 205: } 206: } 207: 208: // replace first names for some entries in table 209: if (rc==RC_SUCCESS) 210: { 211: pfsIn=fopen(szArguments[CLA_REPLACE],"r"); 212: if(pfsIn==NULL) 213: { 214: fprintf( 215: stderr, 216: "can't open %s for read\n", 217: szArguments[CLA_REPLACE] 218: ); 219: rc=RC_ERROR; 220: } 221: } 222: 223: if (rc==RC_SUCCESS) 224: { 225: while ( 226: !GetError() && 227: fgets(szLine, sizeof(szLine), pfsIn) 228: ) 229: { 230: if (strchr(szLine,',')!=NULL) 231: { 232: Extract(szLine,&key,&data); 233: 234: if ((key!=NULL) && (data!=NULL)) 235: { 236: Data data2; 237: ReplaceHashTable( 238: pht, 239: key, 240: data, 241: &data2 242: ); 243: free(data2); 244: } 245: } 246: 247: if (GetError()) 248: rc=RC_ERROR; 249: } 250: fclose(pfsIn); 251: 252: if (!GetError()) 253: { 254: puts("table with some entries changed:"); 255: PrintHashTable(pht); 256: }

Copyright © 2001 Dan Leach 95

257: } 258: 259: if (pht!=NULL) 260: DestroyHashTable(pht); 261: 262: return rc; 263: }

1.16.5 testhash.out 1: initial table: 2: number of entries=29 3: (START HASH TABLE) 4: 1(1): key=Mendelson data=Isaac 5: 8(1): key=Hennessy data=Jason 6: 23(1): key=Townsend data=Mark 7: 28(1): key=Zhang data=Hwi 8: 36(2): key=Presayzen data=Grigory key=Adams data=Michael 9: 40(2): key=Matar data=Roger key=Hayes data=Gregory 10: 44(1): key=Mittal data=Alka 11: 46(3): key=Qian data=Jianhua key=Kuan data=Yun key=Ababneh data=Zaid 12: 49(1): key=James data=Thomas 13: 52(2): key=Kraft data=Christopher key=Grant data=Catherine 14: 57(1): key=Gattu data=Malini 15: 61(1): key=Stahan data=Jaedra 16: 68(1): key=Devulapalli data=Himabindu 17: 70(1): key=Yu data=Phillip 18: 72(2): key=Mullen data=Edward key=Lovell data=Roger 19: 77(1): key=Trivedi data=Purvi 20: 80(2): key=Harnavanich data=Oranuj key=Chan data=Jennifer 21: 81(1): key=Ko data=Young 22: 83(1): key=Morris data=Steve 23: 85(1): key=Krishnamurthy data=Shubha 24: 89(1): key=Yao data=Qin 25: 93(1): key=Raymond data=Frank 26: (END HASH TABLE) 27: 28: table with some entries removed: 29: number of entries=17 30: (START HASH TABLE) 31: 23(1): key=Townsend data=Mark 32: 28(1): key=Zhang data=Hwi 33: 36(1): key=Presayzen data=Grigory 34: 44(1): key=Mittal data=Alka 35: 46(1): key=Qian data=Jianhua 36: 49(1): key=James data=Thomas 37: 57(1): key=Gattu data=Malini 38: 61(1): key=Stahan data=Jaedra 39: 68(1): key=Devulapalli data=Himabindu 40: 70(1): key=Yu data=Phillip 41: 72(1): key=Lovell data=Roger 42: 77(1): key=Trivedi data=Purvi 43: 80(1): key=Chan data=Jennifer 44: 81(1): key=Ko data=Young 45: 85(1): key=Krishnamurthy data=Shubha 46: 89(1): key=Yao data=Qin

Copyright © 2001 Dan Leach 96

47: 93(1): key=Raymond data=Frank 48: (END HASH TABLE) 49: 50: table with some entries changed: 51: number of entries=17 52: (START HASH TABLE) 53: 23(1): key=Townsend data=Mark 54: 28(1): key=Zhang data=Audrey 55: 36(1): key=Presayzen data=Greg 56: 44(1): key=Mittal data=Alka 57: 46(1): key=Qian data=Jane 58: 49(1): key=James data=Tom 59: 57(1): key=Gattu data=Malini 60: 61(1): key=Stahan data=Jaedra 61: 68(1): key=Devulapalli data=Hima 62: 70(1): key=Yu data=Phil 63: 72(1): key=Lovell data=Roger 64: 77(1): key=Trivedi data=Purvi 65: 80(1): key=Chan data=Jenn 66: 81(1): key=Ko data=Young 67: 85(1): key=Krishnamurthy data=Shubha 68: 89(1): key=Yao data=Qin 69: 93(1): key=Raymond data=Frank 70: (END HASH TABLE)

1.16.6 names.txt 1:Ababneh,Zaid 2:Adams,Michael 3:Chan,Jennifer 4:Devulapalli,Himabindu 5:Gattu,Malini 6:Grant,Catherine 7:Harnavanich,Oranuj 8:Hayes,Gregory 9:Hennessy,Jason 10: James,Thomas 11: Ko,Young 12: Kraft,Christopher 13: Krishnamurthy,Shubha 14: Kuan,Yun 15: Lovell,Roger 16: Matar,Roger 17: Mendelson,Isaac 18: Mittal,Alka 19: Morris,Steve 20: Mullen,Edward 21: Presayzen,Grigory 22: Qian,Jianhua 23: Raymond,Frank 24: Stahan,Jaedra 25: Townsend,Mark 26: Trivedi,Purvi 27: Yao,Qin 28: Yu,Phillip 29: Zhang,Hwi

Copyright © 2001 Dan Leach 97

1.16.7 delete.txt 1: Ababneh,Zaid 2: Adams,Michael 3: Grant,Catherine 4: Harnavanich,Oranuj 5: Hayes,Gregory 6: Hennessy,Jason 7: Kraft,Christopher 8: Kuan,Yun 9: Matar,Roger 10: Mendelson,Isaac 11: Morris,Steve 12: Mullen,Edward

1.16.8 replace.txt 1:Chan,Jenn 2:Devulapalli,Hima 3: James,Tom 4:Ko,Young 5:Presayzen,Greg 6:Qian,Jane 7:Raymond,Frank 8:Yu,Phil 9:Zhang,Audrey

1.16.9 bldthd.bat 1: cl /DPDLIST /Fethd.exe testhash.c hasht.c pdlist.c error.c

1.16.10 bldths.bat 1: cl /DPSLIST /Feths.exe testhash.c hasht.c pslist.c error.c

Copyright © 2001 Dan Leach 98

1.17 Binary Trees

1.17.1 tree.h 1: // tree.h 2: // interface to binary tree data structure 3: // Dan Leach 4: 5: #pragma once 6:#include "stddef.h" 7: 8: typedef char * TreeEntry; 9: 10: typedef struct tree 11: { 12: TreeEntry m_te; 13: struct tree * m_ptreeLeft; 14: struct tree * m_ptreeRight; 15: } Tree; 16: 17: Tree * MakeTreeNode (TreeEntry te); 18: Tree * TreeCreate(); 19: Boolean TreeEmpty(Tree * ptree); 20: Tree * TreeLeft(Tree * ptree); 21: Tree * TreeRight(Tree * ptree); 22: Boolean TreeLeaf(Tree * ptree); 23: TreeEntry TreeRetrieve(Tree * ptree); 24: void TreeJoinLeft(Tree * ptree, Tree * ptreeLeft); 25: void TreeJoinRight(Tree * ptree, Tree * ptreeRight); 26: void TreeDestroy(Tree * ptree); 27: void TraverseTreePreOrder(Tree * ptree, void(*Visit)(TreeEntry)); 28: void TraverseTreeInOrder(Tree * ptree, void(*Visit)(TreeEntry)); 29: void TraverseTreePostOrder(Tree * ptree, void(*Visit)(TreeEntry));

1.17.2 tree.c 1: // tree.c 2: // implementation file for tree data structure 3: // Dan Leach 4: 5: #include <stdio.h> 6:#include <stdlib.h> 7:#include <string.h> 8:#include "error.h" 9: #include "tree.h" 10: 11: // make a tree node 12: Tree * MakeTreeNode (TreeEntry te) 13: { 14: Tree * ptree = (Tree *)calloc(sizeof(Tree),1); 15: 16: if (ptree!=NULL) 17: { 18: ptree->m_te=te;

Copyright © 2001 Dan Leach 99

19: ptree->m_ptreeLeft=NULL; 20: ptree->m_ptreeRight=NULL; 21: } 22: else 23: Error("No space for additional tree node can be obtainted"); 24: 25: return ptree; 26: } 27: 28: // create an empty tree 29: Tree * TreeCreate() 30: { 31: return NULL; 32: } 33: 34: // return if the tree is empty 35: Boolean TreeEmpty(Tree * ptree) 36: { 37: return (ptree==NULL); 38: } 39: 40: // return the left side of a binary tree 41: Tree * TreeLeft(Tree * ptree) 42: { 43: return ptree->m_ptreeLeft; 44: } 45: 46: // return the right side of a binary tree 47: Tree * TreeRight(Tree * ptree) 48: { 49: return ptree->m_ptreeRight; 50: } 51: 52: // return if a node is a leaf 53: Boolean TreeLeaf(Tree * ptree) 54: { 55: if (!TreeEmpty(ptree)) 56: return TreeEmpty(TreeLeft(ptree)) && 57: TreeEmpty(TreeRight(ptree)); 58: else 59: { 60: Error("Attempt to check if TreeEmpty tree is leaf\n"); 61: return false; 62: } 63: } 64: 65: // return the information in binary tree node 66: TreeEntry TreeRetrieve(Tree * ptree) 67: { 68: if (!TreeEmpty(ptree)) 69: return ptree->m_te; 70: else 71: { 72: Error("Attempt to get retrieve from an empty tree\n"); 73: return 0; 74: }

Copyright © 2001 Dan Leach 100

75: } 76: 77: // set the left side of a binary tree 78: void TreeJoinLeft(Tree * ptree, Tree * ptreeLeft) 79: { 80: ptree->m_ptreeLeft=ptreeLeft; 81: } 82: 83: // set the right side of a binary tree 84: void TreeJoinRight(Tree * ptree, Tree * ptreeRight) 85: { 86: ptree->m_ptreeRight=ptreeRight; 87: } 88: 89: // destroy a binary tree and return storage to system 90: void TreeDestroy(Tree * ptree) 91: { 92: if (!TreeEmpty(ptree)) 93: { 94: TreeDestroy(TreeLeft(ptree)); 95: TreeDestroy(TreeRight(ptree)); 96: free(ptree); 97: } 98: } 99: 100: // traverse a tree in preorder 101: void TraverseTreePreOrder(Tree * ptree, void(*Visit)(TreeEntry)) 102: { 103: if (!TreeEmpty(ptree)) 104: { 105: Visit(TreeRetrieve(ptree)); 106: TraverseTreePreOrder(TreeLeft(ptree), Visit); 107: TraverseTreePreOrder(TreeRight(ptree), Visit); 108: } 109: } 110: 111: // traverse a tree in inorder 112: void TraverseTreeInOrder(Tree * ptree, void(*Visit)(TreeEntry)) 113: { 114: if (!TreeEmpty(ptree)) 115: { 116: TraverseTreeInOrder(TreeLeft(ptree), Visit); 117: Visit(TreeRetrieve(ptree)); 118: TraverseTreeInOrder(TreeRight(ptree), Visit); 119: } 120: } 121: 122: // traverse a tree in postorder 123: void TraverseTreePostOrder(Tree * ptree, void(*Visit)(TreeEntry)) 124: { 125: if (!TreeEmpty(ptree)) 126: { 127: TraverseTreePostOrder(TreeLeft(ptree), Visit); 128: TraverseTreePostOrder(TreeRight(ptree), Visit); 129: Visit(TreeRetrieve(ptree)); 130: }

Copyright © 2001 Dan Leach 101

131: }

1.17.3 treesort.c 1: // treesort.c 2: // main program and supporting routines for hw5 3: // Dan Leach 4: 5: #include <stdio.h> 6:#include <stdlib.h> 7:#include <string.h> 8:#include "error.h" 9: #include "tree.h" 10: #include <ctype.h> 11: 12: // add one node to the sort tree 13: Tree * InsertTree( 14: Tree * ptree, 15: Tree * ptreeNew, 16: int (*Compare)(TreeEntry, TreeEntry) 17: ) 18: { 19: if (TreeEmpty(ptree)) 20: ptree=ptreeNew; 21: 22: else if (Compare(TreeRetrieve(ptreeNew),TreeRetrieve(ptree))) 23: { 24: TreeJoinLeft( 25: ptree, 26: InsertTree(ptree->m_ptreeLeft, ptreeNew, Compare) 27: ); 28: } 29: else 30: { 31: TreeJoinRight( 32: ptree, 33: InsertTree(ptree->m_ptreeRight, ptreeNew, Compare) 34: ); 35: } 36: 37: return ptree; 38: } 39: 40: // build a sorted binary tree from a set of tokens 41: Tree * TreeBuild(char * szLine, int (*Compare)(TreeEntry, TreeEntry)) 42: { 43: char * szToken=NULL; 44: TreeEntry te; 45: Tree * ptree=NULL; 46: Tree * ptreeNew=NULL; 47: 48: szToken=strtok(szLine," "); 49: while (szToken!=NULL) 50: { 51: te=(TreeEntry)calloc(1,strlen(szToken)+1); 52: strcpy(te,szToken);

Copyright © 2001 Dan Leach 102

53: ptreeNew=MakeTreeNode(te); 54: ptree=InsertTree(ptree,ptreeNew,Compare); 55: szToken=strtok(NULL, " "); 56: } 57: 58: return ptree; 59: } 60: 61: // definition of return codes 62: typedef enum 63: { 64: RC_SUCCESS=0, 65: RC_SURPRISE, 66: RC_ERROR 67: } ReturnCode; 68: 69: // definition of command line arguments 70: typedef enum 71: { 72: CLA_PROGRAM_NAME=0, 73: CLA_INPUT_FILE_NAME 74: } CommandLineArguments; 75: 76: #define MAX_LINE 200 77: 78: // print one entry 79: void PrintTreeEntry(TreeEntry te) 80: { 81: printf("%s ",te); 82: } 83: 84: // sort the tokens in szLine based on Compare 85: void TreeSort(char * szLine, int (*Compare)(TreeEntry, TreeEntry)) 86: { 87: Tree * ptree = TreeBuild(szLine, Compare); 88: TraverseTreeInOrder(ptree,PrintTreeEntry); 89: TraverseTreePostOrder(ptree,free); 90: TreeDestroy(ptree); 91: } 92: 93: // return true if te1 is greater than te2 94: int Greater(TreeEntry te1, TreeEntry te2) 95: { 96: return stricmp(te1,te2)>0; 97: } 98: 99: // return true if te1 is less than te2 100: int Lesser(TreeEntry te1, TreeEntry te2) 101: { 102: return stricmp(te1,te2)<0; 103: } 104: 105: // main program 106: ReturnCode main( 107: unsigned int uiArgumentCount, 108: char * szArguments[]

Copyright © 2001 Dan Leach 103

109: ) 110: { 111: ReturnCode rc=RC_SUCCESS; 112: FILE * pfsIn=NULL; 113: char szLine [MAX_LINE]; 114: char szLine1 [MAX_LINE]; 115: Tree * ptree=NULL; 116: 117: // too many args 118: if (uiArgumentCount>2) 119: { 120: fprintf( 121: stderr, 122: "usage: %s [filename]\n", 123: szArguments[CLA_PROGRAM_NAME] 124: ); 125: rc=RC_ERROR; 126: } 127: 128: // use input file 129: else if (uiArgumentCount==2) 130: { 131: pfsIn=fopen(szArguments[CLA_INPUT_FILE_NAME],"r"); 132: if(pfsIn==NULL) 133: { 134: fprintf( 135: stderr, 136: "can't open %s for read\n", 137: szArguments[CLA_INPUT_FILE_NAME] 138: ); 139: rc=RC_ERROR; 140: } 141: } 142: 143: // use stdin 144: else 145: pfsIn=stdin; 146: 147: if (rc==RC_SUCCESS) 148: { 149: while ( 150: !GetError() && 151: fgets(szLine, sizeof(szLine), pfsIn) 152: ) 153: { 154: // trim ws 155: szLine[strlen(szLine)-1]='\0'; 156: while (isspace(szLine[strlen(szLine)-1])) 157: szLine[strlen(szLine)-1]='\0'; 158: 159: printf("processing line:\n%s\n", szLine); 160: 161: strcpy(szLine1,szLine); 162: 163: // print and sort 164: if(strlen(szLine)!=0)

Copyright © 2001 Dan Leach 104

165: { 166: printf("sorted in order:\n"); 167: TreeSort(szLine,Lesser); 168: puts(""); 169: printf("sorted in reverse order:\n"); 170: TreeSort(szLine1,Greater); 171: puts(""); 172: puts(""); 173: } 174: } 175: } 176: 177: if (pfsIn!=NULL) 178: fclose(pfsIn); 179: return rc; 180: } 181: /* 182: input file: 183: aardvark A effective Easy Good great best 184: Danny Nisey Tina Debbie Ricky Jimmy 185: less-than greater-than equal-to 186: 187: results in the following output: 188: processing line: 189: aardvark A effective Easy Good great best 190: sorted in order: 191: A aardvark best Easy effective Good great 192: sorted in reverse order: 193: great Good effective Easy best aardvark A 194: 195: processing line: 196: Danny Nisey Tina Debbie Ricky Jimmy 197: sorted in order: 198: Danny Debbie Jimmy Nisey Ricky Tina 199: sorted in reverse order: 200: Tina Ricky Nisey Jimmy Debbie Danny 201: 202: processing line: 203: less-than greater-than equal-to 204: sorted in order: 205: equal-to greater-than less-than 206: sorted in reverse order: 207: less-than greater-than equal-to 208: 209: */

Copyright © 2001 Dan Leach 105

1.18 GraphsGraphs are generalized branching data structures.

1.18.1 graph.h 1: // graph.h 2: // interface to Graph data structure 3: 4: #pragma once 5:#include "stddef.h" 6: #include "list.h" 7: 8: typedef char * VertexName; 9: typedef int Weight; 10: typedef List VertexList; 11: typedef List EdgeList; 12: 13: typedef struct 14: { 15: VertexName m_vn; 16: Boolean m_bVisited; 17: EdgeList * m_pelstEdge; 18: } Vertex; 19: 20: typedef struct 21: { 22: Vertex * m_pv; 23: Weight m_w; 24: } Edge; 25: 26: typedef struct 27: { 28: Boolean m_bDirected; 29: Boolean(*m_pfSameName)(VertexName,VertexName); 30: VertexList * m_pvlstVertex; 31: } Graph; 32: 33: // graph functions 34: Graph * GraphCreate 35: ( 36: Boolean bDirected, 37: Boolean(*SameName)(VertexName,VertexName) 38: ); 39: void GraphDestroy(Graph * pg); 40: void GraphAddVertex(Graph * pg, const VertexName vn); 41: void GraphRemoveVertex(Graph * pg, const VertexName vn, Vertex ** ppv); 42: void GraphJoin( 43: Graph * pg, 44: const VertexName vn1, 45: const VertexName vn2 46: ); 47: void GraphJoinWeight( 48: Graph * pg, 49: const VertexName vn1,

Copyright © 2001 Dan Leach 106

50: const VertexName vn2, 51: Weight w 52: ); 53: void GraphBreak( 54: Graph * pg, 55: const VertexName vn1, 56: const VertexName vn2 57: ); 58: void GraphResetVertexes(Graph * pg); 59: void GraphTraverseDepthFirst(Graph * pg, void(*Visit)(Vertex*)); 60: 61: void GraphPrint 62: ( 63: const Graph * pg, 64: const char * szFormatVertex, 65: const char * szFormatWeight 66: ); 67: Boolean GraphAdjacent( 68: const Graph * pg, 69: const VertexName vn1, 70: const VertexName vn2 71: ); 72: Weight GraphWeight( 73: const Graph * pg, 74: const VertexName vn1, 75: const VertexName vn2 76: ); 77: Vertex * GraphFind( 78: const Graph * pg, 79: const VertexName vn 80: ); 81: VertexList * GraphVertexList(const Graph * pg); 82: Boolean GraphEmpty(const Graph * pg); 83: int GraphNumberOfVertexes(const Graph * pg); 84: 85: // vertex functions 86: void VertexSetEdgeList(Vertex * pv, EdgeList * pelst); 87: void VertexSetVertexName(Vertex * pv, VertexName vn); 88: void VertexSetVisited(Vertex * pv, Boolean bVisited); 89: 90: EdgeList * VertexEdgeList(const Vertex * pv); 91: VertexName VertexVertexName(const Vertex * pv); 92: Boolean VertexVisited(const Vertex * pv); 93: 94: // edge functions 95: void EdgeSetWeight(Edge * pe, Weight w); 96: void EdgeSetVertex(Edge * pe, Vertex * pv); 97: void EdgeAdd(Vertex * pv1, Vertex * pv2, Weight w); 98: 99: Weight EdgeWeight(const Edge * pe); 100: Vertex * EdgeVertex(const Edge * pe);

1.18.2 graph.c 1: // graph.c 2: // implementation of Graph data structure

Copyright © 2001 Dan Leach 107

3: 4: #include "error.h" 5: #include "graph.h" 6:#include <stdio.h> 7:#include <stdlib.h> 8:#include <string.h> 9: 10: // create the graph 11: Graph * GraphCreate 12: ( 13: Boolean bDirected, 14: Boolean(*SameName)(VertexName,VertexName) 15: ) 16: { 17: Graph * pg=(Graph *)calloc(1,sizeof(Graph)); 18: if (pg!=NULL) 19: { 20: pg->m_bDirected=bDirected; 21: pg->m_pfSameName=SameName; 22: pg->m_pvlstVertex=CreateList(); 23: if(GetError()) 24: { 25: Error("Error while creating vertex list"); 26: free(pg); 27: pg=NULL; 28: } 29: } 30: else 31: Error("No space for graph can be obtained"); 32: 33: return pg; 34: } 35: 36: // destroy the graph 37: void GraphDestroy(Graph * pg) 38: { 39: Vertex * pv; 40: VertexList * pvlst = GraphVertexList(pg); 41: Edge * pe; 42: EdgeList * pelst; 43: 44: while (ListSize(pvlst)>0) 45: { 46: DeleteList(pvlst, 0, (int *)&pv); 47: pelst=VertexEdgeList(pv); 48: while (ListSize(pelst)>0) 49: { 50: DeleteList(pelst,0,(int *)&pe); 51: free(pe); 52: } 53: DestroyList(pelst); 54: free(pv); 55: } 56: 57: DestroyList(pvlst); 58: free(pg);

Copyright © 2001 Dan Leach 108

59: } 60: 61: // find vertex from name and set location 62: static Vertex * GraphFindWithLocation( 63: const Graph * pg, 64: const VertexName vn, 65: int * piLocation 66: ) 67: { 68: Vertex * pvReturn=NULL; 69: Vertex * pv; 70: int i; 71: VertexList * pvlst = GraphVertexList(pg); 72: int iSize=ListSize(pvlst); 73: 74: *piLocation=-1; 75: 76: for (i=0;i<iSize;i++) 77: { 78: RetrieveList(pvlst,i,(int *)&pv); 79: if (pg->m_pfSameName(vn,VertexVertexName(pv))) 80: { 81: pvReturn=pv; 82: *piLocation=i; 83: break; 84: } 85: } 86: 87: return pvReturn; 88: } 89: 90: // find vertex from name 91: Vertex * GraphFind( 92: const Graph * pg, 93: const VertexName vn 94: ) 95: { 96: int iLocation; 97: return GraphFindWithLocation(pg,vn,&iLocation); 98: } 99: 100: // add a vertex to the graph 101: void GraphAddVertex(Graph * pg, const VertexName vn) 102: { 103: Vertex * pv=GraphFind(pg,vn); 104: 105: if (pv!=NULL) 106: Error("Vertex already in graph."); 107: else 108: { 109: pv=(Vertex *)calloc(1,sizeof(Vertex)); 110: 111: if (pv!=NULL) 112: { 113: VertexList * pvlst=GraphVertexList(pg); 114: VertexSetVertexName(pv,vn);

Copyright © 2001 Dan Leach 109

115: VertexSetEdgeList(pv,CreateList()); 116: VertexSetVisited(pv,false); 117: InsertList( 118: pvlst, 119: ListSize(pvlst), 120: (int)pv 121: ); 122: } 123: else 124: Error("No space for vertex."); 125: } 126: } 127: 128: // remove an edge 129: void EdgeDelete 130: ( 131: Vertex * pv1, 132: Vertex * pv2 133: ) 134: { 135: int i; 136: Edge * pe; 137: EdgeList * pelst=VertexEdgeList(pv1); 138: int iSize=ListSize(pelst); 139: 140: for(i=0;i<iSize;i++) 141: { 142: RetrieveList(pelst,i,(int *)&pe); 143: if (EdgeVertex(pe)==pv2) 144: { 145: DeleteList(pelst,i,(int *)&pe); 146: free(pe); 147: break; 148: } 149: } 150: } 151: 152: // remove a vertex (and all reference to it) from the graph 153: void GraphRemoveVertex(Graph * pg, const VertexName vn, Vertex ** ppv) 154: { 155: int i; 156: int iLocation=-1; 157: Vertex * pv; 158: VertexList * pvlst=GraphVertexList(pg); 159: int iSize=ListSize(pvlst); 160: EdgeList * pelst; 161: Edge * pe; 162: 163: // find vertex 164: *ppv=GraphFindWithLocation(pg,vn,&iLocation); 165: 166: // remove pointers to vertex 167: for (i=0;(*ppv!=NULL)&&(i<iSize);i++) 168: { 169: RetrieveList(pvlst,i,(int *)&pv); 170: EdgeDelete(pv,*ppv);

Copyright © 2001 Dan Leach 110

171: } 172: 173: // remove vertex 174: if (*ppv!=NULL) 175: { 176: DeleteList(pvlst,iLocation,(int *)&pv); 177: 178: // remove edges 179: pelst=VertexEdgeList(*ppv); 180: while (ListSize(pelst)>0) 181: { 182: DeleteList(pelst,0,(int *)&pe); 183: free(pe); 184: } 185: DestroyList(pelst); 186: } 187: } 188: 189: // add an edge with a weight 190: void EdgeAdd 191: ( 192: Vertex * pv1, 193: Vertex * pv2, 194: Weight w 195: ) 196: { 197: Edge *pe=(Edge *)calloc(1,sizeof(Edge)); 198: EdgeList * pelst; 199: 200: if (pe!=NULL) 201: { 202: EdgeSetVertex(pe,pv2); 203: EdgeSetWeight(pe,w); 204: pelst=VertexEdgeList(pv1); 205: InsertList( 206: pelst, 207: ListSize(pelst), 208: (int)pe 209: ); 210: } 211: else 212: Error("Couldn't allocate edge."); 213: } 214: 215: // add an edge with a weight 216: void GraphJoinWeight( 217: Graph * pg, 218: const VertexName vn1, 219: const VertexName vn2, 220: Weight w 221: ) 222: { 223: Vertex * pv1=NULL; 224: Vertex * pv2=NULL; 225: 226: // find vertexes

Copyright © 2001 Dan Leach 111

227: pv1=GraphFind(pg,vn1); 228: pv2=GraphFind(pg,vn2); 229: 230: if (pv1==NULL) 231: Error("Couldn't find first vertex."); 232: 233: if (pv2==NULL) 234: Error("Couldn't find second vertex."); 235: 236: if ((pv1!=NULL) && (pv2!=NULL)) 237: { 238: EdgeAdd(pv1, pv2, w); 239: if (!pg->m_bDirected) 240: EdgeAdd(pv2, pv1, w); 241: } 242: } 243: 244: // add an edge with no weight 245: void GraphJoin( 246: Graph * pg, 247: const VertexName vn1, 248: const VertexName vn2 249: ) 250: { 251: GraphJoinWeight(pg, vn1, vn2, 0); 252: } 253: 254: // remove an edge 255: void GraphBreak( 256: Graph * pg, 257: const VertexName vn1, 258: const VertexName vn2 259: ) 260: { 261: Vertex * pv1=GraphFind(pg,vn1); 262: Vertex * pv2=GraphFind(pg,vn2); 263: 264: if (pv1==NULL) 265: Error("Couldn't find first vertex."); 266: 267: if (pv2==NULL) 268: Error("Couldn't find second vertex."); 269: 270: if ((pv1!=NULL) && (pv2!=NULL)) 271: { 272: EdgeDelete(pv1, pv2); 273: if (!pg->m_bDirected) 274: EdgeDelete(pv2, pv1); 275: } 276: } 277: 278: // reset visited to false for all vertexes 279: void GraphResetVertexes(Graph * pg) 280: { 281: Vertex * pv; 282: int i;

Copyright © 2001 Dan Leach 112

283: VertexList * pvlst = GraphVertexList(pg); 284: int iSize=ListSize(pvlst); 285: 286: for (i=0;i<iSize;i++) 287: { 288: RetrieveList(pvlst,i,(int *)&pv); 289: VertexSetVisited(pv,false); 290: } 291: } 292: 293: // return true if vn1 is adjacent to vn2 294: Boolean GraphAdjacent( 295: const Graph * pg, 296: const VertexName vn1, 297: const VertexName vn2 298: ) 299: { 300: Vertex * pv1=GraphFind(pg,vn1); 301: Vertex * pv2=GraphFind(pg,vn2); 302: Boolean bReturn=false; 303: 304: if (pv1==NULL) 305: Error("Couldn't find first vertex."); 306: 307: if (pv2==NULL) 308: Error("Couldn't find second vertex."); 309: 310: if ((pv1!=NULL) && (pv2!=NULL)) 311: { 312: int i; 313: Edge * pe; 314: EdgeList * pelst=VertexEdgeList(pv1); 315: int iSize=ListSize(pelst); 316: 317: for(i=0;i<iSize;i++) 318: { 319: RetrieveList(pelst,i,(int *)&pe); 320: if (EdgeVertex(pe)==pv2) 321: { 322: bReturn=true; 323: break; 324: } 325: } 326: } 327: 328: return bReturn; 329: } 330: 331: // return the weight of an edge 332: Weight GraphWeight( 333: const Graph * pg, 334: const VertexName vn1, 335: const VertexName vn2 336: ) 337: { 338: Vertex * pv1=GraphFind(pg,vn1);

Copyright © 2001 Dan Leach 113

339: Vertex * pv2=GraphFind(pg,vn2); 340: Weight wReturn=-1; 341: 342: if (pv1==NULL) 343: Error("Couldn't find first vertex."); 344: 345: if (pv2==NULL) 346: Error("Couldn't find second vertex."); 347: 348: if ((pv1!=NULL) && (pv2!=NULL)) 349: { 350: int i; 351: Edge * pe; 352: EdgeList * pelst=VertexEdgeList(pv1); 353: int iSize=ListSize(pelst); 354: 355: for(i=0;i<iSize;i++) 356: { 357: RetrieveList(pelst,i,(int *)&pe); 358: if (EdgeVertex(pe)==pv2) 359: { 360: wReturn=EdgeWeight(pe); 361: break; 362: } 363: } 364: } 365: 366: return wReturn; 367: } 368: 369: // depth first traversal from a vertex 370: void Traverse(Vertex * pv, void(*Visit)(Vertex *)) 371: { 372: int i; 373: Edge * pe; 374: EdgeList * pelst=VertexEdgeList(pv); 375: int iSize=ListSize(pelst); 376: 377: VertexSetVisited(pv,true); 378: Visit(pv); 379: 380: for(i=0;i<iSize;i++) 381: { 382: RetrieveList(pelst,i,(int *)&pe); 383: if (!VertexVisited(EdgeVertex(pe))) 384: Traverse(EdgeVertex(pe),Visit); 385: } 386: } 387: 388: // depth first 389: void GraphTraverseDepthFirst(Graph * pg, void(*Visit)(Vertex*)) 390: { 391: Vertex * pv; 392: int i; 393: VertexList * pvlst = GraphVertexList(pg); 394: int iSize=ListSize(pvlst);

Copyright © 2001 Dan Leach 114

395: 396: GraphResetVertexes(pg); 397: for (i=0;i<iSize;i++) 398: { 399: RetrieveList(pvlst,i,(int *)&pv); 400: if (!VertexVisited(pv)) 401: Traverse(pv,Visit); 402: } 403: } 404: 405: // print a vertex 406: void VertexPrint 407: ( 408: Vertex * pv, 409: const char * szFormatVertex, 410: const char * szFormatWeight 411: ) 412: { 413: int i; 414: Edge * pe; 415: EdgeList * pelst=VertexEdgeList(pv); 416: int iSize=ListSize(pelst); 417: 418: printf(szFormatVertex,VertexVertexName(pv)); 419: printf(": "); 420: for(i=0;i<iSize;i++) 421: { 422: RetrieveList(pelst,i,(int *)&pe); 423: printf(szFormatVertex, VertexVertexName(EdgeVertex(pe))); 424: if (szFormatWeight!=NULL) 425: printf(szFormatWeight, EdgeWeight(pe)); 426: printf(" "); 427: } 428: } 429: 430: // print the graph 431: void GraphPrint 432: ( 433: const Graph * pg, 434: const char * szFormatVertex, 435: const char * szFormatWeight 436: ) 437: { 438: Vertex * pv; 439: int i; 440: VertexList * pvlst = GraphVertexList(pg); 441: int iSize=ListSize(pvlst); 442: 443: for (i=0;i<iSize;i++) 444: { 445: RetrieveList(pvlst,i,(int *)&pv); 446: VertexPrint(pv, szFormatVertex, szFormatWeight); 447: puts(""); 448: } 449: } 450:

Copyright © 2001 Dan Leach 115

451: // return vertex list from graph 452: VertexList * GraphVertexList(const Graph * pg) 453: { 454: return pg->m_pvlstVertex; 455: } 456: 457: // return true if graph is empty; false, otherwise 458: Boolean GraphEmpty(const Graph * pg) 459: { 460: return GraphNumberOfVertexes(pg)==0; 461: } 462: 463: // return number of vertexes in graph 464: int GraphNumberOfVertexes(const Graph * pg) 465: { 466: return ListSize(pg->m_pvlstVertex); 467: } 468: 469: // set edge list in vertex 470: void VertexSetEdgeList(Vertex * pv, EdgeList * pelst) 471: { 472: pv->m_pelstEdge=pelst; 473: } 474: 475: // set name in vertex 476: void VertexSetVertexName(Vertex * pv, VertexName vn) 477: { 478: pv->m_vn=vn; 479: } 480: 481: // set visited in vertex 482: void VertexSetVisited(Vertex * pv, Boolean bVisited) 483: { 484: pv->m_bVisited=bVisited; 485: } 486: 487: // return edge list in vertex 488: EdgeList * VertexEdgeList(const Vertex * pv) 489: { 490: return pv->m_pelstEdge; 491: } 492: 493: // return vertex name in vertex 494: VertexName VertexVertexName(const Vertex * pv) 495: { 496: return pv->m_vn; 497: } 498: 499: // return visited in vertex 500: Boolean VertexVisited(const Vertex * pv) 501: { 502: return pv->m_bVisited; 503: } 504: 505: // set weight in an edge 506: void EdgeSetWeight(Edge * pe, Weight w)

Copyright © 2001 Dan Leach 116

507: { 508: pe->m_w=w; 509: } 510: 511: // set vertex in an edge 512: void EdgeSetVertex(Edge * pe, Vertex * pv) 513: { 514: pe->m_pv=pv; 515: } 516: 517: // return weight in an edge 518: Weight EdgeWeight(const Edge * pe) 519: { 520: return pe->m_w; 521: } 522: 523: // return vertex in an edge 524: Vertex * EdgeVertex(const Edge * pe) 525: { 526: return pe->m_pv; 527: }

1.18.3 graphtst.c 1: // graphtst.c 2: // test program for a graph 3: 4: #include "graph.h" 5:#include <string.h> 6:#include <stdio.h> 7: 8: int g_iOrder=0; 9: void Visit(Vertex * pv) 10: { 11: printf("%d:%s\n",++g_iOrder,VertexVertexName(pv)); 12: } 13: 14: // compare function 15: Boolean SameName(VertexName vn1, VertexName vn2) 16: { 17: return strcmp(vn1, vn2)==0; 18: } 19: 20: // main test procedure 21: void main() 22: { 23: int i; 24: 25: VertexName vn[9] = 26: {"A","B","C","D","E","F","G","H","I"}; 27: Graph * pg = GraphCreate(false, SameName); 28: 29: // build the set of nodes 30: for (i=0;i<sizeof(vn)/sizeof(VertexName);i++) 31: GraphAddVertex(pg,vn[i]); 32:

Copyright © 2001 Dan Leach 117

33: // join them 34: GraphJoinWeight(pg,"A","B",2); 35: GraphJoinWeight(pg,"A","F",9); 36: GraphJoinWeight(pg,"A","G",5); 37: 38: GraphJoinWeight(pg,"B","C",4); 39: GraphJoinWeight(pg,"B","G",6); 40: 41: GraphJoinWeight(pg,"C","D",2); 42: GraphJoinWeight(pg,"C","H",5); 43: 44: GraphJoinWeight(pg,"D","E",1); 45: GraphJoinWeight(pg,"D","H",1); 46: 47: GraphJoinWeight(pg,"E","F",6); 48: GraphJoinWeight(pg,"E","I",3); 49: 50: GraphJoinWeight(pg,"F","I",1); 51: 52: GraphJoinWeight(pg,"G","H",5); 53: GraphJoinWeight(pg,"G","I",2); 54: 55: GraphJoinWeight(pg,"I","H",4); 56: 57: // print it 58: printf("An undirected graph:\n"); 59: GraphPrint(pg, "%s", "(%d)"); 60: 61: puts(""); 62: 63: // traverse it 64: printf("this is the order of the depth first traversal\n"); 65: GraphTraverseDepthFirst(pg,Visit); 66: puts(""); 67: 68: GraphDestroy(pg); 69: pg = GraphCreate(true, SameName); 70: 71: // build the set of nodes 72: for (i=0;i<sizeof(vn)/sizeof(VertexName);i++) 73: GraphAddVertex(pg,vn[i]); 74: 75: // join them 76: GraphJoinWeight(pg,"A","B",2); 77: GraphJoinWeight(pg,"A","F",9); 78: GraphJoinWeight(pg,"A","G",5); 79: 80: GraphJoinWeight(pg,"B","C",4); 81: GraphJoinWeight(pg,"B","G",6); 82: 83: GraphJoinWeight(pg,"C","D",2); 84: GraphJoinWeight(pg,"C","H",5); 85: 86: GraphJoinWeight(pg,"D","E",1); 87: GraphJoinWeight(pg,"D","H",1); 88:

Copyright © 2001 Dan Leach 118

89: GraphJoinWeight(pg,"E","F",6); 90: GraphJoinWeight(pg,"E","I",3); 91: 92: GraphJoinWeight(pg,"F","I",1); 93: 94: GraphJoinWeight(pg,"G","H",5); 95: GraphJoinWeight(pg,"G","I",2); 96: 97: GraphJoinWeight(pg,"I","H",4); 98: 99: // print it 100: printf("A directed graph:\n"); 101: GraphPrint(pg, "%s", "(%d)"); 102: puts(""); 103: 104: // traverse it 105: printf("this is the order of the depth first traversal\n"); 106: g_iOrder=0; 107: GraphTraverseDepthFirst(pg,Visit); 108: puts(""); 109: 110: GraphDestroy(pg); 111: } 112: 113: /* 114: output: 115: 116: An undirected graph: 117: A: B(2) F(9) G(5) 118: B: A(2) C(4) G(6) 119: C: B(4) D(2) H(5) 120: D: C(2) E(1) H(1) 121: E: D(1) F(6) I(3) 122: F: A(9) E(6) I(1) 123: G: A(5) B(6) H(5) I(2) 124: H: C(5) D(1) G(5) I(4) 125: I: E(3) F(1) G(2) H(4) 126: 127: this is the order of the depth first traversal 128: 1:A 129: 2:B 130: 3:C 131: 4:D 132: 5:E 133: 6:F 134: 7:I 135: 8:G 136: 9:H 137: 138: A directed graph: 139: A: B(2) F(9) G(5) 140: B: C(4) G(6) 141: C: D(2) H(5) 142: D: E(1) H(1) 143: E: F(6) I(3) 144: F: I(1)

Copyright © 2001 Dan Leach 119

145: G: H(5) I(2) 146: H: 147: I: H(4) 148: 149: this is the order of the depth first traversal 150: 1:A 151: 2:B 152: 3:C 153: 4:D 154: 5:E 155: 6:F 156: 7:I 157: 8:H 158: 9:G 159: 160: */

1.18.4 build.bat 1: cl /W4 /DPDLIST graphtst.c graph.c pdlist.c error.c >build.out 2: emacs build.out

1.18.5 shortest.h 1: // shortest.h 2: // interface to shortest path 3: 4: #pragma once 5:#include "stddef.h" 6: #include "graph.h" 7: 8:Graph * ShortestPath 9: ( 10: const Graph * pg, 11: const VertexName vnStart, 12: const VertexName vnEnd, 13: Boolean(*SameName)(VertexName,VertexName) 14: );

1.18.6 shortest.c 1: // shortest.c 2: // implementation of shortest path 3: 4: #include "shortest.h" 5: #include "graph.h" 6:#include "list.h" 7: #include <stdio.h> 8: 9:Graph * ShortestPath 10: ( 11: const Graph * pg, 12: const VertexName vnStart, 13: const VertexName vnEnd, 14: Boolean(*SameName)(VertexName,VertexName) 15: )

Copyright © 2001 Dan Leach 120

16: { 17: Graph * pgShortestPathFound = GraphCreate(false,SameName); 18: Graph * pgFringe = GraphCreate(false,SameName); 19: Graph * pgShortestPath = GraphCreate(GraphDirected(pg),SameName); 20: Weight wDistance=0; 21: Weight w=0; 22: int i=0; 23: int iSize=0; 24: Vertex * pvMin=NULL; 25: Weight wMin=0; 26: Vertex * pvParent=NULL; 27: Vertex * pvMinParent=NULL; 28: Boolean bMinSet=false; 29: List * plstPath=CreateList(); 30: Vertex * pvStart=NULL; 31: Vertex * pvEnd=NULL; 32: Vertex * pvCurrent=NULL; 33: Vertex * pvNext=NULL; 34: EdgeList * pelst=NULL; 35: Edge * pe=NULL; 36: Edge * pe1=NULL; 37: Vertex * pv=NULL; 38: Vertex * pv1=NULL; 39: Boolean bRemove=false; 40: 41: pvStart = GraphFind(pg, vnStart); 42: if (pvStart==NULL) 43: // vnStart not in pg 44: return pgShortestPath; 45: 46: pvEnd = GraphFind(pg, vnEnd); 47: if (pvEnd==NULL) 48: // vnEnd not in pg 49: return pgShortestPath; 50: 51: GraphAddVertex(pgShortestPathFound,vnStart); 52: pvCurrent = pvStart; 53: wDistance=0; 54: 55: while (pvCurrent != pvEnd) 56: { 57: pelst=VertexEdgeList(pvCurrent); 58: iSize=ListSize(pelst); 59: 60: // rebuild fringe 61: for(i=0;i<iSize;i++) 62: { 63: RetrieveList(pelst,i,(int *)&pe); 64: // pv is vertex under consideration 65: pv=EdgeVertex(pe); 66: 67: if ( 68: GraphFind 69: ( 70: pgShortestPathFound, 71: VertexVertexName(pv)

Copyright © 2001 Dan Leach 121

72: ) 73: ==NULL) 74: { 75: // w is distance to v through pvCurrent 76: w=wDistance+EdgeWeight(pe); 77: 78: if ( 79: (pv1=GraphFind 80: ( 81: pgFringe, 82: VertexVertexName(pv) 83: ) 84: )!=NULL) 85: 86: { 87: // already in fringe, replace parent? 88: RetrieveList ( 89: VertexEdgeList(pv1), 90: 0, 91: (int *)&pe1 92: ); 93: if (w<EdgeWeight(pe1)) 94: { 95: GraphRemoveVertex( 96: pgFringe, 97: VertexVertexName(pv), 98: &pv1 99: ); 100: GraphJoinWeight( 101: pgFringe, 102: VertexVertexName(pv), 103: VertexVertexName(pvCurrent), 104: w 105: ); 106: } 107: } 108: else 109: { 110: // add to fringe 111: GraphAddVertex(pgFringe,VertexVertexName(pv)); 112: if ( 113: GraphFind 114: ( 115: pgFringe, 116: VertexVertexName(pvCurrent) 117: ) 118: ==NULL) 119: GraphAddVertex( 120: pgFringe, 121: VertexVertexName(pvCurrent) 122: ); 123: GraphJoinWeight( 124: pgFringe, 125: VertexVertexName(pv), 126: VertexVertexName(pvCurrent), 127: w

Copyright © 2001 Dan Leach 122

128: ); 129: } 130: } 131: } 132: 133: if (GraphEmpty(pgFringe)) 134: // no path from pvStart to pvEnd 135: return pgShortestPath; 136: 137: // find edge with minimum distance 138: bMinSet=false; 139: 140: // rebuild fringe 141: iSize=GraphNumberOfVertexes(pgFringe); 142: for(i=0;i<iSize;i++) 143: { 144: RetrieveList( 145: GraphVertexList(pgFringe), 146: i, 147: (int *)&pv 148: ); 149: if(!ListEmpty(VertexEdgeList(pv))) 150: { 151: RetrieveList(VertexEdgeList(pv),0,(int *)&pe); 152: pvParent=EdgeVertex(pe); 153: w=EdgeWeight(pe); 154: if (!bMinSet) 155: { 156: // no min yet; take this one 157: pvMin=pv; 158: pvMinParent=pvParent; 159: wMin=w; 160: bMinSet=true; 161: } 162: else 163: { 164: // replace min? 165: if (w<wMin) 166: { 167: pvMin=pv; 168: pvMinParent=pvParent; 169: wMin=w; 170: } 171: } 172: } 173: } 174: 175: // remove vMin from fringe 176: GraphRemoveVertex(pgFringe,VertexVertexName(pvMin),&pv1); 177: 178: // join to shortest path found 179: GraphJoinWeight( 180: pgShortestPathFound, 181: VertexVertexName(pvMin), 182: VertexVertexName(pvMinParent), 183: wMin

Copyright © 2001 Dan Leach 123

184: ); 185: 186: // determine whether to remove vMinParent from fringe 187: iSize=GraphNumberOfVertexes(pgFringe); 188: bRemove=true; 189: for(i=0;i<iSize;i++) 190: { 191: RetrieveList( 192: GraphVertexList(pgFringe), 193: i, 194: (int *)&pv 195: ); 196: if(GraphAdjacent( 197: pgFringe, 198: VertexVertexName(pv), 199: VertexVertexName(pvMinParent) 200: ) 201: ) 202: bRemove=false; 203: } 204: 205: if (bRemove) 206: GraphRemoveVertex( 207: pgFringe, 208: VertexVertexName(pvMinParent), 209: &pv1 210: ); 211: 212: // set up for next time 213: pvCurrent=pvMin; 214: wDistance=wMin; 215: } 216: 217: printf("\nAll shortest paths found:\n"); 218: GraphPrint(pgShortestPathFound,"%s","(%d)"); 219: 220: // build shortest path 221: GraphAddVertex(pgShortestPath,VertexVertexName(pvEnd)); 222: 223: printf( 224: "\nThe shortest path from %s to %s was:", 225: VertexVertexName(pvStart), 226: VertexVertexName(pvEnd) 227: ); 228: 229: InsertList(plstPath,0,(int)VertexVertexName(pvEnd)); 230: for ( 231: pv=pvEnd; 232: pv!=pvStart; 233: pv=pvNext 234: ) 235: { 236: pelst=VertexEdgeList(pv); 237: RetrieveList(pelst,0,(int *)&pe); 238: pvNext=EdgeVertex(pe); 239: GraphJoinWeight(

Copyright © 2001 Dan Leach 124

240: pgShortestPath, 241: VertexVertexName(pvNext), 242: VertexVertexName(pv), 243: EdgeWeight(pe) 244: ); 245: InsertList(plstPath,0,(int)VertexVertexName(pvNext)); 246: } 247: 248: PrintList(plstPath); 249: printf("Its length was: %d", wMin); 250: 251: return pgShortestPath; 252: }

1.18.7 shorttst.c 1: // shorttst.c 2: // test program for shortest path 3: 4: #include "graph.h" 5:#include "shortest.h" 6: #include <string.h> 7:#include <stdio.h> 8: 9: // compare function 10: Boolean SameName(VertexName vn1, VertexName vn2) 11: { 12: return strcmp(vn1, vn2)==0; 13: } 14: 15: // main test procedure 16: void main() 17: { 18: int i; 19: 20: VertexName vn[9] = 21: {"A","B","C","D","E","F","G","H","I"}; 22: Graph * pg = GraphCreate(false, SameName); 23: Graph * pgShortest; 24: 25: // build the set of nodes 26: for (i=0;i<sizeof(vn)/sizeof(VertexName);i++) 27: GraphAddVertex(pg,vn[i]); 28: 29: // join them 30: GraphJoinWeight(pg,"A","B",2); 31: GraphJoinWeight(pg,"A","F",9); 32: GraphJoinWeight(pg,"A","G",5); 33: 34: GraphJoinWeight(pg,"B","C",4); 35: GraphJoinWeight(pg,"B","G",6); 36: 37: GraphJoinWeight(pg,"C","D",2); 38: GraphJoinWeight(pg,"C","H",5); 39: 40: GraphJoinWeight(pg,"D","E",1);

Copyright © 2001 Dan Leach 125

41: GraphJoinWeight(pg,"D","H",1); 42: 43: GraphJoinWeight(pg,"E","F",6); 44: GraphJoinWeight(pg,"E","I",3); 45: 46: GraphJoinWeight(pg,"F","I",1); 47: 48: GraphJoinWeight(pg,"G","H",5); 49: GraphJoinWeight(pg,"G","I",2); 50: 51: GraphJoinWeight(pg,"I","H",4); 52: 53: // print it 54: printf("Input graph:\n"); 55: GraphPrint(pg, "%s", "(%d)"); 56: 57: puts(""); 58: 59: // compute and print shortest path from A to H 60: pgShortest=ShortestPath(pg,"A","H",SameName); 61: printf("Shortest path from A to H:\n"); 62: GraphPrint(pgShortest, "%s", "(%d)"); 63: 64: puts(""); 65: 66: GraphDestroy(pgShortest); 67: GraphDestroy(pg); 68: }

1.18.8 build.bat 1: cl /Zi /W4 /DPDLIST shorttst.c shortest.c graph.c error.c pdlist.c >build.out 2: emacs build.out

Copyright © 2001 Dan Leach 126

2. Homeworks for Advanced C++

2.1Homework 1Implement a postfix calculator using a stack which will accept as input a set of strings containing numbers and operations. Store these strings in a file for input (NOTE: take the name of the file from the command line invocation; if no file name is supplied, read from stdin). Write the output to stdout. The numbers are to separated by spaces. Operators are separated from the numbers and other operators by spaces as well. Print the line before processing it. When a number is found, push it onto the stack. When an operator is found, print the operator and contents of the stack, then remove the first number on the stack and place that in a variable to be used as an accumulator. Then remove any other numbers on the stack one at a time and use the operator to combine it with the accumulator variable. When there are no more numbers on the stack, print the result and push its value onto the stack. All number should be treated as integers. The operations that you have to support are +,-,*,/. When a new line is encountered, print "end of computation" and clear the stack before starting work on the next line. You must provide output from your program using the indicated lines.

This input:1 2 3 4 + 110 / 7 8 +10 120 - 12 *2 3 5 30 / 2 3 5 *

Should yield the following output:processing line: 1 2 3 4 + 110 / 7 8 +found operator: +contents of stack: (TOP) 4 3 2 1 (BOTTOM)result: 10found operator: /contents of stack: (TOP) 110 10 (BOTTOM)result: 11found operator: +contents of stack: (TOP) 8 7 11 (BOTTOM)result: 26end of computationprocessing line: 10 120 - 12 *found operator: -contents of stack: (TOP) 120 10 (BOTTOM)result: 110found operator: *contents of stack: (TOP) 12 110 (BOTTOM)result: 1320end of computationprocessing line: 2 3 5 30 / 2 3 5 *found operator: /contents of stack: (TOP) 30 5 3 2 (BOTTOM)result: 1found operator: *contents of stack: (TOP) 5 3 2 1 (BOTTOM)result: 30end of computation

Copyright © 2001 Dan Leach 1

2.2Homework 2Do programming project P1 on page 151 in the text. Test your program using the parameters given on page 149.

2.2.1 bldhw2a.bat 1: cl /Fehw2a.exe /DFIXED_QUEUE hw2.c queuea.c error.c

2.2.2 bldhw2l.bat 1: cl /Fehw2l.exe /DLINKED_QUEUE hw2.c queuel.c error.c

2.2.3 hw2.in 1: 30 2: .47 3: .47

2.2.4 hw2.out

This program simulates an airport with only one runway.One plane can land or depart in each unit of time.Up to 5 planes can be waiting to land or take off at any time.How many units of time will the simulation run? 30 Expected number of arrivals per unit time (real number)? .47 Expected number of departures per unit time? .47 1 : Runway is idle. Plane 1 ready to land. 2 : Plane 1 landed; in queue 0 units. 3 : Runway is idle. Plane 2 ready to land. Plane 3 ready to take off. 4 : Plane 2 landed; in queue 0 units. Plane 4 ready to land. 5 : Plane 4 landed; in queue 0 units. Plane 5 ready to land. 6 : Plane 5 landed; in queue 0 units. Plane 6 ready to land. 7 : Plane 6 landed; in queue 0 units. Plane 7 ready to land. Plane 8 ready to take off. 8 : Plane 7 landed; in queue 0 units. 9 : Plane 3 took off; in queue 5 units. Plane 9 ready to land. 10 : Plane 9 landed; in queue 0 units. Plane 10 ready to land. 11 : Plane 10 landed; in queue 0 units. 12 : Plane 8 took off; in queue 4 units. Plane 11 ready to take off. 13 : Plane 11 took off; in queue 0 units. 14 : Runway is idle. Plane 12 ready to take off. 15 : Plane 12 took off; in queue 0 units. Plane 13 ready to land. Plane 14 ready to take off. 16 : Plane 13 landed; in queue 0 units. Plane 15 ready to take off. 17 : Plane 14 took off; in queue 1 units. 18 : Plane 15 took off; in queue 1 units. Plane 16 ready to land. 19 : Plane 16 landed; in queue 0 units. Plane 17 ready to land. 20 : Plane 17 landed; in queue 0 units. 21 : Runway is idle. Plane 18 ready to take off. 22 : Plane 18 took off; in queue 0 units.

Copyright © 2001 Dan Leach 2

Plane 19 ready to land. Plane 20 ready to take off. 23 : Plane 19 landed; in queue 0 units. Plane 21 ready to land. Plane 22 ready to land. Plane 23 ready to take off. 24 : Plane 21 landed; in queue 0 units. 25 : Plane 22 landed; in queue 1 units. 26 : Plane 20 took off; in queue 3 units. 27 : Plane 23 took off; in queue 3 units. Plane 24 ready to land. Plane 25 ready to land. 28 : Plane 24 landed; in queue 0 units. 29 : Plane 25 landed; in queue 1 units. Plane 26 ready to land. 30 : Plane 26 landed; in queue 0 units.Simulation has concluded after 30 units.Total number of planes processed: 26 Number of planes landed: 17 Number of planes taken off: 9 Number of planes refused use: 0 Number left ready to land: 0 Number left ready to take off: 0 Percentage of time runway idle: 13.33 Average wait time to land: 0.12 Average wait time to take off: 1.89

Copyright © 2001 Dan Leach 3

2.3Homework 3Implement a list sorter which will accept as input a set of strings contained in a file and will output a alphabetically sorted list of unique names from the input. Use a doubly linked linear list for your representation. NOTE: The list should always be sorted, that is, put elements in the list in sorted order. Do a case independent compare when deciding on placement in the list. Use strings in a file for input (NOTE: take the name of the file from the command line invocation; if no file name is supplied, read from stdin). Write the output to stdout. Be sure to clear the list, deleting all information contained in it, prior to exit (but after printing it). Use dynamic storage for the list contents (that is, each node should contain a char * as its data which is calloced to be the exact size of the string it is to hold (including the terminating NULL character)). Trailing white space should be removed from lines prior to insertion in the list. Blank lines (including those which contain all white space characters) in the input file should be ignored. Input lines have a maximum length of 200 characters.

This input:This is a test.SupermanSUPERMANSuperMan

Super ManALfie

AlfieALFIETesting

This is a very long line to be sorting in a file of this nature, but it should work anyway.

Should yield the following output:(LIST START)ALfieSuper ManSupermanTestingThis is a test.This is a very long line to be sorting in a file of this nature, but it should work anyway.(LIST END)

Copyright © 2001 Dan Leach 4

2.4Homework 4Implement a list sorter which will accept as input a set of integers contained in a file and will output a numerically sorted list of numbers (possibly containing duplicates) from the input. You will start by reading the entire list and then copying it because you will need to sort it three times. Once using Insertion Sort, once using Selection Sort, and once using Shell Sort (using the increments: 5, 3, and 1). All exchanges will be done through a routine called Swap which will count the exchanges. All comparisons of keys will be done in separate routines (LT, LE, GT, et al, a al the text) and the comparison routines will increment a common counter. At the end of each sort, print the sorted list, the number of calls to Swap, and the total number of comparisons of keys. You should then clear the counters, clear the sorted list, and sort another copy of the input list. In other words, read the list once, and copy it three times for each sort. Use a doubly linked linear list for your representation (same list structure as for Homework 2, but with a new ListEntry type). Use strings in a file for input (NOTE: take the name of the file from the command line invocation; if no file name is supplied, read from stdin). Write the output to stdout. Be sure to clear the list and all copies, prior to exit (but after printing it). Blank lines (including those which contain all white space characters) in the input file should be ignored. Input lines have a maximum length of 200 characters.

This input:10109877655543221

Should yield the following output:

List after Insertion Sort:(LIST START) 1 2 2 3 4 5 5 5 6 7 7 8 9 10 10 (LIST END)Number of Swaps was: 99Number of comparisons of keys was: 104List after Selection Sort:(LIST START) 1 2 2 3 4 5 5 5 6 7 7 8 9 10 10 (LIST END)Number of Swaps was: 14Number of comparisons of keys was: 105List after Shell Sort1:(LIST START) 1 2 2 3 4 5 5 5 6 7 7 8 9 10 10 (LIST END)Number of Swaps was: 25Number of comparisons of keys was: 48List after Shell Sort2:(LIST START) 1 2 2 3 4 5 5 5 6 7 7 8 9 10 10 (LIST END)Number of Swaps was: 17Number of comparisons of keys was: 55List after Quick Sort:

Copyright © 2001 Dan Leach 5

(LIST START) 1 2 2 3 4 5 5 5 6 7 7 8 9 10 10 (LIST END)Number of Swaps was: 7Number of comparisons of keys was: 112List after Heap Sort:(LIST START) 1 2 2 3 4 5 5 5 6 7 7 8 9 10 10 (LIST END)Number of Swaps was: 38Number of comparisons of keys was: 66List after Radix Sort:(LIST START) 1 2 2 3 4 5 5 5 6 7 7 8 9 10 10 (LIST END)Number of Swaps was: 480Number of comparisons of keys was: 0

Original list:(LIST START) 10 10 9 8 7 7 6 5 5 5 4 3 2 2 1 (LIST END)

Copyright © 2001 Dan Leach 6

2.5Homework 5Implement a program using binary trees which accepts expressions composed of letters and operators in infix representation and uses this to build a binary expression tree. Your program should then traverse the expression tree using the preorder, postorder, and inorder traversals. As with the other assignments, store the input strings in a file for input (NOTE: take the name of the file from the command line invocation; if no file name is supplied, read from stdin). Write the output to stdout. The letters and operators are to separated by spaces. Print the line before processing it. The operators that you have to support are +, -, *, /. When a new line is encountered, print the traversals and destroy the tree before starting work on the next line. You must provide output from your program using the indicated lines. Blank lines (including those which contain all white space characters) in the input file should be ignored. Input lines have a maximum length of 200 characters.

This input:+ A - B C+ + * A B * C D / E F- + * / A B C D E/ + + A B * C D * - E F / G H

Should yield the following output:processing line: + A - B Cpreorder traversal: + A - B Cinorder traversal: A + B - Cpostorder traversal: A B C - +

processing line: + + * A B * C D / E Fpreorder traversal: + + * A B * C D / E Finorder traversal: A * B + C * D + E / Fpostorder traversal: A B * C D * + E F / +

processing line: - + * / A B C D Epreorder traversal: - + * / A B C D Einorder traversal: A / B * C + D - Epostorder traversal: A B / C * D + E -

processing line: / + + A B * C D * - E F / G Hpreorder traversal: / + + A B * C D * - E F / G Hinorder traversal: A + B + C * D / E - F * G / Hpostorder traversal: A B + C D * + E F - G H / * /

Copyright © 2001 Dan Leach 7