Download CIS 211 Data Structures Project 1 The results of a survey of the

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Linked list wikipedia , lookup

Quadtree wikipedia , lookup

Lattice model (finance) wikipedia , lookup

Red–black tree wikipedia , lookup

Interval tree wikipedia , lookup

Binary tree wikipedia , lookup

Binary search tree wikipedia , lookup

B-tree wikipedia , lookup

Transcript
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.