User Tools

Site Tools


haas:spring2015:data:projects:dlt0

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
haas:spring2015:data:projects:dlt0 [2015/04/26 17:03] – [Errata] wedgehaas: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 #__<description> (DATESTAMP)+  * __revision 1__unit test for **traverse_r()** now available (20150502) 
 +  * __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 of two connections- often these are called 'binary' trees. We will use that description interchangeably here with 'doubly linked trees'+The simplest conceptual tree is one which has a maximum of two connections- often these are called 'binary' trees. We will use that description interchangeably here with 'doubly linked trees'.
- +
-The premise behind a tree is that of a parent-child relationship. Each node can be a parent (of two child nodes), and each child can in turn be its own parent (of two child nodes). This creates a connection between relationships of nodes (ie a parent and its descendants), and ends up offering some interesting and useful algorithmic opportunities, along with implementation experience. +
- +
-====A slight Node modification==== +
-With the tree project, we see a modification to our venerable node struct, used consistently and throughout our adventures this semester. +
- +
-We keep all the existing content (and changes) that have endured up to this point, and we merely add one additional member: an **other** pointer that can see use in our //iterative// and //stack-based// implementations of various tree operations. +
- +
-This will also mean mild tweaks are needed to the node library functions, and updated unit tests that will need to be verified.+
  
 +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), and ends up offering some interesting and useful algorithmic opportunities, along with implementation experience.
 ====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 "root" at the very top, and all the branches (nodes, and connections to nodes) growing down and out from the root. 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 "root" at the very top, and all the branches (nodes, and connections to nodes) growing down and out from the root.
Line 39: 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/ordering of values, among other things).   * 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/ordering of values, among other things).
  
-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 53: 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? That speaks to what we're exploring in Data Structures- ideas. It isn't as much about WHAT we're manipulating (nodes), but HOW.
  
-====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 _NODE_H +// 
- +#define  DLT_SUCCESS        256 
-#include <stdlib.h> +#define  DLT_CREATE_FAIL    512 
- +#define  DLT_NULL           1024 
-struct node { +#define  DLT_EMPTY          2048 
-        char         data; +#define  DLT_MAX            4096 
-        struct node *other; +#define  DLT_DEFAULT_FAIL   16384 
-        struct node *prev; +#define  DLT_FAIL           32768
-        struct node *next; +
-}; +
-typedef struct node Node; +
- +
-Node *mknode(char  );     // allocate new node containing value +
-Node *rmnode(Node *);     // deallocate node +
-Node *cpnode(Node *);     // duplicate node +
- +
-#endif+
 </code> </code>
  
 +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/tree.h==== ====In inc/tree.h====
  
Line 84: Line 72:
 #define _TREE_H #define _TREE_H
  
 +#include "data.h"
 #include "list.h" #include "list.h"
- 
-#define  RECURSIVE     0 
-#define  STACK_BASED   1 
-#define  ITERATIVE     2 
  
 #define  INORDER       0 #define  INORDER       0
Line 94: Line 79:
 #define  POSTORDER     2 #define  POSTORDER     2
  
