Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
CIS 211 Data Structures Project 1 The results of a survey of the households in your township have been made available. Each record contains data for one household, including a four-digit integer identification number, the annual income for the household, and the number of members in the household. You may assume that no more than 25 households were surveyed. Write a program to store the survey results into an array of user-defined structures of type household_t. Then perform the following analyses: 1) 2) 3) Print a three column table displaying the data. Calculate the average household income, and list the identification number and income of each household whose income exceeds the average. Determine the percentage of households having incomes below the poverty level. The poverty level income is computed using the formula: P=$7500 + ($950 * (m - 2)) where m is the number of members in the household. This formula shows that the poverty level depends on the number of family members m and the poverty level increases as m gets larger. The following is one data set to use to test your program: ID Number Annual Income Household Members 1041 1062 1327 1483 1900 2112 2345 3210 3600 3601 4725 6217 9280 $12,180 $13,240 $19,800 $24,458 $17,000 $19,125 $17,623 $5,200 $9,500 $11,970 $9,800 $10,000 $8,200 4 3 2 8 2 7 2 6 5 2 3 2 1 CIS 211 Data Structures Project 2 A postfix expression is an expression in which each operator follows its operands. There are some examples of postfix expressions at the bottom of this document. The grouping marks under each expression should help you visualize the operands for each operator. The more familiar infix expression corresponding to each postfix expression is also shown. The advantage of postfix form is that there is no need to group subexpressions in parenthesis or to consider operator precedence. The grouping marks below are only for your convenience and are not required. You may have used pocket calculators that require entry of expressions in postfix form. Use an adaption of the stack program shown in class to write a program that simulates the operation of a calculator byh scanning an integer expression in postfix form and displaying the result. Your program should push each integer operand onto the stack. When an operator is encountered, the top two operands are popped, the operation is performed on its operands, and the result is pushed back onto the stack. The final result should be the only value remaining on the stack when the end of the expression is reached. EXAMPLE INFIX EXPRESSION VALUE 5 6 * 5*6 30 5 6 1 + * 5 * (6 + 1) 35 4 + ((5 * 6) / 3) 14 4 5 6 * 3 / + CIS 211 Data Structures Project 3 Supermarket Simulation Write a program that simulates a check-out line at a supermarket. The line is a queue. Customers arrive in random integer intervals of 1 to 4 minutes. Also, each customer is serviced in random integer intervals of 1 to 4 minutes. Obviously, the rates need to be balanced. If the average arrival rate is larger than the average service rate, the queue will grow infinitely. Even with balanced rates, randomness can still cause long lines. Run the supermarket simulation for a 12 hour day (720 minutes) using the following algorithm. 1) 2) 3) Choose a random integer between 1 and 4 to determine the minute at which the first customer arrives. At the first customer's arrival time: Determine the customers service time (random integer from 1 to 4) Begin servicing the customer Schedule the arrival time of the next customer (random integer 1 to 4 added to the current time) For each minute of the day: If the next customer arrives: Say so (display a message, with the customer count starting with 1) Enqueue the customer Schedule the arrival time of the next customer If the service was completed for the last customer Say so (display a message with the customer count) Dequeue the next customer to be serviced Determine customer's service completion time Run the simulation for 720 minutes and answer each of the following: 1) 1) 2) Total number of customers serviced. Maximum number of customers in queue at any one time. What is the longest wait any one customer experienced? CIS 211 Data Structures Program 4 Binary Tree Delete This program will delete a node from a binary tree. The deletion algorithm is not as straightforward as the insertion algorithm. There are thee cases that are encountered when deleting an item - the item is contained in a leaf node (i.e. it has no children), the item is contained in a node that has one child, or the item is contained that has two children. If the item to be deleted is contained in a leaf node, the node is deleted and the pointer in the parent node is set to NULL. If the item to be deleted is contained in a node with one child, the pointer to the parent node is set to point to the child node and the node containing the data item is deleted. This causes the child node to take the place of the deleted node of the tree. The last case is the most difficult. When a node with two children is deleted, another node in the tree must take its place. However, the pointer in the parent node cannot simply be assigned to point to one of its children of the node to be deleted. In most cases, the resulting binary search tree would not adhere to the following characteristic of binary search trees: The value in any left subtree are less than the value of the parent node, and the values in any right subtree are greater than the value in the parent node. Which node is used as a replacement node to maintain this characteristic? Either the node containing the largest value in the tree less than the value in the node being deleted, or the node containing the smallest value in the tree greater than the value in the node being deleted. Let us consider the node with the smaller value. In a binary search tree, the largest value less than a parent's value is located in the left subtree of the parent node and is guaranteed to be contained in the rightmost node of the subtree. This node is located by walking down the left subtree to the right until the pointer to the right child of the current node is NULL. We are now pointing to the replacement node which is either a leaf node or a node with one child to its left. If the replacement node is a leaf node, the steps to perform the deletion are as follows: 1) 2) 3) 4) Store the pointer to the node to be deleted in a temporary pointer (this pointer is used to delete the dynamically allocated memory) Set the pointer in the parent of the node being deleted to point to the replacement node. Set the pointer in the parent of the node being deleted to point to the replacement node. Set the pointer to the right subtree in the replacement node to point to the right subtree of the node to be deleted. 5) Delete the node to which the temporary pointer points. The deletion steps for a replacement node with a left child are similar to those for a replacement node with no children, but the algorithm also must move the child in to the replacement node's position in the tree. If the replacement node is a node with a left child, the steps to perform the deletion are as follows: 1) 2) 3) 4) 5) Store the pointer to the node to be deleted in a temporary pointer variable Set the pointer in the parent of the node being deleted to point to the replacement node. Set the pointer in the parent of the replacement node to point to the left child of the replacement node. Set the pointer to the right subtree in the replacement node to point to the right subtree of the node to be deleted. Delete the node to which the temporary pointer points. Write function deleteNode which takes as its arguments a pointer to the root node of the tree and the value to be deleted. The function should locate in the tree the node containing the value to be deleted and used the algorithms discussed here to delete the node. If the node is not found in the tree, the function should print a message that indicates whether or not the value is deleted. After deleting an item, call the inOrder, preOrder, and postOrder transversal functions to confirm that the delete operation was performed correctly. CIS 211 Data Structures Project 5 Create a class called "time" that has separate "int" member data for hours, minutes, and seconds. One constructor should initialize this data to 0, and another should initialize it to fixed values. Another member function should display it, in 11:59:59 format. The final member function should add two objects of type "time" pass as arguments. CIS211 Data Structures Project 6 Create code to allow a user to enter multiple lines of text. The terminator for text entry should be “$” and should be identified in the instructions. Once the file is entered, perform the following: 1) 2) 3) 4) 5) Count the number of words in the file. Display the word count on the screen. Calculate and display the average number of letters in each word. Provide a utility whereby all instances of a word in the input file can be replaced by a word entered by the user. The number of replacements should be displayed. This utility should be set up to run until “finished” is entered as the word. Capitalize the first letter of the first word of every sentence if it is not already done. Once all editing is complete, display the newly updated text. Use the “string” class provided by Java/C++ for text manipulation! CIS 211 Data Structures Project 7 In the heyday of the British empire, Great Britain used a monetary system based on pounds, shillings, and pence (listen to those old Beatles/Kinks records!). Anyway, there were 20 shillings to a pound and 12 pence to a shilling(called sterling pounds here). The notation for this system used the pound sign (£) and two decimal points, so that, for example, £5.2.8 meant 5 pounds, 2 shillings, and 8 pence. In the 1950's the British introduced a decimal system where 100 pence equals one pound (decimal pounds). So £5.2.8 in the old system equals £5.13 in the new. Create a class with pounds (type long), shillings (type int), and pence (type int) data items. Create the following member functions: - no argument constructor one-argument constructor, taking type double (for converting from decimal pounds three-argument constructor taking pounds, shillings, and pence getSterling() to get an amount in pounds, shillings, and pence from the user format £9.19.11 putSterling() to display an amount in pounds, shillings, and pence addition (sterling + sterling) using overloaded + operator subtraction (sterling - sterling) using overloaded - operator operator double (to convert to double) To perform arithmetic, you could add each object's data separately. Add the pence, carry, add the shillings, carry, and so on. However, it is easier to use the conversion operator to convert both sterling objects to type double, perform the arithmetic on the doubles, and convert back to sterling. Thus the overloaded + looks like this: sterling sterling :: operator + (sterling d2) { return sterling (double (sterling(pounds, shillings, pence)) + double (s2)); } This creates two temporary double variables, one derived from the object of which the function is a member, and one derived from the argument s2. These double variables are then added, and the result is converted back to sterling and returned. NOTE: You can use the hex character constant ‘\x9c’ to represent the pound character. 6 3. Use a regular queue to manage the set S of nodes which represent the shortest‐path so far. When the loop stops you can read the paths by starting at the rear of the queue. 4. As you read the nodes in a path push them to a stack. When you have read all of the nodes in the path, pop all of the nodes off of the stack and you will have the path to display as required (first node to last node). Note: On a logical level, this is a relatively easy algorithm to implement. However, a successful implementation requires the management of a lot of detail. It cannot be done over night! So, start now and, as always, have fun!!!! #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define TRUE 1 #define FALSE 0 #define SIZE 5 // number of nodes in the graph #define MAX_INDEX SIZE ‐ 1 #define CTY 4 6 7 // struct used to create node in graph struct graph_node { char name[CTY] ; int // set to TRUE when node put into set S int distance ; // records distance in path char from[CTY] ; struct graph_node* pfrom ; struct adj_node* list ; // pointer to beginning of adjacency list for node struct graph_node* before ; // pointer to previous node of a node in queue struct graph_node* next ; // pointer to the next node in a priority list or to struct graph_node* glink_next ; // link to a node in the graph struct graph_node* slink_next ; // pointer to next node in a stack seen ; // name of node // records name of node causing the relaxation // pointer to the node causing relaxation // next node in a queue } ; // struct used to create adjacency list for a node in the graph struct adj_node { char node_name[CTY] ; // name of an adjacent node int weight ; // weight of edge terminating with this node struct adj_node* next ; // points to next node in the adjacency list struct graph_node* pnode ; // could be used to point to node causing relxation } ; 7 8 // struct to implement regular queue struct lo_queue { struct graph_node* front ; struct graph_node* rear ; } ; // struct implement stack struct nstack { struct graph_node* top ; }; // prototypes for functions to implement a regular queue void create_loqueue(struct lo_queue* ) ; int loq_empty(struct lo_queue* ) ; struct graph_node* loq_remove( struct lo_queue* ) ; void loq_insert( struct lo_queue*, struct graph_node* ) ; void loq_read( struct lo_queue* ) ; // prototypes for functions to implement a stack void create_stack(struct nstack* ) ; int empty_stack(struct nstack* ) ; struct graph_node* pop( struct nstack* ) ; void push( struct nstack*, struct graph_node* ) ; 8 9 // struct to implement priority queue struct prqueue { struct graph_node * prqtop ; } ; // prototypes for functions to implement a priority queue void create_prqueue(struct prqueue*) ; int prq_empty(struct prqueue*) ; struct graph_node* prq_remove(struct prqueue*) ; void prq_insert(struct prqueue*, struct graph_node*) ; // prototype for relaxation function void prq_relax(struct prqueue* , struct graph_node* ) ; FILE* outfile ; // output file pointer FILE* infile ; // input file pointer int main() { struct lo_queue city_queue ; // regular queue for set S struct nstack city_stack ; // stack to used to read paths struct prqueue city_prq ; // priority queue used in Dijkstra algorithm struct graph_node* new_rec = NULL ; // used to get new graph nodes struct adj_node* new_lrec = NULL ; // used to get new adjacency list nodes 9 10 struct graph_node* out_node = NULL; // used to return removed nodes char nodes[SIZE][CTY] ; // records names of nodes of directed graph int graph_Matrix[SIZE][SIZE]; // adjacency matrix representation of graph struct graph_node* node_locations[SIZE]; // saves location of graph nodes struct adj_node* plntop = NULL ; // points to top of an adjacency list struct graph_node* pgntop = NULL ; // points to top node in graph struct graph_node* move_gpntr = NULL ; // used to traverse graph nodes struct graph_node* pdest = NULL ; // used to read paths struct graph_node* ppath = NULL ; struct adj_node* move_lpntr = NULL ; // used to traverse nodes in graph int first_lnode = TRUE ; // boolean for first node in adjacency list int first_gnode = TRUE ; // boolean for first node in graph // used to read paths // open files for input and output infile = fopen( "adj_Matrix.txt", "r" ) ; // outfile = fopen( "proj2_out.txt", "w" ) ; // create queue, stack and priority queue // create_loqueue( &city_queue ) ; // create_stack( &city_stack ) ; // create_prqueue( &city_prq ) ; 10 Project Huffman Code Tree 1. You are required to build a Huffman code tree based on the letter frequencies found in the file symb_freq.txt. Use the following procedure for creating such a tree. A. Read the input file symb_freq.txt . For each record read from the file do the following: a. using dynamic memory allocation, generate a node and initialize the fields symbol and frequency with the values read from the file b. record the location of the node by using the array position c. insert the node into an ascending priority queue using the value of the frequency field B. Until only a single node remains in your priority queue dothe following: a. remove two nodes at a time from your priority queue b. using dynamic memory allocation, generate a new node and initialize the symbol and frequency fields. For this new node the value of the symbol field will be a new symbol which is the combination of the symbols from the two nodes removed from the priority queue. The value of the frequency field for this new node will be the sum of the frequency fields from the two nodes removed from the priority queue. c. initialize other fields in the nodes. Initialize the father field for the two nodes removed from the priority queue. Initialize the left and right fields for the new node. d. insert the new node into the ascending priority queue C. Remove the final node from your priority queue. Assign this node to the variable code_root. This is the root of your Huffman Code Tree. 2. You are required to do an inorder traversal of the Huffman Code Tree that you have built. Output from this traversal should be sent to the file code_tree.txt and should appear as: FREQUENCY: 9.056 Symbol: t FREQUENCY: 18.272 Symbol: tvzqxjkfwm 3. You are required to do an level order traversal of the Huffman Code Tree that you have built. In this traversal report only the level and symbols from the code tree that occur on that level. Output from this traversal should also be sent to the file code_tree.txt and should appear as: Level 0: tvzqxjkfwmucrhsenibpygoald Level 1: tvzqxjkfwmucrhs enibpygoald Level 2: tvzqxjkfwm bpygoald ucrhs eni 1 .................................. 4. You are required to print out the symbols and the corresponding code for each symbol. These will be only for the symbols in your original set. This output should also be appended to the file code_tree.txt. The lines in this output should look like: Symbol: d Symbol e Huffman Code: 11111 Huffman Code: 100 The strategy for discovering the code implied by your Huffman tree is to start at each leaf node representing a symbol from your original set of symbols. For each of these, starting at that node you you are going to climb the tree until you have reached the root node. As you climb you are going to build a code using the following rules: 1) If you climb a left branch you will pre-pend'0' to the beginning of the code that you are building. 2) If you climb a right branch you will pre-pend'1' to the beginning of the code that you are building. 3) When you reach the root node you will have a unique code for the symbol in the leaf node from which you started your climb. 4) Depending on your insight you may also make use of the structure struct kuf_code and the variable position. The variable position if you used it previously will have the addresses of all of your leaf nodes for the tree that you have built and the structure struct kuf_code can be used to record codes as you climb the tree. In the end no matter what you use I want your output to look like the two sample lines above and of course I want your code to be correct. 5) You are required to decode the input file bit_file.txt . Send your decoded text to the file decoded_file.txt . The basic strategy fordecoding the input file involves traveling from the root of your Huffman tree down to the leaves. Implementing the the following pseudocode will lead to a successful solution. While not at the end of your input file do the following: a. Read the input file "bit_file.txt" "one character at a time" ( can actually read one line at a time and process appropriately ) b. Starting at the root of your Huffman tree make the following choices based on the current character input from your input file: 1. If the current character input is'0' then travel down the left branch of the tree. 2. If the current character input is'1' then travel down the right branch of the tree. c. Continue to read a character at a time and make choices as indicated in step b. In the tree, when you reach a leaf node the symbol in this node will be the correctlly decoded character for the sequence of '1's and '0's you have just input from the file "bit_file.txt". You have now 2 decoded one character of the message coded in the file "bit_file.txt . Copy the symbol ( character ) into your output file "decoded_file.txt" . d. After arriving at a leaf node if you have not yet come to the end of your input file, you will start again at the root of your Huffman code tree, continue to input from the file "bit_file.txt" and process the input as indicated in steps b. and c. If you are now at the end of the input file and have successfully implemented the procedure as outlined above you will have correctlly decoded the message stored in the file "bit_file.txt" and your project is now completed!!! In the decoding process, please adhere to the following warning. WARNING: When you read your input file ( bit_file.txt ) be aware that the Kuffman Coding Tree DOES NOT contain a code for spaces and punctuation marks. This means that when you find a space or a punctuation mark in the input you should write them to your output file without trying to decode them. NOTE!!! For this project you can find some of the code in your textbook. However, you will do just as well to write your own. Think about what you want to do before writing your code. This project cannot be completed over night so start early and Have fun .....!!! 3 11 // code to create adjacency matrix representation of graph while( !feof(infile) ) { for(int i = 0 ; i < SIZE ; i++) for(int i = 0 ; i < SIZE ; i++) for(int j = 0 ; j < SIZE ; j++) } for(int i = 0 ; i < SIZE ; i++) printf("\n\n") ; for(int i = 0 ; i < SIZE ; i++) { for(int j = 0 ; j < SIZE ; j++) printf("\n") ; } printf("\n\n") ; fscanf(infile,"%s", nodes[i]) ; // record names of nodes // record weights of edges fscanf(infile, "%d", & graph_Matrix[i][j] ) ; printf("%s \n", nodes[i]) ; // print names of nodes to output // print weights of edges to output printf( "%d ", graph_Matrix[i][j] ) ; // code to build adjacency list representation of the graph // get last node of graph first 11 12 printf("\n\n Adjacency List Representation of Directed Graph ") ; // code to print adjacency_list representation of the graph printf("\n\n\n") ; // code to discover shortest paths printf("\n Shortest Paths from Source to Destination \n\n") ; fclose( infile ) ; // fclose( outfile ) ; return( 0 ) ; } // end of function main() 12 CIS211 Sorting Algorithm Comparison I. INTRODUCTION: In this project you will apply the concepts of sorting and you will compare various sorting algorithms’ efficiency and consistency. II. DESCRIPTION: You have learned many different sorting algorithms. In this project, you are going to implement the following 4 sorting algorithms, Quick sort, Shell sort, Insertion sort, and Selection sort, using either C/C++ or JAVA programming language. Analyze your results, make your recommendations and support the reasoning for your choice of the best algorithm. III. ASSIGNMENT: Please do this assignment according to the following steps: 1. You are going to sort randomly generated numbers between 0 and MAXINT using the above four mentioned algorithms. Write four different programs using 100, 1,000, 10,000, and 100,000 integers. 2. For each program, write functions/methods to implement the four algorithms mentioned previously. 3. Name your programs in the format of “sortx” where x is the number of integers used. For example, if you write the program in JAVA, then for the case when the number of integers used is 1000, the program should be named “sort1000.java”. 4. Before your program calls each sorting function/method, it should generate a set of random numbers between 0 and MAXINT, and then apply this same set of random numbers for all four sorting algorithms. 5. Find the execution time for each of the four sorting algorithm. 6. Repeat steps 4 and 5 fifty times. 7. At the end of the program, calculate mean time and standard deviation for each algorithm. 8. Compile all your results using the table below. 100 1,000 10,000 σ ̅ ̅ 100,000 σ ̅ ̅ Shell Sort Insertion Sort Quick Sort σ Selection Sort ̅ = mean time σ = standard deviation σ 9. Analyze your results, make your recommendations and support the reasoning for your choice of the best algorithm. The grading rubric is attached for your reference. Sorting Comparison Project‐‐Page 2 of 2 Grading Rubric Sorting Algorithm Criteria Mean Calculation Standard Deviation Calculation Algorithm Recommendations Readability Excellent Satisfactory Marginal Unsatisfactory Program calculates and displays correct output with no errors Program calculates correctly but displays output with minor errors Program calculates and displays output with minor errors Program calculates and displays incorrect output Program calculates and displays correct output with no errors Program calculates correctly but displays output with minor errors with no impact on recommendations Program calculates and displays incorrect output which would have significant impact on recommendations Recommendations address efficiency, consistency, number data size, and constraints Recommendations address efficiency, consistency and number data size Program calculates and displays output with minor errors which would have minor impact on recommendations Recommendations address efficiency and consistency The code is exceptionally well organized and very easy to follow. The code is fairly easy to read. The code is readable only by someone who knows what it is supposed to be doing. The code is poorly organized and very difficult to read. Recommendations address efficiency only 1 Documentation Code Efficiency The documentation is well written and clearly explains what the code is accomplishing and how. The documentation consists of embedded comment and some simple header documentation that is somewhat useful in understanding the code. The documentation is simply comments embedded in the code with some simple header comments separating routines. The documentation is simply comments embedded in the code and does not help the reader understand the code. The code is extremely efficient without sacrificing readability and understanding. The code is fairly efficient without sacrificing readability and understanding. The code is brute force The code is huge and and unnecessarily appears to be patched long. together. 2 CIS 211 Currency Conversion Project Amazing as it may seem, the old British pounds/shillings/pence money notation (£9.19.11) isn’t the whole story. A penny was further divided into halfpennies and farthings, with a farthing being worth ¼ of a penny. There was a halfpenny coin, a farthing coin, and a halffarthing coin. Fortunately all of this can be numerically expressed in eighths of a penny. 1/8 of a penny is a halffarthing ¼ of a penny is a farthing 3/8 of a penny is a farthing and a half ½ penny is a halfpenny 5/8 penny is a halfpenny plus a halffarthing ¾ penny is a halfpenny plus a farthing 7/8 penny is a halfpenny plus a farthing and a half Create a derived class sterfrac from the class sterling. It should be able to perform all functionality of the original class except for the conversion constructor and operator. Currency should be accepted and displayed in the following format: £9.19.11 – 7/8 where the 7/8 represents the fractional portion of the penny. The only new data item in sterfrac should be an integer called “eighths” which contains the number of eighths. The program, however, should be able to interpret and display fractions such as “1/2” and “1/4”. 1 CIS211: Data Structures Dijkstra Shortest Path Project Basic Background Information The Dijkstra shortest path algorithm is an algorithm used to discover the shortest path between a source and destination node in a directed acyclic graph. The basic idea is that to discover the shortest path between two distant nodes we will choose the shortest path to each intermediate node along the way. This is accomplished by successively creating a set of nodes which at the time of inclusion is the shortest path so far on the way to the final destination. The path length at the time of inclusion is calculated and associated with the newly included node. The weight of an edge is added to the path length of one of the nodes already in the shortest path‐so‐far set. The edge leading to the next node to be included is chosen so that when the weight of the edge is added to the path length of a node already in the set, the resulting path length will be the smallest greater path length. For example if the set presently consist of A2 and B4 (with the numbers representing the path length at the time of inclusion) and edges extending from B4 have weights of 3 and 6 and edges extending out of A2 have weights of 4 and 5, because 4 + 3 = 7 and 4 + 6 = 10 and 2 + 4 = 6 and 2 + 5 = 7 then because 6 is smaller than 7 and 10 the next node to be included will be the node that you get to by following the edge of weight 4 out of the A2 node. If the node is G then G is now included with a path length of 6, G6. Information also included with the newly included node will be a reference to the node that was extended in reaching the newly included node, thus G6 will also record that it came from A. This outlined procedure will continue until the destination node is included in the set. When the destination node is included it will be included with the calculated shortest path. Now the path from the source node to the destination node, accounting for all of the intermediate nodes, can be obtained by back tracking using the “from” reference, all the way back to the source node. Project Statement Write a program to implement the Dijkstra Shortest Path Algorithm. When created use your program to discover the shortest paths in the directed graph that you are given. In developing your program use the solution which incorporates some manifestation and/or modification of a priority queue. 1 2 Project Requirements 1. From an adjacency matrix representation of the directed graph, which is given to you, develop and display an adjacency list representation of the graph. Your output from this section of your program should look like: Adjacency List Representation of Directed Graph s :u3 x5 u :v6 x2 …………………………………………….. y :s3 v7 Note: the letters represent the names of the nodes and the numbers represent the weights/lengths of the edges. As a result, the line that reads s :u3 x5 means that the u node is adjacent to the s node and is connected by an edge of weight 3 and the x node is also adjacent to the s node and is connected by an edge of weight 5. Note: The nodes in the graph that you are given have the names s, u, v, x, and y. The adjacency matrix representation of the graph is stored in a two dimensional array declared as: int graph_Matrix[SIZE][SIZE] ; The values in the array are: 0 3 0 5 0 0 0 6 2 0 0 0 0 0 2 0 1 4 0 0 3 0 7 0 0 To interpret the numbers consider the row index to be the start of the edge and the column index to be the end of the edge, with the number stored at the intersection representing the weight of the edge. Thus the number 4 in the index row 3 (indexes start at 0 ) means that there is an edge from node x to node v and the weight of the edge connecting them is 4. 2 3 2. Starting at a node, find the shortest path from that node to all other nodes. In the output indicate the intermediate nodes along the path with the weight/length of the path at that point. The output from this should look like: Shortest Paths from Source to Destination s0 u3 x5 v9 y11 s0 u3 x5 v9 s0 u3 x5 s0 u3 s0 s0 u3 x5 v9 y11 ……………………………………………………………………………………….. y0 s3 u6 x8 v12 y0 s3 u6 x8 y0 s3 u6 y0 s3 y0 y0 s3 u6 x8 v12 In the output above as an example the line which is s0 u3 x5 v9 means that the path from s to v has a total weight of 9 and has intermediate nodes of u and x. When you arrive at u the path weight is 3, by the time you arrive at x the path weight is 5 and by the time you get to v the path weight is 9. The line s0 u3 x5 v9 y11 at the bottom of the s section is a display of the order in which nodes were added to the set during the execution of the Dijkstra Algorithm. Also indicated is the path weight at the time each node is included in the set. Note: For this requirement, in sequence, each node in the graph will be treated as the starting node. 3 4 Steps in Dijkstra Algorithm Implemented Using a Priority Queue 1. Initialize a set S to the empty set. This set will contain all nodes constituting the shortest path‐so‐far. 2. Initialize the distance field (records the value of the shortest path‐so‐far) of all nodes to a large positive value representing infinity. Initialize the distance field of the first starting node to be 0 (zero). Now, using the distance field as the key, insert all nodes into a priority queue, Q. 3. While the priority queue Q is not empty do the following: a. Remove a node, for reference called u, from the priority queue Q b. Insert this node u into the set S. Then for each node adjacent to node u do the following: i. update the value of the distance field by using the formula adjacent_Node‐>distance = u‐>distance + adjacent_Node‐ >edgeWeight ; This proceedure is called relaxing the adjacent_Nodes ii. in the node that is being relaxed record the u node as the value of the from field for this node ; it is the u node that is relaxing all nodes that are adjacent to it; iii. these adjacent nodes are then reinserted into the priority queue c. repeat steps a. and b. until there are no more nodes to be removed 4. When the priority queue is empty all nodes along the path to the most remote node will have been inserted into the set S. 5. Discover the shortest paths by backtracking from the final node in the set S to the start node in the set S, using the from field recorded in each of the nodes. The weights associated with each of these nodes is the shortest path from the start node to each of the respective intermediate nodes and the final node. Display this information as indicated in the example output above. 4 5 What you are Given 1. You are given code that creates an adjacency matrix representation of a directed graph which is stored in the variable graph_Matrix[][]. As a side effect of creating this representation you are given an array nodes[][] which contains the names of all of the nodes. 2. You are given a prototype for a graph node called struct graph_node and a prototype for a adjacency list node called struct adj_list. For these nodes the purposes of some of the fields are indicated in the appropriate comment. Please note that in the struct graph_node prototype there are several struct graph_node* fields which are used to allow a graph_node to participate in different data structures at the same time. For example slink_next allows the graph_node to be a part of a stack, the glink_next allows the graph_node to be a part of a graph, the next allows the graph_node to be a part of a priority queue and also a regular queue (obviously not at the same time). The before field allows a node in a queue to also participate in a doubly linked list (a node is linked going toward the end and also linked going toward the beginning). 3. You are given other variables and prototypes for functions which can be used as indicated by the associated comment. Note: You are not required to use anything that you are given. These ítems are given only as suggestions of what would be usefull in helping to créate a solution. If you desire, you can choose to ignore everything. You are free to créate a solution of your own design, as long as the project requirements are met!! Other Ideas Possibly Useful in Implementing the Dijkstra Shortest‐Path Algorithm 1. When creating the adjacency list representation of the directed graph, save the memory location for each node in the graph when it is first created/allocated. 2. The relaxation() function actually requires you to find the node be relaxed in the priority queue, remove the node from the priority queue, update the distance information for the node and then re‐insert the node back into the priority queue. 5 CIS211: Project-Doubly Linked List 1. Write a structure for a doubly linked list. It should only store a single integer, but it’s two nodes should be called left and right, not prev and next. (The need for this will become apparent later) 2. Write a function to read in all the integers from a datafile and place them in a doubly linked list. Within the function you should open the datafile “project5.txt” for reading. The datafile should contain a long list of unordered integers each separated by a space. There may be repeats. An example datafile is on the class website. 3. Ex: 76 212 9 55 –66 4 44 22 1 999 998 997 0 45 4. Write a function called treesort(). Treesort’s only parameter will be the first node of your doubly linked list. Although the values of your “first” will change within the function, the pointer itself will not change, so the parameter is just a Node pointer and the function returns no value. Sort your list by creating a binary tree. How do you sort a list by creating a binary tree? First, look in your book, Chapter 5, and see what a binary tree looks like. The basic rules are thus: The first node in your list will become the “root” node in your binary tree. There is no need for you to create any new Nodes in this function. The first node is a special case; it will become the root. So, start by removing the first Node from the list and making it’s left and right equal NULL. (You should still have a valid doublylinked list full of numbers that is just one item shorter then it used to be) Now pull the next Node off the list, and pass it to a function named evaluate() (which we will write in Step 4). Continue this process until you have removed all the nodes from your doubly-linked list. 5. Write the evaluate() function that is needed to complete Step 3. Evaluate should take two parameters, a pointer to the root of your binary tree and a pointer to the Node you just pulled off the front of your doubly-linked list. It should add the new Node to the binary tree in the proper place and return nothing. What is the proper place? Well, look at the root node. Is your new node’s integer greater than or less than it? If it’s greater, then it goes to the right; if it is less it goes to the left. Let us assume that our Node stores an integer that is less than the Root’s integer. We now look to the left. Does that Node exist? If it does not than we insert it to the left. Otherwise, we move our root pointer to the left and re-run the algorithm. This continues until we find a place for the new node and add it to the binary tree. Note- We need a rule for if the number is equal to the Node in question. For our purposes let us say that an equal node should go to the right. Note- You may write the function any way you desire, but recursively may be easiest. 6. Write a printtree() function. The printtree() function must accept as it’s only parameter a pointer to the root of your binary tree. (Which was also once the “first” for your doubly linked list.) The printtree() function should print out all the numbers in the binary tree in order from least to greatest. Note that no pointer points up, only down. This means that your printtree() function will have to be recursive! In your book this order of printing is called an “inorder traversal”. 7. Write a deletetree() function. Obviously, the deletetree() function should take a pointer to the root node and delete all nodes. Bonus Points 8. Write a removeNode() function. It should accept as a parameter a pointer to a Node that will be removed from your tree. A leaf node will be easy. What about a stem node? 9. Write a findNode() function. It should accept as a parameter a pointer to the root of your binary tree and an integer. It should return a pointer to the lowest Node on the tree with that number. (aka farthest from the root) 10. Test your two functions by finding a node or two, removing them, then re-printing your sorted list out.