An Example of Good Documentation Style
CSCI 311
PROGRAM: AVL TREE
AVLTREE.H
// AVLTree.h: interface for the AVLTree class.
//
//////////////////////////////////////////////////////////////////////
/****************************************************************
* Name: XXXXXXXXXXXXXXXXXXX
*
* Class Computer Science 151
*
* Assignment: Program 2
*
*
*
****************************************************************
Program 2: AVLTrees
Status Of Program: Completed
main() Complete and Tested
Usage() Complete and Tested
Class AVLTree Complete and Tested
AddKeyItem() Complete
AVLTree() Complete
~AVLTree() Complete
BalanceStack() Complete
DebugCheckTree() Complete
DebugVerifyTree() Complete
DeleteKeyItem() Complete
DeleteTree() Complete
FindImmediatePredecessor() Complete
FindImmediateSuccessor() Complete
GetStatusMessage() Complete
InOrderTraversal() Complete
LocateInsertDeletePosition() Complete
NodeBalanceFactor() Complete
NodeHeight() Complete
PostOrderTraversal() Complete
PreOrderTraversal() Complete
PrintNode() Complete
PrintNodeData() Complete
Rebalance() Complete
Rotate() Complete
SetFileOut() Complete
traverse_AVL_Inorder() Complete
traverse_AVL_PostOrder() Complete
traverse_AVL_PreOrder() Complete
UnwindAVLStack() Complete
UnwindQueues() Complete
Program Overview:
Functional Description:
This program generates an AVL tree, then reads commands from an input file,
processes those commands and sends the results to the specified output file.
See the "Commands and Formats" table in the specifications document.
Operational Description:
The program reads lines from a file specified in the program command line. Each command line is parsed and the commands are selected using the characters specified in the commands and formats table. Several commands (Add, Delete and Search) have additional fields containing a required integer. Results are sent to an output file, also specified in the command line.
The command line is AVLTrees CmdFile OutputFile [DEBUG].
CmdFile is the input file with commands.
OutputFile is the results file.
The DEBUG command line option changes the output format and causes the
AVLTree::DebugVerifyTree() function to be called after every node addition
or deletion to check the viability of the code.
****************************************************************************
Classes
******************************************************************************
AVLTree
Purpose: The AVL tree is maintained in an AVLTree class.
This class generates the tree and controls all access, additions and deletions.The AVLTree class utilizes a stack and several queues to track movement within the tree.
Functions: See the Specifications and Status Document.
******************************************************************************
Other Objects:
******************************************************************************
I_Node
Purpose: Structure defining a the node data to be stored in the AVL
tree.
******************************************************************************
Other Functions:
Usage()
Purpose: Displays the instructions to run this program.
TrimLine()
Purpose: Trim the command line (remove spaces from the front and
back).
******************************************************************************
Note:
All functions are original code except for AVLTree::traverse_AVL_Inorder(),AVLTree::traverse_AVL_PostOrder() and AVLTree::traverse_AVL_PreOrder() which were copied from the examples in the workbook and modified to format the output.
*/
#if !defined(AFX_AVLTREE_H__275508E6_2E7B_11D4_805C_080009B93EFF__INCLUDED_)
#define AFX_AVLTREE_H__275508E6_2E7B_11D4_805C_080009B93EFF__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <stack>
#include <queue>
#include "fstream.h"
//***************************************************************************
// AVLTree.h: header file for the AVLTree class. contains class declarations
// and information.
//
#define ROTATELEFT 100
#define ROTATERIGHT 101
//*************************************************************
// Structure: I_Node (integer node)
// Purpose: Used by the AVLTree class to hold integer data for the tree
// Archetecure
struct I_Node
{
int iValue; // KeyValue also data
I_Node *LeftChild; // Pointer to the LeftChildNode
I_Node *RightChild; // Ponter to the RightChildNode
int iHeight; // position in the tree from the bottom
// if this is a leaf node it will have a 0 height
// this is an absolute value
int iBalanceFactor; // Right child height - left child height
//
//
//
I_Node() // Constructor for I_Node
{
LeftChild=NULL;
RightChild=NULL;
iHeight=0;
iBalanceFactor=0;
} // constructor
//
};
//*************************************************************
// Class: AVLTree
// Purpose: Implement an AVL Tree with an integer key and provide the
//appropriate access to the tree.
//
//
//
// Implementation Note: We want to convert this to a template in the future.
class AVLTree
{
public:
AVLTree(); //Constructor: initializes Class variables
virtual ~AVLTree(); //Destructor: Deallocates any memory allocated
void SetFileOut(ofstream *ofile); // Set the target file
char * GetStatusMessage(); // Results of previous operation
I_Node * AddKeyItem(int ivalue); // Add a node to the tree
bool DeleteKeyItem(int iValue); // Remove a node from the tree
I_Node * FindValue(int iSearchKey); // Search for the key in the tree
//
//
// Traversals
//
void PostOrderTraversal(ofstream *ofile);
void PreOrderTraversal(ofstream *ofile);
void InOrderTraversal(ofstream *ofile);
private: //Functions
void BalanceStack();
int DebugCheckTree(I_Node *itree_ptr);
void DebugVerifyTree();
void DeleteTree(I_Node *rootptr);
int FindImmediateSuccessor(I_Node *inode);
int FindImmediatePredecessor(I_Node *inode);
I_Node * LocateInsertDeletePosition(int iValue);
int NodeBalanceFactor(I_Node *inode);
int NodeHeight(I_Node *inode);
void PrintNode(I_Node *inode);
void PrintNodeData(I_Node *inode, bool bPrintTitle=false);
void Rebalance(I_Node *UnBalancedNode, I_Node *ParentOfUnBalancedNode);
void Rotate(int iRotateType,I_Node *PivotNode, I_Node *ParentNode);
void traverse_AVL_PostOrder(I_Node *itreeptr);
void traverse_AVL_PreOrder(I_Node *treeptr);
void traverse_AVL_Inorder(I_Node *itree_ptr);
void UnwindAVLStack();
void UnwindQueues();
private: //Data
I_Node * Root; // Pointer to the root node
int iNodeCount; // Number of Nodes in the tree
char StatusString[100]; // What happened in the last operation
bool bError; // Some type of error in the last operation
bool bFound; // Search string was found
ofstream * OutFile; // Output File Stream
//
// We must specify the std name space here
// because stack is a Standard Library template
//
std::stack<I_Node *> AVLStack; // Declare the stack
std::queue<I_Node *> PredecessorQueue;
std::queue<I_Node *> SuccessorQueue;
};
#endif // !defined(AFX_AVLTREE_H__275508E6_2E7B_11D4_805C_080009B93EFF__INCLUDED_)
AVLTREE.CPP
// AVLTree.cpp: implementation of the AVLTree class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "iomanip.h"
#include "AVLTree.h"
extern bool gDebug; //global definition
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
AVLTree::AVLTree()
{
// FUNCTION: AVLTree() //Constructor
//
// Preconditions: None
//
// PostConditions: an empty AVL tree is created
//
// Global vars: none
//
// Local vars: None
//
// Class vars: iNodeCount, Root
//
// Function Calls: None
//
// Functional Desc: Constructor; Initialize Class variables
//
// Operational Desc: Set class variables to their intial condition
iNodeCount=0; // There are no nodes in the tree
Root = NULL; // There is no root node
strcpy(StatusString,"AVLTree Initialized");
}
//*********************************************************
AVLTree::~AVLTree()
{
// FUNCTION: ~AVLTree() //Destructor
//
// Preconditions: The class existed, is now being deleted
//
// PostConditions: The tree is deleted, all memory is freed
//
// Global vars: none
//
// Local vars: None
//
// Function Calls: DeleteTree()
// UnwindQueues()
// UnwindAVLStack()
//
// Functional Desc: Deletes the AVL tree and all memory allocated
// in this calls
//
// Operational Desc: Calls DeleteTree() to delete all nodes in the tree.
// UnwindAVLStack and UnwindQueues
// to ensure that
// these objects are ready for deletion.
//
UnwindQueues(); // Clear the Queue Memory
UnwindAVLStack(); // Clear the stack memory
DeleteTree(Root); // Clear the tree
} //AVLTree::~AVLTree()
//*********************************************************
I_Node * AVLTree::FindValue(int iSearchKey)
{
// FUNCTION: I_Node * FindValue(int iSearchKey)
//
// Preconditions: iSearchKey contains the integer value to search on
//
// PostConditions: Returns a pointer to the node with the matching // value
//
//
// Global vars: none
//
// Class vars: Root
//
// Local vars: I_Node *inode
//
// Function Calls:sprintf(), strcpy()
//
// Functional Desc: Search the tree for a specific value
//
// Operational Desc: Check for a NULL root, indicating an empty tree
// At each node check for a match, then select the
// direction of the next node based on less than
// or greater than values.
//
//
// Handle an empty tree
//
if (Root == NULL) //empty tree;
{
strcpy(StatusString, "Empty Tree");
return(NULL);
}
//
I_Node *inode=Root; // set our temp variable to the root node to start
//
// check for a match at every node that we traverse.
//
while(inode !=NULL)
{
//
// Check for a match
//
if (iSearchKey == inode->iValue) //Is this a match
{
sprintf(StatusString,"Node Found: Value = %d ",inode->iValue);
//Set status
return(inode);
}// if (iSearchKey == inode->iValue)
//
// Check for greater than
//
if (iSearchKey > inode->iValue) // Go down the right hand path
{
if (inode ->RightChild == NULL)
{
strcpy(StatusString, "Node Not Found");
return(NULL);
}//if (inode ->RightChild == NULL)
inode=inode->RightChild; // getthe next node in the path
}//if (iSearchKey > inode->iValue)
else // less than
{ //
//
if (inode->LeftChild== NULL) // Node does not exist
{
strcpy(StatusString, "Node Not Found");
return(NULL);
}//if (inode->LeftChild== NULL)
inode=inode->LeftChild; // Get the next node in the path
}//if (iSearchKey > inode->iValue)
}// while(inode !=NULL)
//
// if we get to here it is an error
//
strcpy(StatusString,"Error: FindValue : Processing Error");
return(NULL);
}//I_Node * AVLTree::FindValue(int iSearchKey)
//*********************************************************
etc………………………………………….
AVLTREES.CPP
// AVLTrees.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "iostream.h" // Needed for cout
#include "fstream.h" // Needed for ifstream, ofstream
#include "string.h" // Needed for strlen
#include "stdlib.h" // Needed for atoi
#include "AVLTree.h" // AVLClass definition
//
// define non class functions called by main
//
void Usage(); // display the user commands
void TrimLine(char *iLine); // Trim whitespace from a line
//
//
// Definitions for main and non class functions
#define MAXLINESIZE 100
//
//
// Global Definitions
//
bool gDebug=false;
//****************************************************************************
int main(int argc, char* argv[])
{
// FUNCTION: int main(int argc, char *argv[])
//
// Preconditions: Command line must contain the source file and the
// target file
//
// PostConditions: none
//
// Global vars: none
//
// Local vars: XXX
//
// Function Calls:
//
// Functional Desc: Verify the command line, open the files,
// parse the source file's commands, execute the commands by
// calling appropriate functions.
//
// Operational Desc: main() first checks the command line to ensure both
// a source file and a target file have been specified.
// Then the source file and target file are opened, (if either is
// unable to be opened main() displays a message and exits).
// Each line of the source file is read and parsed. A switch
// statement controls the selection of the routines to execute
// for each of the commands.
// Both files are closed implicitly at program exit.
//
// Verify the command line
//
if ((argc != 3)&& (argc !=4)) //There must be three command line
// arguments (Program, SourceFile, TargetFile)
{
Usage(); // Display the instruction
return(1); // Exit the program
}
if (argc == 4)
{
if (strcmp("DEBUG",argv[3]) ==0)
gDebug=true;
}
//
// Instantiate the AVL Tree
//
AVLTree AVL;
//
// open the source file
//
// input mode (default)
// no create mode (To check for the files existance and not
// create it
// text mode (default)
ifstream SourceFile(argv[1], ios::nocreate);
//
// Verify the file is opened
//
if (SourceFile.fail() )
{
Usage();
cout << "***************************************" << endl;
cout << "Unable to open the InputFile: " << argv[1] << endl;
cout << "***************************************" << endl << endl;
return(1); // exit the program
}
//
// open the target file
//
ofstream TargetFile(argv[2]); // Create the outputfile instantiation
// open the output file
// Will close when the ofstream class
// destructor gets automatically called at the
// termination of the program
//
// Verify the file is opened
// display error message if the file does not exist
// (or cannot be written to)
//
if(TargetFile.fail())
{
Usage();
cout << "***************************************" << endl;
cout << "Unable to open the OutputFile: " << argv[2] << endl;
cout << "***************************************" << endl << endl;
return(1); // exit the program
}
AVL.SetFileOut(&TargetFile);
//
// Set up the loop conditions
//
char LineBuffer[MAXLINESIZE];
int iKeyValue;
bool bKeyRead; // The keyvalue has been read out of the line
//
// Start the loop
//
while( !SourceFile.eof())
{
//
// Read each line of the Source file
//
SourceFile.getline(LineBuffer,sizeof(LineBuffer));
//
// clear the white space before and after the line
// to ensure we don't have any translation problems
//
TrimLine(LineBuffer);
cout << LineBuffer << endl;
//
// Parse each line of the Source file
//
bKeyRead=(strlen(LineBuffer) >= 3);
// There is a keyvalue on this line
if (bKeyRead)
iKeyValue = atoi(&LineBuffer[2]);
//
// Save the line in the output file
//
TargetFile << LineBuffer << endl;
//
// Execute the parsed commands in the source file
//
switch (LineBuffer[0])
{
case 'A': //Add the integer to the AVL Tree;
if (!bKeyRead) // Ensure there was a keyvalue
TargetFile << "Error: No KeyValue Read" << endl;
AVL.AddKeyItem(iKeyValue);
TargetFile<< AVL.GetStatusMessage()<< endl;
break;
case 'D': // Delete the Key
if (!bKeyRead) // Ensure there was a keyvalue
TargetFile << "Error: No KeyValue Read" << endl;
AVL.DeleteKeyItem(iKeyValue);
TargetFile<< AVL.GetStatusMessage()<< endl;
break;
case 'S': // Search the tree
if (!bKeyRead) // Ensure there was a keyvalue
TargetFile << "Error: No KeyValue Read" << endl;
AVL.FindValue(iKeyValue);
TargetFile<< AVL.GetStatusMessage()<< endl;
break;
case 'P': // PreOrder Traversal
AVL.PreOrderTraversal(&TargetFile);
TargetFile<< AVL.GetStatusMessage()<< endl;
break;
case 'I': //InOrder Traversal
AVL.InOrderTraversal(&TargetFile);
TargetFile<< AVL.GetStatusMessage()<< endl;
break;
case 'R': // PostOrder traversal
AVL.PostOrderTraversal(&TargetFile);
TargetFile<< AVL.GetStatusMessage()<< endl;
break;
}
TargetFile << endl;
} // while( !SourceFile.eof())
//
// Exitted the loop
//
//
// Exit the program
//
cout << "AVLTrees: Completed" << endl;
return 0;
}
//*******************************************************************
void Usage()
{
// FUNCTION: void Usage()
//
// Preconditions: None
//
// PostConditions: Program instructions will be printed to the screen.
//
// Global vars: none
//
// Local vars: none
//
// Function Calls: None
//
// Functional Desc: Print Program instructions to the screen.
//
// Operational Desc: Print program instructions to the screen.
cout << "AVLTrees " << endl;
cout << " Version 1.0.0" << endl << endl;
cout << " Usage: AVLTrees SourceFile TargetFile [DEBUG]" ;
cout << endl<< endl;
cout << "AVLTrees is a wrapper program to test the AVLTree Class" << endl;
cout << "Programmer: Chuck Scholler" << endl;
}
//***********************************************************************
void TrimLine(char *iLine)
{
// FUNCTION: void TrimLine(char *iLine)
//
// Preconditions: iLine contain the line to be trimmed
//
// PostConditions: iLine will contain 0 or more characters in the line
// with no white space
// Modifies the original line
// Global vars: none
//
// Local vars: int ilength
//
// Function Calls: strlen()
//
// Functional Desc: Trim the whitespace at the beginning and end of
// a line
//
// Operational Desc: Work back from the end of the line
// moving the end of the line for any
// whitespaces at the end of the line.
// Then find the beginning of the line
// Copy the line to a temp char buffer,
// then copy back to move the line
//
//
// Remove the right whitespace first, this results in a lower
// copy time for the trim left.
//
int ilength = strlen(iLine);
if (ilength <=0)
return;
//
// ForLoop:
// Purpose: Remove the whitespace at the end of the line
// Assertion (Pre): iLine contains one or more characters to check
// Termination : Exit whenthe first non whitespace character is found
//
for (int i=ilength-1;i>=0;i--)
{
if (iLine[i]!= ' ') // exit the loop if this is not a space
break;
iLine[i]=0; // shorten the line
} // for (int i=ilength-1;i>=0;i--)
//
// We now have a short string, free of white space on the right
// Now trim left
//
// Find the first non white character
//
ilength = strlen(iLine); // may not be the same as before
if (ilength <=0) // Already 0 length
return;
//
// Find the beginning of the line
//
//
// ForLoop:
// Loop Assertion: iLine is a char buffer with 0 or more characters in
// it
// Loop Termination: (1) Loop will fall through when all characters have
// been checked and are blank
// (2) Loop will terminate when the first non-white
// space character is found
for (i=0;i<ilength;i++)
{
if (iLine[i] != ' ')
{
//
// We have found the beginning of line
// Do we have to move the line
//
if (i == 0) // no whitespaces to remove
return;
//
// Copy the line then back
//
char ctemp[MAXLINESIZE];
strcpy(ctemp,&iLine[i]); //copy the line to the temp buffer
strcpy(iLine,ctemp); // copy back to the original
return;
}//if (iLine[i] != ' ')
} //for (i=0;i<ilength;i++)
//
// If we get here we only had a blank line
//
// zero it and return
//
iLine[0]=0;
}//void TrimLine(char *iLine)