-typedef struct tree Tree; 
 struct tree { struct tree {
-    Node *root;                     // pointer to root node of tree +    Node *root;                         // pointer to root node of tree 
-    char  max_height;               // max height of tree (0 = unlimited+    uc    max_height;                   // max height of tree (0 = unlimited)
-    char  height;                   // current height of tree +
-    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    (char           );  // create new tree+code_t mktree    (Tree **, uc        ); // create new tree 
 +code_t cptree_r  (Tree  *, Tree **   ); // copy given tree (recursive) 
 +code_t rmtree    (Tree **            ); // purge and deallocate tree
  
-Tree *set_mode  (Tree *, char   );  // set tree mode (recursestackiter)+code_t addnode   (Tree **, Node *    ); // add given node to tree 
 +code_t grabnode_r(Tree **, Node **   ); // get node from tree (recursive) 
 +code_t traverse_r(Tree  *List **,uc); // traverse tree by mode (recursive)
  
-Tree *addnode   (Tree *, Node * );  // add given node to tree +code_t searchtree(Tree  *, Node **,sc); // find node in tree (by value)
- +
-Tree *copytree_s(Tree *         );  // copy/duplicate given tree (stack-based) +
-Tree *copytree_r(Tree *         );  // copy/duplicate given tree (recursion) +
-Tree *copytree_i(Tree *         );  // copy/duplicate given tree (iterative) +
- +
-Node *searchtree(Tree *, char   );  // find node in 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   );  // stack-based traverse (in mode) +
-List *traverse_r(Tree *, char   );  // recursive traverse (in mode) +
-List *traverse_i(Tree *, char   );  // iterative traverse (in mode) +
- +
-Tree *rmtree    (Tree *         );  // purge and deallocate tree +
- +
-Tree *balance   (Tree *         );  // rebalanced tree (root is midpoint) +
- +
-void  print_tree(Tree *         );  // display tree structure (to STDOUT)+
  
 #endif #endif
Line 139: Line 104:
 Figure out what is going on, the connections, and make sure you understand it. Figure out what is going on, the connections, and make sure you understand it.
  
-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, but we look more closely at how we got there (ie the three different implementation approaches). +===Suggested Implementation Order=== 
-====Reference Implementation==== +To make your life easierI recommend implementing tree library functions in the following order:
-As the layers and complexities risenarrowing 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 to import functioning node, list, and stack implementations into your project for the purposes of testing your tree functionality.+You will really want the later functions to make use of the earlier functions to facilitate implementation (ie **cptree_r()** will likely want to make use of **traverse_r()** and **addnode()**, and **rmtree()** could take advantage of **traverse_r()** and **searchtree()** and **grabnode_r()**).
  
-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 earlieras it only really needs **mktree()**, but you may find its implementation more involved.
- +
-===Using the test reference implementation=== +
-You'll notice that, upon running **make help** in the base-level Makefile, the following new options appear (about halfway in the middle)+
- +
-<cli> +
-**                                                                    ** +
-** make use-test-reference  - use working implementation object files ** +
-** make use-your-own-code   - use your node/list implementation code  ** +
-**                                                                    ** +
-</cli> +
- +
-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: +
- +
-<cli> +
-lab46:~/src/data/dlt0$ make use-test-reference +
-... +
-NODE, LIST, and STACK reference implementation in place, run 'make' to build everything. +
-lab46:~/src/data/dlt0$  +
-</cli> +
- +
-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: +
- +
-<cli> +
-lab46:~/src/data/dlt0$ make +
-... +
-</cli> +
- +
-**__Debugging__:** When using the test reference implementation, you will not be able to debug the contents of the nodelist, and stack functions (the files provided do not have debugging symbols added), so you'll need to take care not to step into these functions (it would be just like stepping into **printf()**. You can still compile the project with debugging support and debug (as usual) those compiled functions (ie the stack functions). +
- +
-===Reverting back to using your code=== +
-If you were trying out the reference implementation to verify tree functionality, and wanted to revert back to your own code, it is as simple as: +
- +
-<cli> +
-lab46:~/src/data/dlt0$ make use-your-own-code +
-Local node/list/stack implementation restored, run 'make clean; make' to build everything. +
-lab46:~/src/data/dlt0$  +
-</cli> +
-====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/tree/unit/**, you will //eventually// find these files: In **testing/tree/unit/**, you will //eventually// find these files:
Line 194: 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 functions +  * **unit-grabnode.c** - unit test for **grabnode_r()** library function 
-  * **unit-set_mode.c** - unit test for **set_mode()** library function +  * **unit-mktree.c**   - unit test for the **mktree()** library function 
-  * **unit-balance.c** - unit test for **balance()** library function +  * **unit-cptree.c**   - unit test for **cptree_r()** library function 
-  * **unit-treeops.c**   - unit test for {mk,rm}tree library functions +  * **unit-rmtree.c**   - unit test for **rmtree()** library function 
-  * **unit-traverse.c** - unit test for **traverse_*()** library functions +  * **unit-traverse.c** - unit test for **traverse_r()** library function
-  * **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, not all unit tests are available/fully functional; so expect some updates.
  
 There are also corresponding **verify-FUNCTION.sh** scripts that will output a "MATCH"/"MISMATCH" to confirm overall conformance with the pertinent tree functionality. There are also corresponding **verify-FUNCTION.sh** scripts that will output a "MATCH"/"MISMATCH" to confirm overall conformance with the pertinent tree functionality.
Line 223: Line 151:
 To assist you in verifying a correct implementation, a fully working implementation of the node and tree libraries should resemble the following (when running the respective verify script): To assist you in verifying a correct implementation, a fully working implementation of the node and tree libraries should resemble the following (when running the respective verify script):
  
- 
-====node library==== 
-Here is what you should get for node: 
- 
-<cli> 
-lab46:~/src/data/dlt0$ bin/verify-node.sh  
-==================================================== 
-=    Verifying Doubly-Linked Node Functionality    = 
-==================================================== 
-  [mknode] Total:   6, Matches:   6, Mismatches:   0 
-  [cpnode] Total:   8, Matches:   8, Mismatches:   0 
-  [rmnode] Total:   2, Matches:   2, Mismatches:   0 
-==================================================== 
- [RESULTS] Total:  16, Matches:  16, Mismatches:   0 
-==================================================== 
-lab46:~/src/data/dlt0$  
-</cli> 
- 
-With the addition of the **other** pointer, we have a few additional combinations to test. 
  
  
haas/spring2015/data/projects/dlt0.1430067784.txt.gz · Last modified: 2015/04/26 17:03 by wedge