This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
haas:spring2015:data:projects:dlt0 [2015/04/26 17:04] – [A slight Node modification] wedge | haas:spring2015:data:projects:dlt0 [2015/05/03 13:58] (current) – [Errata] wedge | ||
---|---|---|---|
Line 11: | Line 11: | ||
This section will document any updates applied to the project since original release: | This section will document any updates applied to the project since original release: | ||
- | * __revision | + | * __revision |
+ | * __revision 2__: unit tests for **cptree_r()** and **rmtree()** now available (20150502) | ||
+ | * __revision 3__: unit tests for **grabnode_r()** now available (20150503) | ||
+ | |||
=====Objective===== | =====Objective===== | ||
Line 21: | Line 25: | ||
Truth be told, the simplest tree is merely a list- the underlying data structure we've worked with all semester. But now, under this new light, we can start to look at a list as merely a procession of singled childed nodes. The more things are different, the more they are the same... | Truth be told, the simplest tree is merely a list- the underlying data structure we've worked with all semester. But now, under this new light, we can start to look at a list as merely a procession of singled childed nodes. The more things are different, the more they are the same... | ||
- | The simplest conceptual tree is one which has a minimum | + | The simplest conceptual tree is one which has a maximum |
- | + | ||
- | The premise behind a tree is that of a parent-child relationship. Each node can be a parent (of up to two child nodes), and each child can in turn be its own parent (of up to two child nodes). This creates a connection between relationships of nodes (ie a parent and its descendants), | + | |
+ | The premise behind a binary tree is that of a parent-child relationship. Each node can be a parent (of up to two child nodes), and each child can in turn be its own parent (of up to two child nodes). This creates a connection between relationships of nodes (ie a parent and its descendants), | ||
====conceptualizing a tree==== | ====conceptualizing a tree==== | ||
It is common to think of a tree as a vertical structure, upside-down from the item we commonly think of in nature. Here we will have the tree's " | It is common to think of a tree as a vertical structure, upside-down from the item we commonly think of in nature. Here we will have the tree's " | ||
Line 33: | Line 35: | ||
* a tree has a **root** which forms the basis or starting point of the structure; all nodes are reachable (and related through means of descendance) from the root. | * a tree has a **root** which forms the basis or starting point of the structure; all nodes are reachable (and related through means of descendance) from the root. | ||
- | * to put an item on the tree, we insert or **add** it (which you will have 3 separate opportunities to implement in this project!). When we add a node to the tree, it gets positioned in the appropriately available child link off some parent node. | + | * to put an item on the tree, we insert or **add** it. When we add a node to the tree, it gets positioned in the appropriately available child link off some parent node. |
- | * to get an item off of the tree, we **grab** it (my term- often times it is referred to as deleting a node from the tree). Just as with a list, disconnecting a node from the structure can involve a lot of work to maintain connections and overall integrity of the data structure. | + | * to get an item off of the tree, we **grab** it (my term- often times it is referred to as deleting a node from the tree). Just as with a list and its obtain action, disconnecting a node from the structure can involve a lot of work to maintain connections and overall integrity of the data structure. |
* an important action that will be taking place is the traversal of the tree- ie walking it in certain orders to achieve desired results (sorting/ | * an important action that will be taking place is the traversal of the tree- ie walking it in certain orders to achieve desired results (sorting/ | ||
- | As we will be placing nodes in the tree according to their stored values (lesser values go to the left, or previous; greater values go to the right, or next), our tree will naturally sort our data for us. | + | As we will be placing nodes in the tree according to their stored values (lesser values go to the left, or prior; greater values go to the right, or after), our tree will naturally sort our data for us, allowing us to search through its contents quite advantageously. As such, the tree we will be implementing is also known as a //binary search tree//. |
====tree height can matter==== | ====tree height can matter==== | ||
Line 47: | Line 48: | ||
=====Project Overview===== | =====Project Overview===== | ||
- | For this project, we're going to be implementing the tree data structure utilizing nodes. | + | For this project, we're going to be implementing the tree data structure utilizing nodes. Isn't it neat how we've been able to use this same basic structure in so many different ways and configurations? |
- | ====In inc/node.h==== | + | ====In inc/data.h==== |
+ | Here we see some additional status code defines: | ||
<code c 1> | <code c 1> | ||
- | #ifndef _NODE_H | + | // Status codes for the tree implementation |
- | # | + | // |
- | + | #define | |
- | #include < | + | # |
- | + | # | |
- | struct node { | + | #define |
- | char | + | # |
- | struct node *other; | + | # |
- | struct node *prev; | + | #define |
- | struct node *next; | + | |
- | }; | + | |
- | typedef struct node Node; | + | |
- | + | ||
- | Node *mknode(char | + | |
- | Node *rmnode(Node *); // deallocate node | + | |
- | Node *cpnode(Node *); // duplicate node | + | |
- | + | ||
- | #endif | + | |
</ | </ | ||
+ | I also created the typedefs **sc** and **uc** to simplify the declaration of **signed char**s and **unsigned char**s (respectively). These can me seen just above the bottom of the file. | ||
====In inc/ | ====In inc/ | ||
Line 78: | Line 72: | ||
#define _TREE_H | #define _TREE_H | ||
+ | #include " | ||
#include " | #include " | ||
- | |||
- | # | ||
- | # | ||
- | # | ||
# | # | ||
Line 88: | Line 79: | ||
# | # | ||
- | typedef struct tree Tree; | ||
struct tree { | struct tree { | ||
- | Node *root; | + | Node *root; |
- | | + | |
- | char height; | + | |
- | Tree *(*copy)(Tree * ); // copy tree (function pointer) | + | |
- | Tree *(*grab)(Tree *, Node **); // grab node (function pointer) | + | |
- | List *(*walk)(Tree *, char ); // walk tree (function pointer) | + | |
}; | }; | ||
+ | typedef struct tree Tree; | ||
- | Tree *mktree | + | code_t |
+ | code_t cptree_r | ||
+ | code_t rmtree | ||
- | Tree *set_mode | + | code_t addnode |
+ | code_t grabnode_r(Tree **, Node ** ); // get node from tree (recursive) | ||
+ | code_t traverse_r(Tree | ||
- | Tree *addnode | + | code_t searchtree(Tree *, Node **,sc); // find node in tree (by value) |
- | + | ||
- | Tree *copytree_s(Tree * | + | |
- | Tree *copytree_r(Tree * | + | |
- | Tree *copytree_i(Tree * | + | |
- | + | ||
- | Node *searchtree(Tree | + | |
- | + | ||
- | Tree *grabnode_s(Tree *, Node **); // stack-based grabnode | + | |
- | Tree *grabnode_r(Tree *, Node **); // recursive grabnode | + | |
- | Tree *grabnode_i(Tree *, Node **); // iterative grabnode | + | |
- | + | ||
- | List *traverse_s(Tree *, char | + | |
- | List *traverse_r(Tree *, char | + | |
- | List *traverse_i(Tree *, char | + | |
- | + | ||
- | Tree *rmtree | + | |
- | + | ||
- | Tree *balance | + | |
- | + | ||
- | void print_tree(Tree * | + | |
#endif | #endif | ||
Line 133: | Line 104: | ||
Figure out what is going on, the connections, | Figure out what is going on, the connections, | ||
- | Of particular focus in this project, in addition to the important tree concepts, is that of implementation. Until now we've only bothered to just get it done and working... now, not only do we care about functionality, | + | ===Suggested |
- | ====Reference | + | To make your life easier, I recommend implementing tree library functions in the following order: |
- | As the layers and complexities rise, narrowing down the source of errors becomes increasingly important. | + | |
- | If your tree copytree_i() isn't working, is it because of a problem with your tree? Or might it be in an underlying node operation it relies upon? | + | - **mktree()** |
+ | - **addnode()** | ||
+ | - **searchtree()** | ||
+ | - **traverse_r()** | ||
+ | - **grabnode_r()** | ||
+ | - **cptree_r()** | ||
+ | - **rmtree()** | ||
- | To aid you in your development efforts, you now have the ability | + | You will really want the later functions |
- | This also provides another opportunity for those who have fallen behind to stay current, as they can work on this project without having needed to successfully get full node or stack (and by extension- list) functionality. | + | Note that **grabnode_r()** can be implemented earlier, as it only really needs **mktree()**, but you may find its implementation |
- | + | ||
- | ===Using the test reference implementation=== | + | |
- | You'll notice | + | |
- | + | ||
- | < | + | |
- | ** ** | + | |
- | ** make use-test-reference | + | |
- | ** make use-your-own-code | + | |
- | ** ** | + | |
- | </ | + | |
- | + | ||
- | In order to make use of it, you'll need to run **make use-test-reference** from the base of your **dlt0** project directory, as follows: | + | |
- | + | ||
- | < | + | |
- | lab46: | + | |
- | ... | + | |
- | NODE, LIST, and STACK reference implementation in place, run ' | + | |
- | lab46: | + | |
- | </ | + | |
- | + | ||
- | You'll see that final message indicating everything is in place (it automatically runs a **make clean** for you), and then you can go ahead and build everything with it: | + | |
- | + | ||
- | < | + | |
- | lab46: | + | |
- | ... | + | |
- | </ | + | |
- | + | ||
- | **__Debugging__: | + | |
- | + | ||
- | ===Reverting back to using your code=== | + | |
- | If you were trying out the reference | + | |
- | + | ||
- | < | + | |
- | lab46: | + | |
- | Local node/ | + | |
- | lab46: | + | |
- | </ | + | |
- | ====Node Library unit tests==== | + | |
- | As a result of the addition of **other**, an updated set of unit tests will be released (this will mean a different number of total tests for list than previously). | + | |
- | + | ||
- | Be sure to run the various node unit tests and verification scripts to see which functions have fallen out of compliance with the node struct specification changes issued in this project. The **verify-node.sh** script can be especially useful in getting a big picture view of what work is needed. | + | |
====Tree library unit tests==== | ====Tree library unit tests==== | ||
In **testing/ | In **testing/ | ||
Line 188: | Line 123: | ||
* **unit-addnode.c** - unit test for the various **addnode()** library function | * **unit-addnode.c** - unit test for the various **addnode()** library function | ||
* **unit-searchtree.c** - unit test for the various **searchtree()** library function | * **unit-searchtree.c** - unit test for the various **searchtree()** library function | ||
- | * **unit-grab.c** - unit test for **grabnode_*()** library | + | * **unit-grabnode.c** - unit test for **grabnode_r()** library |
- | * **unit-set_mode.c** - unit test for **set_mode()** library function | + | * **unit-mktree.c** |
- | * **unit-balance.c** - unit test for **balance()** library function | + | * **unit-cptree.c** |
- | * **unit-treeops.c** - unit test for {mk, | + | * **unit-rmtree.c** - unit test for **rmtree()** |
- | * **unit-traverse.c** - unit test for **traverse_*()** library | + | * **unit-traverse.c** - unit test for **traverse_r()** library |
- | * **unit-print.c** - unit test for displaying tree structure | + | |
- | **NOTE**: At the time of project release, unit tests are not yet available; so they will be released as they are developed. | + | **NOTE**: At the time of project release, |
There are also corresponding **verify-FUNCTION.sh** scripts that will output a " | There are also corresponding **verify-FUNCTION.sh** scripts that will output a " | ||
Line 217: | Line 151: | ||
To assist you in verifying a correct implementation, | To assist you in verifying a correct implementation, | ||
- | |||
- | ====node library==== | ||
- | Here is what you should get for node: | ||
- | |||
- | <cli> | ||
- | lab46: | ||
- | ==================================================== | ||
- | = Verifying Doubly-Linked Node Functionality | ||
- | ==================================================== | ||
- | [mknode] Total: | ||
- | [cpnode] Total: | ||
- | [rmnode] Total: | ||
- | ==================================================== | ||
- | | ||
- | ==================================================== | ||
- | lab46: | ||
- | </ | ||
- | |||
- | With the addition of the **other** pointer, we have a few additional combinations to test. | ||