# include <iostream>
using namespace std;
class Node
{
public:
int d;Node*temp1;
Node*next;Node*temp2;
};
void insert(Node*&head,int x)
{
Node*node = new Node(); // allocate memory 2 node let node be an abstract data
node->d = x; // define data in the new node as new data (saving data define in there)
node->next = head; // Let next of the new node as head
head = node; // let pointer name head point new node
}
void print(Node*node)
{
while (node != NULL)
{
cout<<' '<<node->d;
node = node->next;
}
}
void Delete(Node*&head,int n) // Delete node at position
{
int i;Node*node=head;// temp1 points 2(n-1)th
if(n==1)
{
head = node->next; // head now points 2 second node.
return;
}
for(i=0;i<n-2;i++)
{
head = node->next;
} // temp1 points 2 (n-1)th Node
Node*nnode= node->next; // nth node temp1=node temp2=nnode
node-> next = nnode->next; //(n+1)th Node
}
int main()
{
Node*head = NULL; // Start with empty List
int a,n,i,x;
cin>>n;
for(i=0;i<n;i++)
{
cin>>x;
insert(*&head,x);
}
cout<<"Enter a position:";
cin>>a;
Delete(head,a);print(head);
}
The Output is:
3 // how many number that singly linked list can received
1 2 3 // define many numbers
Enter a position : 1
2 1 // false output it should be 2 3
The output should be:
3
1 2 3
Enter a position : 1
Linked List is 1->2->3
position 1 is remove // at any position we want 2 remove it will show that position we remove
2->3
Enter a position : 4
No data at 4th position
Linked List is 2->3
In the Delete function you have the loop
for(i=0;i<n-2;i++)
{
head = node->next;
}
Because you pass head by reference, you actively destroy the list with this loop. Furthermore since you have node = head earlier, the assignment is effectively head = head->next in the first iteration.
You need to use the variable node instead of head:
for(i=0;i<n-2;i++)
{
node = node->next;
}
You also need to protect against going beyond the end of the list:
for(i = 0; (i < n - 2) && (node->next != nullptr) ;i++)
For starters the declaration of the node of a singly linked list has redundant data members temp1 and temp2 that do not make sense.
The declarations can look like
struct Node
{
int data;
Node *next;
};
In this case the function insert (that you could call like
insert(head,x);
instead of
insert(*&head,x);
as you are doing) will look like
void insert( Node * &head, int x )
{
head = new Node { x, head };
}
In C++ (and in C) indices start from 0. So the function delete also shall accept indices starting from 0. The type of the corresponding parameter shall be an unsigned integer type for example size_t. Otherwise the user can pass a negative number as an index.
The function produces memory leaks because it in fact does not free allocated nodes. It can invoke undefined behavior when the pointer to the head node is equal to NULL. And in general the function does not make sense.
It can be defined the following way
bool Delete( Node * &head, size_t n )
{
Node **current = &head;
while ( *current && n-- )
{
current = &( *current )->next;
}
bool success = *current != nullptr;
if ( success )
{
Node *tmp = *current;
*current = ( *current )->next;
delete tmp;
}
return success;
}
Here is a demonstrative program.
#include <iostream>
struct Node
{
int data;
Node *next;
};
void insert( Node * &head, int x )
{
head = new Node { x, head };
}
bool Delete( Node * &head, size_t n )
{
Node **current = &head;
while ( *current && n-- )
{
current = &( *current )->next;
}
bool success = *current != nullptr;
if ( success )
{
Node *tmp = *current;
*current = ( *current )->next;
delete tmp;
}
return success;
}
std::ostream & print( Node * &head, std::ostream &os = std::cout )
{
for ( Node *current = head; current != nullptr; current = current->next )
{
os << current->data << " -> ";
}
return os << "null";
}
int main()
{
Node *head = nullptr;
for ( int i = 3; i != 0; i-- ) insert( head, i );
print( head ) << '\n';
size_t pos = 0;
if ( Delete( head, pos ) )
{
print( head ) << '\n';
}
else
{
std::cout << "No data at the position " << pos << '\n';
}
pos = 4;
if ( Delete( head, pos ) )
{
print( head ) << '\n';
}
else
{
std::cout << "No data at the position " << pos << '\n';
}
pos = 1;
if ( Delete( head, pos ) )
{
print( head ) << '\n';
}
else
{
std::cout << "No data at the position " << pos << '\n';
}
pos = 0;
if ( Delete( head, pos ) )
{
print( head ) << '\n';
}
else
{
std::cout << "No data at the position " << pos << '\n';
}
return 0;
}
Its output is
1 -> 2 -> 3 -> null
2 -> 3 -> null
No data at the position 4
2 -> null
null
I am doing a class assignment, where I have to create a linked list representing a big number, but I cant get the print function to work.
This is the code:
Header
class List
{
private:
struct node
{
int data;
node* next;
};
node* head;
node* temp;
node* curr;
public:
List();
void addNode(std::string digits);
void printList();
};
Constructor
List::List()
{
head = NULL;
curr = NULL;
temp = NULL;
}
Function that creates the list
void List::addNode(string digits)
{
int o = 1;
int j = 0;
int i = 0;
node *n;
node *head;
node *temp;
//=================================================================================//
n = new node;
if (digits[0]=='-')
{
n -> data = -1;
head = n;
temp = n;
}
else
{
n -> data = 1;
head = n;
temp = n;
}
//================================================================================//
if ((head->data) == -1)
{
while (o < digits.length())
{
n = new node;
n->data = stoi(digits.substr(o,1));
temp -> next = n;
temp = temp -> next;
o++;
}
}
else
{
while(i < digits.length())
{
n = new node;
n->data = stoi(digits.substr(i,1));
temp -> next = n;
temp = temp -> next;
i++;
}
}
The print function I've been trying to implement, it gives no output (blank):
void List::printList()
{
node* curr = head;
while(curr != NULL)
{
cout<<curr -> data<<" ";
curr = curr -> next;
}
}
The list prints fine when I use this code in the addNode function:
if ((head -> data) == -1)
{
while(j < digits.length())
{
cout<<head -> data<<" ";
head = head -> next;
j++;
}
}
else
{
while(j<=digits.length())
{
cout<<head -> data<<" ";
head = head -> next;
j++;
}
}
For starters these data members
node* temp;
node* curr;
are redundant. Instead of them you can use similar local variables in member functions of the class if it is required.
The function addNode deals with the local variable head instead of the data member with the same name.
void List::addNode(string digits)
{
int o = 1;
int j = 0;
int i = 0;
node *n;
node *head;
//…
Also you forgot to set the data member next of the last node to nullptr.
If the member function will be called a second time then there will be memory leaks.
Calling the standard function std::stoi for one character
n->data = stoi(digits.substr(i,1));
is inefficient.
The class can look the following way as it is shown in the demonstrative program below. You will need to add other required member functions (as for example the copy constructor or destructor) yourself.
#include <iostream>
#include <string>
class List
{
private:
struct node
{
int data;
node *next;
} *head = nullptr;
public:
List() = default;
void addNode( const std::string &digits );
std::ostream & printList( std::ostream &os = std::cout ) const;
};
void List::addNode( const std::string &digits )
{
if ( !digits.empty() &&
!( digits.size() == 1 && ( digits[0] == '-' || digits[0] == '+') ) )
{
node **current = &head;
while ( *current )
{
node *tmp = *current;
*current = ( *current )->next;
delete tmp;
}
std::string::size_type i = 0;
*current = new node { digits[i] == '-' ? -1 : 1, nullptr };
if ( digits[i] == '-' || digits[i] == '+' ) ++i;
for ( ; i < digits.size(); i++ )
{
current = &( *current )->next;
*current = new node { digits[i] - '0', nullptr };
}
}
}
std::ostream & List::printList( std::ostream &os ) const
{
if ( head != nullptr )
{
if ( head->data == -1 ) os << '-';
for ( node *current = head->next; current != nullptr; current = current->next )
{
os << current->data;
}
}
return os;
}
int main()
{
List lst;
lst.addNode( "-123456789" );
lst.printList() << '\n';
lst.addNode( "987654321" );
lst.printList() << '\n';
return 0;
}
The program output is
-123456789
987654321
I tried to do an insertion sort in a linked list. When only one element is inserted(i.e the first one),it executes well and fine but for multiple elements it gives segmentation fault. Can anyone tell me where the problem is?
#include <iostream>
using namespace std;
struct node
{
int data;
node* next;
} *head = NULL;
node* createNode(int x)
{
node *temp = new node;
temp->data = x;
temp->next = NULL;
return temp;
}
void insertSort(int x)
{
if(head==NULL)
{
node *temp = createNode(x);
head = temp;
return;
}
node *temp = createNode(x);
node *prev = NULL;
node *curr = head;
bool inserted = false;
while(curr != NULL || !inserted)
{
if(temp->data < head->data)
{
temp->next = head;
head = temp;
inserted = true;
}
else
{
if(temp->data < curr->data)
{
prev->next = temp;
temp->next = curr;
inserted = true;
}
else
{
prev = curr;
curr = curr->next;
}
}
}
if(!inserted)
{
prev->next = temp;
}
}
void display()
{
node *p = head;
while(p != NULL)
{
cout<<p->data<<" ";
p = p->next;
}
}
For starters the function insertSort has redundant code
if(head==NULL)
{
node *temp = createNode(x);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
head = temp;
return;
}
node *temp = createNode(x);
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Secondly the condition in the while statement
while(curr != NULL || !inserted)
is incorrect. There must be
while(curr != NULL && !inserted)
In any case the function is too complicated. It can be written simpler.
Here is a demonstrative program that shows how the function can be implemented.
#include <iostream>
#include <cstdlib>
#include <ctime>
struct node
{
int data;
node* next;
} *head = nullptr;
node* createNode(int x)
{
return new node { x, nullptr };
}
std::ostream & display( std::ostream &os = std::cout )
{
for ( node *current = head; current != nullptr; current = current->next )
{
os << current->data << " - > ";
}
return os << "NULL";
}
void insertSort( int x )
{
node *new_node = createNode( x );
node **current = &head;
while ( *current != NULL && not ( x < ( *current )->data ) )
{
current = &( *current )->next;
}
new_node->next = *current;
*current = new_node;
}
int main()
{
const int N = 10;
std::srand( ( unsigned int )std::time( nullptr ) );
for ( int i = 0; i < N; i++ ) insertSort( std::rand() % N );
display() << '\n';
return 0;
}
The program output might look like
1 - > 2 - > 2 - > 3 - > 3 - > 3 - > 3 - > 8 - > 9 - > 9 - > NULL
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am trying to insert a node into a linked list after it finds a name in the list.
My problem is that when i print out the linked list it prints the nodes up to and including the node containing the name but then outputs infinitely the node I inserted. Any help would be greatly appreciated. Thanks!
(some extra information),(the pointer student is pointing to a dynamically created node already). :)
bool StudentLinkedList::insertStudentAfter(StudentNode* student, string _name)
{
StudentNode* curr = headP;
StudentNode* prev = headP;
while (curr != NULL)
{
if (curr->getName() == _name)
{
StudentNode* dummy = curr -> getnext();
curr->setNext(student);
prev = prev->getnext();
curr=curr ->getnext();
curr->setNext(dummy);
prev = curr;
curr = curr->getnext();
length++;
return true;
}
prev = curr;
curr = curr->getnext();
}
return false;
}
You have to simply insert your new node between curr & prev
If you really want to appreciate accept and upvote the answer
bool StudentLinkedList::insertStudentAfter(StudentNode* student, string _name)
{
StudentNode* curr = headP;
StudentNode* prev = headP;
while (curr != NULL)
{
if (curr->getName() == _name)
{
student->setNext(curr->getnext());
curr->setNext(student);
length++;
return true;
}
prev = curr;
curr = curr->getnext();
}
return false;
}
Your function is too complicated. The more complicated function the more bugs it contains and it is more difficult to read it.:)
The function can be written the following way. I assume that there are defined the following functions
getNext, setNext, getPrev, setPrev
^^^^
Here you are.
bool StudentLinkedList::insertStudentAfter( StudentNode *student,
const std::string &name )
{
StudentNode *current = headP;
while ( current != nullptr && current->getName() != name )
{
current = current->getNext();
}
bool success = current != nullptr;
if ( success )
{
student->setPrev( current );
student->setNext( current->getNext() );
if ( current->getNext() != nullptr )
{
current->getNext()->setPrev( student );
}
current->setNext( student );
}
return success;
}
Take into account that if the list also has a data member called something like tail then the function also has to change the tail variable if current->getNext is equal to nullptr.
For example
if ( current->getNext() != nullptr )
{
current->getNext()->setPrev( student );
}
else
{
tailP = student;
//^^^^
}
Here is a demonstrative program that shows how the class could be defined using your approach
#include <iostream>
#include <string>
class StudentLinkedList
{
private:
class StudentNode
{
private:
StudentNode *next;
StudentNode *prev;
std::string name;
public:
StudentNode( const std::string &name )
: next( nullptr ), prev( nullptr ), name( name ) {}
StudentNode * getNext() const { return next; }
StudentNode * getPrev() const { return prev; }
const std::string & getName() const { return name; }
void setNext( StudentNode *student ) { next = student; }
void setPrev( StudentNode *student ) { prev = student; }
} *head = nullptr, *tail = nullptr;
public:
StudentLinkedList() = default;
StudentLinkedList( const StudentLinkedList & ) = delete;
StudentLinkedList & operator =( const StudentLinkedList & ) = delete;
~StudentLinkedList()
{
while ( head != nullptr)
{
StudentNode *tmp = head;
head = head->getNext();
delete tmp;
}
tail = head;
}
void appendStudent( const std::string &name )
{
StudentNode *student = new StudentNode( name );
appendStudent( student );
}
void insertStudentAfter( const std::string ¤t_name,
const std::string &new_name )
{
StudentNode *student = new StudentNode( new_name );
insertStudentAfter( student, current_name );
}
friend std::ostream & operator <<( std::ostream &os, const StudentLinkedList &lsdt );
private:
void appendStudent( StudentNode *student )
{
if ( tail == nullptr )
{
head = tail = student;
}
else
{
tail->setNext( student );
tail = tail->getNext();
}
}
bool insertStudentAfter( StudentNode *student, const std::string &name )
{
StudentNode *current = head;
while ( current != nullptr && current->getName() != name )
{
current = current->getNext();
}
bool success = current != nullptr;
if ( success )
{
student->setPrev( current );
student->setNext( current->getNext() );
if ( current->getNext() != nullptr )
{
current->getNext()->setPrev( student );
}
else
{
tail = student;
}
current->setNext( student );
}
return success;
}
};
std::ostream & operator <<( std::ostream &os, const StudentLinkedList &lst )
{
for ( StudentLinkedList::StudentNode *current = lst.head;
current != nullptr;
current = current->getNext() )
{
os << current->getName() << ' ';
}
return os;
}
int main()
{
const size_t N = ( 'Z' - 'A' + 1 ) / 2;
StudentLinkedList students;
for ( size_t i = 0; i < N; i++ )
{
char name[2] = { char( 'A' + 2 * i ) };
students.appendStudent( name );
}
std::cout << students << std::endl;
for ( size_t i = 0; i < N; i++ )
{
char new_name[2] = { char( 'A' + 2 * i + 1 ) };
char current_name[2] = { char( 'A' + 2 * i ) };
students.insertStudentAfter( current_name, new_name );
}
std::cout << students << std::endl;
return 0;
}
The program output is
A C E G I K M O Q S U W Y
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
Could someone help me with this, as an on-going personal interest I've working on creating a binary tree class, and have also created my own deque class dequeList, that I want to use within my binary tree class FibTree, I'm very much a novice C++ programmer and having difficulty with the fundamentals.
I've created a binary tree of Fibonacci numbers and I'm trying to write out sets, and I'm using the methods startWriteSets and writeSets to do this; my problem is that I'm trying to declare a new dequeList with the startWriteSets method, then pass this to the writeSets method, but Im getting compile errors; could someone help me utilise my dequeList without compilation errors, I'm using Xcode 3.2.2.
Compile errors:
Compile main.cpp
'dequeList has not been declared
Compile deque.cpp
'dequeList has not been declared
Compile fibtree.cpp
'dequeList has not been declared
Compile fibtree.cpp
'dequeList has not been declared
error: no matching function for call to 'FibTree::writeSets(dequeList*&, const FibTree::Node*&)'
note: candidates are: void FibTree::writeSets(int*&, const FibTree::Node*)
error: prototype for 'void FibTree::writeSets(dequeList*&, const FibTree::Node*)' does not match any in class 'FibTree'
error: candidate is: void FibTree::writeSets(int*&, const FibTree::Node*)
error: 'setsList' was not declared in this scope
error: 'setsList' was not declared in this scope
My code is listed below, with errors:
deque.h
/*
* deque.h
* fibonacci / deque / interface
* deque holding FibTree::Node datatype
* using a double-linked list implementation
*/
#ifndef DEQUE_H
#define DEQUE_H
#include "fibtree.h"
class dequeNode {
public:
dequeNode* prev;
dequeNode* next;
FibTree::Node const* data;
dequeNode( void );
dequeNode( FibTree::Node const* );
};
class dequeList {
public:
dequeNode* firstNode;
dequeNode* lastNode;
dequeList( void );
void enque( FibTree::Node const* );
void enqueFront( FibTree::Node const* );
FibTree::Node const* deque( void );
FibTree::Node const* dequeFront( void );
bool isEmpty( void );
private:
void insertAfter( dequeList* list, dequeNode* node, dequeNode* newNode );
void insertBefore( dequeList* list, dequeNode* node, dequeNode* newNode );
void insertBeginning( dequeList* list, dequeNode* newNode );
void insertEnd( dequeList* list, dequeNode* newNode );
void removeNode( dequeList* list, dequeNode* node );
dequeNode* frontNode( dequeList* list ); // examine front
dequeNode* backNode( dequeList* list ); // examine back
void popFront( dequeList* list ); // delete first
void popBack( dequeList* list ); // delete last
void pushBack( dequeList* list, FibTree::Node const* n );
void pushFront( dequeList* list, FibTree::Node const* n );
};
#endif
deque.cpp
/*
* deque.cpp
* fibonacci / deque / implementation
*
*/
#include "deque.h"
#include <cstddef>
// Constructors
dequeNode::dequeNode()
: prev( NULL ), next( NULL ), data( NULL )
{
};
dequeNode::dequeNode( FibTree::Node const* n )
: prev( NULL ), next( NULL ), data( n )
{
};
dequeList::dequeList()
: firstNode( NULL ), lastNode( NULL )
{
};
// Public Methods
void dequeList::enque( FibTree::Node const* n ) {
pushBack( this, n );
}
void dequeList::enqueFront( FibTree::Node const* n ) {
pushFront( this, n );
}
const FibTree::Node* dequeList::deque( void ) {
dequeNode* node = frontNode( this );
const FibTree::Node* data = node->data;
popFront( this );
return data;
}
bool dequeList::isEmpty( void ) {
if ( this->firstNode == NULL && this->lastNode == NULL ) {
return true;
} else {
return false;
}
}
// Private methods
void dequeList::insertAfter( dequeList* list, dequeNode* node, dequeNode* newNode ) {
newNode->prev = node;
newNode->next = node->next;
if ( node->next == NULL ) {
list->lastNode = newNode;
} else {
node->next->prev = newNode;
}
node->next = newNode;
}
void dequeList::insertBefore( dequeList* list, dequeNode* node, dequeNode* newNode ) {
newNode->prev = node->prev;
newNode->next = node;
if ( node->prev == NULL ) {
list->firstNode = newNode;
} else {
node->prev->next = newNode;
}
node->prev = newNode;
}
void dequeList::insertBeginning( dequeList* list, dequeNode* newNode ){
if ( list->firstNode == NULL ) {
list->firstNode = newNode;
list->lastNode = newNode;
newNode->prev = NULL;
newNode->next = NULL;
} else {
insertBefore( list , list->firstNode, newNode );
}
}
void dequeList::insertEnd( dequeList* list, dequeNode* newNode ){
if (list->lastNode == NULL) {
insertBeginning( list, newNode );
} else {
insertAfter( list, list->lastNode, newNode );
}
}
void dequeList::removeNode( dequeList* list, dequeNode* node ) { // pop_front / pop_back
if (node->prev == NULL) {
list->firstNode = node->next;
} else {
node->prev->next = node->next;
}
if (node->next == NULL) {
list->lastNode = node->prev;
} else {
node->next->prev = node->prev;
}
delete node;
}
dequeNode* dequeList::frontNode( dequeList* list ) { // Examine first
return list->lastNode;
}
dequeNode* dequeList::backNode( dequeList* list ) { // Examine last
return list->firstNode;
}
void dequeList::popFront( dequeList* list ) { // Delete first
removeNode(list, list->lastNode);
}
void dequeList::popBack( dequeList* list ) { // Delete last
removeNode(list, list->firstNode);
}
void dequeList::pushBack( dequeList* list, FibTree::Node const* n ) { // Append (Enque)
dequeNode* newNode = new dequeNode( n );
insertBeginning(list, newNode);
}
void dequeList::pushFront( dequeList* list, FibTree::Node const* n ) { // Prepend
dequeNode* newNode = new dequeNode( n );
insertEnd(list, newNode);
}
fibtree.h
/*
* fibtree.h
* Fibonacci binary tree / interface
*
*/
#ifndef FIBTREE_H
#define FIBTREE_H
#include <string>
#include <iostream>
#include <vector>
#include "deque.h"
class FibTree {
public:
class Node {
public:
int data;
Node const* left;
Node const* right;
Node const* parent;
int n;
int level;
int index;
Node (void);
bool isLeftChild(void) const;
bool isRightChild(void) const;
bool isLeafNode(void) const;
bool hasLeftChild(void) const;
bool hasRightChild(void) const;
bool hasParent(void) const;
};
Node const* root; // 'root' pointer to constant Node
FibTree (int);
Node const* getRoot(void); // Getters
int getHeight(Node const* root);
void preOrder(Node const* root); // Tree traversals
void preOrderFormatted(Node const* root, std::string indent = "");
void inOrder(Node const* root);
void postOrder(Node const* root);
void breadthFirst(Node const* root);
void levelOrderBreadthFirst(Node const* root);
void loBFStructured(Node const* root);
void writeFibTree(Node const* root); // Serialisation
***error: 'dequeList' has not been declared***
void startWriteSets(Node const* root); // Write all sets of tree
void writeSets(dequeList* &leftQueue, Node const* cur); // Used by startWriteSets
int countNodes(Node const* root); // Node counting
int countLeafNodes(Node const* root);
int countInteriorNodes(Node const* root);
private:
static Node* buildTree( int n, int level = 0, int i = 1, Node* parent = NULL );
void printNode (Node const* root);
};
#endif
fibfree.cpp
/*
* fibtree.cpp
* Fibonacci binary tree / implementation
*
*/
#include <string>
#include <vector>
#include <iostream>
#include "deque.h"
#include "fibtree.h"
// FibTree Constructor
FibTree::FibTree(int n) {
this->root = buildTree( n );
};
// Getters
FibTree::Node const* FibTree::getRoot(void) {
return this->root;
}
int FibTree::getHeight( Node const* root ) {
if( root == NULL || root->isLeafNode() ) {
return 0;
}
return std::max(getHeight(root->left), getHeight(root->right)) + 1;
}
// Traversals
void FibTree::preOrder(Node const* root) { // Preorder Depth First Traversal (root, left, right)
if (root == NULL)
return;
printNode(root);
preOrder(root->left);
preOrder(root->right);
}
void FibTree::preOrderFormatted(Node const* root, std::string indent ) { // Pre-order formatted
if (root != NULL) {
std::cout << indent;
if ( !root->isLeafNode() ) {
std::cout << "|-";
indent += "| ";
} else {
std::cout << "\\-";
indent += " ";
}
if ( root->isLeftChild() ) {
std::cout << root->data << " [L]" << " i=" << root->index << std::endl;
} else if ( root->parent != NULL ) {
std::cout << root->data << " [R]" << " i=" << root->index << std::endl;
} else {
std::cout << root->data << " i=" << root->index << std::endl;
}
if ( root->hasLeftChild() ) {
preOrderFormatted( root->left, indent );
}
if ( root->hasRightChild() ) {
preOrderFormatted( root->right, indent );
}
}
}
void FibTree::inOrder(Node const* root) { // Inorder (Symetric) Depth First Traversal (left, root, right); producing a sorted sequence.
if (root == NULL)
return;
inOrder(root->left);
printNode(root);
inOrder(root->right);
}
void FibTree::postOrder(Node const* root) { // Postorder Depth First Traversal (left, right, root).
if (root == NULL)
return;
postOrder(root->left);
postOrder(root->right);
printNode(root);
}
void FibTree::breadthFirst(Node const* root) { // Breadth-first traversal
dequeList* list = new dequeList();
list->enque(root);
while ( !list->isEmpty() ) {
Node const* node = list->deque();
printNode( node );
if ( node->hasLeftChild() ) {
list->enque( node->left );
}
if ( node->hasRightChild() ) {
list->enque( node->right );
}
}
}
void FibTree::levelOrderBreadthFirst(Node const* root) { // Level-order Breadth-first traversal
dequeList* thisLevel = new dequeList();
thisLevel->enque(root);
while ( !thisLevel->isEmpty() ) {
dequeList* nextLevel = new dequeList();
dequeNode* thisNode = thisLevel->lastNode; // iterate thisLevel
while ( thisNode != NULL ) {
printNode( thisNode->data );
thisNode = thisNode->prev;
}
std::cout << std::endl;
while ( !thisLevel->isEmpty() ) { // get next level
Node const* node = thisLevel->deque();
if ( node->hasLeftChild() ) {
nextLevel->enque( node->left );
}
if ( node->hasRightChild() ) {
nextLevel->enque( node->right );
}
}
thisLevel = nextLevel;
}
}
void FibTree::loBFStructured(Node const* root) { // Level-order Breadth-first traversal structured output
// Each node is centred above it's children
// Calculate width of of each node:
// Amount of Hoz space required to display this node's entire subtree,
// such that it doesn't overlap with it's left or right siblings' subtree
// width = 1 + sum (width of children's nodes)
// DF traversal through tree to calc each node's width
// To display: LOBF traversal
dequeList* thisLevel = new dequeList();
thisLevel->enque(root);
while ( !thisLevel->isEmpty() ) {
dequeList* nextLevel = new dequeList();
dequeNode* thisNode = thisLevel->lastNode; // iterate thisLevel
while ( thisNode != NULL ) {
int width = countNodes(thisNode->data);
width +=2;
while(width--)
std::putchar(' ');
std::cout << thisNode->data->data << '(' << thisNode->data->index << ')';
thisNode = thisNode->prev;
}
std::cout << std::endl;
while ( !thisLevel->isEmpty() ) { // get next level
Node const* node = thisLevel->deque();
if ( node->hasLeftChild() ) {
nextLevel->enque( node->left );
}
if ( node->hasRightChild() ) {
nextLevel->enque( node->right );
}
}
thisLevel = nextLevel;
}
}
// Serialisation
void FibTree::writeFibTree(Node const* root) { // Preorder tree serialisation method
if ( root == NULL ) {
std::cout << "# ";
return;
} else {
std::cout << root->data << " ";
writeFibTree( root->left );
writeFibTree( root->right );
}
}
// Write sets of tree
void FibTree::startWriteSets(Node const* root) {
//std::vector<Node const*> setsList;
dequeList* leftQueue = new dequeList();
std::cout << root->data << '(' << root->index << ')' << ',';
writeSets(leftQueue, root);
***error: no matching function for call to 'FibTree::writeSets(dequeList*&, const FibTree::Node*&)'***
}
//void FibTree::writeSets(std::vector<Node const*> &setsList, Node const* cur) {
void FibTree::writeSets(dequeList* &leftQueue, Node const* cur) {
***error: prototype for 'void FibTree::writeSets(dequeList*&, const FibTree::Node*)' does not match any in class 'FibTree'***
std::vector<Node const*>::iterator nodeIterator;
std::cout << '(';
if (! setsList.empty()) { ***error: 'setsList' was not declared in this scope***
setsList.pop_front();
}
// Displays all preceding left values
for (nodeIterator = setsList.begin(); nodeIterator != setsList.end(); nodeIterator++) { ***error: 'setsList' was not declared in this scope***
std::cout << (*nodeIterator)->data << '(' << (*nodeIterator)->index << ')' << ',';
}
if (cur->hasLeftChild()) {
std::cout << cur->left->data << '(' << cur->left->index << ')' << ',';
setsList.push_back(cur->left);
}
if (cur->hasRightChild()) {
std::cout << cur->right->data << '(' << cur->right->index << ')' << ',';
writeSets(setsList,cur->right);
}
setsList.pop_back();
std::cout << ')';
}
// Node counting
int FibTree::countNodes(Node const* root) { // Count all tree nodes
int count = 0;
if ( root->hasLeftChild() )
count += countNodes(root->left);
if ( root->hasRightChild() )
count += countNodes(root->right);
count += 1;
return count;
}
int FibTree::countLeafNodes(Node const* root) { // count all leaf nodes
// An almost complete strictly binary tree with n leafs has 2n - 1 nodes
int count = 0;
if ( root->hasLeftChild() )
count += countLeafNodes(root->left);
if ( root->hasRightChild() )
count += countLeafNodes(root->right);
if (!root->hasLeftChild() && !root->hasRightChild())
count += 1;
return count;
}
int FibTree::countInteriorNodes(Node const* root) { // Return number of internal nodes in tree
int count = 0;
if ( root->hasLeftChild() )
count += countInteriorNodes(root->left);
if ( root->hasRightChild() )
count += countInteriorNodes(root->right);
if ( (root->hasLeftChild() || root->hasRightChild()) && root->hasRightChild() )
count += 1;
return count;
}
// Private FibTree methods
FibTree::Node* FibTree::buildTree( int n, int level, int i, Node* parent ) { // Build Tree structure
Node* thisNode = new Node();
thisNode->n = n;
thisNode->level = level;
thisNode->index = i;
thisNode->parent = parent;
if (n < 2) {
thisNode->left = NULL;
thisNode->right = NULL;
thisNode->data = n;
return thisNode;
} else {
thisNode->left = buildTree( n - 1 , level + 1, i*2, thisNode );
thisNode->right = buildTree( n - 2, level + 1, i*2+1, thisNode );
thisNode->data = thisNode->left->data + thisNode->right->data;
return thisNode;
}
}
void FibTree::printNode(Node const* node) {
std::cout << node->data << "[" << node->index << "]" << " ";
}
// FibTree Node constructor
FibTree::Node::Node()
: data( 0 ),
left( NULL ),
right( NULL ),
parent( NULL ),
n( 0 ),
level( 0 ),
index( 0 )
{
};
bool FibTree::Node::isLeftChild(void) const { // a pointer (Root) to const parameter, can only call const methods on it
bool hasParent = this->parent != NULL;
if ( hasParent ) {
return this == this->parent->left;
} else {
return false;
}
}
bool FibTree::Node::isRightChild(void) const {
bool hasParent = this->parent != NULL;
if ( hasParent ) {
return this == this->parent->right;
} else {
return false;
}
}
bool FibTree::Node::isLeafNode(void) const {
if (this->left == NULL && this->right == NULL) {
return true;
} else {
return false;
}
}
bool FibTree::Node::hasLeftChild(void) const {
if ( this->left != NULL ) {
return true;
} else {
return false;
}
}
bool FibTree::Node::hasRightChild(void) const {
if ( this->right != NULL ) {
return true;
} else {
return false;
}
}
bool FibTree::Node::hasParent(void) const {
if ( this->parent != NULL ) {
return true;
} else {
return false;
}
}
main.cpp
#include <iostream>
#include "deque.h"
#include "fibtree.h"
int main (int argc, const char* argv[]) {
if (argc > 1) {
int n = atoi( argv[1] ); // convert string to int
FibTree f(n);
//f.preOrder(f.getRoot());
std::cout << "All Nodes count: " << f.countNodes(f.getRoot()) << std::endl;
std::cout << "Leaf Nodes count: " << f.countLeafNodes(f.getRoot()) << std::endl;
std::cout << "Interior Nodes count: " << f.countInteriorNodes(f.getRoot()) << std::endl;
std::cout << "Tree Height: " << f.getHeight(f.getRoot()) << std::endl;
//f.writeFibTree(f.getRoot());
f.loBFStructured(f.getRoot());
f.startWriteSets(f.getRoot());
std::cout << std::endl;
}
return 0;
}
Any insights as to where I'm fundamentally going wrong would be greatly appreciated.
Many thanks in advance.
Alex
It's a circular dependency issue, causing the includes not to work as you expect.
Explanations:
In main.cpp you include deque.h. But deque.h includes itself fibtree.h before declaring anything. Unfortunatley FibTree class needs dequeList, so the header includes itself deque.h at its beginning. As DEQUE_H is already defined at this moment, the file IS NOT included again. When encoutering the first use of dequeList in fibtree.h, this class is not yet defined ! Hence the error.
Solution:
When you have two interdependent classes, you need to use a forward declaration.
To solve this, you could just add in fibtree.h the following line before the FibTree definition:
class dequeList; // Forward declaration
As in this file you do not refer to a dequeList object but only to a pointer to a dequeList, this forward declaration will be sufficient for the compiler to know that your class exist. Your FibTree class can then be completely defined, and then your compiler can process the dequeList header. Et voilà !