Corning Community College CSCS2320 Data Structures ======Project: SLN0====== =====Errata===== This section will document any updates applied to the project since original release: * __revision #__: (DATESTAMP) =====Objective===== In this project, we start conceptualizing aspects of the program we wrote in last week's project (with the arrays), and start looking at each unit of information as an arbitrary **node** unit, connected to its immediate proceeding neighbor via a **link**. This gets us into a central theme of the course which we'll be running with from now until the end- the idea of linked nodes, or in our current case: singly-linked nodes. =====Overview===== For this project, we will explore a variation of C-like pseudo-code and drawings. The pseudocode can easily be in a file you can submit using the submit tool. As for the drawings- I will take submission of these as actually handing me sheets of paper; or, you may digitize your work and submit it in an archive along with the pseudocode. Please, do **NOT** put any drawings or pseudocode related to your solutions to this project's problems on your Journal. I don't want it to be a temptation to others. ====A node==== A node is an arbitrary unit of information we will be using this semester in our study of algorithms and organization of data. We will be creating it, and then using it much as we would any of the existing data types and variables we make use of in C. For starters, our "node" will contain two items: * a data field called **info** * an arrow pointing to the next neighboring node to our immediate right, called **right** If we do not have another node to point an arrow at, we'll want to point it at a specific value indicating nothing. In our case, that value is **NULL** (must be all caps). As such, if we were to have a solitary node containing a 17, and its 'to' pointer pointing at nothing (NULL), it could be drawn as follows: {{ :haas:fall2017:data:projects:sln0-0.png |}} ===names and nodes=== Now, it is important to keep tabs on our nodes, in some form. A node can exist, but if we have no means of getting to it, it is lost in space, unavailable to us. For this reason, we often assign names to some of our nodes. Especially as a means of identifying the starting node in a group of nodes. If we were planning to have a group of nodes (we might call it a **list**), we'd more than likely want (at least) to identify the first node in that group by a name, say: **start** So here is a picture of what that same node would look like, while also associating a variable known as **start** with it. {{ :haas:fall2016:data:projects:sln0-1.png |}} ===temporary node variables=== We may also wish to assign additional names to certain nodes, to be used in on-going transactions on the group. As these variables are destined to change frequently, we may think of them more as "temporary" variables, and we'd assign a name fitting of such a role, say: **tmp** To assign a **tmp** variable to point at our existing node (which can be referenced by our **start** variable), we'd use the following pseudocode: tmp = start; And that would produce the following result: {{ :haas:fall2016:data:projects:sln0-2.png |}} Note that **tmp** does **NOT** point to **start**, which points to the node-- instead, **tmp** points to what **start** points to. This is very important. ===altering the contents of a node=== To change the value in the node (to, say 57), we'd use the following pseudocode logic (note that, in order to access the node, it needs to have a name): tmp -> info = 57 That would leave us with the following image: {{ :haas:fall2016:data:projects:sln0-3.png |}} ===connecting two nodes together=== If we had a second node, **tmp2**, containing a 37 and pointing at nothing, we'd have a scenario like this: {{ :haas:fall2016:data:projects:sln0-4.png |}} If we wanted start's node to point to tmp2's node, we'd want to do something like this: start -> right = tmp2 (as tmp was also pointing to the same node, we could just as easily have said "tmp -> right = tmp2", and we may have wanted to use that approach instead, as the idea behind **start** is to use it as an anchoring reference point only). The result of that assignment results in the following: {{ :haas:fall2016:data:projects:sln0-5.png |}} ===connecting a new node, which becomes the start=== What if we were to add a third node to our scenario (containing a 48): {{ :haas:fall2016:data:projects:sln0-6.png |}} We have our existing two connected nodes, and our new node, currently identified by **tmp3**. Now, what if we wanted tmp3 to be the left-most node in our group? How would we connect it? Like this: tmp3 -> right = start {{ :haas:fall2016:data:projects:sln0-7.png |}} BUT: the intention of having **start** is to always have it pointing at the FIRST node in our list. So, as a result of that assignment, we need to re-assign start. We do so as follows: start = tmp3 That results in the following: {{ :haas:fall2016:data:projects:sln0-8.png |}} Note that, at any point, the tmp/tmp2/tmp3 variables can go away, yet we'd still have control over our nodes (via start): tmp = tmp2 = tmp3 = NULL {{ :haas:fall2016:data:projects:sln0-9.png |}} If it hasn't become obvious yet, drawing pictures like this (especially in a step-by-step manner) will be invaluable in aiding you through both debugging and solving these various tasks you'll face this semester. The longer you hold out and resist from drawing pictures, the longer a lot of this may be difficult or frustrating. ====Creating a node==== To create a node, in pseudo-code, we call a special "**mknode()**" function. As a parameter, it takes the value we wish to initially be present in the node (the **info** field). **mknode()** returns the location of this new node, so in order to prevent it from getting lost, we need to assign a variable to it (much as our start, tmp, tmp2, tmp3 variables do). In this case, let us assign our variable **tmp** to this newly created node containing a 12: tmp = mknode(12) The picture drawn should resemble: {{ :haas:fall2016:data:projects:sln0-a.png |}} ====Copying a node==== We also have the ability to copy an existing node. This will duplicate the node and its contents (two copies). If we wanted tmp2 to be a copy of tmp, we'd say: tmp2 = cpnode(tmp) Which would give us: {{ :haas:fall2016:data:projects:sln0-b.png |}} Note that assigning a variable to an existing node is NOT the same as copying. If we were to say: tmp3 = tmp Does this create another copy? NO. It merely creates a scenario where two variables reference one node: {{ :haas:fall2016:data:projects:sln0-c.png |}} ====Removing a node==== We also have the ability to remove (de-allocate) a node. If we are all done with it, we should be sure we remove it so it is no longer using any resources. This will de-allocate the node referenced by tmp2: tmp2 = rmnode(tmp2) The result will be this: {{ :haas:fall2016:data:projects:sln0-d.png |}} We can run into interesting situations when we remove a node that has multiple variables pointing at it. For instance-- tmp and tmp3. If we were to say: tmp3 = rmnode(tmp3) We'd potentially end up with the following scenario: {{ :haas:fall2016:data:projects:sln0-e.png |}} That's because when we de-allocate, it doesn't immediately go away, but is merely marked for removal. We should not rely on that data being there, even though it may still be accessible. This is an example of what may result in **undefined behavior**, and could certainly lead to unexpected run-time errors, typically of the form **segmentation fault**. So, in the case of nodes with multiple variable references, if we care about those variables, we should take care to properly set them. =====Project===== Last week's project used an array to perform various transactions on a collection of items. What was the array will become a set of nodes, linked together in the fashion described in this project. We used nodes in a productive manner- under the guise of a list, which is merely a way of organizing nodes. It is important to note, with a list, that any anchoring variables (such as **start**) MUST point to their respective part of the list. If a change results in the invalidation or alteration of that variable's position, it MUST be adjusted so that it can retain its value as a list marker. Temporary variables come and go.. feel free to make use of them as needed; just make sure you don't overcomplicate a problem by using too many. For this project, I would like for you to write me the necessary pseudocode and draw the necessary step-by-step pictures to correctly accomplish the following. The pseudocode should go in a file called **sln0.text** to be submitted, and pictures drawn can be submitted electronically (even uploaded to lab46 and submitted using the submit tool). Do this for the following: ====Building a list==== Let's say we had a list generated with the following: start = tmp = mknode(2) tmp -> right = mknode(4) tmp = tmp -> right start -> right -> right = mknode(8) tmp = tmp -> right tmp -> right = mknode(16) What does the resulting list look like? Where are the start and tmp variables pointing? ====Inserting into the list==== Write the code and draw the pictures to show the steps necessary for putting a new node (containing a 6) BEFORE the node containing an 8 ====Inserting into the list==== Assuming you do not know the composition of the list, write the code and draw the pictures to show the steps necessary for putting a new node (containing a 0) BEFORE the node containing a 2 ====Displaying the list==== Assuming you do not know the composition of the list, write the code to display the list contents from start to end (end is defined as when a node's 'right' pointer points to NULL) ====Appending to the list==== Assuming you do not know the composition of the list, write the code and draw the pictures to show the steps necessary for putting a new node (containing a 1) after the node containing a 0 ====Grabbing from the list==== Assuming you do not know the composition of the list, write the code and draw the pictures to show the steps necessary for taking the node containing 6 and disconnecting it from the list. You may deallocate the node once properly disconnected. ====Appending to the list==== Assuming you do not know the composition of the list, write the code and draw the pictures to show the steps necessary for putting a new node (containing a 12) after the node containing an 8 ====Copying the list==== Assuming you do not know the composition of the list, write the code and draw the pictures to show the steps necessary for taking the existing list (as referenced by start), and make a copy of that list, where the copied list is referenced by a variable called start2. ====Grabbing from the list==== Assuming you do not know the composition of the list, write the code and draw the pictures to show the steps necessary for taking the node containing 0 (from the copied list) and disconnecting it from that list. You may deallocate the node once properly disconnected. ====Final Results==== Draw pictures showing the final states of both lists, with respective variables pointing to nodes (or NULL, as appropriate). =====Submission Criteria===== To be successful in this project, the following criteria must be met: * Project must be submit on time, by the posted deadline. * Late submissions will lose 25% credit per day, with the submission window closing on the 4th day following the deadline. * Sufficient comments explaining the point of provided logic **MUST** be present * Submit a copy of your results to me using the **submit** tool (**make submit** will do this) by the deadline. * Have it on paper? You can digitize the final result, upload it to lab46 and submit it, or just hand me your submission on paper (it better be legible and neat). ====Submit Tool Usage==== Let's say you have completed work on the project, and are ready to submit, you would do the following (assuming you have a program called list.txt): lab46:~/src/data/sln0$ submit data sln0 list.jpg listpseudo.txt Submitting data project "sln0": -> list.jpg(OK) -> listpseudo.txt(OK) SUCCESSFULLY SUBMITTED lab46:~/src/data/sln0$